diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 55d606f..f3b137f 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -69,6 +69,19 @@ import { TimerPage } from "./views/TimerPage";
import type { AuthUser, PeriodType } from "./types";
import type { Dispatch, SetStateAction } from "react";
+type NavMenuEntry =
+ | {
+ type: "item";
+ href: string;
+ label: string;
+ icon: typeof Timer;
+ active: boolean;
+ }
+ | {
+ type: "separator";
+ key: string;
+ };
+
function routeFromPath(pathname: string) {
const periodTicketMatch = pathname.match(/^\/analysis\/(month|day)\/([^/]+)\/tickets\/(\d+)$/);
@@ -518,17 +531,20 @@ export function App() {
return ;
}
- const navItems = [
- { href: "/timer", label: "Timer", icon: Timer, active: path.startsWith("/timer") || path === "/" },
- { href: "/analysis", label: "Auswertung", icon: BarChart3, active: path.startsWith("/analysis") },
- { href: "/monthly-close", label: "Monatsabschluss", icon: ClipboardCheck, active: path.startsWith("/monthly-close") },
- { href: "/statistics", label: "Statistiken", icon: ChartNoAxesCombined, active: path.startsWith("/statistics") },
- { href: "/recurring", label: "Fixe Abrechnung", icon: Repeat, active: path.startsWith("/recurring") },
- { href: "/faq", label: "FAQ", icon: CircleHelp, active: path.startsWith("/faq") },
- { href: "/profile", label: "Profil", icon: UserCog, active: path.startsWith("/profile") },
+ const navItems: NavMenuEntry[] = [
+ { type: "item", href: "/timer", label: "Timer", icon: Timer, active: path.startsWith("/timer") || path === "/" },
+ { type: "item", href: "/analysis", label: "Auswertung", icon: BarChart3, active: path.startsWith("/analysis") },
+ { type: "separator", key: "after-analysis" },
+ { type: "item", href: "/monthly-close", label: "Monatsabschluss", icon: ClipboardCheck, active: path.startsWith("/monthly-close") },
+ { type: "separator", key: "after-monthly-close" },
+ { type: "item", href: "/statistics", label: "Statistiken", icon: ChartNoAxesCombined, active: path.startsWith("/statistics") },
+ { type: "item", href: "/recurring", label: "Fixe Abrechnung", icon: Repeat, active: path.startsWith("/recurring") },
+ { type: "item", href: "/profile", label: "Profil", icon: UserCog, active: path.startsWith("/profile") },
...(currentUser.role === "admin"
- ? [{ href: "/admin/users", label: "Benutzer", icon: Shield, active: path.startsWith("/admin/users") }]
+ ? [{ type: "item" as const, href: "/admin/users", label: "Benutzer", icon: Shield, active: path.startsWith("/admin/users") }]
: []),
+ { type: "separator", key: "before-faq" },
+ { type: "item", href: "/faq", label: "FAQ", icon: CircleHelp, active: path.startsWith("/faq") },
];
const runningTimer = timers.find((timer) => timer.phase === "running") ?? null;
const runningElapsedSeconds = runningTimer ? Math.floor(activeElapsedMs(runningTimer, tick) / 1000) : 0;
@@ -589,16 +605,22 @@ export function App() {
Workflows
- {navItems.map((item) => (
-
-
-
-
- {item.label}
-
-
-
- ))}
+ {navItems.map((item) =>
+ item.type === "separator" ? (
+
+
+
+ ) : (
+
+
+
+
+ {item.label}
+
+
+
+ )
+ )}
diff --git a/frontend/src/components/HelpLink.tsx b/frontend/src/components/HelpLink.tsx
index 346bd13..14a604c 100644
--- a/frontend/src/components/HelpLink.tsx
+++ b/frontend/src/components/HelpLink.tsx
@@ -1,6 +1,8 @@
import { CircleHelp } from "lucide-react";
import { Button } from "@/components/ui/button";
+import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
+import { getHelpSection } from "../help-content";
type HelpLinkProps = {
anchor: string;
@@ -9,11 +11,34 @@ type HelpLinkProps = {
};
export function HelpLink({ anchor, label = "Hilfe öffnen", className }: HelpLinkProps) {
+ const section = getHelpSection(anchor);
+
return (
-
+
);
}
diff --git a/frontend/src/help-content.ts b/frontend/src/help-content.ts
new file mode 100644
index 0000000..34df3c9
--- /dev/null
+++ b/frontend/src/help-content.ts
@@ -0,0 +1,277 @@
+export type HelpSection = {
+ id: string;
+ title: string;
+ description: string;
+ quickItems: string[];
+ details: string[];
+};
+
+export const helpSections: HelpSection[] = [
+ {
+ id: "grundprinzip",
+ title: "Grundprinzip",
+ description: "TicketTracker ist die Arbeitszeiterfassung neben Ticketsystem und CRM. Die App misst Arbeit, bewertet Sessions und macht Monatsabschlüsse kontrollierbar.",
+ quickItems: [
+ "Sessions sind die getrackten oder nachgetragenen Arbeitszeiten.",
+ "Teamspace-Werte sind Tageswerte pro Ticket, nicht einzelne Sessions.",
+ "Abgeschlossen wird nur der Monat."
+ ],
+ details: [
+ "TicketTracker ersetzt nicht das Ticketsystem. Ticketnummern dienen als Bezug zur Arbeit, die eigentliche Dokumentation bleibt im vorhandenen Ticketsystem.",
+ "TicketTracker ersetzt auch nicht das CRM. Die CRM- beziehungsweise Teamspace-Zeit wird als Kontrollwert gepflegt, damit getrackte Zeiten und eingetragene Abrechnung gegenübergestellt werden können.",
+ "Eine Session ist immer einem Benutzer zugeordnet. In den normalen Auswertungen sieht jeder Benutzer nur seine eigenen Sessions.",
+ "Ticketdaten wie Organisation und Art können aus bestehenden Tickets übernommen werden, auch wenn ein anderer Benutzer das Ticket schon bearbeitet hat.",
+ "Tickets werden nicht abgeschlossen. Sie gruppieren Sessions. Relevant für den Abschluss ist nur, ob alle Sessions eines Monats bewertet sind.",
+ "Der Monatsabschluss sperrt den Monat gegen versehentliche Änderungen. Muss doch noch etwas korrigiert werden, kann der Monat wieder geöffnet werden."
+ ]
+ },
+ {
+ id: "timer",
+ title: "Timer",
+ description: "Timer erfassen laufende Arbeit an Tickets. Es können mehrere Timer vorbereitet sein, aber immer nur einer läuft aktiv.",
+ quickItems: [
+ "Ticketnummer eingeben und Timer starten.",
+ "Aktivieren eines Timers pausiert alle anderen Timer automatisch.",
+ "Beim Beenden stoppt die Zeit sofort; Details werden danach gespeichert."
+ ],
+ details: [
+ "Neue Timer werden mit einer Ticketnummer im Format Ticket#XXXXXX gestartet.",
+ "Alle laufenden und pausierten Timer bleiben in der Seitenleiste sichtbar, damit du auf jeder Unterseite sehen kannst, was vorbereitet oder aktiv ist.",
+ "Wenn ein anderer Timer aktiviert wird, pausiert TicketTracker die übrigen Timer automatisch. Dadurch kann nie versehentlich auf zwei Tickets gleichzeitig Zeit laufen.",
+ "Beim Klick auf Beenden wird die Stoppuhr sofort angehalten. Das Speichern der Tätigkeit findet danach statt und verlängert die gemessene Zeit nicht.",
+ "Existiert das Ticket bereits, übernimmt TicketTracker Organisation und Art. Dann muss beim Beenden nur noch die Tätigkeit eingetragen werden.",
+ "Existiert das Ticket noch nicht, müssen Organisation, Tätigkeit und Art angegeben werden.",
+ "Pausen werden von der Gesamtdauer abgezogen. Die gespeicherte Zeit wird auf volle Minuten gerundet.",
+ "Der Schnellstart im Kopfbereich funktioniert auf allen Unterseiten und nutzt dieselbe Timerlogik."
+ ]
+ },
+ {
+ id: "session-nachtragen",
+ title: "Session Nachtragen",
+ description: "Nachtragen ist für vergessene Zeiten gedacht, wenn kein Timer gelaufen ist.",
+ quickItems: [
+ "Datum, Von, Bis und Tätigkeit eintragen.",
+ "Benutzer tragen eigene Sessions nach; Admins können Benutzer auswählen.",
+ "Tätigkeiten sind mehrzeilig."
+ ],
+ details: [
+ "Beim Nachtragen wird aus Datum, Startzeit und Endzeit automatisch die Dauer berechnet.",
+ "Das Ende muss nach dem Beginn liegen. Übernacht-Sessions sind aktuell nicht vorgesehen und sollten als getrennte Einträge gepflegt werden.",
+ "Die Organisation muss aus der synchronisierten Organisationsliste gewählt werden. Freitext ist absichtlich gesperrt.",
+ "Die Tätigkeit ist eine Textarea. Zeilenumbrüche bleiben erhalten und werden in der Ticketdetailansicht wieder ausgegeben.",
+ "Nachgetragene Sessions starten immer offen. Sie müssen später als Abgerechnet oder Nicht abrechenbar bewertet werden.",
+ "Admins können im Adminbereich zusätzlich bestimmen, welchem Benutzer die nachgetragene Session gehört.",
+ "In der Ticketdetailansicht kann eine Session direkt zum geöffneten Ticket nachgetragen werden. Ticketnummer und Stammdaten sind dort schon vorbelegt beziehungsweise aus dem Ticket abgeleitet."
+ ]
+ },
+ {
+ id: "ticketdaten",
+ title: "Ticketdaten",
+ description: "Ticketdaten sind Stammdaten für ein Ticket und können nachträglich korrigiert werden.",
+ quickItems: [
+ "Ticketnummer, Organisation und Art sind bearbeitbar.",
+ "Organisationen kommen aus der lokalen Zammad-Synchronisation.",
+ "Die Art wiederkehrender Sessions kommt aus der Regel."
+ ],
+ details: [
+ "Ticketnummern können korrigiert werden, falls beim Starten oder Nachtragen ein falscher Bezug gewählt wurde.",
+ "Die Organisation wird immer über die Suchliste gewählt. Dadurch sind spätere Auswertungen pro Organisation zuverlässig.",
+ "Änderungen an Organisation und Art werden auf vorhandene manuelle Sessions dieses Tickets übernommen.",
+ "Bei wiederkehrenden Sessions ist die Art nicht direkt an der Session änderbar. Sie wird ausschließlich über die fixe Abrechnungsregel gesteuert.",
+ "Wenn ein Ticket bereits durch einen anderen Benutzer bekannt ist, können dessen Ticketdaten beim Beenden eines Timers übernommen werden. Die Session selbst bleibt trotzdem deinem Benutzer zugeordnet."
+ ]
+ },
+ {
+ id: "organisationen",
+ title: "Organisationen",
+ description: "Organisationen kommen aus Zammad und bilden die Grundlage für saubere Kunden- und Monatsauswertungen.",
+ quickItems: [
+ "Nur Admins synchronisieren Organisationen.",
+ "Freitext ist danach nicht mehr möglich.",
+ "Gespeichert werden Zammad-ID, Name und Zeitstempel."
+ ],
+ details: [
+ "Im Adminbereich werden Zammad-URL und API-Key gespeichert. Der API-Key wird danach nicht mehr im Klartext angezeigt.",
+ "Beim Sync fragt TicketTracker die Organisationen aus Zammad ab und schreibt sie in die lokale Datenbank.",
+ "Neue Organisationen werden angelegt, geänderte Namen werden aktualisiert.",
+ "Organisationen, die in Zammad nicht mehr vorhanden sind, werden aus der lokalen Liste entfernt beziehungsweise von vorhandenen Tickets und Sessions gelöst.",
+ "Alte Sessions oder Tickets mit Freitext-Organisationen müssen manuell korrigiert werden, indem eine Organisation aus der Liste gewählt wird.",
+ "Die bewusst schlanke Organisationstabelle enthält interne ID, Zammad-ID, Name sowie Erstell- und Änderungszeitpunkte."
+ ]
+ },
+ {
+ id: "auswertung",
+ title: "Auswertung",
+ description: "Die Auswertung ist die Arbeitsliste für Monat und Tag: Tickets öffnen, Sessions prüfen, sortieren und bewerten.",
+ quickItems: [
+ "Monat oder Tag wählen; die Ansicht aktualisiert automatisch.",
+ "Tickets können gefiltert, gruppiert und sortiert werden.",
+ "Die Einstellungen bleiben nach Refresh und Browserneustart erhalten."
+ ],
+ details: [
+ "Die Monatsansicht zeigt alle Tickets, die im gewählten Monat mindestens eine Session haben.",
+ "Die Tagesansicht zeigt dieselben Datenlogiken auf einen einzelnen Tag gefiltert. Es gibt keinen Tagesabschluss.",
+ "Die Pfeile neben der Zeitraum-Eingabe springen jeweils einen Monat oder einen Tag vor beziehungsweise zurück.",
+ "Der Gesamtaufwand-Graph zeigt den getrackten Aufwand im Zeitraum. In der Monatsansicht pro Tag, in der Tagesansicht pro Stunde.",
+ "Die Ticketliste kann nach Typ, Organisation oder Status gruppiert werden. Gruppenüberschriften zeigen Anzahl, Zeit und offene Bewertungen.",
+ "Filter und Sortierungen bleiben im Browser gespeichert und können über Zurücksetzen wieder auf Standard gestellt werden.",
+ "Das Copy-Icon neben der Ticketnummer kopiert die Nummer direkt in die Zwischenablage."
+ ]
+ },
+ {
+ id: "ticketdetail",
+ title: "Ticketdetailansicht",
+ description: "Die Ticketdetailansicht ist die Bearbeitungsfläche für Sessions, Bewertungen und Teamspace-Tageswerte eines Tickets.",
+ quickItems: [
+ "Sessions sind nach Tag gruppiert.",
+ "Teamspace wird pro Ticket und Tag gespeichert.",
+ "Monats- und Tagesansicht verwenden denselben Teamspace-Wert."
+ ],
+ details: [
+ "Oben steht die Ticketnummer mit Copy-Icon, damit sie schnell in andere Systeme übernommen werden kann.",
+ "Die Session-Einträge sind nach Kalendertagen gruppiert. Pro Tagesgruppe steht die Summe der getrackten Zeit.",
+ "Das Teamspace-Feld wird als Stundenwert gepflegt, zum Beispiel 1, 1,5 oder 2.25.",
+ "Während der Eingabe wird der Teamspace-Wert nicht sofort gespeichert. Sobald eine Änderung vorliegt, erscheint ein Speichern-Button.",
+ "Ein leeres Teamspace-Feld entfernt den gespeicherten Teamspace-Wert für diesen Ticket-Tag.",
+ "Der Teamspace-Wert hängt am Ticket, Benutzer und Tag. Deshalb ist er in Monats- und Tagesansicht identisch.",
+ "Sessions können bewertet, bearbeitet oder gelöscht werden. Gelöschte letzte Sessions können dazu führen, dass ein leeres Ticket entfernt wird."
+ ]
+ },
+ {
+ id: "sessions-bewerten",
+ title: "Sessions Bewerten",
+ description: "Bewertungen bestimmen, ob eine Session abgerechnet wurde oder bewusst nicht abrechenbar ist.",
+ quickItems: [
+ "Jede Session braucht genau eine Bewertung.",
+ "Abgerechnet und Nicht abrechenbar können durch erneuten Klick zurückgenommen werden.",
+ "Offene Bewertungen blockieren den Monatsabschluss."
+ ],
+ details: [
+ "Abgerechnet bedeutet: Die Session wurde für die Abrechnung beziehungsweise im CRM berücksichtigt.",
+ "Nicht abrechenbar bedeutet: Die Session gehört zum Arbeitsnachweis, wird aber nicht abgerechnet.",
+ "Ein erneuter Klick auf den aktiven Bewertungsbutton entfernt die Bewertung und macht die Session wieder offen.",
+ "Nicht abrechenbare Sessions zählen als bewertet. Sie blockieren den Monatsabschluss nicht.",
+ "Wenn ein Monat abgeschlossen ist, sind Bewertungen gesperrt. Öffne den Monat zuerst wieder, wenn du etwas korrigieren musst.",
+ "Die offenen Bewertungen findest du gebündelt im Monatsabschluss."
+ ]
+ },
+ {
+ id: "sessions-bearbeiten",
+ title: "Sessions Bearbeiten und Löschen",
+ description: "Sessions können korrigiert, gelöscht und bei wiederkehrenden Einträgen als Ausnahme behandelt werden.",
+ quickItems: [
+ "Bearbeiten läuft über das Stift-Icon.",
+ "Löschen läuft über das Papierkorb-Icon.",
+ "Wiederkehrende gelöschte Sessions werden nicht neu erzeugt."
+ ],
+ details: [
+ "Beim Bearbeiten sind Datum, Von-Uhrzeit, Bis-Uhrzeit, Organisation und Tätigkeit änderbar.",
+ "Die Art ist bei manuellen Sessions änderbar. Bei wiederkehrenden Sessions ist sie gesperrt und kommt aus der Regel.",
+ "Die Dauer wird aus Von und Bis neu berechnet und wieder auf Minuten gerundet.",
+ "Beim Löschen wird geprüft, ob dadurch ein Ticket für dich oder komplett leer wird. Leere Tickets werden entfernt.",
+ "Wenn die letzte Session eines Tickets gelöscht wird, springt die Ansicht zurück zur Auswertung.",
+ "Wiederkehrend erzeugte Sessions werden beim Löschen als Ausnahme gespeichert. Dadurch erscheinen sie beim nächsten Öffnen des Monats nicht wieder automatisch.",
+ "Wenn eine wiederkehrende Leistung nur an einem anderen Tag erledigt wurde, wird die erzeugte Session bearbeitet beziehungsweise verschoben."
+ ]
+ },
+ {
+ id: "monatsabschluss",
+ title: "Monatsabschluss",
+ description: "Der Monatsabschluss ist die Kontrollseite für offene Bewertungen und Teamspace-Punkte vor dem Abschluss.",
+ quickItems: [
+ "Bewertungen sind Pflicht für den Abschluss.",
+ "Tage ohne Teamspace-Wert können zur Kenntnis genommen werden.",
+ "Der Monat kann wieder geöffnet werden."
+ ],
+ details: [
+ "Ein Monat kann abgeschlossen werden, sobald alle Sessions dieses Monats bewertet sind.",
+ "Tage ohne Teamspace-Wert blockieren den Abschluss nicht automatisch. Sie sind eine Prüfliste für CRM-Abgleich und Nacharbeit.",
+ "Wenn eine Session bewusst nicht in Teamspace eingetragen wird, kann der fehlende Tageswert zur Kenntnis genommen werden.",
+ "Zur Kenntnis genommene Einträge können über die Checkbox Zur Kenntnis anzeigen wieder eingeblendet werden.",
+ "Die Kenntnisnahme kann pro Eintrag über Zurücknehmen rückgängig gemacht werden.",
+ "Die Einstellung, ob zur Kenntnis genommene Einträge angezeigt werden, bleibt im Browser gespeichert.",
+ "Offene Bewertungen werden nach Ticket gruppiert. Ein Klick auf Ticket öffnen führt zur Bewertung im Ticket.",
+ "Es gibt keinen Tagesabschluss. Tagesansichten dienen nur der Kontrolle."
+ ]
+ },
+ {
+ id: "fixe-abrechnungen",
+ title: "Fixe Abrechnungen",
+ description: "Fixe Abrechnungen erzeugen wiederkehrende Sessions für planbare regelmäßige Leistungen.",
+ quickItems: [
+ "Jeder Benutzer verwaltet eigene fixe Abrechnungen.",
+ "Ticket ist optional; ohne Ticket entsteht Fix#ID.",
+ "Feiertage in Bayern werden übersprungen."
+ ],
+ details: [
+ "Fixe Abrechnungen sind für regelmäßige Leistungen gedacht, zum Beispiel jeden Donnerstag vier Stunden oder mehrere Wochentage mit unterschiedlichen Dauern.",
+ "Das Ticketfeld darf leer bleiben. Dann gruppiert TicketTracker die erzeugten Sessions automatisch unter Fix#ID.",
+ "Die Organisation, Art und Tätigkeit kommen aus der Regel und werden auf erzeugte Sessions angewendet.",
+ "Beim Muster Wochentage werden einzelne Slots mit Wochentag, Startzeit und Dauer gepflegt.",
+ "Beim Muster Alle X Wochen zählt das Gültig-von-Datum als Startpunkt. Das Intervall läuft wochenweise.",
+ "Gültig bis ist optional. Wird es später gesetzt oder geändert, werden erzeugte Sessions außerhalb der Gültigkeit entfernt.",
+ "Bayerische Feiertage werden bei der automatischen Anlage ausgelassen.",
+ "Einzelne erzeugte Sessions können wegen Urlaub, Krankheit oder Feiertagsverschiebung gelöscht oder verschoben werden."
+ ]
+ },
+ {
+ id: "statistiken",
+ title: "Statistiken",
+ description: "Statistiken vergleichen getrackte Arbeit, bewertete Sessions und Teamspace-Werte.",
+ quickItems: [
+ "Sessions und Teamspace haben getrennte Farben.",
+ "Positive oder gleiche Differenz ist grün.",
+ "Negative Differenz ist rot."
+ ],
+ details: [
+ "Die Statistikseite betrachtet immer einen Monat.",
+ "Getrackt zeigt die Summe aller Session-Zeiten und die Anzahl der Sessions und Tickets.",
+ "Teamspace zeigt, wie viel Zeit für dieselben Ticket-Tage im CRM eingetragen wurde.",
+ "Eine positive Differenz bedeutet: In Teamspace steht mehr Zeit als in den Sessions getrackt wurde.",
+ "Eine negative Differenz bedeutet: In Teamspace steht weniger Zeit als getrackt wurde.",
+ "Bewertet umfasst sowohl Abgerechnet als auch Nicht abrechenbar. Offen sind nur Sessions ohne Bewertung.",
+ "Der Monatsverlauf zeigt getrackte Session-Zeit als Balken und Teamspace als Linie.",
+ "Organisationen, Typen und Ticket-Hotspots helfen dabei, Auffälligkeiten im Monat schnell zu finden."
+ ]
+ },
+ {
+ id: "profil",
+ title: "Profil",
+ description: "Im Profil pflegt jeder Benutzer die eigenen Zugangsdaten.",
+ quickItems: [
+ "Benutzername und voller Name sind änderbar.",
+ "Passwortänderung benötigt das aktuelle Passwort.",
+ "Der volle Name wird in der Oberfläche angezeigt."
+ ],
+ details: [
+ "Der Benutzername wird beim Login verwendet und muss eindeutig sein.",
+ "Der volle Name erscheint in der App, zum Beispiel im Kopfbereich oder im Adminbereich.",
+ "Wenn du dein Passwort ändern willst, musst du das aktuelle Passwort sowie das neue Passwort zweimal eingeben.",
+ "Bleiben die Passwortfelder leer, werden nur Benutzername und voller Name gespeichert.",
+ "Admins können Benutzer ebenfalls verwalten, aber jeder Benutzer kann die eigenen Daten jederzeit selbst pflegen."
+ ]
+ },
+ {
+ id: "admin",
+ title: "Adminbereich",
+ description: "Der Adminbereich verwaltet Benutzer, Session-Zuordnung, manuelle Admin-Nachträge und Zammad-Sync.",
+ quickItems: [
+ "Admins legen Benutzer an und bearbeiten Rollen.",
+ "Sessions können anderen Benutzern zugewiesen werden.",
+ "Zammad-Organisationen werden über Data-Sync aktualisiert."
+ ],
+ details: [
+ "Neue Benutzer bekommen Benutzername, vollen Namen, Passwort, Rolle und Aktivstatus.",
+ "Admins können bestehende Benutzer bearbeiten, Passwörter setzen und Benutzer deaktivieren.",
+ "Der eigene Admin-Zugang kann nicht versehentlich deaktiviert oder zur normalen User-Rolle herabgestuft werden.",
+ "In der Session-Zuordnung sehen Admins die letzten Sessions inklusive Besitzer und können einzelne Sessions umverteilen.",
+ "Beim Umverteilen werden die betroffenen Monatsabschlüsse für alten und neuen Besitzer wieder geöffnet, damit Bewertungen und Auswertungen konsistent bleiben.",
+ "Admins können Sessions für andere Benutzer nachtragen, wenn Zeiten vergessen wurden.",
+ "Der Data-Sync speichert Zammad-Zugangsdaten und synchronisiert Organisationen in die lokale Datenbank."
+ ]
+ }
+];
+
+export function getHelpSection(anchor: string) {
+ return helpSections.find((section) => section.id === anchor) ?? helpSections[0];
+}
diff --git a/frontend/src/views/FaqPage.tsx b/frontend/src/views/FaqPage.tsx
index 610c2af..daa59e2 100644
--- a/frontend/src/views/FaqPage.tsx
+++ b/frontend/src/views/FaqPage.tsx
@@ -3,163 +3,7 @@ import { ArrowUp, BookOpenCheck } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-
-type FaqSection = {
- id: string;
- title: string;
- description: string;
- items: string[];
-};
-
-const faqSections: FaqSection[] = [
- {
- id: "grundprinzip",
- title: "Grundprinzip",
- description: "TicketTracker ersetzt weder Ticketsystem noch CRM. Die App misst Zeiten, bewertet Sessions und bereitet den Monatsabschluss vor.",
- items: [
- "Session-Zeit ist die gemessene oder manuell erfasste Arbeitszeit einer Tätigkeit.",
- "Teamspace-Zeit ist der Tageswert, der für ein Ticket wirklich im CRM eingetragen wurde.",
- "Abgeschlossen wird nur ein Monat. Tickets werden nicht geschlossen, sondern nur über ihre Sessions bewertet."
- ]
- },
- {
- id: "timer",
- title: "Timer",
- description: "Timer sind für laufende Arbeit an Tickets gedacht.",
- items: [
- "Ticketnummer im Format Ticket#XXXXXX eingeben und Timer starten.",
- "Es können mehrere Timer vorbereitet sein, aber immer nur einer läuft aktiv.",
- "Wird ein Timer aktiviert, werden alle anderen automatisch pausiert.",
- "Beim Klick auf Beenden stoppt die Zeit sofort. Danach werden Tätigkeit und gegebenenfalls Organisation und Art gespeichert."
- ]
- },
- {
- id: "session-nachtragen",
- title: "Session Nachtragen",
- description: "Vergessene Zeiten können nachträglich als Session angelegt werden.",
- items: [
- "Benutzer tragen eigene Sessions nach. Admins können Sessions auch anderen Benutzern zuweisen.",
- "Pflichtangaben sind Ticket, Organisation, Art, Datum, Von, Bis und Tätigkeit.",
- "Das Tätigkeitsfeld ist mehrzeilig. Zeilenumbrüche bleiben in den Auswertungen erhalten."
- ]
- },
- {
- id: "ticketdaten",
- title: "Ticketdaten",
- description: "Ticketdaten können in der Ticketdetailansicht korrigiert werden.",
- items: [
- "Bearbeitbar sind Ticketnummer, Organisation und Art.",
- "Änderungen an Organisation und Art werden auf vorhandene manuelle Sessions des Tickets übernommen.",
- "Bei wiederkehrenden Sessions kommt die Art aus der Regel der fixen Abrechnung."
- ]
- },
- {
- id: "organisationen",
- title: "Organisationen",
- description: "Organisationen werden aus Zammad synchronisiert und danach aus der lokalen Liste gewählt.",
- items: [
- "Freitext ist nicht mehr erlaubt, damit Auswertungen je Organisation sauber möglich sind.",
- "Alte Freitexte müssen manuell korrigiert werden.",
- "Der Zammad-Sync speichert nur interne ID, Zammad-ID, Name und Zeitstempel."
- ]
- },
- {
- id: "auswertung",
- title: "Auswertung",
- description: "Die Auswertung zeigt Monats- oder Tageswerte und listet Tickets im gewählten Zeitraum.",
- items: [
- "Mit den Pfeilen neben Monat oder Datum wechselst du den Zeitraum. Die Daten aktualisieren sich automatisch.",
- "Tickets können gefiltert, gruppiert und sortiert werden. Diese Einstellungen bleiben gespeichert.",
- "Der Graph zeigt den Gesamtaufwand des gewählten Zeitraums."
- ]
- },
- {
- id: "ticketdetail",
- title: "Ticketdetailansicht",
- description: "Hier werden alle Sessions eines Tickets im gewählten Monat oder Tag bearbeitet.",
- items: [
- "Sessions sind nach Tagen gruppiert.",
- "Pro Tag wird die getrackte Zeit angezeigt.",
- "Das Teamspace-Feld speichert die Stunden, die für diesen Ticket-Tag wirklich im CRM eingetragen wurden.",
- "Der Teamspace-Wert ist in Monats- und Tagesansicht derselbe."
- ]
- },
- {
- id: "sessions-bewerten",
- title: "Sessions Bewerten",
- description: "Jede Session braucht eine Bewertung für die Abrechnung.",
- items: [
- "Möglich sind Abgerechnet und Nicht abrechenbar.",
- "Ein erneuter Klick auf die gewählte Bewertung nimmt sie zurück.",
- "Bewertungen können bei abgeschlossenem Monat erst geändert werden, nachdem der Monat wieder geöffnet wurde."
- ]
- },
- {
- id: "sessions-bearbeiten",
- title: "Sessions Bearbeiten und Löschen",
- description: "Sessions können korrigiert oder gelöscht werden.",
- items: [
- "Bearbeitbar sind Datum, Von, Bis, Organisation, Tätigkeit und Art.",
- "Bei wiederkehrenden Sessions ist die Art gesperrt und wird über die Regel geändert.",
- "Wird die letzte Session eines Tickets gelöscht, wird das leere Ticket entfernt.",
- "Gelöschte wiederkehrende Sessions werden als Ausnahme gespeichert und nicht automatisch neu erzeugt."
- ]
- },
- {
- id: "monatsabschluss",
- title: "Monatsabschluss",
- description: "Der Monatsabschluss bündelt offene Bewertungen und Teamspace-Prüfpunkte.",
- items: [
- "Ein Monat kann abgeschlossen werden, sobald alle Sessions des Monats bewertet sind.",
- "Tage ohne Teamspace-Wert können zur Kenntnis genommen werden, wenn sie bewusst nicht ins CRM gehören.",
- "Zur Kenntnis genommene Teamspace-Punkte können eingeblendet und zurückgenommen werden.",
- "Einen Tagesabschluss gibt es nicht."
- ]
- },
- {
- id: "fixe-abrechnungen",
- title: "Fixe Abrechnungen",
- description: "Fixe Abrechnungen erzeugen wiederkehrende Sessions für den eigenen Account.",
- items: [
- "Ticket ist optional. Ohne Ticket wird automatisch Fix#ID verwendet.",
- "Muster können Wochentage oder alle X Wochen sein.",
- "Gültig bis ist optional. Wird es später gesetzt, werden nicht mehr gültige erzeugte Sessions entfernt.",
- "Bayerische Feiertage werden übersprungen."
- ]
- },
- {
- id: "statistiken",
- title: "Statistiken",
- description: "Die Statistikseite vergleicht getrackte Sessions mit Teamspace-Zeiten.",
- items: [
- "Sessions und Teamspace haben eigene Farben.",
- "Eine positive oder ausgeglichene Differenz ist grün.",
- "Eine negative Differenz ist rot und bedeutet: in Teamspace ist weniger eingetragen als getrackt.",
- "Organisationen, Typen und Ticket-Hotspots helfen bei der Monatskontrolle."
- ]
- },
- {
- id: "profil",
- title: "Profil",
- description: "Jeder Benutzer kann eigene Accountdaten pflegen.",
- items: [
- "Benutzername und voller Name können geändert werden.",
- "Passwortänderungen benötigen das aktuelle Passwort.",
- "Der volle Name wird in der App angezeigt."
- ]
- },
- {
- id: "admin",
- title: "Adminbereich",
- description: "Admins verwalten Benutzer, Sessions und Zammad-Organisationen.",
- items: [
- "Admins legen Benutzer an und können deren Daten bearbeiten.",
- "Sessions können zwischen Benutzern umverteilt werden.",
- "Admins können Sessions für andere Benutzer nachtragen.",
- "Der Zammad-Zugang wird gespeichert und der Organisationssync aktualisiert die lokale Organisationsliste."
- ]
- }
-];
+import { helpSections } from "../help-content";
export function FaqPage() {
return (
@@ -167,9 +11,9 @@ export function FaqPage() {
FAQ und Anleitung
-
Kurzanleitung für Timer, Auswertung, Teamspace, fixe Abrechnungen und Adminfunktionen.
+
Ausführliche Anleitung für Timer, Auswertung, Teamspace, fixe Abrechnungen, Monatsabschluss und Adminfunktionen.
@@ -178,10 +22,10 @@ export function FaqPage() {
Schnellnavigation
- Die Fragezeichen in der App springen direkt in diese Abschnitte.
+ Die Fragezeichen in der App öffnen eine Kurzfassung. Von dort gelangst du direkt zum passenden ausführlichen Abschnitt.
- {faqSections.map((section) => (
+ {helpSections.map((section) => (
@@ -190,22 +34,36 @@ export function FaqPage() {