فهرست منبع

improved user dialog (#172)

Bernt Christian Egeland 4 ماه پیش
والد
کامیت
d31420bdf4

+ 3 - 0
messages/de/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "Das Rechnungsdatum oder Fälligkeitsdatum ist überschritten. Möchten Sie die Daten vor dem Fortfahren aktualisieren?",
     "datesExpiredDescription": "Das Rechnungsdatum oder Fälligkeitsdatum ist überschritten. Möchten Sie die Daten vor dem Fortfahren aktualisieren?",
     "datesExpiredUpdate": "Daten aktualisieren und fortfahren",
     "datesExpiredUpdate": "Daten aktualisieren und fortfahren",
     "datesExpiredProceed": "Ohne Änderungen fortfahren",
     "datesExpiredProceed": "Ohne Änderungen fortfahren",
+    "datesExpiredUseToday": "Auf heutiges Datum aktualisieren",
+    "datesExpiredCustomize": "Daten manuell auswählen",
+    "datesExpiredBack": "Zurück",
     "datesExpiredSetToday": "Auf heute setzen",
     "datesExpiredSetToday": "Auf heute setzen",
     "customFieldsInvalid": "Bitte füllen Sie alle erforderlichen benutzerdefinierten Felder aus",
     "customFieldsInvalid": "Bitte füllen Sie alle erforderlichen benutzerdefinierten Felder aus",
     "customFieldsSaveFailed": "Benutzerdefinierte Felder konnten nicht gespeichert werden"
     "customFieldsSaveFailed": "Benutzerdefinierte Felder konnten nicht gespeichert werden"

+ 3 - 0
messages/en/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "The invoice date or due date has passed. Would you like to update them before proceeding?",
     "datesExpiredDescription": "The invoice date or due date has passed. Would you like to update them before proceeding?",
     "datesExpiredUpdate": "Update dates and proceed",
     "datesExpiredUpdate": "Update dates and proceed",
     "datesExpiredProceed": "Proceed without changes",
     "datesExpiredProceed": "Proceed without changes",
+    "datesExpiredUseToday": "Update to today's date",
+    "datesExpiredCustomize": "Choose dates manually",
+    "datesExpiredBack": "Back",
     "datesExpiredSetToday": "Set to today",
     "datesExpiredSetToday": "Set to today",
     "customFieldsInvalid": "Please fill in all required custom fields",
     "customFieldsInvalid": "Please fill in all required custom fields",
     "customFieldsSaveFailed": "Failed to save custom fields"
     "customFieldsSaveFailed": "Failed to save custom fields"

+ 3 - 0
messages/es/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "La fecha de la factura o la fecha de vencimiento ha pasado. ¿Desea actualizarlas antes de continuar?",
     "datesExpiredDescription": "La fecha de la factura o la fecha de vencimiento ha pasado. ¿Desea actualizarlas antes de continuar?",
     "datesExpiredUpdate": "Actualizar fechas y continuar",
     "datesExpiredUpdate": "Actualizar fechas y continuar",
     "datesExpiredProceed": "Continuar sin cambios",
     "datesExpiredProceed": "Continuar sin cambios",
+    "datesExpiredUseToday": "Actualizar a la fecha de hoy",
+    "datesExpiredCustomize": "Elegir fechas manualmente",
+    "datesExpiredBack": "Atrás",
     "datesExpiredSetToday": "Establecer a hoy",
     "datesExpiredSetToday": "Establecer a hoy",
     "customFieldsInvalid": "Por favor complete todos los campos personalizados obligatorios",
     "customFieldsInvalid": "Por favor complete todos los campos personalizados obligatorios",
     "customFieldsSaveFailed": "Error al guardar los campos personalizados"
     "customFieldsSaveFailed": "Error al guardar los campos personalizados"

+ 3 - 0
messages/fr/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "La date de facturation ou la date d'échéance est dépassée. Souhaitez-vous les mettre à jour avant de continuer ?",
     "datesExpiredDescription": "La date de facturation ou la date d'échéance est dépassée. Souhaitez-vous les mettre à jour avant de continuer ?",
     "datesExpiredUpdate": "Mettre à jour les dates et continuer",
     "datesExpiredUpdate": "Mettre à jour les dates et continuer",
     "datesExpiredProceed": "Continuer sans modifications",
     "datesExpiredProceed": "Continuer sans modifications",
+    "datesExpiredUseToday": "Mettre à jour à la date du jour",
+    "datesExpiredCustomize": "Choisir les dates manuellement",
+    "datesExpiredBack": "Retour",
     "datesExpiredSetToday": "Définir à aujourd'hui",
     "datesExpiredSetToday": "Définir à aujourd'hui",
     "customFieldsInvalid": "Veuillez remplir tous les champs personnalisés obligatoires",
     "customFieldsInvalid": "Veuillez remplir tous les champs personnalisés obligatoires",
     "customFieldsSaveFailed": "Échec de l'enregistrement des champs personnalisés"
     "customFieldsSaveFailed": "Échec de l'enregistrement des champs personnalisés"

+ 3 - 0
messages/it/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "La data della fattura o la data di scadenza è passata. Vuoi aggiornare le date prima di procedere?",
     "datesExpiredDescription": "La data della fattura o la data di scadenza è passata. Vuoi aggiornare le date prima di procedere?",
     "datesExpiredUpdate": "Aggiorna le date e procedi",
     "datesExpiredUpdate": "Aggiorna le date e procedi",
     "datesExpiredProceed": "Procedi senza modifiche",
     "datesExpiredProceed": "Procedi senza modifiche",
+    "datesExpiredUseToday": "Aggiorna alla data di oggi",
+    "datesExpiredCustomize": "Scegli le date manualmente",
+    "datesExpiredBack": "Indietro",
     "datesExpiredSetToday": "Imposta a oggi",
     "datesExpiredSetToday": "Imposta a oggi",
     "customFieldsInvalid": "Compila tutti i campi personalizzati obbligatori",
     "customFieldsInvalid": "Compila tutti i campi personalizzati obbligatori",
     "customFieldsSaveFailed": "Impossibile salvare i campi personalizzati"
     "customFieldsSaveFailed": "Impossibile salvare i campi personalizzati"

+ 3 - 0
messages/lt/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "Sąskaitos data arba mokėjimo terminas pasibaigė. Ar norite jas atnaujinti prieš tęsiant?",
     "datesExpiredDescription": "Sąskaitos data arba mokėjimo terminas pasibaigė. Ar norite jas atnaujinti prieš tęsiant?",
     "datesExpiredUpdate": "Atnaujinti datas ir tęsti",
     "datesExpiredUpdate": "Atnaujinti datas ir tęsti",
     "datesExpiredProceed": "Tęsti be pakeitimų",
     "datesExpiredProceed": "Tęsti be pakeitimų",
+    "datesExpiredUseToday": "Atnaujinti į šiandienos datą",
+    "datesExpiredCustomize": "Pasirinkti datas rankiniu būdu",
+    "datesExpiredBack": "Atgal",
     "datesExpiredSetToday": "Nustatyti šiandienos datą",
     "datesExpiredSetToday": "Nustatyti šiandienos datą",
     "customFieldsInvalid": "Užpildykite visus privalomus pasirinktinius laukus",
     "customFieldsInvalid": "Užpildykite visus privalomus pasirinktinius laukus",
     "customFieldsSaveFailed": "Nepavyko išsaugoti pasirinktinių laukų"
     "customFieldsSaveFailed": "Nepavyko išsaugoti pasirinktinių laukų"

+ 3 - 0
messages/nb/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "Fakturadatoen eller forfallsdatoen har passert. Vil du oppdatere dem før du fortsetter?",
     "datesExpiredDescription": "Fakturadatoen eller forfallsdatoen har passert. Vil du oppdatere dem før du fortsetter?",
     "datesExpiredUpdate": "Oppdater datoer og fortsett",
     "datesExpiredUpdate": "Oppdater datoer og fortsett",
     "datesExpiredProceed": "Fortsett uten endringer",
     "datesExpiredProceed": "Fortsett uten endringer",
+    "datesExpiredUseToday": "Oppdater til dagens dato",
+    "datesExpiredCustomize": "Velg datoer manuelt",
+    "datesExpiredBack": "Tilbake",
     "datesExpiredSetToday": "Sett til i dag",
     "datesExpiredSetToday": "Sett til i dag",
     "customFieldsInvalid": "Vennligst fyll ut alle obligatoriske egendefinerte felt",
     "customFieldsInvalid": "Vennligst fyll ut alle obligatoriske egendefinerte felt",
     "customFieldsSaveFailed": "Kunne ikke lagre egendefinerte felt"
     "customFieldsSaveFailed": "Kunne ikke lagre egendefinerte felt"

+ 3 - 0
messages/nl/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "De factuurdatum of vervaldatum is verstreken. Wilt u de datums bijwerken voordat u verdergaat?",
     "datesExpiredDescription": "De factuurdatum of vervaldatum is verstreken. Wilt u de datums bijwerken voordat u verdergaat?",
     "datesExpiredUpdate": "Datums bijwerken en doorgaan",
     "datesExpiredUpdate": "Datums bijwerken en doorgaan",
     "datesExpiredProceed": "Doorgaan zonder wijzigingen",
     "datesExpiredProceed": "Doorgaan zonder wijzigingen",
+    "datesExpiredUseToday": "Bijwerken naar vandaag",
+    "datesExpiredCustomize": "Datums handmatig kiezen",
+    "datesExpiredBack": "Terug",
     "datesExpiredSetToday": "Instellen op vandaag",
     "datesExpiredSetToday": "Instellen op vandaag",
     "customFieldsInvalid": "Vul alle verplichte aangepaste velden in",
     "customFieldsInvalid": "Vul alle verplichte aangepaste velden in",
     "customFieldsSaveFailed": "Kan aangepaste velden niet opslaan"
     "customFieldsSaveFailed": "Kan aangepaste velden niet opslaan"

+ 3 - 0
messages/pl/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "Data faktury lub termin płatności już minął. Czy chcesz zaktualizować daty przed kontynuowaniem?",
     "datesExpiredDescription": "Data faktury lub termin płatności już minął. Czy chcesz zaktualizować daty przed kontynuowaniem?",
     "datesExpiredUpdate": "Zaktualizuj daty i kontynuuj",
     "datesExpiredUpdate": "Zaktualizuj daty i kontynuuj",
     "datesExpiredProceed": "Kontynuuj bez zmian",
     "datesExpiredProceed": "Kontynuuj bez zmian",
+    "datesExpiredUseToday": "Zaktualizuj do dzisiejszej daty",
+    "datesExpiredCustomize": "Wybierz daty ręcznie",
+    "datesExpiredBack": "Wstecz",
     "datesExpiredSetToday": "Ustaw na dziś",
     "datesExpiredSetToday": "Ustaw na dziś",
     "customFieldsInvalid": "Proszę wypełnić wszystkie wymagane pola niestandardowe",
     "customFieldsInvalid": "Proszę wypełnić wszystkie wymagane pola niestandardowe",
     "customFieldsSaveFailed": "Nie udało się zapisać pól niestandardowych"
     "customFieldsSaveFailed": "Nie udało się zapisać pól niestandardowych"

+ 3 - 0
messages/pt-BR/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "A data da fatura ou a data de vencimento já passou. Deseja atualizar as datas antes de prosseguir?",
     "datesExpiredDescription": "A data da fatura ou a data de vencimento já passou. Deseja atualizar as datas antes de prosseguir?",
     "datesExpiredUpdate": "Atualizar datas e prosseguir",
     "datesExpiredUpdate": "Atualizar datas e prosseguir",
     "datesExpiredProceed": "Prosseguir sem alterações",
     "datesExpiredProceed": "Prosseguir sem alterações",
+    "datesExpiredUseToday": "Atualizar para a data de hoje",
+    "datesExpiredCustomize": "Escolher datas manualmente",
+    "datesExpiredBack": "Voltar",
     "datesExpiredSetToday": "Definir para hoje",
     "datesExpiredSetToday": "Definir para hoje",
     "customFieldsInvalid": "Preencha todos os campos personalizados obrigatórios",
     "customFieldsInvalid": "Preencha todos os campos personalizados obrigatórios",
     "customFieldsSaveFailed": "Falha ao salvar campos personalizados"
     "customFieldsSaveFailed": "Falha ao salvar campos personalizados"

+ 3 - 0
messages/ru/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "Дата счёта или срок оплаты истёк. Хотите обновить даты перед продолжением?",
     "datesExpiredDescription": "Дата счёта или срок оплаты истёк. Хотите обновить даты перед продолжением?",
     "datesExpiredUpdate": "Обновить даты и продолжить",
     "datesExpiredUpdate": "Обновить даты и продолжить",
     "datesExpiredProceed": "Продолжить без изменений",
     "datesExpiredProceed": "Продолжить без изменений",
+    "datesExpiredUseToday": "Обновить до сегодняшней даты",
+    "datesExpiredCustomize": "Выбрать даты вручную",
+    "datesExpiredBack": "Назад",
     "datesExpiredSetToday": "Установить на сегодня",
     "datesExpiredSetToday": "Установить на сегодня",
     "customFieldsInvalid": "Заполните все обязательные пользовательские поля",
     "customFieldsInvalid": "Заполните все обязательные пользовательские поля",
     "customFieldsSaveFailed": "Не удалось сохранить пользовательские поля"
     "customFieldsSaveFailed": "Не удалось сохранить пользовательские поля"

+ 3 - 0
messages/tr/service.json

@@ -11,6 +11,9 @@
     "datesExpiredDescription": "Fatura tarihi veya vade tarihi geçmiş. Devam etmeden önce tarihleri güncellemek ister misiniz?",
     "datesExpiredDescription": "Fatura tarihi veya vade tarihi geçmiş. Devam etmeden önce tarihleri güncellemek ister misiniz?",
     "datesExpiredUpdate": "Tarihleri güncelle ve devam et",
     "datesExpiredUpdate": "Tarihleri güncelle ve devam et",
     "datesExpiredProceed": "Değişiklik yapmadan devam et",
     "datesExpiredProceed": "Değişiklik yapmadan devam et",
+    "datesExpiredUseToday": "Bugünün tarihine güncelle",
+    "datesExpiredCustomize": "Tarihleri manuel olarak seç",
+    "datesExpiredBack": "Geri",
     "datesExpiredSetToday": "Bugüne ayarla",
     "datesExpiredSetToday": "Bugüne ayarla",
     "customFieldsInvalid": "Lütfen tüm zorunlu özel alanları doldurun",
     "customFieldsInvalid": "Lütfen tüm zorunlu özel alanları doldurun",
     "customFieldsSaveFailed": "Özel alanlar kaydedilemedi"
     "customFieldsSaveFailed": "Özel alanlar kaydedilemedi"

+ 13 - 1
src/features/vehicles/Components/service-edit/InvoiceDetailsSection.tsx

@@ -1,6 +1,6 @@
 'use client'
 'use client'
 
 
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
 import { useTranslations } from 'next-intl'
 import { useTranslations } from 'next-intl'
 import { Input } from '@/components/ui/input'
 import { Input } from '@/components/ui/input'
 import { Label } from '@/components/ui/label'
 import { Label } from '@/components/ui/label'
@@ -49,6 +49,18 @@ export function InvoiceDetailsSection({
     initialData.invoiceDueDate ? new Date(initialData.invoiceDueDate + 'T00:00:00') : undefined
     initialData.invoiceDueDate ? new Date(initialData.invoiceDueDate + 'T00:00:00') : undefined
   )
   )
 
 
+  useEffect(() => {
+    setInvoiceDate(
+      initialData.invoiceDate ? new Date(initialData.invoiceDate + 'T00:00:00') : undefined
+    )
+  }, [initialData.invoiceDate])
+
+  useEffect(() => {
+    setInvoiceDueDate(
+      initialData.invoiceDueDate ? new Date(initialData.invoiceDueDate + 'T00:00:00') : undefined
+    )
+  }, [initialData.invoiceDueDate])
+
   const formatDate = (date: Date | undefined) => {
   const formatDate = (date: Date | undefined) => {
     if (!date) return ''
     if (!date) return ''
     return date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })
     return date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })

+ 134 - 96
src/features/vehicles/Components/service-page/ServicePageClient.tsx

@@ -111,6 +111,7 @@ export function ServicePageClient({
   const [pendingInvoiceDate, setPendingInvoiceDate] = useState<Date>(today)
   const [pendingInvoiceDate, setPendingInvoiceDate] = useState<Date>(today)
   const [pendingDueDate, setPendingDueDate] = useState<Date>(suggestedDueDate)
   const [pendingDueDate, setPendingDueDate] = useState<Date>(suggestedDueDate)
   const [updatingDates, setUpdatingDates] = useState(false)
   const [updatingDates, setUpdatingDates] = useState(false)
+  const [customizingDates, setCustomizingDates] = useState(false)
 
 
   const formatDate = (date: Date) =>
   const formatDate = (date: Date) =>
     date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })
     date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })
@@ -515,6 +516,7 @@ export function ServicePageClient({
           if (!open) {
           if (!open) {
             dateCheckResolveRef.current?.(false)
             dateCheckResolveRef.current?.(false)
             dateCheckResolveRef.current = null
             dateCheckResolveRef.current = null
+            setCustomizingDates(false)
           }
           }
           setShowDateCheck(open)
           setShowDateCheck(open)
         }}
         }}
@@ -528,105 +530,141 @@ export function ServicePageClient({
             <DialogDescription>{t('page.datesExpiredDescription')}</DialogDescription>
             <DialogDescription>{t('page.datesExpiredDescription')}</DialogDescription>
           </DialogHeader>
           </DialogHeader>
 
 
-          <div className="space-y-3">
-            <Button
-              variant="secondary"
-              size="sm"
-              className="w-full"
-              onClick={() => {
-                const now = new Date(new Date().toISOString().split('T')[0])
-                setPendingInvoiceDate(now)
-                setPendingDueDate(
-                  defaultDueDays > 0
-                    ? new Date(now.getTime() + defaultDueDays * 86400000)
-                    : new Date(now.getTime() + 14 * 86400000)
-                )
-              }}
-            >
-              {t('page.datesExpiredSetToday')}
-            </Button>
-
-            <div className="space-y-1">
-              <Label className="text-xs">{t('basicInfo.invoiceDate')}</Label>
-              <Popover>
-                <PopoverTrigger asChild>
-                  <Button
-                    variant="outline"
-                    className="w-full justify-start text-left font-normal h-9 text-sm"
-                  >
-                    <CalendarIcon className="mr-2 h-3.5 w-3.5" />
-                    <span suppressHydrationWarning>{formatDate(pendingInvoiceDate)}</span>
-                  </Button>
-                </PopoverTrigger>
-                <PopoverContent className="w-auto p-0" align="start">
-                  <Calendar
-                    mode="single"
-                    selected={pendingInvoiceDate}
-                    onSelect={(d) => d && setPendingInvoiceDate(d)}
-                  />
-                </PopoverContent>
-              </Popover>
-            </div>
-
-            <div className="space-y-1">
-              <Label className="text-xs">{t('basicInfo.invoiceDueDate')}</Label>
-              <Popover>
-                <PopoverTrigger asChild>
-                  <Button
-                    variant="outline"
-                    className="w-full justify-start text-left font-normal h-9 text-sm"
-                  >
-                    <CalendarIcon className="mr-2 h-3.5 w-3.5" />
-                    <span suppressHydrationWarning>{formatDate(pendingDueDate)}</span>
-                  </Button>
-                </PopoverTrigger>
-                <PopoverContent className="w-auto p-0" align="start">
-                  <Calendar
-                    mode="single"
-                    selected={pendingDueDate}
-                    onSelect={(d) => d && setPendingDueDate(d)}
-                  />
-                </PopoverContent>
-              </Popover>
-            </div>
-          </div>
-
-          <div className="flex flex-col gap-2 pt-2">
-            <Button
-              disabled={updatingDates}
-              onClick={async () => {
-                if (updatingDates) return
-                setUpdatingDates(true)
-                try {
-                  await updateServiceRecord({
-                    id: record.id,
-                    invoiceDate: toISODate(pendingInvoiceDate),
-                    invoiceDueDate: toISODate(pendingDueDate),
-                  })
+          {!customizingDates ? (
+            <div className="flex flex-col gap-2 pt-2">
+              <Button
+                disabled={updatingDates}
+                onClick={async () => {
+                  if (updatingDates) return
+                  const now = new Date(new Date().toISOString().split('T')[0])
+                  const due =
+                    defaultDueDays > 0
+                      ? new Date(now.getTime() + defaultDueDays * 86400000)
+                      : new Date(now.getTime() + 14 * 86400000)
+                  setPendingInvoiceDate(now)
+                  setPendingDueDate(due)
+                  setUpdatingDates(true)
+                  try {
+                    await updateServiceRecord({
+                      id: record.id,
+                      invoiceDate: toISODate(now),
+                      invoiceDueDate: toISODate(due),
+                    })
+                    setShowDateCheck(false)
+                    dateCheckResolveRef.current?.(true)
+                    dateCheckResolveRef.current = null
+                    router.refresh()
+                  } finally {
+                    setUpdatingDates(false)
+                  }
+                }}
+              >
+                {updatingDates && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
+                {t('page.datesExpiredUseToday')}
+              </Button>
+              <Button
+                variant="outline"
+                disabled={updatingDates}
+                onClick={() => {
                   setShowDateCheck(false)
                   setShowDateCheck(false)
                   dateCheckResolveRef.current?.(true)
                   dateCheckResolveRef.current?.(true)
                   dateCheckResolveRef.current = null
                   dateCheckResolveRef.current = null
-                  router.refresh()
-                } finally {
-                  setUpdatingDates(false)
-                }
-              }}
-            >
-              {updatingDates && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
-              {t('page.datesExpiredUpdate')}
-            </Button>
-            <Button
-              variant="outline"
-              disabled={updatingDates}
-              onClick={() => {
-                setShowDateCheck(false)
-                dateCheckResolveRef.current?.(true)
-                dateCheckResolveRef.current = null
-              }}
-            >
-              {t('page.datesExpiredProceed')}
-            </Button>
-          </div>
+                }}
+              >
+                {t('page.datesExpiredProceed')}
+              </Button>
+              <Button
+                variant="ghost"
+                size="sm"
+                disabled={updatingDates}
+                onClick={() => setCustomizingDates(true)}
+              >
+                {t('page.datesExpiredCustomize')}
+              </Button>
+            </div>
+          ) : (
+            <>
+              <div className="space-y-3">
+                <div className="space-y-1">
+                  <Label className="text-xs">{t('basicInfo.invoiceDate')}</Label>
+                  <Popover>
+                    <PopoverTrigger asChild>
+                      <Button
+                        variant="outline"
+                        className="w-full justify-start text-left font-normal h-9 text-sm"
+                      >
+                        <CalendarIcon className="mr-2 h-3.5 w-3.5" />
+                        <span suppressHydrationWarning>{formatDate(pendingInvoiceDate)}</span>
+                      </Button>
+                    </PopoverTrigger>
+                    <PopoverContent className="w-auto p-0" align="start">
+                      <Calendar
+                        mode="single"
+                        selected={pendingInvoiceDate}
+                        onSelect={(d) => d && setPendingInvoiceDate(d)}
+                      />
+                    </PopoverContent>
+                  </Popover>
+                </div>
+
+                <div className="space-y-1">
+                  <Label className="text-xs">{t('basicInfo.invoiceDueDate')}</Label>
+                  <Popover>
+                    <PopoverTrigger asChild>
+                      <Button
+                        variant="outline"
+                        className="w-full justify-start text-left font-normal h-9 text-sm"
+                      >
+                        <CalendarIcon className="mr-2 h-3.5 w-3.5" />
+                        <span suppressHydrationWarning>{formatDate(pendingDueDate)}</span>
+                      </Button>
+                    </PopoverTrigger>
+                    <PopoverContent className="w-auto p-0" align="start">
+                      <Calendar
+                        mode="single"
+                        selected={pendingDueDate}
+                        onSelect={(d) => d && setPendingDueDate(d)}
+                      />
+                    </PopoverContent>
+                  </Popover>
+                </div>
+              </div>
+
+              <div className="flex flex-col gap-2 pt-2">
+                <Button
+                  disabled={updatingDates}
+                  onClick={async () => {
+                    if (updatingDates) return
+                    setUpdatingDates(true)
+                    try {
+                      await updateServiceRecord({
+                        id: record.id,
+                        invoiceDate: toISODate(pendingInvoiceDate),
+                        invoiceDueDate: toISODate(pendingDueDate),
+                      })
+                      setShowDateCheck(false)
+                      setCustomizingDates(false)
+                      dateCheckResolveRef.current?.(true)
+                      dateCheckResolveRef.current = null
+                      router.refresh()
+                    } finally {
+                      setUpdatingDates(false)
+                    }
+                  }}
+                >
+                  {updatingDates && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
+                  {t('page.datesExpiredUpdate')}
+                </Button>
+                <Button
+                  variant="outline"
+                  disabled={updatingDates}
+                  onClick={() => setCustomizingDates(false)}
+                >
+                  {t('page.datesExpiredBack')}
+                </Button>
+              </div>
+            </>
+          )}
         </DialogContent>
         </DialogContent>
       </Dialog>
       </Dialog>
     </div>
     </div>