@endora-commerce/mod-sales-channels 0.100.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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/admin/api/sales-channels-client.d.ts +69 -0
  4. package/dist/admin/api/sales-channels-client.d.ts.map +1 -0
  5. package/dist/admin/api/sales-channels-client.js +74 -0
  6. package/dist/admin/api/sales-channels-client.js.map +1 -0
  7. package/dist/admin/components/ChannelIdentityForm.d.ts +24 -0
  8. package/dist/admin/components/ChannelIdentityForm.d.ts.map +1 -0
  9. package/dist/admin/components/ChannelIdentityForm.js +147 -0
  10. package/dist/admin/components/ChannelIdentityForm.js.map +1 -0
  11. package/dist/admin/components/DefaultChannelBadge.d.ts +21 -0
  12. package/dist/admin/components/DefaultChannelBadge.d.ts.map +1 -0
  13. package/dist/admin/components/DefaultChannelBadge.js +26 -0
  14. package/dist/admin/components/DefaultChannelBadge.js.map +1 -0
  15. package/dist/admin/components/EntityChannelMembership.d.ts +52 -0
  16. package/dist/admin/components/EntityChannelMembership.d.ts.map +1 -0
  17. package/dist/admin/components/EntityChannelMembership.js +98 -0
  18. package/dist/admin/components/EntityChannelMembership.js.map +1 -0
  19. package/dist/admin/index.d.ts +44 -0
  20. package/dist/admin/index.d.ts.map +1 -0
  21. package/dist/admin/index.js +148 -0
  22. package/dist/admin/index.js.map +1 -0
  23. package/dist/admin/pages/SalesChannelEditPage.d.ts +25 -0
  24. package/dist/admin/pages/SalesChannelEditPage.d.ts.map +1 -0
  25. package/dist/admin/pages/SalesChannelEditPage.js +185 -0
  26. package/dist/admin/pages/SalesChannelEditPage.js.map +1 -0
  27. package/dist/admin/pages/SalesChannelsListPage.d.ts +25 -0
  28. package/dist/admin/pages/SalesChannelsListPage.d.ts.map +1 -0
  29. package/dist/admin/pages/SalesChannelsListPage.js +91 -0
  30. package/dist/admin/pages/SalesChannelsListPage.js.map +1 -0
  31. package/dist/admin/zones/OrganizationChannelMembership.d.ts +34 -0
  32. package/dist/admin/zones/OrganizationChannelMembership.d.ts.map +1 -0
  33. package/dist/admin/zones/OrganizationChannelMembership.js +11 -0
  34. package/dist/admin/zones/OrganizationChannelMembership.js.map +1 -0
  35. package/dist/admin/zones/ProductChannelMembership.d.ts +23 -0
  36. package/dist/admin/zones/ProductChannelMembership.d.ts.map +1 -0
  37. package/dist/admin/zones/ProductChannelMembership.js +11 -0
  38. package/dist/admin/zones/ProductChannelMembership.js.map +1 -0
  39. package/dist/backend/commands/set-default.command.d.ts +53 -0
  40. package/dist/backend/commands/set-default.command.d.ts.map +1 -0
  41. package/dist/backend/commands/set-default.command.js +87 -0
  42. package/dist/backend/commands/set-default.command.js.map +1 -0
  43. package/dist/backend/index.d.ts +71 -0
  44. package/dist/backend/index.d.ts.map +1 -0
  45. package/dist/backend/index.js +81 -0
  46. package/dist/backend/index.js.map +1 -0
  47. package/dist/backend/routes.admin.d.ts +12 -0
  48. package/dist/backend/routes.admin.d.ts.map +1 -0
  49. package/dist/backend/routes.admin.js +302 -0
  50. package/dist/backend/routes.admin.js.map +1 -0
  51. package/dist/backend/routes.storefront.d.ts +36 -0
  52. package/dist/backend/routes.storefront.d.ts.map +1 -0
  53. package/dist/backend/routes.storefront.js +58 -0
  54. package/dist/backend/routes.storefront.js.map +1 -0
  55. package/dist/backend/services/index.d.ts +2 -0
  56. package/dist/backend/services/index.d.ts.map +1 -0
  57. package/dist/backend/services/index.js +2 -0
  58. package/dist/backend/services/index.js.map +1 -0
  59. package/dist/backend/services/sales-channel-attribution-registry.d.ts +28 -0
  60. package/dist/backend/services/sales-channel-attribution-registry.d.ts.map +1 -0
  61. package/dist/backend/services/sales-channel-attribution-registry.js +50 -0
  62. package/dist/backend/services/sales-channel-attribution-registry.js.map +1 -0
  63. package/dist/backend/services/sales-channels.service.d.ts +247 -0
  64. package/dist/backend/services/sales-channels.service.d.ts.map +1 -0
  65. package/dist/backend/services/sales-channels.service.js +535 -0
  66. package/dist/backend/services/sales-channels.service.js.map +1 -0
  67. package/dist/manifest.d.ts +185 -0
  68. package/dist/manifest.d.ts.map +1 -0
  69. package/dist/manifest.js +204 -0
  70. package/dist/manifest.js.map +1 -0
  71. package/docs/sales_channels/admin-usage.md +77 -0
  72. package/docs/sales_channels/developer-guide.md +107 -0
  73. package/docs/sales_channels/index.md +95 -0
  74. package/i18n/en.json +75 -0
  75. package/i18n/pl.json +75 -0
  76. package/package.json +88 -0
  77. package/tailwind.css +14 -0
@@ -0,0 +1,98 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useState } from 'react';
3
+ import { ApiError, apiClient } from '@endora-commerce/admin-kit/lib';
4
+ import { Alert, AlertDescription, Badge, Button, Card, CardContent, CardHeader, CardTitle, Select, } from '@endora-commerce/admin-kit/ui';
5
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
6
+ import { DefaultChannelBadge } from './DefaultChannelBadge.js';
7
+ const BASE = '/api/v1/admin/sales-channels';
8
+ export function EntityChannelMembership({ entityType, entityId, onChanged, }) {
9
+ const t = useTranslation('sales_channels');
10
+ const [channels, setChannels] = useState([]);
11
+ const [allChannels, setAllChannels] = useState([]);
12
+ const [loading, setLoading] = useState(false);
13
+ const [busy, setBusy] = useState(false);
14
+ const [error, setError] = useState(null);
15
+ const [pickerCode, setPickerCode] = useState('');
16
+ const refresh = useCallback(async () => {
17
+ if (!entityId)
18
+ return;
19
+ setLoading(true);
20
+ setError(null);
21
+ try {
22
+ const [forEntity, all] = await Promise.all([
23
+ apiClient.get(`${BASE}/by-entity/${entityType}/${encodeURIComponent(entityId)}`),
24
+ apiClient.get(`${BASE}?activeOnly=true`),
25
+ ]);
26
+ setChannels(forEntity.channels);
27
+ setAllChannels(all.items);
28
+ }
29
+ catch (err) {
30
+ setError(err instanceof ApiError
31
+ ? err.envelope.error.message
32
+ : 'Failed to load channel memberships.');
33
+ }
34
+ finally {
35
+ setLoading(false);
36
+ }
37
+ }, [entityType, entityId]);
38
+ useEffect(() => {
39
+ void refresh();
40
+ }, [refresh]);
41
+ const candidates = useMemo(() => allChannels.filter((c) => !channels.some((m) => m.id === c.id)), [allChannels, channels]);
42
+ const handleAdd = useCallback(async () => {
43
+ if (!entityId || !pickerCode)
44
+ return;
45
+ setBusy(true);
46
+ setError(null);
47
+ try {
48
+ await apiClient.put(`${BASE}/${encodeURIComponent(pickerCode)}/${entityType}/${encodeURIComponent(entityId)}`, {});
49
+ setPickerCode('');
50
+ await refresh();
51
+ onChanged?.();
52
+ }
53
+ catch (err) {
54
+ setError(err instanceof ApiError ? err.envelope.error.message : 'Add failed.');
55
+ }
56
+ finally {
57
+ setBusy(false);
58
+ }
59
+ }, [pickerCode, entityType, entityId, refresh, onChanged]);
60
+ const handleRemove = useCallback(async (code) => {
61
+ if (!entityId)
62
+ return;
63
+ const path = `${BASE}/${encodeURIComponent(code)}/${entityType}/${encodeURIComponent(entityId)}`;
64
+ setBusy(true);
65
+ setError(null);
66
+ try {
67
+ try {
68
+ await apiClient.delete(path);
69
+ }
70
+ catch (err) {
71
+ if (err instanceof ApiError &&
72
+ err.envelope.error.code === 'ENTITY_WOULD_HAVE_ZERO_CHANNELS') {
73
+ if (window.confirm(`${err.envelope.error.message}\n\nRebind this ${entityType} to the system default channel and continue?`)) {
74
+ await apiClient.delete(`${path}?fallbackToDefault=true`);
75
+ }
76
+ else {
77
+ return;
78
+ }
79
+ }
80
+ else {
81
+ throw err;
82
+ }
83
+ }
84
+ await refresh();
85
+ onChanged?.();
86
+ }
87
+ catch (err) {
88
+ setError(err instanceof ApiError ? err.envelope.error.message : 'Remove failed.');
89
+ }
90
+ finally {
91
+ setBusy(false);
92
+ }
93
+ }, [entityType, entityId, refresh, onChanged]);
94
+ if (!entityId)
95
+ return null;
96
+ return (_jsxs(Card, { className: "mb-4", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: t('membership.title') }) }), _jsxs(CardContent, { children: [error && (_jsx(Alert, { variant: "destructive", className: "mb-4", children: _jsx(AlertDescription, { children: error }) })), loading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('membership.loading') })) : (_jsxs(_Fragment, { children: [channels.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('membership.empty', { entityType }) })) : (_jsx("ul", { className: "grid gap-2", children: channels.map((c) => (_jsxs("li", { className: "flex items-center justify-between rounded-md border border-input p-2", children: [_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-mono text-xs", children: c.code }), _jsx(DefaultChannelBadge, { systemDefault: c.systemDefault }), !c.active && (_jsx(Badge, { variant: "outline", className: "text-[10px]", children: t('status.inactive') })), _jsx("span", { className: "text-xs text-muted-foreground", children: c.name['en-US'] ?? c.name['en'] ?? Object.values(c.name)[0] ?? '' })] }), _jsx(Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => void handleRemove(c.code), children: t('membership.action.remove') })] }, c.id))) })), candidates.length > 0 && (_jsxs("div", { className: "mt-4 grid grid-cols-[1fr_auto] gap-2", children: [_jsxs(Select, { value: pickerCode, onChange: (e) => setPickerCode(e.target.value), disabled: busy, children: [_jsx("option", { value: "", children: t('membership.action.pickChannel') }), candidates.map((c) => (_jsxs("option", { value: c.code, children: [c.code, c.systemDefault ? t('membership.defaultSuffix') : ''] }, c.id)))] }), _jsx(Button, { onClick: () => void handleAdd(), disabled: busy || !pickerCode, children: t('membership.action.add') })] }))] }))] })] }));
97
+ }
98
+ //# sourceMappingURL=EntityChannelMembership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityChannelMembership.js","sourceRoot":"","sources":["../../../src/admin/components/EntityChannelMembership.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * `sales_channels`' admin surface — three routes, one sidebar entry and two
3
+ * zone contributions (feature 091, P7a and P7b for the zones, Phase 4 batch 14
4
+ * for the registrations;
5
+ * `specs/091-module-owned-admin-surfaces/contracts/admin-component-contribution.md`
6
+ * §10).
7
+ *
8
+ * **Batch 14 added the three routes and the sidebar entry**, and it is the
9
+ * paragraph that used to stand here arriving as a fact: this entry said its
10
+ * screens *"are still under `admin/src/modules/sales_channels/` and move in
11
+ * Phase 4's batch 14"*. They are this package's now. The property that let the
12
+ * zones land first is unchanged and is what schedules both halves —
13
+ * `check:admin-registrations` counts routes and nav entries and a zone is
14
+ * neither, so a contributor and a host may each move without the other.
15
+ *
16
+ * **This module is also a zone *host*, which is the other half of batch 14.**
17
+ * `SalesChannelEditPage.tsx` renders `sales_channel.editor.after`, the member
18
+ * P7c published for it, and `inventory` contributes its warehouse routing panel
19
+ * there.
20
+ *
21
+ * **What it drains**: the third admin key in
22
+ * `backend/scripts/ledgers/cross-module-imports/catalog.ts` —
23
+ * `ProductEditor.tsx` importing `EntityChannelMembership` from this module's
24
+ * admin directory and rendering it as the whole body of its Channels tab. The
25
+ * host keeps the tab and its label, which is its own vocabulary (Z14), and
26
+ * counts this contribution to decide whether to show the button (Z15).
27
+ *
28
+ * **Zone and not a published component**, decided from the signature read off
29
+ * the file in this merge request (§9.3): `(entityType, entityId, onChanged?)` —
30
+ * identifiers in, a change notification back and no `value`/`onChange` pair, so
31
+ * the component owns its own persistence. That is Z1 question 2.
32
+ *
33
+ * **P7b added the second contribution**, over the same component: it drains the
34
+ * `EntityChannelMembership` key of
35
+ * `backend/scripts/ledgers/cross-module-imports/organizations.ts`, and it is a
36
+ * contribution to a *different* member rather than a `match` on this one,
37
+ * because two hosts with a place each are two members (Z13).
38
+ *
39
+ * **This entry exports data and nothing else** (R2); every component is a
40
+ * dynamic-import factory (R6).
41
+ */
42
+ import { type AdminContributions } from '@endora-commerce/admin-kit/contributions';
43
+ export declare const contributions: AdminContributions;
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,0CAA0C,CAAC;AA2ClD,eAAO,MAAM,aAAa,EAAE,kBA0E3B,CAAC"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * `sales_channels`' admin surface — three routes, one sidebar entry and two
3
+ * zone contributions (feature 091, P7a and P7b for the zones, Phase 4 batch 14
4
+ * for the registrations;
5
+ * `specs/091-module-owned-admin-surfaces/contracts/admin-component-contribution.md`
6
+ * §10).
7
+ *
8
+ * **Batch 14 added the three routes and the sidebar entry**, and it is the
9
+ * paragraph that used to stand here arriving as a fact: this entry said its
10
+ * screens *"are still under `admin/src/modules/sales_channels/` and move in
11
+ * Phase 4's batch 14"*. They are this package's now. The property that let the
12
+ * zones land first is unchanged and is what schedules both halves —
13
+ * `check:admin-registrations` counts routes and nav entries and a zone is
14
+ * neither, so a contributor and a host may each move without the other.
15
+ *
16
+ * **This module is also a zone *host*, which is the other half of batch 14.**
17
+ * `SalesChannelEditPage.tsx` renders `sales_channel.editor.after`, the member
18
+ * P7c published for it, and `inventory` contributes its warehouse routing panel
19
+ * there.
20
+ *
21
+ * **What it drains**: the third admin key in
22
+ * `backend/scripts/ledgers/cross-module-imports/catalog.ts` —
23
+ * `ProductEditor.tsx` importing `EntityChannelMembership` from this module's
24
+ * admin directory and rendering it as the whole body of its Channels tab. The
25
+ * host keeps the tab and its label, which is its own vocabulary (Z14), and
26
+ * counts this contribution to decide whether to show the button (Z15).
27
+ *
28
+ * **Zone and not a published component**, decided from the signature read off
29
+ * the file in this merge request (§9.3): `(entityType, entityId, onChanged?)` —
30
+ * identifiers in, a change notification back and no `value`/`onChange` pair, so
31
+ * the component owns its own persistence. That is Z1 question 2.
32
+ *
33
+ * **P7b added the second contribution**, over the same component: it drains the
34
+ * `EntityChannelMembership` key of
35
+ * `backend/scripts/ledgers/cross-module-imports/organizations.ts`, and it is a
36
+ * contribution to a *different* member rather than a `match` on this one,
37
+ * because two hosts with a place each are two members (Z13).
38
+ *
39
+ * **This entry exports data and nothing else** (R2); every component is a
40
+ * dynamic-import factory (R6).
41
+ */
42
+ import { zoneComponent, } from '@endora-commerce/admin-kit/contributions';
43
+ /**
44
+ * The one code that opens every surface below — the three screens and the two
45
+ * contributions alike.
46
+ *
47
+ * `packages/modules/sales_channels/src/backend/routes.admin.ts` gates the
48
+ * channel roster and one channel with `sales_channels:read` and every write
49
+ * with `sales_channels:write`, which each screen checks for itself through
50
+ * `useAuth().hasPermission`. It also gates
51
+ * `GET /api/v1/admin/sales-channels/by-entity/:entityType/:entityId` and
52
+ * `GET /api/v1/admin/sales-channels` with `sales_channels:read`; the add and
53
+ * remove behind the panel's two controls take `sales_channels:write`, which a
54
+ * contribution cannot declare a second time. The read code is what makes the
55
+ * surface appear, and it is the honest one: an operator holding it can see the
56
+ * memberships even if the buttons then refuse.
57
+ */
58
+ const READ_PERMISSION = 'sales_channels:read';
59
+ /**
60
+ * The code the create route enforces.
61
+ *
62
+ * `POST /api/v1/admin/sales-channels` is `requireAdmin('sales_channels:write')`
63
+ * and `/sales-channels/new` lands straight on the form — a screen whose only
64
+ * purpose is a write. The codes are opaque strings, so an operator holding the
65
+ * read code alone must not reach it; this module's own `new-sales-channel`
66
+ * palette action declares the same code, which is what
67
+ * `check:action-route-permissions` holds the pair to. Batch 10 settled the
68
+ * shape for `credentials`' `/credentials/new`, and this is the same screen one
69
+ * module over.
70
+ *
71
+ * **One operator-visible tightening, recorded rather than glossed.** The route
72
+ * was `App.tsx`'s and therefore ungated, so a read-only operator could open a
73
+ * create form whose save button would then refuse. The roster's *+ New channel*
74
+ * button was ungated too and is gated on this code in the same merge request,
75
+ * so the dead end is closed at both ends rather than moved from one to the
76
+ * other.
77
+ */
78
+ const WRITE_PERMISSION = 'sales_channels:write';
79
+ /** The module's landing route: the channel roster. */
80
+ const ROUTE_PATH = '/sales-channels';
81
+ export const contributions = {
82
+ routes: [
83
+ {
84
+ path: ROUTE_PATH,
85
+ component: () => import('./pages/SalesChannelsListPage.js'),
86
+ requiredPermission: READ_PERMISSION,
87
+ index: true,
88
+ },
89
+ {
90
+ // The create form and the editor are one component, told apart by the
91
+ // `:code` parameter — `App.tsx` declared them as two routes over one
92
+ // element and this declaration keeps that shape. `/sales-channels/new` is
93
+ // declared first, and `<Routes>` ranks by specificity rather than by
94
+ // declaration order, so the static segment wins whatever the order; the
95
+ // ordering is kept anyway, so a reader does not have to know that to see
96
+ // why the parametric route is safe here.
97
+ //
98
+ // **The create route carries the write code and the editor carries the
99
+ // read one**, which is the split `credentials` already ships: a screen
100
+ // whose only purpose is a write is opened by the code that write demands,
101
+ // and an existing channel is opened by the code that reads it.
102
+ path: `${ROUTE_PATH}/new`,
103
+ component: () => import('./pages/SalesChannelEditPage.js'),
104
+ requiredPermission: WRITE_PERMISSION,
105
+ },
106
+ {
107
+ path: `${ROUTE_PATH}/:code`,
108
+ component: () => import('./pages/SalesChannelEditPage.js'),
109
+ requiredPermission: READ_PERMISSION,
110
+ },
111
+ ],
112
+ nav: [
113
+ {
114
+ to: ROUTE_PATH,
115
+ // Module-relative (R8), resolved in this module's own namespace out of
116
+ // `packages/modules/sales_channels/i18n/`. It was
117
+ // `appShell.nav.salesChannels` in the shared `_i18n` bundle, one of the
118
+ // four shared files a module author had to edit.
119
+ labelKey: 'nav.salesChannels.label',
120
+ // The glyph `AppShell.tsx` rendered by hand, and already on
121
+ // `KnownIconNameSchema`.
122
+ icon: 'Store',
123
+ section: 'channels',
124
+ // First in *Channels*, which is where the hand-written table put it and
125
+ // where the operator has always seen it. `dictionaries` declares 200 and
126
+ // 300 and `seo` 400, and the host declares no row in this section once
127
+ // this one leaves, so 100 is the whole of what keeps this row on top.
128
+ weight: 100,
129
+ requiredPermission: READ_PERMISSION,
130
+ },
131
+ ],
132
+ zones: [
133
+ zoneComponent('product.editor.channels', () => import('./zones/ProductChannelMembership.js'), {
134
+ // The only contribution to this place, so the weight orders nothing
135
+ // today. Declared rather than defaulted so a second contributor arrives
136
+ // beside it rather than ahead of it by accident.
137
+ weight: 100,
138
+ requiredPermission: READ_PERMISSION,
139
+ }),
140
+ // Weight 100 of four contributors to the organization detail's zone
141
+ // (feature 091, P7b): this panel first, then `price_lists` at 200,
142
+ // `quick_order` at 300 and `carts` at 400. That is the order the operator
143
+ // saw when the panels were scattered through `OrganizationDetail.tsx`,
144
+ // preserved rather than re-chosen.
145
+ zoneComponent('organization.detail.after', () => import('./zones/OrganizationChannelMembership.js'), { weight: 100, requiredPermission: READ_PERMISSION }),
146
+ ],
147
+ };
148
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EACL,aAAa,GAEd,MAAM,0CAA0C,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAEhD,sDAAsD;AACtD,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAErC,MAAM,CAAC,MAAM,aAAa,GAAuB;IAC/C,MAAM,EAAE;QACN;YACE,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,kCAAkC,CAAC;YAC3D,kBAAkB,EAAE,eAAe;YACnC,KAAK,EAAE,IAAI;SACZ;QACD;YACE,sEAAsE;YACtE,qEAAqE;YACrE,0EAA0E;YAC1E,qEAAqE;YACrE,wEAAwE;YACxE,yEAAyE;YACzE,yCAAyC;YACzC,EAAE;YACF,uEAAuE;YACvE,uEAAuE;YACvE,0EAA0E;YAC1E,+DAA+D;YAC/D,IAAI,EAAE,GAAG,UAAU,MAAM;YACzB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iCAAiC,CAAC;YAC1D,kBAAkB,EAAE,gBAAgB;SACrC;QACD;YACE,IAAI,EAAE,GAAG,UAAU,QAAQ;YAC3B,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iCAAiC,CAAC;YAC1D,kBAAkB,EAAE,eAAe;SACpC;KACF;IACD,GAAG,EAAE;QACH;YACE,EAAE,EAAE,UAAU;YACd,uEAAuE;YACvE,kDAAkD;YAClD,wEAAwE;YACxE,iDAAiD;YACjD,QAAQ,EAAE,yBAAyB;YACnC,4DAA4D;YAC5D,yBAAyB;YACzB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,UAAU;YACnB,wEAAwE;YACxE,yEAAyE;YACzE,uEAAuE;YACvE,sEAAsE;YACtE,MAAM,EAAE,GAAG;YACX,kBAAkB,EAAE,eAAe;SACpC;KACF;IACD,KAAK,EAAE;QACL,aAAa,CACX,yBAAyB,EACzB,GAAG,EAAE,CAAC,MAAM,CAAC,qCAAqC,CAAC,EACnD;YACE,oEAAoE;YACpE,wEAAwE;YACxE,iDAAiD;YACjD,MAAM,EAAE,GAAG;YACX,kBAAkB,EAAE,eAAe;SACpC,CACF;QACD,oEAAoE;QACpE,mEAAmE;QACnE,0EAA0E;QAC1E,uEAAuE;QACvE,mCAAmC;QACnC,aAAa,CACX,2BAA2B,EAC3B,GAAG,EAAE,CAAC,MAAM,CAAC,0CAA0C,CAAC,EACxD,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,EAAE,eAAe,EAAE,CACrD;KACF;CACF,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type ReactNode } from 'react';
2
+ /**
3
+ * SalesChannelEditPage — feature 005 / T042.
4
+ *
5
+ * Two roles in one component, distinguished by the `:code` path
6
+ * parameter:
7
+ * - `code === 'new'` → create form (POST).
8
+ * - any other value → edit form (GET → PATCH).
9
+ *
10
+ * The form surfaces 409 / 412 / 422 errors from the backend as a
11
+ * conflict banner so the operator can choose to refresh and retry
12
+ * (412) or rename / re-pick a code (409).
13
+ *
14
+ * Membership tabs (US3 / T064) are NOT rendered here yet; the page
15
+ * deliberately scopes itself to identity + lifecycle so US2 ships
16
+ * standalone.
17
+ */
18
+ export declare function SalesChannelEditPage(): ReactNode;
19
+ /**
20
+ * The registry loads a route component through a dynamic-import factory and
21
+ * reads its default export (feature 091, FR-013). The named export stays: it is
22
+ * the spelling this module's own code and its tests use.
23
+ */
24
+ export default SalesChannelEditPage;
25
+ //# sourceMappingURL=SalesChannelEditPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SalesChannelEditPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/SalesChannelEditPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAczE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,IAAI,SAAS,CAuOhD;AAED;;;;GAIG;AACH,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,185 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ import { useNavigate, useParams } from 'react-router-dom';
4
+ import { ApiError } from '@endora-commerce/admin-kit/lib';
5
+ import { Alert, AlertDescription, Badge, Button, PageHeader } from '@endora-commerce/admin-kit/ui';
6
+ import { salesChannelsClient } from '../api/sales-channels-client.js';
7
+ import { ChannelIdentityForm, } from '../components/ChannelIdentityForm.js';
8
+ import { DefaultChannelBadge } from '../components/DefaultChannelBadge.js';
9
+ import { AdminZone } from '@endora-commerce/admin-kit/zones';
10
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
11
+ /**
12
+ * SalesChannelEditPage — feature 005 / T042.
13
+ *
14
+ * Two roles in one component, distinguished by the `:code` path
15
+ * parameter:
16
+ * - `code === 'new'` → create form (POST).
17
+ * - any other value → edit form (GET → PATCH).
18
+ *
19
+ * The form surfaces 409 / 412 / 422 errors from the backend as a
20
+ * conflict banner so the operator can choose to refresh and retry
21
+ * (412) or rename / re-pick a code (409).
22
+ *
23
+ * Membership tabs (US3 / T064) are NOT rendered here yet; the page
24
+ * deliberately scopes itself to identity + lifecycle so US2 ships
25
+ * standalone.
26
+ */
27
+ export function SalesChannelEditPage() {
28
+ const t = useTranslation('sales_channels');
29
+ const { code: routeCode } = useParams();
30
+ const navigate = useNavigate();
31
+ const isCreate = routeCode === 'new' || routeCode === undefined;
32
+ const [channel, setChannel] = useState(null);
33
+ const [loading, setLoading] = useState(!isCreate);
34
+ const [saving, setSaving] = useState(false);
35
+ const [error, setError] = useState(null);
36
+ useEffect(() => {
37
+ if (isCreate)
38
+ return;
39
+ let cancelled = false;
40
+ (async () => {
41
+ setLoading(true);
42
+ setError(null);
43
+ try {
44
+ const detail = await salesChannelsClient.getByCode(routeCode);
45
+ if (!cancelled)
46
+ setChannel(detail);
47
+ }
48
+ catch (err) {
49
+ if (!cancelled) {
50
+ setError(err instanceof ApiError ? err.envelope.error.message : 'Failed to load channel.');
51
+ }
52
+ }
53
+ finally {
54
+ if (!cancelled)
55
+ setLoading(false);
56
+ }
57
+ })();
58
+ return () => {
59
+ cancelled = true;
60
+ };
61
+ }, [isCreate, routeCode]);
62
+ const handleSubmit = useCallback(async (value) => {
63
+ setSaving(true);
64
+ setError(null);
65
+ try {
66
+ if (isCreate) {
67
+ const created = await salesChannelsClient.create({
68
+ code: value.code,
69
+ name: { 'en-US': value.name },
70
+ ...(value.themeCode ? { themeCode: value.themeCode } : {}),
71
+ languages: value.languages,
72
+ defaultLanguage: value.defaultLanguage,
73
+ currencies: value.currencies,
74
+ defaultCurrency: value.defaultCurrency,
75
+ active: value.active,
76
+ });
77
+ navigate(`/sales-channels/${encodeURIComponent(created.code)}`, { replace: true });
78
+ return;
79
+ }
80
+ if (!channel)
81
+ return;
82
+ const updated = await salesChannelsClient.update(channel.code, {
83
+ expectedVersion: channel.version,
84
+ name: { 'en-US': value.name },
85
+ ...(value.themeCode !== undefined ? { themeCode: value.themeCode || null } : {}),
86
+ languages: value.languages,
87
+ defaultLanguage: value.defaultLanguage,
88
+ currencies: value.currencies,
89
+ defaultCurrency: value.defaultCurrency,
90
+ active: value.active,
91
+ });
92
+ setChannel(updated);
93
+ }
94
+ catch (err) {
95
+ setError(err instanceof ApiError ? err.envelope.error.message : 'Save failed.');
96
+ }
97
+ finally {
98
+ setSaving(false);
99
+ }
100
+ }, [channel, isCreate, navigate]);
101
+ const handleDeactivate = useCallback(async () => {
102
+ if (!channel || channel.systemDefault)
103
+ return;
104
+ setSaving(true);
105
+ setError(null);
106
+ try {
107
+ const updated = await salesChannelsClient.deactivate(channel.code);
108
+ setChannel(updated);
109
+ }
110
+ catch (err) {
111
+ setError(err instanceof ApiError ? err.envelope.error.message : 'Deactivate failed.');
112
+ }
113
+ finally {
114
+ setSaving(false);
115
+ }
116
+ }, [channel]);
117
+ const handleActivate = useCallback(async () => {
118
+ if (!channel)
119
+ return;
120
+ setSaving(true);
121
+ setError(null);
122
+ try {
123
+ const updated = await salesChannelsClient.activate(channel.code);
124
+ setChannel(updated);
125
+ }
126
+ catch (err) {
127
+ setError(err instanceof ApiError ? err.envelope.error.message : 'Activate failed.');
128
+ }
129
+ finally {
130
+ setSaving(false);
131
+ }
132
+ }, [channel]);
133
+ const handleDelete = useCallback(async () => {
134
+ if (!channel || channel.systemDefault)
135
+ return;
136
+ if (!window.confirm(`Delete sales channel "${channel.code}"? This is irreversible. ` +
137
+ `If any product / customer / category would be left with zero channels, ` +
138
+ `the platform will refuse — you can opt to rebind them to the system default instead.`))
139
+ return;
140
+ setSaving(true);
141
+ setError(null);
142
+ try {
143
+ try {
144
+ await salesChannelsClient.delete(channel.code, { fallbackToDefault: false });
145
+ }
146
+ catch (err) {
147
+ if (err instanceof ApiError &&
148
+ err.envelope.error.code === 'ENTITY_WOULD_HAVE_ZERO_CHANNELS') {
149
+ if (window.confirm(`${err.envelope.error.message}\n\nRebind those entities to the system default and delete?`)) {
150
+ await salesChannelsClient.delete(channel.code, { fallbackToDefault: true });
151
+ }
152
+ else {
153
+ return;
154
+ }
155
+ }
156
+ else {
157
+ throw err;
158
+ }
159
+ }
160
+ navigate('/sales-channels');
161
+ }
162
+ catch (err) {
163
+ setError(err instanceof ApiError ? err.envelope.error.message : 'Delete failed.');
164
+ }
165
+ finally {
166
+ setSaving(false);
167
+ }
168
+ }, [channel, navigate]);
169
+ if (loading) {
170
+ return _jsx("p", { className: "text-sm text-muted-foreground", children: t('edit.loading') });
171
+ }
172
+ if (!isCreate && !channel) {
173
+ return (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error ?? 'Channel not found.' }) }));
174
+ }
175
+ return (_jsxs(_Fragment, { children: [_jsx(PageHeader, { title: isCreate ? ('New Sales Channel') : (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-mono text-base", children: channel.code }), _jsx(DefaultChannelBadge, { systemDefault: channel.systemDefault }), !channel.active && (_jsx(Badge, { variant: "outline", className: "text-[10px]", children: "Inactive" }))] })), description: isCreate
176
+ ? 'Create a new place of sale. After saving, manage its product / customer / price-list memberships from the channel detail page or from the entity edit screens.'
177
+ : 'Edit the channel’s identity. Lifecycle actions live in the toolbar; membership tabs land in a follow-up.', actions: channel ? (_jsxs("div", { className: "flex gap-2", children: [channel.active ? (_jsx(Button, { variant: "outline", onClick: () => void handleDeactivate(), disabled: saving || channel.systemDefault, children: "Deactivate" })) : (_jsx(Button, { variant: "outline", onClick: () => void handleActivate(), disabled: saving, children: "Re-activate" })), _jsx(Button, { variant: "destructive", onClick: () => void handleDelete(), disabled: saving || channel.systemDefault, children: "Delete" })] })) : null }), _jsx(ChannelIdentityForm, { mode: isCreate ? 'create' : 'edit', initial: channel, lockCode: !isCreate, errorMessage: error, saving: saving, onSubmit: (v) => void handleSubmit(v), onCancel: () => navigate('/sales-channels') }), channel && !isCreate ? (_jsx("div", { style: { marginTop: 24 }, children: _jsx(AdminZone, { name: "sales_channel.editor.after", props: { channelId: channel.id } }) })) : null] }));
178
+ }
179
+ /**
180
+ * The registry loads a route component through a dynamic-import factory and
181
+ * reads its default export (feature 091, FR-013). The named export stays: it is
182
+ * the spelling this module's own code and its tests use.
183
+ */
184
+ export default SalesChannelEditPage;
185
+ //# sourceMappingURL=SalesChannelEditPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SalesChannelEditPage.js","sourceRoot":"","sources":["../../../src/admin/pages/SalesChannelEditPage.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type ReactNode } from 'react';
2
+ /**
3
+ * SalesChannelsListPage — feature 005 / T041.
4
+ *
5
+ * Top-level list view. The system-default channel always lives in
6
+ * the list; the activeOnly filter toggles whether deactivated
7
+ * channels are hidden. The "+ New channel" CTA sends the operator
8
+ * to the create form (`/sales-channels/new`).
9
+ *
10
+ * The system-default column is where the flag moves (feature 072 / D-51). The
11
+ * list is the right surface for it because the decision is comparative — which
12
+ * of these channels should be the fallback — and because the current default
13
+ * has to be visible while another one is promoted. The current default's cell
14
+ * is deliberately inert: the flag is moved by promoting a different channel,
15
+ * never by clearing it here, which is what keeps "exactly one default" true at
16
+ * every moment.
17
+ */
18
+ export declare function SalesChannelsListPage(): ReactNode;
19
+ /**
20
+ * The registry loads a route component through a dynamic-import factory and
21
+ * reads its default export (feature 091, FR-013). The named export stays: it is
22
+ * the spelling this module's own code and its tests use.
23
+ */
24
+ export default SalesChannelsListPage;
25
+ //# sourceMappingURL=SalesChannelsListPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SalesChannelsListPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/SalesChannelsListPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASzE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,CAmLjD;AAED;;;;GAIG;AACH,eAAe,qBAAqB,CAAC"}