@open-mercato/core 0.8.1-develop.7221.1.ece7ca874e → 0.8.1-develop.7227.1.9248c14599
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/.turbo/turbo-build.log +1 -1
- package/dist/modules/catalog/backend/catalog/prices/[id]/edit/page.js +166 -0
- package/dist/modules/catalog/backend/catalog/prices/[id]/edit/page.js.map +7 -0
- package/dist/modules/catalog/backend/catalog/prices/[id]/edit/page.meta.js +16 -0
- package/dist/modules/catalog/backend/catalog/prices/[id]/edit/page.meta.js.map +7 -0
- package/dist/modules/catalog/backend/catalog/prices/create/page.js +68 -0
- package/dist/modules/catalog/backend/catalog/prices/create/page.js.map +7 -0
- package/dist/modules/catalog/backend/catalog/prices/create/page.meta.js +25 -0
- package/dist/modules/catalog/backend/catalog/prices/create/page.meta.js.map +7 -0
- package/dist/modules/catalog/backend/catalog/prices/page.js +11 -0
- package/dist/modules/catalog/backend/catalog/prices/page.js.map +7 -0
- package/dist/modules/catalog/backend/catalog/prices/page.meta.js +16 -0
- package/dist/modules/catalog/backend/catalog/prices/page.meta.js.map +7 -0
- package/dist/modules/catalog/components/prices/PriceScopeSelectors.js +201 -0
- package/dist/modules/catalog/components/prices/PriceScopeSelectors.js.map +7 -0
- package/dist/modules/catalog/components/prices/PricesDataTable.js +273 -0
- package/dist/modules/catalog/components/prices/PricesDataTable.js.map +7 -0
- package/dist/modules/catalog/components/prices/normalizePriceRecord.js +43 -0
- package/dist/modules/catalog/components/prices/normalizePriceRecord.js.map +7 -0
- package/dist/modules/catalog/components/prices/priceFormFields.js +195 -0
- package/dist/modules/catalog/components/prices/priceFormFields.js.map +7 -0
- package/dist/modules/catalog/components/prices/useBatchLabels.js +42 -0
- package/dist/modules/catalog/components/prices/useBatchLabels.js.map +7 -0
- package/dist/modules/catalog/data/validators.js +21 -2
- package/dist/modules/catalog/data/validators.js.map +2 -2
- package/dist/modules/catalog/extension-points.js +2 -1
- package/dist/modules/catalog/extension-points.js.map +2 -2
- package/dist/modules/catalog/lib/pricing.js +37 -8
- package/dist/modules/catalog/lib/pricing.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +5 -1
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +2 -2
- package/dist/modules/communication_channels/backend/profile/communication-channels/ConnectChannelMenu.js +88 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/ConnectChannelMenu.js.map +7 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +17 -19
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/connect-credential-channel.js +7 -2
- package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +2 -2
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +11 -2
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
- package/dist/modules/communication_channels/commands/queue-import-history.js +40 -7
- package/dist/modules/communication_channels/commands/queue-import-history.js.map +2 -2
- package/dist/modules/communication_channels/extension-points.js +1 -1
- package/dist/modules/communication_channels/extension-points.js.map +1 -1
- package/dist/modules/communication_channels/lib/connect-channel.js +33 -0
- package/dist/modules/communication_channels/lib/connect-channel.js.map +2 -2
- package/dist/modules/communication_channels/lib/import-history-limits.js +69 -0
- package/dist/modules/communication_channels/lib/import-history-limits.js.map +7 -0
- package/dist/modules/communication_channels/workers/channel-import-history.js +36 -2
- package/dist/modules/communication_channels/workers/channel-import-history.js.map +2 -2
- package/dist/modules/messages/api/route.js +5 -1
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +3 -2
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/data/validators.js +12 -2
- package/dist/modules/messages/data/validators.js.map +2 -2
- package/dist/modules/messages/subscribers/message-notification.js +4 -1
- package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +19 -1
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/catalog/AGENTS.md +6 -2
- package/src/modules/catalog/backend/catalog/prices/[id]/edit/page.meta.ts +12 -0
- package/src/modules/catalog/backend/catalog/prices/[id]/edit/page.tsx +198 -0
- package/src/modules/catalog/backend/catalog/prices/create/page.meta.ts +23 -0
- package/src/modules/catalog/backend/catalog/prices/create/page.tsx +70 -0
- package/src/modules/catalog/backend/catalog/prices/page.meta.ts +12 -0
- package/src/modules/catalog/backend/catalog/prices/page.tsx +14 -0
- package/src/modules/catalog/components/prices/PriceScopeSelectors.tsx +243 -0
- package/src/modules/catalog/components/prices/PricesDataTable.tsx +320 -0
- package/src/modules/catalog/components/prices/normalizePriceRecord.ts +71 -0
- package/src/modules/catalog/components/prices/priceFormFields.tsx +228 -0
- package/src/modules/catalog/components/prices/useBatchLabels.ts +57 -0
- package/src/modules/catalog/data/validators.ts +43 -2
- package/src/modules/catalog/extension-points.ts +1 -0
- package/src/modules/catalog/i18n/de.json +72 -0
- package/src/modules/catalog/i18n/en.json +72 -0
- package/src/modules/catalog/i18n/es.json +72 -0
- package/src/modules/catalog/i18n/ko.json +72 -0
- package/src/modules/catalog/i18n/pl.json +72 -0
- package/src/modules/catalog/lib/pricing.ts +103 -9
- package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +6 -1
- package/src/modules/communication_channels/backend/profile/communication-channels/ConnectChannelMenu.tsx +120 -0
- package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +20 -17
- package/src/modules/communication_channels/commands/connect-credential-channel.ts +9 -0
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +17 -2
- package/src/modules/communication_channels/commands/queue-import-history.ts +59 -11
- package/src/modules/communication_channels/extension-points.ts +1 -1
- package/src/modules/communication_channels/i18n/de.json +4 -3
- package/src/modules/communication_channels/i18n/en.json +4 -3
- package/src/modules/communication_channels/i18n/es.json +4 -3
- package/src/modules/communication_channels/i18n/ko.json +4 -3
- package/src/modules/communication_channels/i18n/pl.json +4 -3
- package/src/modules/communication_channels/lib/adapter.ts +16 -2
- package/src/modules/communication_channels/lib/connect-channel.ts +49 -0
- package/src/modules/communication_channels/lib/import-history-limits.ts +109 -0
- package/src/modules/communication_channels/workers/channel-import-history.ts +46 -5
- package/src/modules/messages/api/route.ts +8 -2
- package/src/modules/messages/commands/messages.ts +17 -2
- package/src/modules/messages/data/validators.ts +26 -11
- package/src/modules/messages/subscribers/message-notification.ts +17 -5
- package/src/modules/query_index/lib/engine.ts +23 -1
- package/src/modules/sales/AGENTS.md +2 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
|
|
5
|
+
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
6
|
+
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
|
|
7
|
+
import { updateCrud, deleteCrud } from "@open-mercato/ui/backend/utils/crud";
|
|
8
|
+
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
9
|
+
import { ErrorMessage, RecordNotFoundState } from "@open-mercato/ui/backend/detail";
|
|
10
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
11
|
+
import { E } from "../../../../../../../generated/entities.ids.generated.js";
|
|
12
|
+
import { usePriceFormFields } from "../../../../../components/prices/priceFormFields.js";
|
|
13
|
+
import { normalizePriceRecord } from "../../../../../components/prices/normalizePriceRecord.js";
|
|
14
|
+
function toDateInputValue(value) {
|
|
15
|
+
if (!value) return "";
|
|
16
|
+
const date = new Date(value);
|
|
17
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
18
|
+
return date.toISOString().slice(0, 10);
|
|
19
|
+
}
|
|
20
|
+
function buildUpdatePayload(id, values, t) {
|
|
21
|
+
const productId = values.productId?.trim() || void 0;
|
|
22
|
+
const variantId = values.variantId?.trim() || void 0;
|
|
23
|
+
if (!productId && !variantId) {
|
|
24
|
+
const message = t("catalog.prices.form.errors.productOrVariantRequired", "Choose a product or a variant.");
|
|
25
|
+
throw createCrudFormError(message, { productId: message });
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
id,
|
|
29
|
+
productId,
|
|
30
|
+
variantId,
|
|
31
|
+
priceKindId: values.priceKindId?.trim() || void 0,
|
|
32
|
+
currencyCode: values.currencyCode?.trim() || void 0,
|
|
33
|
+
unitPriceNet: values.unitPriceNet?.trim() || void 0,
|
|
34
|
+
unitPriceGross: values.unitPriceGross?.trim() || void 0,
|
|
35
|
+
taxRate: values.taxRate?.trim() || void 0,
|
|
36
|
+
minQuantity: values.minQuantity ?? void 0,
|
|
37
|
+
maxQuantity: values.maxQuantity ?? void 0,
|
|
38
|
+
startsAt: values.startsAt?.trim() || void 0,
|
|
39
|
+
endsAt: values.endsAt?.trim() || void 0,
|
|
40
|
+
customerId: values.customerId?.trim() || void 0,
|
|
41
|
+
customerGroupId: values.customerGroupId?.trim() || void 0,
|
|
42
|
+
channelId: values.channelId?.trim() || void 0,
|
|
43
|
+
offerId: values.offerId?.trim() || void 0,
|
|
44
|
+
userId: values.userId?.trim() || void 0,
|
|
45
|
+
userGroupId: values.userGroupId?.trim() || void 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function EditCatalogPricePage({ params }) {
|
|
49
|
+
const priceId = params?.id ?? "";
|
|
50
|
+
const t = useT();
|
|
51
|
+
const { fields, groups } = usePriceFormFields();
|
|
52
|
+
const [initialValues, setInitialValues] = React.useState(null);
|
|
53
|
+
const [loading, setLoading] = React.useState(true);
|
|
54
|
+
const [error, setError] = React.useState(null);
|
|
55
|
+
const [isNotFound, setIsNotFound] = React.useState(false);
|
|
56
|
+
React.useEffect(() => {
|
|
57
|
+
if (!priceId) return;
|
|
58
|
+
let cancelled = false;
|
|
59
|
+
async function load() {
|
|
60
|
+
setLoading(true);
|
|
61
|
+
setError(null);
|
|
62
|
+
setIsNotFound(false);
|
|
63
|
+
try {
|
|
64
|
+
const { ok, status, result } = await apiCall(
|
|
65
|
+
`/api/catalog/prices?ids=${encodeURIComponent(priceId)}&pageSize=1`
|
|
66
|
+
);
|
|
67
|
+
if (!ok) {
|
|
68
|
+
if (status === 404) {
|
|
69
|
+
if (!cancelled) setIsNotFound(true);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
throw new Error(t("catalog.prices.form.errors.load", "Failed to load price rule"));
|
|
73
|
+
}
|
|
74
|
+
const raw = Array.isArray(result?.items) ? result.items[0] : null;
|
|
75
|
+
if (!raw) {
|
|
76
|
+
if (!cancelled) setIsNotFound(true);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (cancelled) return;
|
|
80
|
+
const record = normalizePriceRecord(raw);
|
|
81
|
+
setInitialValues({
|
|
82
|
+
id: record.id,
|
|
83
|
+
productId: record.productId ?? "",
|
|
84
|
+
variantId: record.variantId ?? "",
|
|
85
|
+
priceKindId: record.priceKindId ?? "",
|
|
86
|
+
currencyCode: record.currencyCode ?? "",
|
|
87
|
+
unitPriceNet: record.unitPriceNet ?? "",
|
|
88
|
+
unitPriceGross: record.unitPriceGross ?? "",
|
|
89
|
+
taxRate: record.taxRate ?? "",
|
|
90
|
+
minQuantity: record.minQuantity ?? 1,
|
|
91
|
+
maxQuantity: record.maxQuantity ?? void 0,
|
|
92
|
+
startsAt: toDateInputValue(record.startsAt),
|
|
93
|
+
endsAt: toDateInputValue(record.endsAt),
|
|
94
|
+
customerId: record.customerId ?? "",
|
|
95
|
+
customerGroupId: record.customerGroupId ?? "",
|
|
96
|
+
channelId: record.channelId ?? "",
|
|
97
|
+
offerId: record.offerId ?? "",
|
|
98
|
+
userId: record.userId ?? "",
|
|
99
|
+
userGroupId: record.userGroupId ?? "",
|
|
100
|
+
updatedAt: record.updatedAt ?? null
|
|
101
|
+
});
|
|
102
|
+
} catch (err) {
|
|
103
|
+
if (!cancelled) {
|
|
104
|
+
const fallback = t("catalog.prices.form.errors.load", "Failed to load price rule");
|
|
105
|
+
const message = err instanceof Error ? err.message : fallback;
|
|
106
|
+
setError(message);
|
|
107
|
+
}
|
|
108
|
+
} finally {
|
|
109
|
+
if (!cancelled) setLoading(false);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
load();
|
|
113
|
+
return () => {
|
|
114
|
+
cancelled = true;
|
|
115
|
+
};
|
|
116
|
+
}, [priceId, t]);
|
|
117
|
+
if (!priceId) {
|
|
118
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: t("catalog.prices.form.errors.idRequired", "Price rule identifier is required.") }) }) });
|
|
119
|
+
}
|
|
120
|
+
if (isNotFound) {
|
|
121
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
122
|
+
RecordNotFoundState,
|
|
123
|
+
{
|
|
124
|
+
label: t("catalog.prices.form.errors.notFound", "Price rule not found"),
|
|
125
|
+
backHref: "/backend/catalog/prices",
|
|
126
|
+
backLabel: t("catalog.prices.form.actions.backToList", "Back to price rules")
|
|
127
|
+
}
|
|
128
|
+
) }) });
|
|
129
|
+
}
|
|
130
|
+
if (error && !loading) {
|
|
131
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(ErrorMessage, { label: error }) }) });
|
|
132
|
+
}
|
|
133
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
134
|
+
CrudForm,
|
|
135
|
+
{
|
|
136
|
+
title: t("catalog.prices.form.editTitle", "Edit price rule"),
|
|
137
|
+
titleHeadingLevel: 1,
|
|
138
|
+
backHref: "/backend/catalog/prices",
|
|
139
|
+
fields,
|
|
140
|
+
groups,
|
|
141
|
+
collapsibleGroups: true,
|
|
142
|
+
entityId: E.catalog.catalog_product_price,
|
|
143
|
+
initialValues: initialValues ?? { id: priceId },
|
|
144
|
+
optimisticLockUpdatedAt: initialValues?.updatedAt,
|
|
145
|
+
isLoading: loading,
|
|
146
|
+
loadingMessage: t("catalog.prices.form.loading", "Loading price rule..."),
|
|
147
|
+
submitLabel: t("catalog.prices.form.action.save", "Save"),
|
|
148
|
+
cancelHref: "/backend/catalog/prices",
|
|
149
|
+
successRedirect: `/backend/catalog/prices?flash=${encodeURIComponent(t("catalog.prices.flash.updated", "Price rule updated"))}&type=success`,
|
|
150
|
+
onSubmit: async (values) => {
|
|
151
|
+
const payload = buildUpdatePayload(priceId, values, t);
|
|
152
|
+
await updateCrud("catalog/prices", payload);
|
|
153
|
+
},
|
|
154
|
+
onDelete: async () => {
|
|
155
|
+
await deleteCrud("catalog/prices", priceId, {
|
|
156
|
+
errorMessage: t("catalog.prices.form.errors.delete", "Failed to delete price rule")
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
deleteRedirect: `/backend/catalog/prices?flash=${encodeURIComponent(t("catalog.prices.flash.deleted", "Price rule deleted"))}&type=success`
|
|
160
|
+
}
|
|
161
|
+
) }) });
|
|
162
|
+
}
|
|
163
|
+
export {
|
|
164
|
+
EditCatalogPricePage as default
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../../src/modules/catalog/backend/catalog/prices/%5Bid%5D/edit/page.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { E } from '#generated/entities.ids.generated'\nimport { usePriceFormFields, type PriceFormValues } from '../../../../../components/prices/priceFormFields'\nimport { normalizePriceRecord } from '../../../../../components/prices/normalizePriceRecord'\n\ntype PriceListResponse = {\n items?: Array<Record<string, unknown>>\n}\n\nfunction toDateInputValue(value: string | null | undefined): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return ''\n return date.toISOString().slice(0, 10)\n}\n\nfunction buildUpdatePayload(\n id: string,\n values: PriceFormValues,\n t: (key: string, fallback?: string) => string,\n): Record<string, unknown> {\n const productId = values.productId?.trim() || undefined\n const variantId = values.variantId?.trim() || undefined\n if (!productId && !variantId) {\n const message = t('catalog.prices.form.errors.productOrVariantRequired', 'Choose a product or a variant.')\n throw createCrudFormError(message, { productId: message })\n }\n return {\n id,\n productId,\n variantId,\n priceKindId: values.priceKindId?.trim() || undefined,\n currencyCode: values.currencyCode?.trim() || undefined,\n unitPriceNet: values.unitPriceNet?.trim() || undefined,\n unitPriceGross: values.unitPriceGross?.trim() || undefined,\n taxRate: values.taxRate?.trim() || undefined,\n minQuantity: values.minQuantity ?? undefined,\n maxQuantity: values.maxQuantity ?? undefined,\n startsAt: values.startsAt?.trim() || undefined,\n endsAt: values.endsAt?.trim() || undefined,\n customerId: values.customerId?.trim() || undefined,\n customerGroupId: values.customerGroupId?.trim() || undefined,\n channelId: values.channelId?.trim() || undefined,\n offerId: values.offerId?.trim() || undefined,\n userId: values.userId?.trim() || undefined,\n userGroupId: values.userGroupId?.trim() || undefined,\n }\n}\n\nexport default function EditCatalogPricePage({ params }: { params?: { id?: string } }) {\n const priceId = params?.id ?? ''\n const t = useT()\n const { fields, groups } = usePriceFormFields()\n const [initialValues, setInitialValues] = React.useState<PriceFormValues | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n React.useEffect(() => {\n if (!priceId) return\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n setIsNotFound(false)\n try {\n const { ok, status, result } = await apiCall<PriceListResponse>(\n `/api/catalog/prices?ids=${encodeURIComponent(priceId)}&pageSize=1`,\n )\n if (!ok) {\n if (status === 404) {\n if (!cancelled) setIsNotFound(true)\n return\n }\n throw new Error(t('catalog.prices.form.errors.load', 'Failed to load price rule'))\n }\n const raw = Array.isArray(result?.items) ? result.items[0] : null\n if (!raw) {\n if (!cancelled) setIsNotFound(true)\n return\n }\n if (cancelled) return\n const record = normalizePriceRecord(raw)\n setInitialValues({\n id: record.id,\n productId: record.productId ?? '',\n variantId: record.variantId ?? '',\n priceKindId: record.priceKindId ?? '',\n currencyCode: record.currencyCode ?? '',\n unitPriceNet: record.unitPriceNet ?? '',\n unitPriceGross: record.unitPriceGross ?? '',\n taxRate: record.taxRate ?? '',\n minQuantity: record.minQuantity ?? 1,\n maxQuantity: record.maxQuantity ?? undefined,\n startsAt: toDateInputValue(record.startsAt),\n endsAt: toDateInputValue(record.endsAt),\n customerId: record.customerId ?? '',\n customerGroupId: record.customerGroupId ?? '',\n channelId: record.channelId ?? '',\n offerId: record.offerId ?? '',\n userId: record.userId ?? '',\n userGroupId: record.userGroupId ?? '',\n updatedAt: record.updatedAt ?? null,\n })\n } catch (err) {\n if (!cancelled) {\n const fallback = t('catalog.prices.form.errors.load', 'Failed to load price rule')\n const message = err instanceof Error ? err.message : fallback\n setError(message)\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n load()\n return () => {\n cancelled = true\n }\n }, [priceId, t])\n\n if (!priceId) {\n return (\n <Page>\n <PageBody>\n <p className=\"text-sm text-destructive\">\n {t('catalog.prices.form.errors.idRequired', 'Price rule identifier is required.')}\n </p>\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('catalog.prices.form.errors.notFound', 'Price rule not found')}\n backHref=\"/backend/catalog/prices\"\n backLabel={t('catalog.prices.form.actions.backToList', 'Back to price rules')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error && !loading) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error} />\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <CrudForm<PriceFormValues>\n title={t('catalog.prices.form.editTitle', 'Edit price rule')}\n titleHeadingLevel={1}\n backHref=\"/backend/catalog/prices\"\n fields={fields}\n groups={groups}\n collapsibleGroups\n entityId={E.catalog.catalog_product_price}\n initialValues={initialValues ?? { id: priceId }}\n optimisticLockUpdatedAt={initialValues?.updatedAt}\n isLoading={loading}\n loadingMessage={t('catalog.prices.form.loading', 'Loading price rule...')}\n submitLabel={t('catalog.prices.form.action.save', 'Save')}\n cancelHref=\"/backend/catalog/prices\"\n successRedirect={`/backend/catalog/prices?flash=${encodeURIComponent(t('catalog.prices.flash.updated', 'Price rule updated'))}&type=success`}\n onSubmit={async (values) => {\n const payload = buildUpdatePayload(priceId, values, t)\n await updateCrud('catalog/prices', payload)\n }}\n onDelete={async () => {\n await deleteCrud('catalog/prices', priceId, {\n errorMessage: t('catalog.prices.form.errors.delete', 'Failed to delete price rule'),\n })\n }}\n deleteRedirect={`/backend/catalog/prices?flash=${encodeURIComponent(t('catalog.prices.flash.deleted', 'Price rule deleted'))}&type=success`}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const metadata = {
|
|
2
|
+
requireAuth: true,
|
|
3
|
+
requireFeatures: ["catalog.pricing.manage"],
|
|
4
|
+
pageTitle: "Edit price rule",
|
|
5
|
+
pageTitleKey: "catalog.prices.form.editTitle",
|
|
6
|
+
pageGroup: "Catalog",
|
|
7
|
+
navHidden: true,
|
|
8
|
+
breadcrumb: [
|
|
9
|
+
{ label: "Price rules", labelKey: "catalog.prices.page.title", href: "/backend/catalog/prices" },
|
|
10
|
+
{ label: "Edit", labelKey: "common.edit" }
|
|
11
|
+
]
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
metadata
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=page.meta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../../src/modules/catalog/backend/catalog/prices/%5Bid%5D/edit/page.meta.ts"],
|
|
4
|
+
"sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['catalog.pricing.manage'],\n pageTitle: 'Edit price rule',\n pageTitleKey: 'catalog.prices.form.editTitle',\n pageGroup: 'Catalog',\n navHidden: true,\n breadcrumb: [\n { label: 'Price rules', labelKey: 'catalog.prices.page.title', href: '/backend/catalog/prices' },\n { label: 'Edit', labelKey: 'common.edit' },\n ],\n}\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,wBAAwB;AAAA,EAC1C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,IACV,EAAE,OAAO,eAAe,UAAU,6BAA6B,MAAM,0BAA0B;AAAA,IAC/F,EAAE,OAAO,QAAQ,UAAU,cAAc;AAAA,EAC3C;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
|
|
4
|
+
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
5
|
+
import { createCrud } from "@open-mercato/ui/backend/utils/crud";
|
|
6
|
+
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
7
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
8
|
+
import { E } from "../../../../../../generated/entities.ids.generated.js";
|
|
9
|
+
import { PRICE_FORM_INITIAL_VALUES, usePriceFormFields } from "../../../../components/prices/priceFormFields.js";
|
|
10
|
+
function buildPricePayload(values, t) {
|
|
11
|
+
const productId = values.productId?.trim() || void 0;
|
|
12
|
+
const variantId = values.variantId?.trim() || void 0;
|
|
13
|
+
if (!productId && !variantId) {
|
|
14
|
+
const message = t("catalog.prices.form.errors.productOrVariantRequired", "Choose a product or a variant.");
|
|
15
|
+
throw createCrudFormError(message, { productId: message });
|
|
16
|
+
}
|
|
17
|
+
const priceKindId = values.priceKindId?.trim() || void 0;
|
|
18
|
+
const currencyCode = values.currencyCode?.trim() || void 0;
|
|
19
|
+
const payload = {
|
|
20
|
+
productId,
|
|
21
|
+
variantId,
|
|
22
|
+
priceKindId,
|
|
23
|
+
currencyCode,
|
|
24
|
+
unitPriceNet: values.unitPriceNet?.trim() || void 0,
|
|
25
|
+
unitPriceGross: values.unitPriceGross?.trim() || void 0,
|
|
26
|
+
taxRate: values.taxRate?.trim() || void 0,
|
|
27
|
+
minQuantity: values.minQuantity ?? void 0,
|
|
28
|
+
maxQuantity: values.maxQuantity ?? void 0,
|
|
29
|
+
startsAt: values.startsAt?.trim() || void 0,
|
|
30
|
+
endsAt: values.endsAt?.trim() || void 0,
|
|
31
|
+
customerId: values.customerId?.trim() || void 0,
|
|
32
|
+
customerGroupId: values.customerGroupId?.trim() || void 0,
|
|
33
|
+
channelId: values.channelId?.trim() || void 0,
|
|
34
|
+
offerId: values.offerId?.trim() || void 0,
|
|
35
|
+
userId: values.userId?.trim() || void 0,
|
|
36
|
+
userGroupId: values.userGroupId?.trim() || void 0
|
|
37
|
+
};
|
|
38
|
+
return payload;
|
|
39
|
+
}
|
|
40
|
+
function CreateCatalogPricePage() {
|
|
41
|
+
const t = useT();
|
|
42
|
+
const { fields, groups } = usePriceFormFields();
|
|
43
|
+
const successMessage = encodeURIComponent(t("catalog.prices.flash.created", "Price rule created"));
|
|
44
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
45
|
+
CrudForm,
|
|
46
|
+
{
|
|
47
|
+
title: t("catalog.prices.form.createTitle", "Create price rule"),
|
|
48
|
+
titleHeadingLevel: 1,
|
|
49
|
+
backHref: "/backend/catalog/prices",
|
|
50
|
+
fields,
|
|
51
|
+
groups,
|
|
52
|
+
collapsibleGroups: true,
|
|
53
|
+
entityId: E.catalog.catalog_product_price,
|
|
54
|
+
initialValues: PRICE_FORM_INITIAL_VALUES,
|
|
55
|
+
submitLabel: t("catalog.prices.form.action.save", "Save"),
|
|
56
|
+
cancelHref: "/backend/catalog/prices",
|
|
57
|
+
successRedirect: `/backend/catalog/prices?flash=${successMessage}&type=success`,
|
|
58
|
+
onSubmit: async (values) => {
|
|
59
|
+
const payload = buildPricePayload(values, t);
|
|
60
|
+
await createCrud("catalog/prices", payload);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
) }) });
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
CreateCatalogPricePage as default
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/catalog/backend/catalog/prices/create/page.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { E } from '#generated/entities.ids.generated'\nimport { PRICE_FORM_INITIAL_VALUES, usePriceFormFields, type PriceFormValues } from '../../../../components/prices/priceFormFields'\n\nfunction buildPricePayload(values: PriceFormValues, t: (key: string, fallback?: string) => string): Record<string, unknown> {\n const productId = values.productId?.trim() || undefined\n const variantId = values.variantId?.trim() || undefined\n if (!productId && !variantId) {\n const message = t('catalog.prices.form.errors.productOrVariantRequired', 'Choose a product or a variant.')\n throw createCrudFormError(message, { productId: message })\n }\n const priceKindId = values.priceKindId?.trim() || undefined\n const currencyCode = values.currencyCode?.trim() || undefined\n const payload: Record<string, unknown> = {\n productId,\n variantId,\n priceKindId,\n currencyCode,\n unitPriceNet: values.unitPriceNet?.trim() || undefined,\n unitPriceGross: values.unitPriceGross?.trim() || undefined,\n taxRate: values.taxRate?.trim() || undefined,\n minQuantity: values.minQuantity ?? undefined,\n maxQuantity: values.maxQuantity ?? undefined,\n startsAt: values.startsAt?.trim() || undefined,\n endsAt: values.endsAt?.trim() || undefined,\n customerId: values.customerId?.trim() || undefined,\n customerGroupId: values.customerGroupId?.trim() || undefined,\n channelId: values.channelId?.trim() || undefined,\n offerId: values.offerId?.trim() || undefined,\n userId: values.userId?.trim() || undefined,\n userGroupId: values.userGroupId?.trim() || undefined,\n }\n return payload\n}\n\nexport default function CreateCatalogPricePage() {\n const t = useT()\n const { fields, groups } = usePriceFormFields()\n const successMessage = encodeURIComponent(t('catalog.prices.flash.created', 'Price rule created'))\n\n return (\n <Page>\n <PageBody>\n <CrudForm<PriceFormValues>\n title={t('catalog.prices.form.createTitle', 'Create price rule')}\n titleHeadingLevel={1}\n backHref=\"/backend/catalog/prices\"\n fields={fields}\n groups={groups}\n collapsibleGroups\n entityId={E.catalog.catalog_product_price}\n initialValues={PRICE_FORM_INITIAL_VALUES}\n submitLabel={t('catalog.prices.form.action.save', 'Save')}\n cancelHref=\"/backend/catalog/prices\"\n successRedirect={`/backend/catalog/prices?flash=${successMessage}&type=success`}\n onSubmit={async (values) => {\n const payload = buildPricePayload(values, t)\n await createCrud('catalog/prices', payload)\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAiDQ;AA/CR,SAAS,MAAM,gBAAgB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;AACpC,SAAS,YAAY;AACrB,SAAS,SAAS;AAClB,SAAS,2BAA2B,0BAAgD;AAEpF,SAAS,kBAAkB,QAAyB,GAAwE;AAC1H,QAAM,YAAY,OAAO,WAAW,KAAK,KAAK;AAC9C,QAAM,YAAY,OAAO,WAAW,KAAK,KAAK;AAC9C,MAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,UAAM,UAAU,EAAE,uDAAuD,gCAAgC;AACzG,UAAM,oBAAoB,SAAS,EAAE,WAAW,QAAQ,CAAC;AAAA,EAC3D;AACA,QAAM,cAAc,OAAO,aAAa,KAAK,KAAK;AAClD,QAAM,eAAe,OAAO,cAAc,KAAK,KAAK;AACpD,QAAM,UAAmC;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,OAAO,cAAc,KAAK,KAAK;AAAA,IAC7C,gBAAgB,OAAO,gBAAgB,KAAK,KAAK;AAAA,IACjD,SAAS,OAAO,SAAS,KAAK,KAAK;AAAA,IACnC,aAAa,OAAO,eAAe;AAAA,IACnC,aAAa,OAAO,eAAe;AAAA,IACnC,UAAU,OAAO,UAAU,KAAK,KAAK;AAAA,IACrC,QAAQ,OAAO,QAAQ,KAAK,KAAK;AAAA,IACjC,YAAY,OAAO,YAAY,KAAK,KAAK;AAAA,IACzC,iBAAiB,OAAO,iBAAiB,KAAK,KAAK;AAAA,IACnD,WAAW,OAAO,WAAW,KAAK,KAAK;AAAA,IACvC,SAAS,OAAO,SAAS,KAAK,KAAK;AAAA,IACnC,QAAQ,OAAO,QAAQ,KAAK,KAAK;AAAA,IACjC,aAAa,OAAO,aAAa,KAAK,KAAK;AAAA,EAC7C;AACA,SAAO;AACT;AAEe,SAAR,yBAA0C;AAC/C,QAAM,IAAI,KAAK;AACf,QAAM,EAAE,QAAQ,OAAO,IAAI,mBAAmB;AAC9C,QAAM,iBAAiB,mBAAmB,EAAE,gCAAgC,oBAAoB,CAAC;AAEjG,SACE,oBAAC,QACC,8BAAC,YACC;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,EAAE,mCAAmC,mBAAmB;AAAA,MAC/D,mBAAmB;AAAA,MACnB,UAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,mBAAiB;AAAA,MACjB,UAAU,EAAE,QAAQ;AAAA,MACpB,eAAe;AAAA,MACf,aAAa,EAAE,mCAAmC,MAAM;AAAA,MACxD,YAAW;AAAA,MACX,iBAAiB,iCAAiC,cAAc;AAAA,MAChE,UAAU,OAAO,WAAW;AAC1B,cAAM,UAAU,kBAAkB,QAAQ,CAAC;AAC3C,cAAM,WAAW,kBAAkB,OAAO;AAAA,MAC5C;AAAA;AAAA,EACF,GACF,GACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
const createPageIcon = React.createElement(
|
|
3
|
+
"svg",
|
|
4
|
+
{ width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2 },
|
|
5
|
+
React.createElement("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
6
|
+
React.createElement("polyline", { points: "14 2 14 8 20 8" }),
|
|
7
|
+
React.createElement("path", { d: "M12 11v6M9 14h6" })
|
|
8
|
+
);
|
|
9
|
+
const metadata = {
|
|
10
|
+
requireAuth: true,
|
|
11
|
+
requireFeatures: ["catalog.pricing.manage"],
|
|
12
|
+
pageTitle: "Create price rule",
|
|
13
|
+
pageTitleKey: "catalog.prices.form.createTitle",
|
|
14
|
+
pageGroup: "Catalog",
|
|
15
|
+
pageGroupKey: "catalog.nav.group",
|
|
16
|
+
icon: createPageIcon,
|
|
17
|
+
breadcrumb: [
|
|
18
|
+
{ label: "Price rules", labelKey: "catalog.prices.page.title", href: "/backend/catalog/prices" },
|
|
19
|
+
{ label: "Create", labelKey: "common.create" }
|
|
20
|
+
]
|
|
21
|
+
};
|
|
22
|
+
export {
|
|
23
|
+
metadata
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=page.meta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/catalog/backend/catalog/prices/create/page.meta.ts"],
|
|
4
|
+
"sourcesContent": ["import React from 'react'\n\nconst createPageIcon = React.createElement(\n 'svg',\n { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 },\n React.createElement('path', { d: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z' }),\n React.createElement('polyline', { points: '14 2 14 8 20 8' }),\n React.createElement('path', { d: 'M12 11v6M9 14h6' }),\n)\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['catalog.pricing.manage'],\n pageTitle: 'Create price rule',\n pageTitleKey: 'catalog.prices.form.createTitle',\n pageGroup: 'Catalog',\n pageGroupKey: 'catalog.nav.group',\n icon: createPageIcon,\n breadcrumb: [\n { label: 'Price rules', labelKey: 'catalog.prices.page.title', href: '/backend/catalog/prices' },\n { label: 'Create', labelKey: 'common.create' },\n ],\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,WAAW;AAElB,MAAM,iBAAiB,MAAM;AAAA,EAC3B;AAAA,EACA,EAAE,OAAO,IAAI,QAAQ,IAAI,SAAS,aAAa,MAAM,QAAQ,QAAQ,gBAAgB,aAAa,EAAE;AAAA,EACpG,MAAM,cAAc,QAAQ,EAAE,GAAG,6DAA6D,CAAC;AAAA,EAC/F,MAAM,cAAc,YAAY,EAAE,QAAQ,iBAAiB,CAAC;AAAA,EAC5D,MAAM,cAAc,QAAQ,EAAE,GAAG,kBAAkB,CAAC;AACtD;AAEO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,wBAAwB;AAAA,EAC1C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,MAAM;AAAA,EACN,YAAY;AAAA,IACV,EAAE,OAAO,eAAe,UAAU,6BAA6B,MAAM,0BAA0B;AAAA,IAC/F,EAAE,OAAO,UAAU,UAAU,gBAAgB;AAAA,EAC/C;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
|
|
4
|
+
import PricesDataTable from "../../../components/prices/PricesDataTable.js";
|
|
5
|
+
function CatalogPricesPage() {
|
|
6
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(PricesDataTable, {}) }) });
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
CatalogPricesPage as default
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/catalog/backend/catalog/prices/page.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport PricesDataTable from '../../../components/prices/PricesDataTable'\n\nexport default function CatalogPricesPage() {\n return (\n <Page>\n <PageBody>\n <PricesDataTable />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AASQ;AAPR,SAAS,MAAM,gBAAgB;AAC/B,OAAO,qBAAqB;AAEb,SAAR,oBAAqC;AAC1C,SACE,oBAAC,QACC,8BAAC,YACC,8BAAC,mBAAgB,GACnB,GACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const metadata = {
|
|
2
|
+
requireAuth: true,
|
|
3
|
+
requireFeatures: ["catalog.products.view"],
|
|
4
|
+
pageTitle: "Price rules",
|
|
5
|
+
pageTitleKey: "catalog.prices.page.title",
|
|
6
|
+
pageGroup: "Catalog",
|
|
7
|
+
pageGroupKey: "catalog.nav.group",
|
|
8
|
+
pagePriority: 30,
|
|
9
|
+
pageOrder: 110,
|
|
10
|
+
icon: "tag",
|
|
11
|
+
breadcrumb: [{ label: "Price rules", labelKey: "catalog.prices.page.title" }]
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
metadata
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=page.meta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/catalog/backend/catalog/prices/page.meta.ts"],
|
|
4
|
+
"sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['catalog.products.view'],\n pageTitle: 'Price rules',\n pageTitleKey: 'catalog.prices.page.title',\n pageGroup: 'Catalog',\n pageGroupKey: 'catalog.nav.group',\n pagePriority: 30,\n pageOrder: 110,\n icon: 'tag',\n breadcrumb: [{ label: 'Price rules', labelKey: 'catalog.prices.page.title' }],\n}\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,uBAAuB;AAAA,EACzC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY,CAAC,EAAE,OAAO,eAAe,UAAU,4BAA4B,CAAC;AAC9E;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ComboboxInput } from "@open-mercato/ui/backend/inputs/ComboboxInput";
|
|
5
|
+
import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
6
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
7
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
8
|
+
const logger = createLogger("catalog").child({ component: "PriceScopeSelectors" });
|
|
9
|
+
function pickString(item, ...keys) {
|
|
10
|
+
for (const key of keys) {
|
|
11
|
+
const value = item[key];
|
|
12
|
+
if (typeof value === "string" && value.length) return value;
|
|
13
|
+
}
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
async function loadOptions(path, params, mapItem) {
|
|
17
|
+
try {
|
|
18
|
+
const search = new URLSearchParams(params);
|
|
19
|
+
const payload = await readApiResultOrThrow(
|
|
20
|
+
`${path}?${search.toString()}`,
|
|
21
|
+
void 0,
|
|
22
|
+
{ fallback: { items: [] } }
|
|
23
|
+
);
|
|
24
|
+
const items = Array.isArray(payload.items) ? payload.items : [];
|
|
25
|
+
return items.map(mapItem).filter((option) => option !== null);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
logger.error("catalog.prices.scopeSelect.load", { err, path });
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function resolveOne(path, idParam, id, mapItem) {
|
|
32
|
+
const options = await loadOptions(path, { [idParam]: id, pageSize: "1" }, mapItem);
|
|
33
|
+
return options[0]?.label ?? id;
|
|
34
|
+
}
|
|
35
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
36
|
+
function buildLookupParams(query, pageSize) {
|
|
37
|
+
const trimmed = (query ?? "").trim();
|
|
38
|
+
if (UUID_PATTERN.test(trimmed)) return { ids: trimmed, pageSize: "1" };
|
|
39
|
+
return { search: trimmed, pageSize };
|
|
40
|
+
}
|
|
41
|
+
function PriceProductSelect({
|
|
42
|
+
value,
|
|
43
|
+
onChange,
|
|
44
|
+
disabled
|
|
45
|
+
}) {
|
|
46
|
+
const t = useT();
|
|
47
|
+
const mapItem = React.useCallback((item) => {
|
|
48
|
+
const id = pickString(item, "id");
|
|
49
|
+
if (!id) return null;
|
|
50
|
+
const title = pickString(item, "title", "name") || id;
|
|
51
|
+
const sku = pickString(item, "sku");
|
|
52
|
+
return { value: id, label: sku ? `${title} (${sku})` : title };
|
|
53
|
+
}, []);
|
|
54
|
+
return /* @__PURE__ */ jsx(
|
|
55
|
+
ComboboxInput,
|
|
56
|
+
{
|
|
57
|
+
value,
|
|
58
|
+
onChange,
|
|
59
|
+
disabled,
|
|
60
|
+
allowCustomValues: false,
|
|
61
|
+
clearable: true,
|
|
62
|
+
placeholder: t("catalog.prices.select.product.placeholder", "Search products\u2026"),
|
|
63
|
+
loadSuggestions: (query) => loadOptions("/api/catalog/products", buildLookupParams(query, "10"), mapItem),
|
|
64
|
+
resolveLabel: (id) => resolveOne("/api/catalog/products", "id", id, mapItem)
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
function PriceVariantSelect({
|
|
69
|
+
productId,
|
|
70
|
+
value,
|
|
71
|
+
onChange
|
|
72
|
+
}) {
|
|
73
|
+
const t = useT();
|
|
74
|
+
const mapItem = React.useCallback((item) => {
|
|
75
|
+
const id = pickString(item, "id");
|
|
76
|
+
if (!id) return null;
|
|
77
|
+
const name = pickString(item, "name") || id;
|
|
78
|
+
const sku = pickString(item, "sku");
|
|
79
|
+
return { value: id, label: sku ? `${name} (${sku})` : name };
|
|
80
|
+
}, []);
|
|
81
|
+
const disabled = !productId;
|
|
82
|
+
return /* @__PURE__ */ jsx(
|
|
83
|
+
ComboboxInput,
|
|
84
|
+
{
|
|
85
|
+
value,
|
|
86
|
+
onChange,
|
|
87
|
+
disabled,
|
|
88
|
+
allowCustomValues: false,
|
|
89
|
+
clearable: true,
|
|
90
|
+
placeholder: disabled ? t("catalog.prices.form.field.product", "Product") : t("catalog.prices.select.product.placeholder", "Search products\u2026"),
|
|
91
|
+
loadSuggestions: (query) => disabled ? Promise.resolve([]) : loadOptions("/api/catalog/variants", { ...buildLookupParams(query, "10"), productId }, mapItem),
|
|
92
|
+
resolveLabel: (id) => resolveOne("/api/catalog/variants", "id", id, mapItem)
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function PriceCustomerSelect({
|
|
97
|
+
value,
|
|
98
|
+
onChange
|
|
99
|
+
}) {
|
|
100
|
+
const t = useT();
|
|
101
|
+
const mapItem = React.useCallback((item) => {
|
|
102
|
+
const id = pickString(item, "id");
|
|
103
|
+
if (!id) return null;
|
|
104
|
+
const name = pickString(item, "displayName", "display_name", "name") || id;
|
|
105
|
+
const email = pickString(item, "primaryEmail", "primary_email");
|
|
106
|
+
return { value: id, label: name, description: email || null };
|
|
107
|
+
}, []);
|
|
108
|
+
return /* @__PURE__ */ jsx(
|
|
109
|
+
ComboboxInput,
|
|
110
|
+
{
|
|
111
|
+
value,
|
|
112
|
+
onChange,
|
|
113
|
+
allowCustomValues: false,
|
|
114
|
+
clearable: true,
|
|
115
|
+
placeholder: t("catalog.prices.select.customer.placeholder", "Search customers\u2026"),
|
|
116
|
+
loadSuggestions: (query) => loadOptions("/api/customers/people", buildLookupParams(query, "10"), mapItem),
|
|
117
|
+
resolveLabel: (id) => resolveOne("/api/customers/people", "id", id, mapItem)
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
function PriceChannelSelect({
|
|
122
|
+
value,
|
|
123
|
+
onChange
|
|
124
|
+
}) {
|
|
125
|
+
const t = useT();
|
|
126
|
+
const mapItem = React.useCallback((item) => {
|
|
127
|
+
const id = pickString(item, "id");
|
|
128
|
+
if (!id) return null;
|
|
129
|
+
const name = pickString(item, "name") || id;
|
|
130
|
+
const code = pickString(item, "code");
|
|
131
|
+
return { value: id, label: code ? `${name} (${code})` : name };
|
|
132
|
+
}, []);
|
|
133
|
+
return /* @__PURE__ */ jsx(
|
|
134
|
+
ComboboxInput,
|
|
135
|
+
{
|
|
136
|
+
value,
|
|
137
|
+
onChange,
|
|
138
|
+
allowCustomValues: false,
|
|
139
|
+
clearable: true,
|
|
140
|
+
placeholder: t("catalog.prices.select.channel.placeholder", "Select a channel\u2026"),
|
|
141
|
+
loadSuggestions: (query) => loadOptions("/api/sales/channels", buildLookupParams(query, "50"), mapItem),
|
|
142
|
+
resolveLabel: (id) => resolveOne("/api/sales/channels", "id", id, mapItem)
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
function PricePriceKindSelect({
|
|
147
|
+
value,
|
|
148
|
+
onChange
|
|
149
|
+
}) {
|
|
150
|
+
const t = useT();
|
|
151
|
+
const mapItem = React.useCallback((item) => {
|
|
152
|
+
const id = pickString(item, "id");
|
|
153
|
+
if (!id) return null;
|
|
154
|
+
const title = pickString(item, "title") || id;
|
|
155
|
+
const code = pickString(item, "code");
|
|
156
|
+
return { value: id, label: code ? `${title} (${code})` : title };
|
|
157
|
+
}, []);
|
|
158
|
+
return /* @__PURE__ */ jsx(
|
|
159
|
+
ComboboxInput,
|
|
160
|
+
{
|
|
161
|
+
value,
|
|
162
|
+
onChange,
|
|
163
|
+
allowCustomValues: false,
|
|
164
|
+
placeholder: t("catalog.prices.select.priceKind.placeholder", "Select a price kind\u2026"),
|
|
165
|
+
loadSuggestions: (query) => loadOptions("/api/catalog/price-kinds", buildLookupParams(query, "20"), mapItem),
|
|
166
|
+
resolveLabel: (id) => resolveOne("/api/catalog/price-kinds", "id", id, mapItem)
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
function PriceCurrencySelect({
|
|
171
|
+
value,
|
|
172
|
+
onChange
|
|
173
|
+
}) {
|
|
174
|
+
const t = useT();
|
|
175
|
+
const mapItem = React.useCallback((item) => {
|
|
176
|
+
const code = pickString(item, "value");
|
|
177
|
+
if (!code) return null;
|
|
178
|
+
const label = pickString(item, "label") || code;
|
|
179
|
+
return { value: code, label: label === code ? code : `${code} \u2014 ${label}` };
|
|
180
|
+
}, []);
|
|
181
|
+
return /* @__PURE__ */ jsx(
|
|
182
|
+
ComboboxInput,
|
|
183
|
+
{
|
|
184
|
+
value,
|
|
185
|
+
onChange,
|
|
186
|
+
allowCustomValues: false,
|
|
187
|
+
placeholder: t("catalog.prices.select.currency.placeholder", "Select a currency\u2026"),
|
|
188
|
+
loadSuggestions: (query) => loadOptions("/api/currencies/currencies/options", { search: query ?? "", limit: "20" }, mapItem),
|
|
189
|
+
resolveLabel: (id) => resolveOne("/api/currencies/currencies/options", "search", id, mapItem)
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
export {
|
|
194
|
+
PriceChannelSelect,
|
|
195
|
+
PriceCurrencySelect,
|
|
196
|
+
PriceCustomerSelect,
|
|
197
|
+
PricePriceKindSelect,
|
|
198
|
+
PriceProductSelect,
|
|
199
|
+
PriceVariantSelect
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=PriceScopeSelectors.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/catalog/components/prices/PriceScopeSelectors.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { ComboboxInput, type ComboboxOption } from '@open-mercato/ui/backend/inputs/ComboboxInput'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('catalog').child({ component: 'PriceScopeSelectors' })\n\ntype RemoteItem = Record<string, unknown>\n\nfunction pickString(item: RemoteItem, ...keys: string[]): string {\n for (const key of keys) {\n const value = item[key]\n if (typeof value === 'string' && value.length) return value\n }\n return ''\n}\n\nasync function loadOptions(\n path: string,\n params: Record<string, string>,\n mapItem: (item: RemoteItem) => ComboboxOption | null,\n): Promise<ComboboxOption[]> {\n try {\n const search = new URLSearchParams(params)\n const payload = await readApiResultOrThrow<{ items?: RemoteItem[] }>(\n `${path}?${search.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n return items.map(mapItem).filter((option): option is ComboboxOption => option !== null)\n } catch (err) {\n logger.error('catalog.prices.scopeSelect.load', { err, path })\n return []\n }\n}\n\nasync function resolveOne(\n path: string,\n idParam: string,\n id: string,\n mapItem: (item: RemoteItem) => ComboboxOption | null,\n): Promise<string> {\n const options = await loadOptions(path, { [idParam]: id, pageSize: '1' }, mapItem)\n return options[0]?.label ?? id\n}\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\n/**\n * A typed query that is itself a record id (a pasted UUID) is searched via\n * the generic `ids=` narrowing instead of the entity's free-text `search=`\n * filter \u2014 free-text search matches title/name/sku columns, never the id\n * column, so pasting an exact id would otherwise return zero suggestions.\n */\nfunction buildLookupParams(query: string | undefined, pageSize: string): Record<string, string> {\n const trimmed = (query ?? '').trim()\n if (UUID_PATTERN.test(trimmed)) return { ids: trimmed, pageSize: '1' }\n return { search: trimmed, pageSize }\n}\n\nexport function PriceProductSelect({\n value,\n onChange,\n disabled,\n}: {\n value: string\n onChange: (next: string) => void\n disabled?: boolean\n}) {\n const t = useT()\n const mapItem = React.useCallback((item: RemoteItem): ComboboxOption | null => {\n const id = pickString(item, 'id')\n if (!id) return null\n const title = pickString(item, 'title', 'name') || id\n const sku = pickString(item, 'sku')\n return { value: id, label: sku ? `${title} (${sku})` : title }\n }, [])\n return (\n <ComboboxInput\n value={value}\n onChange={onChange}\n disabled={disabled}\n allowCustomValues={false}\n clearable\n placeholder={t('catalog.prices.select.product.placeholder', 'Search products\u2026')}\n loadSuggestions={(query) => loadOptions('/api/catalog/products', buildLookupParams(query, '10'), mapItem)}\n resolveLabel={(id) => resolveOne('/api/catalog/products', 'id', id, mapItem)}\n />\n )\n}\n\nexport function PriceVariantSelect({\n productId,\n value,\n onChange,\n}: {\n productId: string\n value: string\n onChange: (next: string) => void\n}) {\n const t = useT()\n const mapItem = React.useCallback((item: RemoteItem): ComboboxOption | null => {\n const id = pickString(item, 'id')\n if (!id) return null\n const name = pickString(item, 'name') || id\n const sku = pickString(item, 'sku')\n return { value: id, label: sku ? `${name} (${sku})` : name }\n }, [])\n const disabled = !productId\n return (\n <ComboboxInput\n value={value}\n onChange={onChange}\n disabled={disabled}\n allowCustomValues={false}\n clearable\n placeholder={\n disabled\n ? t('catalog.prices.form.field.product', 'Product')\n : t('catalog.prices.select.product.placeholder', 'Search products\u2026')\n }\n loadSuggestions={(query) =>\n disabled\n ? Promise.resolve([])\n : loadOptions('/api/catalog/variants', { ...buildLookupParams(query, '10'), productId }, mapItem)\n }\n resolveLabel={(id) => resolveOne('/api/catalog/variants', 'id', id, mapItem)}\n />\n )\n}\n\nexport function PriceCustomerSelect({\n value,\n onChange,\n}: {\n value: string\n onChange: (next: string) => void\n}) {\n const t = useT()\n const mapItem = React.useCallback((item: RemoteItem): ComboboxOption | null => {\n const id = pickString(item, 'id')\n if (!id) return null\n const name = pickString(item, 'displayName', 'display_name', 'name') || id\n const email = pickString(item, 'primaryEmail', 'primary_email')\n return { value: id, label: name, description: email || null }\n }, [])\n return (\n <ComboboxInput\n value={value}\n onChange={onChange}\n allowCustomValues={false}\n clearable\n placeholder={t('catalog.prices.select.customer.placeholder', 'Search customers\u2026')}\n loadSuggestions={(query) => loadOptions('/api/customers/people', buildLookupParams(query, '10'), mapItem)}\n resolveLabel={(id) => resolveOne('/api/customers/people', 'id', id, mapItem)}\n />\n )\n}\n\nexport function PriceChannelSelect({\n value,\n onChange,\n}: {\n value: string\n onChange: (next: string) => void\n}) {\n const t = useT()\n const mapItem = React.useCallback((item: RemoteItem): ComboboxOption | null => {\n const id = pickString(item, 'id')\n if (!id) return null\n const name = pickString(item, 'name') || id\n const code = pickString(item, 'code')\n return { value: id, label: code ? `${name} (${code})` : name }\n }, [])\n return (\n <ComboboxInput\n value={value}\n onChange={onChange}\n allowCustomValues={false}\n clearable\n placeholder={t('catalog.prices.select.channel.placeholder', 'Select a channel\u2026')}\n loadSuggestions={(query) => loadOptions('/api/sales/channels', buildLookupParams(query, '50'), mapItem)}\n resolveLabel={(id) => resolveOne('/api/sales/channels', 'id', id, mapItem)}\n />\n )\n}\n\nexport function PricePriceKindSelect({\n value,\n onChange,\n}: {\n value: string\n onChange: (next: string) => void\n}) {\n const t = useT()\n const mapItem = React.useCallback((item: RemoteItem): ComboboxOption | null => {\n const id = pickString(item, 'id')\n if (!id) return null\n const title = pickString(item, 'title') || id\n const code = pickString(item, 'code')\n return { value: id, label: code ? `${title} (${code})` : title }\n }, [])\n return (\n <ComboboxInput\n value={value}\n onChange={onChange}\n allowCustomValues={false}\n placeholder={t('catalog.prices.select.priceKind.placeholder', 'Select a price kind\u2026')}\n loadSuggestions={(query) => loadOptions('/api/catalog/price-kinds', buildLookupParams(query, '20'), mapItem)}\n resolveLabel={(id) => resolveOne('/api/catalog/price-kinds', 'id', id, mapItem)}\n />\n )\n}\n\nexport function PriceCurrencySelect({\n value,\n onChange,\n}: {\n value: string\n onChange: (next: string) => void\n}) {\n const t = useT()\n const mapItem = React.useCallback((item: RemoteItem): ComboboxOption | null => {\n const code = pickString(item, 'value')\n if (!code) return null\n const label = pickString(item, 'label') || code\n return { value: code, label: label === code ? code : `${code} \u2014 ${label}` }\n }, [])\n return (\n <ComboboxInput\n value={value}\n onChange={onChange}\n allowCustomValues={false}\n placeholder={t('catalog.prices.select.currency.placeholder', 'Select a currency\u2026')}\n loadSuggestions={(query) => loadOptions('/api/currencies/currencies/options', { search: query ?? '', limit: '20' }, mapItem)}\n resolveLabel={(id) => resolveOne('/api/currencies/currencies/options', 'search', id, mapItem)}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|