@voyantjs/finance-ui 0.81.14 → 0.81.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/booking-invoice-dialog.d.ts +44 -0
- package/dist/components/booking-invoice-dialog.d.ts.map +1 -0
- package/dist/components/booking-invoice-dialog.js +349 -0
- package/dist/components/record-booking-payment-dialog.d.ts.map +1 -1
- package/dist/components/record-booking-payment-dialog.js +59 -20
- package/dist/i18n/en.d.ts +35 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +36 -1
- package/dist/i18n/messages.d.ts +47 -0
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/i18n/provider.d.ts +70 -0
- package/dist/i18n/provider.d.ts.map +1 -1
- package/dist/i18n/ro.d.ts +35 -0
- package/dist/i18n/ro.d.ts.map +1 -1
- package/dist/i18n/ro.js +36 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +13 -13
- package/dist/components/booking-invoice-sheet.d.ts +0 -25
- package/dist/components/booking-invoice-sheet.d.ts.map +0 -1
- package/dist/components/booking-invoice-sheet.js +0 -116
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useInvoiceMutation } from "@voyantjs/finance-react";
|
|
4
|
-
import { Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, Textarea, } from "@voyantjs/ui/components";
|
|
5
|
-
import { CurrencyCombobox } from "@voyantjs/ui/components/currency-combobox";
|
|
6
|
-
import { CurrencyInput } from "@voyantjs/ui/components/currency-input";
|
|
7
|
-
import { DatePicker } from "@voyantjs/ui/components/date-picker";
|
|
8
|
-
import { zodResolver } from "@voyantjs/ui/lib/zod-resolver";
|
|
9
|
-
import { Loader2 } from "lucide-react";
|
|
10
|
-
import { useEffect } from "react";
|
|
11
|
-
import { useForm } from "react-hook-form";
|
|
12
|
-
import { z } from "zod/v4";
|
|
13
|
-
import { useFinanceUiMessagesOrDefault } from "../i18n/index.js";
|
|
14
|
-
import { invoiceStatuses } from "../i18n/messages.js";
|
|
15
|
-
function createBookingInvoiceFormSchema(messages) {
|
|
16
|
-
return z.object({
|
|
17
|
-
invoiceNumber: z.string().min(1, messages.invoiceDialog.validation.invoiceNumberRequired),
|
|
18
|
-
status: z.enum(invoiceStatuses),
|
|
19
|
-
currency: z.string().min(3).max(3, messages.invoiceDialog.validation.currencyIsoCode),
|
|
20
|
-
subtotalCents: z.coerce.number().int().min(0).default(0),
|
|
21
|
-
taxCents: z.coerce.number().int().min(0).default(0),
|
|
22
|
-
totalCents: z.coerce.number().int().min(0).default(0),
|
|
23
|
-
issueDate: z.string().min(1, messages.invoiceDialog.validation.issueDateRequired),
|
|
24
|
-
dueDate: z.string().min(1, messages.invoiceDialog.validation.dueDateRequired),
|
|
25
|
-
notes: z.string().optional().nullable(),
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
function generateInvoiceNumber() {
|
|
29
|
-
const now = new Date();
|
|
30
|
-
const y = now.getFullYear();
|
|
31
|
-
const seq = String(Math.floor(Math.random() * 9000) + 1000);
|
|
32
|
-
return `INV-${y}-${seq}`;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Slide-in invoice creator scoped to a single booking. The booking link
|
|
36
|
-
* is set from props and not editable here — the assumption is that the
|
|
37
|
-
* sheet is launched from a booking detail page where the booking is
|
|
38
|
-
* already in context. Use `<InvoiceDialog />` for the global "pick any
|
|
39
|
-
* booking" flow.
|
|
40
|
-
*/
|
|
41
|
-
export function BookingInvoiceSheet({ open, onOpenChange, bookingId, defaultPersonId, defaultOrganizationId, defaultCurrency = "EUR", // i18n-literal-ok domain default currency
|
|
42
|
-
defaultAmountCents = null, onSuccess, }) {
|
|
43
|
-
const { create } = useInvoiceMutation();
|
|
44
|
-
const messages = useFinanceUiMessagesOrDefault();
|
|
45
|
-
const dialog = messages.invoiceDialog;
|
|
46
|
-
const schema = createBookingInvoiceFormSchema(messages);
|
|
47
|
-
const form = useForm({
|
|
48
|
-
resolver: zodResolver(schema),
|
|
49
|
-
defaultValues: {
|
|
50
|
-
invoiceNumber: "",
|
|
51
|
-
status: "draft",
|
|
52
|
-
currency: defaultCurrency,
|
|
53
|
-
subtotalCents: defaultAmountCents ?? 0,
|
|
54
|
-
taxCents: 0,
|
|
55
|
-
totalCents: defaultAmountCents ?? 0,
|
|
56
|
-
issueDate: "",
|
|
57
|
-
dueDate: "",
|
|
58
|
-
notes: "",
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
if (!open)
|
|
63
|
-
return;
|
|
64
|
-
const today = new Date().toISOString().split("T")[0];
|
|
65
|
-
form.reset({
|
|
66
|
-
invoiceNumber: generateInvoiceNumber(),
|
|
67
|
-
status: "draft",
|
|
68
|
-
currency: defaultCurrency,
|
|
69
|
-
subtotalCents: defaultAmountCents ?? 0,
|
|
70
|
-
taxCents: 0,
|
|
71
|
-
totalCents: defaultAmountCents ?? 0,
|
|
72
|
-
issueDate: today,
|
|
73
|
-
dueDate: "",
|
|
74
|
-
notes: "",
|
|
75
|
-
});
|
|
76
|
-
}, [open, defaultCurrency, defaultAmountCents, form]);
|
|
77
|
-
const onSubmit = async (values) => {
|
|
78
|
-
const saved = await create.mutateAsync({
|
|
79
|
-
invoiceNumber: values.invoiceNumber,
|
|
80
|
-
bookingId,
|
|
81
|
-
personId: defaultPersonId ?? null,
|
|
82
|
-
organizationId: defaultOrganizationId ?? null,
|
|
83
|
-
status: values.status,
|
|
84
|
-
currency: values.currency,
|
|
85
|
-
subtotalCents: values.subtotalCents,
|
|
86
|
-
taxCents: values.taxCents,
|
|
87
|
-
totalCents: values.totalCents,
|
|
88
|
-
paidCents: 0,
|
|
89
|
-
balanceDueCents: values.totalCents,
|
|
90
|
-
issueDate: values.issueDate,
|
|
91
|
-
dueDate: values.dueDate,
|
|
92
|
-
notes: values.notes || null,
|
|
93
|
-
});
|
|
94
|
-
onOpenChange(false);
|
|
95
|
-
onSuccess?.(saved);
|
|
96
|
-
};
|
|
97
|
-
return (_jsx(Sheet, { open: open, onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", className: "flex w-full flex-col sm:max-w-xl", children: [_jsxs(SheetHeader, { children: [_jsx(SheetTitle, { children: dialog.titles.create }), _jsx(SheetDescription, { children: messages.invoicesPage.description })] }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto px-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.invoiceNumber }), _jsx(Input, { ...form.register("invoiceNumber"), placeholder: dialog.placeholders.invoiceNumber }), form.formState.errors.invoiceNumber ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.invoiceNumber.message })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.status }), _jsxs(Select, { value: form.watch("status"), onValueChange: (value) => form.setValue("status", (value ?? "draft")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: invoiceStatuses.map((status) => (_jsx(SelectItem, { value: status, children: messages.common.invoiceStatusLabels[status] }, status))) })] })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.currency }), _jsx(CurrencyCombobox, { value: form.watch("currency") || null, onChange: (next) => form.setValue("currency", next ?? defaultCurrency, {
|
|
98
|
-
shouldValidate: true,
|
|
99
|
-
shouldDirty: true,
|
|
100
|
-
}) })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.subtotalCents }), _jsx(CurrencyInput, { value: form.watch("subtotalCents"), onChange: (next) => form.setValue("subtotalCents", next ?? 0, {
|
|
101
|
-
shouldDirty: true,
|
|
102
|
-
shouldValidate: true,
|
|
103
|
-
}), currency: form.watch("currency") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.taxCents }), _jsx(CurrencyInput, { value: form.watch("taxCents"), onChange: (next) => form.setValue("taxCents", next ?? 0, {
|
|
104
|
-
shouldDirty: true,
|
|
105
|
-
shouldValidate: true,
|
|
106
|
-
}), currency: form.watch("currency") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.totalCents }), _jsx(CurrencyInput, { value: form.watch("totalCents"), onChange: (next) => form.setValue("totalCents", next ?? 0, {
|
|
107
|
-
shouldDirty: true,
|
|
108
|
-
shouldValidate: true,
|
|
109
|
-
}), currency: form.watch("currency") })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.issueDate }), _jsx(DatePicker, { value: form.watch("issueDate") || null, onChange: (next) => form.setValue("issueDate", next ?? "", {
|
|
110
|
-
shouldDirty: true,
|
|
111
|
-
shouldValidate: true,
|
|
112
|
-
}), placeholder: dialog.placeholders.issueDate, className: "w-full" }), form.formState.errors.issueDate ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.issueDate.message })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.dueDate }), _jsx(DatePicker, { value: form.watch("dueDate") || null, onChange: (next) => form.setValue("dueDate", next ?? "", {
|
|
113
|
-
shouldDirty: true,
|
|
114
|
-
shouldValidate: true,
|
|
115
|
-
}), placeholder: dialog.placeholders.dueDate, className: "w-full" }), form.formState.errors.dueDate ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.dueDate.message })) : null] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: dialog.placeholders.notes })] })] }), _jsxs(SheetFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "button", disabled: create.isPending, onClick: () => void form.handleSubmit(onSubmit)(), children: [create.isPending ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null, dialog.actions.create] })] })] }) }));
|
|
116
|
-
}
|