This commit is contained in:
michael committed 2026-09-30 16:59:14 +02:00
1 parent 35cb578a96
commit d5952d82bb
11 files changed
+1081 -119

No files matched your search

+26 -4
View File
@@ -129,6 +129,10 @@ function notifyZammadArticleResult(result: CreateSessionResult) {
}
}
function notifyTodosChanged() {
window.dispatchEvent(new Event("tickettracker:todos-changed"));
}
function zammadSyncStorageKey(userId: string) {
return `tickettracker.zammad-sync.${userId}`;
}
@@ -259,6 +263,18 @@ function teamspaceBillingKey(day: string, projectTeamspaceEntryId: string | null
return `${projectTeamspaceEntryId ?? "ticket"}::${day}`;
}
function dayBillingProjectEntryIdForView(
projectTeamspaceEntryId: string | null | undefined,
hasMultipleProjectTeamspaceEntries: boolean,
defaultProjectEntryId: string | null
) {
if (!hasMultipleProjectTeamspaceEntries) {
return null;
}
return projectTeamspaceEntryId ?? defaultProjectEntryId;
}
function projectEditForm(project: ProjectSummary): ProjectEditFormState {
const entries = projectTeamspaceEntries(project).map((entry, index) => ({
clientId: entry.id || projectEntryId(),
@@ -824,10 +840,12 @@ export function TicketDetailPage({ periodType, period, ticketId, onNavigate, onS
}, [periodType, period, ticketId]);
useEffect(() => {
const defaultEntryId = data?.project ? projectTeamspaceEntries(data.project).find((entry) => entry.is_default)?.id ?? null : null;
const loadedProjectEntries = data?.project ? projectTeamspaceEntries(data.project) : [];
const hasMultipleEntries = loadedProjectEntries.length > 1;
const defaultEntryId = loadedProjectEntries.find((entry) => entry.is_default)?.id ?? null;
const nextInputs = Object.fromEntries(
(data?.dayBillings ?? []).map((billing) => [
teamspaceBillingKey(billing.day, billing.project_teamspace_entry_id ?? defaultEntryId),
teamspaceBillingKey(billing.day, dayBillingProjectEntryIdForView(billing.project_teamspace_entry_id, hasMultipleEntries, defaultEntryId)),
formatHoursInput(billing.billed_minutes)
])
);
@@ -920,11 +938,11 @@ export function TicketDetailPage({ periodType, period, ticketId, onNavigate, onS
() =>
new Map(
(data?.dayBillings ?? []).map((billing) => [
teamspaceBillingKey(billing.day, billing.project_teamspace_entry_id ?? defaultProjectEntryId),
teamspaceBillingKey(billing.day, dayBillingProjectEntryIdForView(billing.project_teamspace_entry_id, requiresProjectTeamspaceEntry, defaultProjectEntryId)),
billing.billed_minutes
])
),
[data?.dayBillings, defaultProjectEntryId]
[data?.dayBillings, defaultProjectEntryId, requiresProjectTeamspaceEntry]
);
const savedDayBillingInput = (key: string) => formatHoursInput(dayBillingMap.get(key));
const isDayBillingDirty = (key: string) => (dayBillingInputs[key] ?? "") !== savedDayBillingInput(key);
@@ -1186,6 +1204,9 @@ export function TicketDetailPage({ periodType, period, ticketId, onNavigate, onS
: `${result.created} angelegt, ${result.skipped} ohne Transfer.`;
const notify = result.created === 0 && result.errors.length > 0 ? toast.error : toast.success;
notify("Mail-Sessions importiert", { description });
if (result.created > 0) {
notifyTodosChanged();
}
await load();
} catch (error) {
toast.error("Mail-Sessions konnten nicht importiert werden", {
@@ -1514,6 +1535,7 @@ export function TicketDetailPage({ periodType, period, ticketId, onNavigate, onS
description: "Der Eintrag wurde diesem Ticket zugeordnet. Betroffene Abschlüsse wurden wieder geöffnet."
});
notifyZammadArticleResult(result);
notifyTodosChanged();
setTicketSession({
...emptyTicketSessionForm(),
organizationId: ticket.organization_id ?? "",