@voyantjs/pricing-ui 0.13.0

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.
Files changed (71) hide show
  1. package/README.md +13 -0
  2. package/dist/components/cancellation-policy-combobox.d.ts +9 -0
  3. package/dist/components/cancellation-policy-combobox.d.ts.map +1 -0
  4. package/dist/components/cancellation-policy-combobox.js +49 -0
  5. package/dist/components/cancellation-policy-rule-dialog.d.ts +11 -0
  6. package/dist/components/cancellation-policy-rule-dialog.d.ts.map +1 -0
  7. package/dist/components/cancellation-policy-rule-dialog.js +87 -0
  8. package/dist/components/dropoff-price-rule-dialog.d.ts +10 -0
  9. package/dist/components/dropoff-price-rule-dialog.d.ts.map +1 -0
  10. package/dist/components/dropoff-price-rule-dialog.js +96 -0
  11. package/dist/components/extra-price-rule-dialog.d.ts +10 -0
  12. package/dist/components/extra-price-rule-dialog.d.ts.map +1 -0
  13. package/dist/components/extra-price-rule-dialog.js +92 -0
  14. package/dist/components/option-price-rule-combobox.d.ts +9 -0
  15. package/dist/components/option-price-rule-combobox.d.ts.map +1 -0
  16. package/dist/components/option-price-rule-combobox.js +45 -0
  17. package/dist/components/option-price-rule-dialog.d.ts +9 -0
  18. package/dist/components/option-price-rule-dialog.d.ts.map +1 -0
  19. package/dist/components/option-price-rule-dialog.js +132 -0
  20. package/dist/components/option-start-time-rule-dialog.d.ts +10 -0
  21. package/dist/components/option-start-time-rule-dialog.d.ts.map +1 -0
  22. package/dist/components/option-start-time-rule-dialog.js +90 -0
  23. package/dist/components/option-unit-price-rule-dialog.d.ts +10 -0
  24. package/dist/components/option-unit-price-rule-dialog.d.ts.map +1 -0
  25. package/dist/components/option-unit-price-rule-dialog.js +103 -0
  26. package/dist/components/option-unit-tier-dialog.d.ts +10 -0
  27. package/dist/components/option-unit-tier-dialog.d.ts.map +1 -0
  28. package/dist/components/option-unit-tier-dialog.js +78 -0
  29. package/dist/components/pickup-price-rule-dialog.d.ts +10 -0
  30. package/dist/components/pickup-price-rule-dialog.d.ts.map +1 -0
  31. package/dist/components/pickup-price-rule-dialog.js +88 -0
  32. package/dist/components/price-catalog-combobox.d.ts +9 -0
  33. package/dist/components/price-catalog-combobox.d.ts.map +1 -0
  34. package/dist/components/price-catalog-combobox.js +45 -0
  35. package/dist/components/price-schedule-combobox.d.ts +10 -0
  36. package/dist/components/price-schedule-combobox.d.ts.map +1 -0
  37. package/dist/components/price-schedule-combobox.js +48 -0
  38. package/dist/components/price-schedule-dialog.d.ts +9 -0
  39. package/dist/components/price-schedule-dialog.d.ts.map +1 -0
  40. package/dist/components/price-schedule-dialog.js +87 -0
  41. package/dist/components/pricing-category-combobox.d.ts +9 -0
  42. package/dist/components/pricing-category-combobox.d.ts.map +1 -0
  43. package/dist/components/pricing-category-combobox.js +54 -0
  44. package/dist/components/pricing-category-dependency-dialog.d.ts +9 -0
  45. package/dist/components/pricing-category-dependency-dialog.d.ts.map +1 -0
  46. package/dist/components/pricing-category-dependency-dialog.js +11 -0
  47. package/dist/components/pricing-category-dependency-form.d.ts +15 -0
  48. package/dist/components/pricing-category-dependency-form.d.ts.map +1 -0
  49. package/dist/components/pricing-category-dependency-form.js +90 -0
  50. package/dist/components/pricing-category-dialog.d.ts +9 -0
  51. package/dist/components/pricing-category-dialog.d.ts.map +1 -0
  52. package/dist/components/pricing-category-dialog.js +13 -0
  53. package/dist/components/pricing-category-form.d.ts +15 -0
  54. package/dist/components/pricing-category-form.d.ts.map +1 -0
  55. package/dist/components/pricing-category-form.js +99 -0
  56. package/dist/components/pricing-category-list.d.ts +5 -0
  57. package/dist/components/pricing-category-list.d.ts.map +1 -0
  58. package/dist/components/pricing-category-list.js +44 -0
  59. package/dist/components/pricing-shared-labels.d.ts +22 -0
  60. package/dist/components/pricing-shared-labels.d.ts.map +1 -0
  61. package/dist/components/pricing-shared-labels.js +32 -0
  62. package/dist/components/product-combobox.d.ts +9 -0
  63. package/dist/components/product-combobox.d.ts.map +1 -0
  64. package/dist/components/product-combobox.js +41 -0
  65. package/dist/components/product-option-combobox.d.ts +10 -0
  66. package/dist/components/product-option-combobox.d.ts.map +1 -0
  67. package/dist/components/product-option-combobox.js +51 -0
  68. package/dist/index.d.ts +23 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +22 -0
  71. package/package.json +70 -0
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { usePriceCatalog, usePriceCatalogs } from "@voyantjs/pricing-react";
3
+ import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyantjs/voyant-ui/components/combobox";
4
+ import * as React from "react";
5
+ const PAGE_SIZE = 25;
6
+ export function PriceCatalogCombobox({ value, onChange, placeholder = "Search price catalogs…", disabled, }) {
7
+ const [search, setSearch] = React.useState("");
8
+ const listQuery = usePriceCatalogs({ search: search || undefined, limit: PAGE_SIZE });
9
+ const selectedQuery = usePriceCatalog(value, { enabled: !!value });
10
+ const items = React.useMemo(() => {
11
+ const map = new Map();
12
+ for (const item of listQuery.data?.data ?? [])
13
+ map.set(item.id, item);
14
+ if (selectedQuery.data)
15
+ map.set(selectedQuery.data.id, selectedQuery.data);
16
+ return Array.from(map.values());
17
+ }, [listQuery.data?.data, selectedQuery.data]);
18
+ const itemMap = React.useMemo(() => new Map(items.map((item) => [item.id, item])), [items]);
19
+ const selected = value ? itemMap.get(value) : undefined;
20
+ const selectedLabel = selected ? `${selected.name} · ${selected.code}` : "";
21
+ const [inputValue, setInputValue] = React.useState(selectedLabel);
22
+ React.useEffect(() => {
23
+ if (selectedLabel)
24
+ setInputValue(selectedLabel);
25
+ }, [selectedLabel]);
26
+ return (_jsxs(Combobox, { items: items.map((item) => item.id), value: value ?? null, inputValue: inputValue, autoHighlight: true, disabled: disabled, itemToStringValue: (id) => {
27
+ const item = itemMap.get(id);
28
+ return item ? `${item.name} · ${item.code}` : "";
29
+ }, onInputValueChange: (next) => {
30
+ setInputValue(next);
31
+ setSearch(next);
32
+ if (!next)
33
+ onChange(null);
34
+ }, onValueChange: (next) => {
35
+ const id = next ?? null;
36
+ onChange(id);
37
+ const item = id ? itemMap.get(id) : null;
38
+ setInputValue(item ? `${item.name} · ${item.code}` : "");
39
+ }, children: [_jsx(ComboboxInput, { placeholder: placeholder, showClear: !!value }), _jsxs(ComboboxContent, { children: [_jsx(ComboboxEmpty, { children: listQuery.isPending || selectedQuery.isPending ? "Loading…" : "No price catalogs found." }), _jsx(ComboboxList, { children: _jsx(ComboboxCollection, { children: (id) => {
40
+ const item = itemMap.get(id);
41
+ if (!item)
42
+ return null;
43
+ return (_jsx(ComboboxItem, { value: item.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: item.name }), _jsxs("span", { className: "truncate text-xs text-muted-foreground", children: [item.code, " \u00B7 ", item.currencyCode] })] }) }, item.id));
44
+ } }) })] })] }));
45
+ }
@@ -0,0 +1,10 @@
1
+ type Props = {
2
+ priceCatalogId?: string | null;
3
+ value: string | null | undefined;
4
+ onChange: (value: string | null) => void;
5
+ placeholder?: string;
6
+ disabled?: boolean;
7
+ };
8
+ export declare function PriceScheduleCombobox({ priceCatalogId, value, onChange, placeholder, disabled, }: Props): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=price-schedule-combobox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price-schedule-combobox.d.ts","sourceRoot":"","sources":["../../src/components/price-schedule-combobox.tsx"],"names":[],"mappings":"AAgBA,KAAK,KAAK,GAAG;IACX,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAID,wBAAgB,qBAAqB,CAAC,EACpC,cAAc,EACd,KAAK,EACL,QAAQ,EACR,WAAuC,EACvC,QAAQ,GACT,EAAE,KAAK,2CAyEP"}
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { usePriceSchedule, usePriceSchedules, } from "@voyantjs/pricing-react";
3
+ import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyantjs/voyant-ui/components/combobox";
4
+ import * as React from "react";
5
+ const PAGE_SIZE = 25;
6
+ export function PriceScheduleCombobox({ priceCatalogId, value, onChange, placeholder = "Search price schedules…", disabled, }) {
7
+ const [search, setSearch] = React.useState("");
8
+ const listQuery = usePriceSchedules({
9
+ priceCatalogId: priceCatalogId || undefined,
10
+ search: search || undefined,
11
+ limit: PAGE_SIZE,
12
+ enabled: !!priceCatalogId,
13
+ });
14
+ const selectedQuery = usePriceSchedule(value, { enabled: !!value });
15
+ const items = React.useMemo(() => {
16
+ const map = new Map();
17
+ for (const item of listQuery.data?.data ?? [])
18
+ map.set(item.id, item);
19
+ if (selectedQuery.data)
20
+ map.set(selectedQuery.data.id, selectedQuery.data);
21
+ return Array.from(map.values());
22
+ }, [listQuery.data?.data, selectedQuery.data]);
23
+ const itemMap = React.useMemo(() => new Map(items.map((item) => [item.id, item])), [items]);
24
+ const selected = value ? itemMap.get(value) : undefined;
25
+ const selectedLabel = selected ? selected.name : "";
26
+ const [inputValue, setInputValue] = React.useState(selectedLabel);
27
+ React.useEffect(() => {
28
+ if (selectedLabel)
29
+ setInputValue(selectedLabel);
30
+ }, [selectedLabel]);
31
+ return (_jsxs(Combobox, { items: items.map((item) => item.id), value: value ?? null, inputValue: inputValue, autoHighlight: true, disabled: disabled || !priceCatalogId, itemToStringValue: (id) => itemMap.get(id)?.name ?? "", onInputValueChange: (next) => {
32
+ setInputValue(next);
33
+ setSearch(next);
34
+ if (!next)
35
+ onChange(null);
36
+ }, onValueChange: (next) => {
37
+ const id = next ?? null;
38
+ onChange(id);
39
+ setInputValue(id ? (itemMap.get(id)?.name ?? "") : "");
40
+ }, children: [_jsx(ComboboxInput, { placeholder: placeholder, showClear: !!value }), _jsxs(ComboboxContent, { children: [_jsx(ComboboxEmpty, { children: listQuery.isPending || selectedQuery.isPending
41
+ ? "Loading…"
42
+ : "No price schedules found." }), _jsx(ComboboxList, { children: _jsx(ComboboxCollection, { children: (id) => {
43
+ const item = itemMap.get(id);
44
+ if (!item)
45
+ return null;
46
+ return (_jsx(ComboboxItem, { value: item.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: item.name }), item.code ? (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: item.code })) : null] }) }, item.id));
47
+ } }) })] })] }));
48
+ }
@@ -0,0 +1,9 @@
1
+ import { type PriceScheduleRecord } from "@voyantjs/pricing-react";
2
+ export interface PriceScheduleDialogProps {
3
+ open: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ schedule?: PriceScheduleRecord;
6
+ onSuccess?: (schedule: PriceScheduleRecord) => void;
7
+ }
8
+ export declare function PriceScheduleDialog({ open, onOpenChange, schedule, onSuccess, }: PriceScheduleDialogProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=price-schedule-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price-schedule-dialog.d.ts","sourceRoot":"","sources":["../../src/components/price-schedule-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,mBAAmB,EAA4B,MAAM,yBAAyB,CAAA;AAuC5F,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,QAAQ,CAAC,EAAE,mBAAmB,CAAA;IAC9B,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,KAAK,IAAI,CAAA;CACpD;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,SAAS,GACV,EAAE,wBAAwB,2CAqL1B"}
@@ -0,0 +1,87 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { usePriceScheduleMutation } from "@voyantjs/pricing-react";
4
+ import { Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Switch, Textarea, } from "@voyantjs/voyant-ui/components";
5
+ import { DatePicker } from "@voyantjs/voyant-ui/components/date-picker";
6
+ import { zodResolver } from "@voyantjs/voyant-ui/lib/zod-resolver";
7
+ import { Loader2 } from "lucide-react";
8
+ import { useEffect } from "react";
9
+ import { useForm } from "react-hook-form";
10
+ import { z } from "zod/v4";
11
+ import { PriceCatalogCombobox } from "./price-catalog-combobox";
12
+ const scheduleFormSchema = z.object({
13
+ priceCatalogId: z.string().min(1, "Catalog is required"),
14
+ name: z.string().min(1, "Name is required").max(255),
15
+ code: z.string().max(100).optional().nullable(),
16
+ recurrenceRule: z.string().min(1, "RRULE is required"),
17
+ timezone: z.string().max(100).optional().nullable(),
18
+ validFrom: z.string().optional().nullable(),
19
+ validTo: z.string().optional().nullable(),
20
+ priority: z.coerce.number().int(),
21
+ active: z.boolean(),
22
+ notes: z.string().optional().nullable(),
23
+ });
24
+ export function PriceScheduleDialog({ open, onOpenChange, schedule, onSuccess, }) {
25
+ const isEditing = !!schedule;
26
+ const { create, update } = usePriceScheduleMutation();
27
+ const form = useForm({
28
+ resolver: zodResolver(scheduleFormSchema),
29
+ defaultValues: {
30
+ priceCatalogId: "",
31
+ name: "",
32
+ code: "",
33
+ recurrenceRule: "FREQ=YEARLY;BYMONTH=6,7,8",
34
+ timezone: "",
35
+ validFrom: "",
36
+ validTo: "",
37
+ priority: 0,
38
+ active: true,
39
+ notes: "",
40
+ },
41
+ });
42
+ useEffect(() => {
43
+ if (open && schedule) {
44
+ form.reset({
45
+ priceCatalogId: schedule.priceCatalogId,
46
+ name: schedule.name,
47
+ code: schedule.code ?? "",
48
+ recurrenceRule: schedule.recurrenceRule,
49
+ timezone: schedule.timezone ?? "",
50
+ validFrom: schedule.validFrom ?? "",
51
+ validTo: schedule.validTo ?? "",
52
+ priority: schedule.priority,
53
+ active: schedule.active,
54
+ notes: schedule.notes ?? "",
55
+ });
56
+ }
57
+ else if (open) {
58
+ form.reset();
59
+ }
60
+ }, [open, schedule, form]);
61
+ const onSubmit = async (values) => {
62
+ const payload = {
63
+ priceCatalogId: values.priceCatalogId,
64
+ name: values.name,
65
+ code: values.code || null,
66
+ recurrenceRule: values.recurrenceRule,
67
+ timezone: values.timezone || null,
68
+ validFrom: values.validFrom || null,
69
+ validTo: values.validTo || null,
70
+ priority: values.priority,
71
+ active: values.active,
72
+ notes: values.notes || null,
73
+ };
74
+ const saved = isEditing
75
+ ? await update.mutateAsync({ id: schedule.id, input: payload })
76
+ : await create.mutateAsync(payload);
77
+ onSuccess?.(saved);
78
+ onOpenChange(false);
79
+ };
80
+ const validFrom = form.watch("validFrom");
81
+ const validTo = form.watch("validTo");
82
+ const isSubmitting = create.isPending || update.isPending;
83
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing ? "Edit Price Schedule" : "New Price Schedule" }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), children: [_jsxs(DialogBody, { className: "grid gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Catalog" }), _jsx(PriceCatalogCombobox, { value: form.watch("priceCatalogId"), onChange: (value) => form.setValue("priceCatalogId", value ?? "", {
84
+ shouldDirty: true,
85
+ shouldValidate: true,
86
+ }) }), form.formState.errors.priceCatalogId ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.priceCatalogId.message })) : null] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Name" }), _jsx(Input, { ...form.register("name"), placeholder: "High Season" }), form.formState.errors.name ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.name.message })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Code" }), _jsx(Input, { ...form.register("code"), placeholder: "high-season" })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Recurrence rule (RRULE)" }), _jsx(Textarea, { ...form.register("recurrenceRule"), placeholder: "FREQ=YEARLY;BYMONTH=6,7,8", rows: 2, className: "font-mono text-xs" }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["e.g. ", _jsx("code", { children: "FREQ=YEARLY;BYMONTH=6,7,8" }), " for June-August."] }), form.formState.errors.recurrenceRule ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.recurrenceRule.message })) : null] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Valid from" }), _jsx(DatePicker, { value: typeof validFrom === "string" && validFrom.length > 0 ? validFrom : null, onChange: (value) => form.setValue("validFrom", value ?? "", { shouldDirty: true }), placeholder: "Optional" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Valid to" }), _jsx(DatePicker, { value: typeof validTo === "string" && validTo.length > 0 ? validTo : null, onChange: (value) => form.setValue("validTo", value ?? "", { shouldDirty: true }), placeholder: "Optional" })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Timezone" }), _jsx(Input, { ...form.register("timezone"), placeholder: "Europe/Istanbul" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Priority" }), _jsx(Input, { ...form.register("priority"), type: "number" })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: form.watch("active"), onCheckedChange: (checked) => form.setValue("active", checked) }), _jsx(Label, { children: "Active" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Notes" }), _jsx(Textarea, { ...form.register("notes") })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }), _jsxs(Button, { type: "submit", disabled: isSubmitting, children: [isSubmitting ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null, isEditing ? "Save Changes" : "Create Schedule"] })] })] })] }) }));
87
+ }
@@ -0,0 +1,9 @@
1
+ type PricingCategoryComboboxProps = {
2
+ value: string | null | undefined;
3
+ onChange: (value: string | null) => void;
4
+ placeholder?: string;
5
+ disabled?: boolean;
6
+ };
7
+ export declare function PricingCategoryCombobox({ value, onChange, placeholder, disabled, }: PricingCategoryComboboxProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=pricing-category-combobox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-category-combobox.d.ts","sourceRoot":"","sources":["../../src/components/pricing-category-combobox.tsx"],"names":[],"mappings":"AAcA,KAAK,4BAA4B,GAAG;IAClC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAID,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,QAAQ,EACR,WAA0C,EAC1C,QAAQ,GACT,EAAE,4BAA4B,2CA4E9B"}
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { usePricingCategories } from "@voyantjs/pricing-react";
4
+ import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyantjs/voyant-ui/components/combobox";
5
+ import * as React from "react";
6
+ const PAGE_SIZE = 25;
7
+ export function PricingCategoryCombobox({ value, onChange, placeholder = "Search pricing categories…", disabled, }) {
8
+ const [search, setSearch] = React.useState("");
9
+ const { data, isPending } = usePricingCategories({
10
+ search: search || undefined,
11
+ limit: PAGE_SIZE,
12
+ active: undefined,
13
+ });
14
+ const items = data?.data ?? [];
15
+ const itemMap = React.useMemo(() => {
16
+ const map = new Map();
17
+ for (const item of items)
18
+ map.set(item.id, item);
19
+ return map;
20
+ }, [items]);
21
+ const selected = value ? itemMap.get(value) : undefined;
22
+ const selectedLabel = selected
23
+ ? `${selected.name}${selected.code ? ` (${selected.code})` : ""}`
24
+ : "";
25
+ const [inputValue, setInputValue] = React.useState(selectedLabel);
26
+ React.useEffect(() => {
27
+ if (selectedLabel)
28
+ setInputValue(selectedLabel);
29
+ }, [selectedLabel]);
30
+ return (_jsxs(Combobox, { items: items.map((item) => item.id), value: value ?? null, inputValue: inputValue, autoHighlight: true, disabled: disabled, itemToStringValue: (id) => {
31
+ const item = itemMap.get(id);
32
+ return item ? `${item.name}${item.code ? ` (${item.code})` : ""}` : "";
33
+ }, onInputValueChange: (next) => {
34
+ setInputValue(next);
35
+ setSearch(next);
36
+ if (!next)
37
+ onChange(null);
38
+ }, onValueChange: (next) => {
39
+ const id = next ?? null;
40
+ onChange(id);
41
+ if (!id) {
42
+ setInputValue("");
43
+ return;
44
+ }
45
+ const item = itemMap.get(id);
46
+ const label = item ? `${item.name}${item.code ? ` (${item.code})` : ""}` : "";
47
+ setInputValue(label);
48
+ }, children: [_jsx(ComboboxInput, { placeholder: placeholder, showClear: !!value }), _jsxs(ComboboxContent, { children: [_jsx(ComboboxEmpty, { children: isPending ? "Loading…" : "No pricing categories found." }), _jsx(ComboboxList, { children: _jsx(ComboboxCollection, { children: (id) => {
49
+ const item = itemMap.get(id);
50
+ if (!item)
51
+ return null;
52
+ return (_jsx(ComboboxItem, { value: item.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: item.name }), item.code ? (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: item.code })) : null] }) }, item.id));
53
+ } }) })] })] }));
54
+ }
@@ -0,0 +1,9 @@
1
+ import type { PricingCategoryDependencyRecord } from "@voyantjs/pricing-react";
2
+ export interface PricingCategoryDependencyDialogProps {
3
+ open: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ dependency?: PricingCategoryDependencyRecord;
6
+ onSuccess?: (dependency: PricingCategoryDependencyRecord) => void;
7
+ }
8
+ export declare function PricingCategoryDependencyDialog({ open, onOpenChange, dependency, onSuccess, }: PricingCategoryDependencyDialogProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=pricing-category-dependency-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-category-dependency-dialog.d.ts","sourceRoot":"","sources":["../../src/components/pricing-category-dependency-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAA;AAY9E,MAAM,WAAW,oCAAoC;IACnD,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,UAAU,CAAC,EAAE,+BAA+B,CAAA;IAC5C,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,+BAA+B,KAAK,IAAI,CAAA;CAClE;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,SAAS,GACV,EAAE,oCAAoC,2CAyBtC"}
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@voyantjs/voyant-ui/components/dialog";
4
+ import { PricingCategoryDependencyForm } from "./pricing-category-dependency-form";
5
+ export function PricingCategoryDependencyDialog({ open, onOpenChange, dependency, onSuccess, }) {
6
+ const isEdit = Boolean(dependency);
7
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { "data-slot": "pricing-category-dependency-dialog", className: "sm:max-w-[720px]", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: isEdit ? "Edit category dependency" : "Add category dependency" }), _jsx(DialogDescription, { children: "Rules between pricing categories such as requires, excludes, and quantity limits." })] }), _jsx(PricingCategoryDependencyForm, { mode: dependency ? { kind: "edit", dependency } : { kind: "create" }, onSuccess: (saved) => {
8
+ onSuccess?.(saved);
9
+ onOpenChange(false);
10
+ }, onCancel: () => onOpenChange(false) })] }) }));
11
+ }
@@ -0,0 +1,15 @@
1
+ import { type PricingCategoryDependencyRecord } from "@voyantjs/pricing-react";
2
+ type Mode = {
3
+ kind: "create";
4
+ } | {
5
+ kind: "edit";
6
+ dependency: PricingCategoryDependencyRecord;
7
+ };
8
+ export interface PricingCategoryDependencyFormProps {
9
+ mode: Mode;
10
+ onSuccess?: (dependency: PricingCategoryDependencyRecord) => void;
11
+ onCancel?: () => void;
12
+ }
13
+ export declare function PricingCategoryDependencyForm({ mode, onSuccess, onCancel, }: PricingCategoryDependencyFormProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
15
+ //# sourceMappingURL=pricing-category-dependency-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-category-dependency-form.d.ts","sourceRoot":"","sources":["../../src/components/pricing-category-dependency-form.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,+BAA+B,EAErC,MAAM,yBAAyB,CAAA;AAiBhC,KAAK,IAAI,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,+BAA+B,CAAA;CAAE,CAAA;AAE9F,MAAM,WAAW,kCAAkC;IACjD,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,+BAA+B,KAAK,IAAI,CAAA;IACjE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AA+DD,wBAAgB,6BAA6B,CAAC,EAC5C,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,EAAE,kCAAkC,2CAmJpC"}
@@ -0,0 +1,90 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { usePricingCategoryDependencyMutation, } from "@voyantjs/pricing-react";
4
+ import { Button } from "@voyantjs/voyant-ui/components/button";
5
+ import { Input } from "@voyantjs/voyant-ui/components/input";
6
+ import { Label } from "@voyantjs/voyant-ui/components/label";
7
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/voyant-ui/components/select";
8
+ import { Switch } from "@voyantjs/voyant-ui/components/switch";
9
+ import { Textarea } from "@voyantjs/voyant-ui/components/textarea";
10
+ import { Loader2 } from "lucide-react";
11
+ import * as React from "react";
12
+ import { PricingCategoryCombobox } from "./pricing-category-combobox";
13
+ const DEPENDENCY_TYPES = [
14
+ { value: "requires", label: "Requires" },
15
+ { value: "limits_per_master", label: "Limits per master" },
16
+ { value: "limits_sum", label: "Limits sum" },
17
+ { value: "excludes", label: "Excludes" },
18
+ ];
19
+ function initialState(mode) {
20
+ if (mode.kind === "edit") {
21
+ const dependency = mode.dependency;
22
+ return {
23
+ pricingCategoryId: dependency.pricingCategoryId,
24
+ masterPricingCategoryId: dependency.masterPricingCategoryId,
25
+ dependencyType: dependency.dependencyType,
26
+ maxPerMaster: dependency.maxPerMaster != null ? String(dependency.maxPerMaster) : "",
27
+ maxDependentSum: dependency.maxDependentSum != null ? String(dependency.maxDependentSum) : "",
28
+ active: dependency.active,
29
+ notes: dependency.notes ?? "",
30
+ };
31
+ }
32
+ return {
33
+ pricingCategoryId: "",
34
+ masterPricingCategoryId: "",
35
+ dependencyType: "requires",
36
+ maxPerMaster: "",
37
+ maxDependentSum: "",
38
+ active: true,
39
+ notes: "",
40
+ };
41
+ }
42
+ function toInteger(value) {
43
+ const trimmed = value.trim();
44
+ if (!trimmed)
45
+ return null;
46
+ const parsed = Number(trimmed);
47
+ return Number.isFinite(parsed) ? parsed : null;
48
+ }
49
+ function toPayload(state) {
50
+ return {
51
+ pricingCategoryId: state.pricingCategoryId,
52
+ masterPricingCategoryId: state.masterPricingCategoryId,
53
+ dependencyType: state.dependencyType,
54
+ maxPerMaster: toInteger(state.maxPerMaster),
55
+ maxDependentSum: toInteger(state.maxDependentSum),
56
+ active: state.active,
57
+ notes: state.notes.trim() || null,
58
+ };
59
+ }
60
+ export function PricingCategoryDependencyForm({ mode, onSuccess, onCancel, }) {
61
+ const [state, setState] = React.useState(() => initialState(mode));
62
+ const [error, setError] = React.useState(null);
63
+ const { create, update } = usePricingCategoryDependencyMutation();
64
+ React.useEffect(() => {
65
+ setState(initialState(mode));
66
+ setError(null);
67
+ }, [mode]);
68
+ const isSubmitting = create.isPending || update.isPending;
69
+ const handleSubmit = async (event) => {
70
+ event.preventDefault();
71
+ setError(null);
72
+ if (!state.masterPricingCategoryId || !state.pricingCategoryId) {
73
+ setError("Both master and dependent categories are required.");
74
+ return;
75
+ }
76
+ try {
77
+ const dependency = mode.kind === "create"
78
+ ? await create.mutateAsync(toPayload(state))
79
+ : await update.mutateAsync({ id: mode.dependency.id, input: toPayload(state) });
80
+ onSuccess?.(dependency);
81
+ }
82
+ catch (err) {
83
+ setError(err instanceof Error ? err.message : "Failed to save category dependency.");
84
+ }
85
+ };
86
+ return (_jsxs("form", { "data-slot": "pricing-category-dependency-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { children: "Master category" }), _jsx(PricingCategoryCombobox, { value: state.masterPricingCategoryId, onChange: (value) => setState((prev) => ({ ...prev, masterPricingCategoryId: value ?? "" })), placeholder: "Search category" })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { children: "Dependent category" }), _jsx(PricingCategoryCombobox, { value: state.pricingCategoryId, onChange: (value) => setState((prev) => ({ ...prev, pricingCategoryId: value ?? "" })), placeholder: "Search category" })] })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { children: "Dependency type" }), _jsxs(Select, { items: DEPENDENCY_TYPES, value: state.dependencyType, onValueChange: (value) => setState((prev) => ({
87
+ ...prev,
88
+ dependencyType: value,
89
+ })), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: DEPENDENCY_TYPES.map((type) => (_jsx(SelectItem, { value: type.value, children: type.label }, type.value))) })] })] }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-dependency-max-per-master", children: "Max per master" }), _jsx(Input, { id: "pricing-category-dependency-max-per-master", type: "number", min: "0", value: state.maxPerMaster, onChange: (event) => setState((prev) => ({ ...prev, maxPerMaster: event.target.value })) })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-dependency-max-dependent-sum", children: "Max dependent sum" }), _jsx(Input, { id: "pricing-category-dependency-max-dependent-sum", type: "number", min: "0", value: state.maxDependentSum, onChange: (event) => setState((prev) => ({ ...prev, maxDependentSum: event.target.value })) })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: state.active, onCheckedChange: (active) => setState((prev) => ({ ...prev, active })) }), _jsx(Label, { children: "Active" })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-dependency-notes", children: "Notes" }), _jsx(Textarea, { id: "pricing-category-dependency-notes", value: state.notes, onChange: (event) => setState((prev) => ({ ...prev, notes: event.target.value })) })] }), error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null, _jsxs("div", { className: "flex items-center justify-end gap-2", children: [onCancel ? (_jsx(Button, { type: "button", variant: "ghost", onClick: onCancel, children: "Cancel" })) : null, _jsxs(Button, { type: "submit", disabled: isSubmitting, children: [isSubmitting ? (_jsx(Loader2, { className: "mr-2 size-4 animate-spin", "aria-hidden": "true" })) : null, mode.kind === "edit" ? "Save changes" : "Add dependency"] })] })] }));
90
+ }
@@ -0,0 +1,9 @@
1
+ import type { PricingCategoryRecord } from "@voyantjs/pricing-react";
2
+ export interface PricingCategoryDialogProps {
3
+ open: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ category?: PricingCategoryRecord;
6
+ onSuccess?: (category: PricingCategoryRecord) => void;
7
+ }
8
+ export declare function PricingCategoryDialog({ open, onOpenChange, category, onSuccess, }: PricingCategoryDialogProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=pricing-category-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-category-dialog.d.ts","sourceRoot":"","sources":["../../src/components/pricing-category-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAYpE,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAA;CACtD;AAED,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,SAAS,GACV,EAAE,0BAA0B,2CAyB5B"}
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@voyantjs/voyant-ui/components/dialog";
4
+ import { PricingCategoryForm } from "./pricing-category-form";
5
+ export function PricingCategoryDialog({ open, onOpenChange, category, onSuccess, }) {
6
+ const isEdit = Boolean(category);
7
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { "data-slot": "pricing-category-dialog", className: "sm:max-w-[720px]", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: isEdit ? "Edit pricing category" : "New pricing category" }), _jsx(DialogDescription, { children: isEdit
8
+ ? "Update reusable pricing category rules and eligibility."
9
+ : "Create a reusable pricing category for products and options." })] }), _jsx(PricingCategoryForm, { mode: category ? { kind: "edit", category } : { kind: "create" }, onSuccess: (saved) => {
10
+ onSuccess?.(saved);
11
+ onOpenChange(false);
12
+ }, onCancel: () => onOpenChange(false) })] }) }));
13
+ }
@@ -0,0 +1,15 @@
1
+ import { type PricingCategoryRecord } from "@voyantjs/pricing-react";
2
+ type Mode = {
3
+ kind: "create";
4
+ } | {
5
+ kind: "edit";
6
+ category: PricingCategoryRecord;
7
+ };
8
+ export interface PricingCategoryFormProps {
9
+ mode: Mode;
10
+ onSuccess?: (category: PricingCategoryRecord) => void;
11
+ onCancel?: () => void;
12
+ }
13
+ export declare function PricingCategoryForm({ mode, onSuccess, onCancel }: PricingCategoryFormProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
15
+ //# sourceMappingURL=pricing-category-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-category-form.d.ts","sourceRoot":"","sources":["../../src/components/pricing-category-form.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,yBAAyB,CAAA;AAehC,KAAK,IAAI,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,qBAAqB,CAAA;CAAE,CAAA;AAElF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACrD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAqFD,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,wBAAwB,2CAyK1F"}
@@ -0,0 +1,99 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { usePricingCategoryMutation, } from "@voyantjs/pricing-react";
4
+ import { Button } from "@voyantjs/voyant-ui/components/button";
5
+ import { Input } from "@voyantjs/voyant-ui/components/input";
6
+ import { Label } from "@voyantjs/voyant-ui/components/label";
7
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/voyant-ui/components/select";
8
+ import { Switch } from "@voyantjs/voyant-ui/components/switch";
9
+ import { Loader2 } from "lucide-react";
10
+ import * as React from "react";
11
+ const CATEGORY_TYPES = [
12
+ { value: "adult", label: "Adult" },
13
+ { value: "child", label: "Child" },
14
+ { value: "infant", label: "Infant" },
15
+ { value: "senior", label: "Senior" },
16
+ { value: "group", label: "Group" },
17
+ { value: "room", label: "Room" },
18
+ { value: "vehicle", label: "Vehicle" },
19
+ { value: "service", label: "Service" },
20
+ { value: "other", label: "Other" },
21
+ ];
22
+ function initialState(mode) {
23
+ if (mode.kind === "edit") {
24
+ const category = mode.category;
25
+ return {
26
+ name: category.name,
27
+ code: category.code ?? "",
28
+ categoryType: category.categoryType,
29
+ seatOccupancy: String(category.seatOccupancy),
30
+ isAgeQualified: category.isAgeQualified,
31
+ minAge: category.minAge != null ? String(category.minAge) : "",
32
+ maxAge: category.maxAge != null ? String(category.maxAge) : "",
33
+ active: category.active,
34
+ sortOrder: String(category.sortOrder),
35
+ };
36
+ }
37
+ return {
38
+ name: "",
39
+ code: "",
40
+ categoryType: "adult",
41
+ seatOccupancy: "1",
42
+ isAgeQualified: false,
43
+ minAge: "",
44
+ maxAge: "",
45
+ active: true,
46
+ sortOrder: "0",
47
+ };
48
+ }
49
+ function toInteger(value) {
50
+ const trimmed = value.trim();
51
+ if (!trimmed)
52
+ return null;
53
+ const parsed = Number(trimmed);
54
+ return Number.isFinite(parsed) ? parsed : null;
55
+ }
56
+ function toPayload(state) {
57
+ return {
58
+ name: state.name.trim(),
59
+ code: state.code.trim() || null,
60
+ categoryType: state.categoryType,
61
+ seatOccupancy: toInteger(state.seatOccupancy) ?? 0,
62
+ isAgeQualified: state.isAgeQualified,
63
+ minAge: state.isAgeQualified ? toInteger(state.minAge) : null,
64
+ maxAge: state.isAgeQualified ? toInteger(state.maxAge) : null,
65
+ active: state.active,
66
+ sortOrder: toInteger(state.sortOrder) ?? 0,
67
+ };
68
+ }
69
+ export function PricingCategoryForm({ mode, onSuccess, onCancel }) {
70
+ const [state, setState] = React.useState(() => initialState(mode));
71
+ const [error, setError] = React.useState(null);
72
+ const { create, update } = usePricingCategoryMutation();
73
+ React.useEffect(() => {
74
+ setState(initialState(mode));
75
+ setError(null);
76
+ }, [mode]);
77
+ const isSubmitting = create.isPending || update.isPending;
78
+ const handleSubmit = async (event) => {
79
+ event.preventDefault();
80
+ setError(null);
81
+ if (!state.name.trim()) {
82
+ setError("Category name is required.");
83
+ return;
84
+ }
85
+ try {
86
+ const category = mode.kind === "create"
87
+ ? await create.mutateAsync(toPayload(state))
88
+ : await update.mutateAsync({ id: mode.category.id, input: toPayload(state) });
89
+ onSuccess?.(category);
90
+ }
91
+ catch (err) {
92
+ setError(err instanceof Error ? err.message : "Failed to save pricing category.");
93
+ }
94
+ };
95
+ return (_jsxs("form", { "data-slot": "pricing-category-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-name", children: "Name" }), _jsx(Input, { id: "pricing-category-name", required: true, autoFocus: true, value: state.name, onChange: (event) => setState((prev) => ({ ...prev, name: event.target.value })), placeholder: "Adult" })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-code", children: "Code" }), _jsx(Input, { id: "pricing-category-code", value: state.code, onChange: (event) => setState((prev) => ({ ...prev, code: event.target.value })), placeholder: "adult" })] })] }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { children: "Type" }), _jsxs(Select, { items: CATEGORY_TYPES, value: state.categoryType, onValueChange: (value) => setState((prev) => ({
96
+ ...prev,
97
+ categoryType: value,
98
+ })), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: CATEGORY_TYPES.map((type) => (_jsx(SelectItem, { value: type.value, children: type.label }, type.value))) })] })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-seat-occupancy", children: "Seat occupancy" }), _jsx(Input, { id: "pricing-category-seat-occupancy", type: "number", min: "0", value: state.seatOccupancy, onChange: (event) => setState((prev) => ({ ...prev, seatOccupancy: event.target.value })) })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: state.isAgeQualified, onCheckedChange: (isAgeQualified) => setState((prev) => ({ ...prev, isAgeQualified })) }), _jsx(Label, { children: "Age qualified" })] }), state.isAgeQualified ? (_jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-min-age", children: "Min age" }), _jsx(Input, { id: "pricing-category-min-age", type: "number", min: "0", value: state.minAge, onChange: (event) => setState((prev) => ({ ...prev, minAge: event.target.value })) })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-max-age", children: "Max age" }), _jsx(Input, { id: "pricing-category-max-age", type: "number", min: "0", value: state.maxAge, onChange: (event) => setState((prev) => ({ ...prev, maxAge: event.target.value })) })] })] })) : null, _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "pricing-category-sort-order", children: "Sort order" }), _jsx(Input, { id: "pricing-category-sort-order", type: "number", value: state.sortOrder, onChange: (event) => setState((prev) => ({ ...prev, sortOrder: event.target.value })) })] }), _jsxs("div", { className: "flex items-center gap-2 pt-7", children: [_jsx(Switch, { checked: state.active, onCheckedChange: (active) => setState((prev) => ({ ...prev, active })) }), _jsx(Label, { children: "Active" })] })] }), error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null, _jsxs("div", { className: "flex items-center justify-end gap-2", children: [onCancel ? (_jsx(Button, { type: "button", variant: "ghost", onClick: onCancel, children: "Cancel" })) : null, _jsxs(Button, { type: "submit", disabled: isSubmitting, children: [isSubmitting ? (_jsx(Loader2, { className: "mr-2 size-4 animate-spin", "aria-hidden": "true" })) : null, mode.kind === "edit" ? "Save changes" : "Create category"] })] })] }));
99
+ }
@@ -0,0 +1,5 @@
1
+ export interface PricingCategoryListProps {
2
+ pageSize?: number;
3
+ }
4
+ export declare function PricingCategoryList({ pageSize }?: PricingCategoryListProps): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=pricing-category-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-category-list.d.ts","sourceRoot":"","sources":["../../src/components/pricing-category-list.tsx"],"names":[],"mappings":"AA8BA,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,QAAa,EAAE,GAAE,wBAA6B,2CAyKnF"}