Add global ticket history view

This commit is contained in:
michael committed 2026-09-01 10:23:51 +02:00
1 parent 19cc37d42a
commit b67dbad0b1
5 files changed
+421 -39

No files matched your search

+22 -7
View File
@@ -70,7 +70,7 @@ import { StatisticsPage } from "./views/StatisticsPage";
import { SetupPage } from "./views/SetupPage";
import { TicketDetailPage } from "./views/TicketDetailPage";
import { TimerPage } from "./views/TimerPage";
import type { AuthUser, PeriodType, TicketSearchResult } from "./types";
import type { AuthUser, PeriodType, TicketDetailPeriodType, TicketSearchResult } from "./types";
import type { Dispatch, DragEvent, SetStateAction } from "react";
type NavMenuEntry =
@@ -90,7 +90,7 @@ type OpenTicketNavItem = {
key: string;
ticketId: string;
ticketNumber: string;
periodType: PeriodType;
periodType: TicketDetailPeriodType;
period: string;
path: string;
dirty: boolean;
@@ -111,13 +111,13 @@ function readOpenTickets(userId: string): OpenTicketNavItem[] {
const parsed = JSON.parse(raw) as Partial<OpenTicketNavItem>[];
return parsed
.filter((item) => item.key && item.ticketId && item.ticketNumber && item.periodType && item.period && item.path)
.filter((item) => item.key && item.ticketId && item.ticketNumber && item.path)
.map((item) => ({
key: String(item.key),
ticketId: String(item.ticketId),
ticketNumber: String(item.ticketNumber),
periodType: item.periodType === "day" ? "day" : "month",
period: String(item.period),
periodType: item.periodType === "day" ? "day" : item.periodType === "month" ? "month" : "all",
period: item.period ? String(item.period) : "all",
path: String(item.path),
dirty: false
}));
@@ -127,6 +127,17 @@ function readOpenTickets(userId: string): OpenTicketNavItem[] {
}
function routeFromPath(pathname: string) {
const ticketMatch = pathname.match(/^\/tickets\/(\d+)$/);
if (ticketMatch) {
return {
page: "ticket" as const,
periodType: "all" as const,
period: "all",
ticketId: ticketMatch[1],
};
}
const periodTicketMatch = pathname.match(/^\/analysis\/(month|day)\/([^/]+)\/tickets\/(\d+)$/);
if (periodTicketMatch) {
@@ -318,7 +329,7 @@ function HeaderTicketSearch({ className, onNavigate }: HeaderTicketSearchProps)
}, [trimmedQuery]);
function openTicket(ticket: TicketSearchResult) {
onNavigate(`/analysis/month/${ticket.latest_period}/tickets/${ticket.ticket_id}`);
onNavigate(`/tickets/${ticket.ticket_id}`);
setQuery("");
setResults([]);
setOpen(false);
@@ -967,7 +978,11 @@ export function App() {
<a
href={ticket.path}
className="flex min-w-0 flex-1 items-center gap-2 text-sm"
title={`${ticket.ticketNumber} (${ticket.periodType === "month" ? "Monat" : "Tag"} ${ticket.period})`}
title={
ticket.periodType === "all"
? `${ticket.ticketNumber} (alle Sessions)`
: `${ticket.ticketNumber} (${ticket.periodType === "month" ? "Monat" : "Tag"} ${ticket.period})`
}
onClick={navHandler(ticket.path)}
>
<span className={cn("size-2 shrink-0 rounded-full", ticket.dirty ? "bg-amber-400" : isActive ? "bg-primary-foreground" : "bg-muted-foreground/70")} />