Invoice and supplier-invoice creation now open as pop-up dialogs on their list pages instead of navigating to standalone form pages — the same UX as NewJournalEntryDialog (capped-height scroll, explicit-close-only so a half-typed invoice survives stray Escape/backdrop clicks). - InvoiceEditor gains a `bare` variant (page chrome stripped, inline actions replacing the fixed mobile bar, live document-type title kept) hosted by the new NewInvoiceDialog (sm:max-w-5xl). Draft editing pages unchanged. - The 2,057-line supplier form moves out of the route page into components/supplier-invoices/NewSupplierInvoiceForm.tsx with bare/inboxItemId/onCreated/onCancel props, hosted by NewSupplierInvoiceDialog (sm:max-w-4xl). - Modals are URL-driven (?new=1): header buttons, empty states, command palette, and the reports CTA all open the same dialog; browser back closes it. /invoices/new and /supplier-invoices/new survive as redirects (bookmarks, agent intents, /expenses/new alias, inbox deep links). - The invoice-inbox "Skapa leverantörsfaktura" action opens the modal in place and refreshes the inbox on success instead of navigating away. No new i18n keys; dialog titles reuse existing strings. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import { useTranslations } from 'next-intl'
|
|
import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog'
|
|
import InvoiceEditor from '@/components/invoices/InvoiceEditor'
|
|
|
|
interface Props {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
}
|
|
|
|
/**
|
|
* "Ny faktura" as a modal — mirrors NewJournalEntryDialog. Wraps the bare
|
|
* InvoiceEditor; the editor's own review/confirm/send dialogs stack on top of
|
|
* this one, and every successful create navigates to the invoice detail page
|
|
* (unmounting the host list page and this dialog with it).
|
|
*
|
|
* The accessible title is visually hidden: the bare editor renders its own
|
|
* live heading, which tracks document type (faktura/proforma/följesedel) and
|
|
* shows the invoice-number preview — a static DialogTitle would duplicate or
|
|
* contradict it.
|
|
*/
|
|
export default function NewInvoiceDialog({ open, onOpenChange }: Props) {
|
|
const t = useTranslations('invoice_editor')
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent
|
|
className="sm:max-w-5xl max-h-[95dvh] sm:max-h-[90vh] overflow-y-auto"
|
|
// A half-typed invoice must survive an accidental backdrop click or a
|
|
// stray Escape (nested comboboxes and date pickers portal outside the
|
|
// dialog). Closing is explicit — the header X. Same convention as
|
|
// NewJournalEntryDialog.
|
|
onEscapeKeyDown={(e) => e.preventDefault()}
|
|
onPointerDownOutside={(e) => e.preventDefault()}
|
|
onInteractOutside={(e) => e.preventDefault()}
|
|
>
|
|
<DialogTitle className="sr-only">{t('title_invoice')}</DialogTitle>
|
|
<InvoiceEditor mode="create" bare />
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|