From 02742b3163dc70af4a799a27dbb99a9e6fa8094a Mon Sep 17 00:00:00 2001 From: Luca <102960244+Luca-Timo@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:20:49 +0200 Subject: [PATCH] feat(hours): open the hours invoice in the editor to add items After 'Create draft invoice' mints the single scheduled invoice from a per-event customer's unbilled hours, navigate to the bill editor so the admin can add other line items before it ships (invoice is already status='scheduled' + editable). Updated the per-event hint copy. --- frontend/src/components/admin/HoursSection.tsx | 10 +++++++--- frontend/src/i18n/locales/de.json | 2 +- frontend/src/i18n/locales/en.json | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/admin/HoursSection.tsx b/frontend/src/components/admin/HoursSection.tsx index da02c43f..6f4abd41 100644 --- a/frontend/src/components/admin/HoursSection.tsx +++ b/frontend/src/components/admin/HoursSection.tsx @@ -15,7 +15,7 @@ import React, { useMemo, useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { toast } from 'react-toastify'; import { Clock, AlertTriangle } from 'lucide-react'; import { Button, Card, LocalizedDateInput, TimeField } from '../common'; @@ -46,6 +46,7 @@ export const HoursSection: React.FC = ({ }) => { const { t } = useTranslation(); const qc = useQueryClient(); + const navigate = useNavigate(); const { format: fmtDate, formatTime: fmtTime } = useLocalizedDate(); const [entryDate, setEntryDate] = useState(() => new Date().toISOString().slice(0, 10)); const [startTime, setStartTime] = useState('09:00'); @@ -154,10 +155,13 @@ export const HoursSection: React.FC = ({ const billMutation = useMutation({ mutationFn: () => customerAdminService.billUnbilledHourEntries(customerId), - onSuccess: () => { + onSuccess: ({ invoiceId }) => { qc.invalidateQueries({ queryKey: ['admin-customer-hour-entries', customerId] }); qc.invalidateQueries({ queryKey: ['admin-customer', customerId] }); toast.success(t('customers.hours.toast.billed', 'Hours billed')); + // Open the new scheduled invoice so the admin can add other line + // items in addition to the hours before it ships. + if (invoiceId) navigate(`/admin/clients/bills/${invoiceId}/edit`); }, onError: (err: any) => { toast.error(err?.response?.data?.error || 'Failed to bill hours'); @@ -202,7 +206,7 @@ export const HoursSection: React.FC = ({ ? t('customers.hours.monthlyHint', 'Entries auto-append to the current monthly draft. Edit / delete remains possible until the scheduler arms the draft for send.') : t('customers.hours.perEventHint', - 'Logged entries stay unbilled until you click "Create draft invoice" — a standalone draft invoice is generated with one line per entry, ready for you to review before sending.')} + 'Logged entries stay unbilled until you click "Create draft invoice" — one scheduled invoice is generated with a line per entry and opened in the editor, so you can add other items before it ships.')}

{/* Rate summary — hidden in compact mode (history-only on the diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 45df10eb..c1e1314e 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -3107,7 +3107,7 @@ "hours": { "section": "Stunden", "monthlyHint": "Einträge werden automatisch dem aktuellen monatlichen Entwurf angehängt. Bearbeiten/Löschen möglich, bis der Scheduler den Versand auslöst.", - "perEventHint": "Erfasste Einträge bleiben unverrechnet, bis Sie auf „Rechnungsentwurf erstellen“ klicken — dann wird ein eigenständiger Rechnungsentwurf mit einer Zeile pro Eintrag erzeugt, den Sie vor dem Versand prüfen können.", + "perEventHint": "Erfasste Einträge bleiben unverrechnet, bis Sie auf „Rechnungsentwurf erstellen“ klicken — dann wird eine geplante Rechnung mit einer Zeile pro Eintrag erzeugt und im Editor geöffnet, sodass Sie vor dem Versand weitere Positionen hinzufügen können.", "form": { "title": "Neuen Eintrag erfassen", "date": "Datum", diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index ca1ec218..a92a972a 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -3107,7 +3107,7 @@ "hours": { "section": "Hours", "monthlyHint": "Entries auto-append to the current monthly draft. Edit / delete remains possible until the scheduler arms the draft for send.", - "perEventHint": "Logged entries stay unbilled until you click \"Create draft invoice\" — a standalone draft invoice is generated with one line per entry, ready for you to review before sending.", + "perEventHint": "Logged entries stay unbilled until you click \"Create draft invoice\" — one scheduled invoice is generated with a line per entry and opened in the editor, so you can add other items before it ships.", "form": { "title": "Log new entry", "date": "Date",