@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # sales_channels
2
+
3
+ Owns the **admin surface** for sales channels — CRUD, lifecycle and the
4
+ membership routes — and the nine `sales_channel_*` membership bridge tables and
5
+ their migration. A single deployment serves multiple channels; catalog
6
+ visibility, related/cross-sell/up-sell links, promotions/coupons, pricing, CMS,
7
+ mega-menu and blog are all scoped to the request's channel through those bridges.
8
+
9
+ ## What lives in the kernel (feature 072, T019)
10
+
11
+ Channel *resolution* is a platform concern, not a module one: the resolution
12
+ order is a refusal contract (Constitution XII) and 49 call sites read the
13
+ resolved channel. So the `SalesChannel` entity, the resolver middleware and
14
+ resolver service, `SalesChannelMembershipService`, the cache and its invalidator
15
+ and `DefaultChannelReconciler` all live under
16
+ `backend/src/kernel/sales-channels/`. This module keeps
17
+ `services/sales-channels.service.ts` (admin CRUD, zero external importers) and
18
+ `routes.admin.ts`.
19
+
20
+ Nothing about the resolution order or the refusal behaviour changed with the
21
+ move; a module may import the kernel freely.
22
+
23
+ ## The single resolution contract (feature 053 / FR-002)
24
+
25
+ The **canonical resolver middleware**
26
+ (`kernel/sales-channels/sales-channel-resolver.middleware.ts`)
27
+ runs as a Fastify `onRequest` hook on every `/api/v1/*` request (bypassing
28
+ `/api/v1/_health`). It resolves the channel **once**, in this order:
29
+
30
+ 1. `X-Sales-Channel: <code>` header
31
+ 2. `?salesChannel=<code>` query — storefront only; ignored on `/api/v1/admin/*`
32
+ 3. `SALES_CHANNEL_HOST_MAP` host mapping
33
+ 4. the **system-default** channel (`systemDefault = true`) — the single
34
+ empty-channel fallback (the legacy `isPublic` fallback is retired)
35
+
36
+ It validates existence + active state (unknown → `UNKNOWN_SALES_CHANNEL`,
37
+ inactive → `INACTIVE_SALES_CHANNEL`), attaches the result to
38
+ `request.salesChannel` (a `CachedChannel`, backed by the LRU+Redis cache), and
39
+ echoes `X-Sales-Channel: <resolvedCode>` on the response.
40
+
41
+ ### Consuming the channel — the one rule
42
+
43
+ Storefront-facing modules **MUST** read `request.salesChannel` (via
44
+ `getResolvedChannel(request)`) and **MUST NOT** re-parse the header/query/host or
45
+ re-query `SalesChannel` to derive the request channel. Routes hand services the
46
+ resolved channel object; services never re-resolve. Reading `channel.isPublic`
47
+ (price visibility) off the already-resolved channel is fine — it is a display
48
+ flag, not resolution.
49
+
50
+ This invariant is enforced by `backend/scripts/check-channel-resolution.ts`
51
+ (CI `--enforce`). Bridge membership is read only through
52
+ `SalesChannelMembershipService`; `check:module-boundary`'s `sql` predicate is what
53
+ refuses a raw `sales_channel_*` statement (D-87).
54
+
55
+ Full contract + consumption guide: `specs/053-sales-channel-scoping-unification/`
56
+ (`contracts/resolved-channel-context.md`, `contracts/header-dialect.md`,
57
+ `quickstart.md`).
58
+
59
+ ### Notes
60
+
61
+ - The `X-Sales-Channel-Id` (UUID) header is **removed** — `X-Sales-Channel`
62
+ (code) is the only dialect.
63
+ - Activation/deactivation invalidates the resolver cache through the
64
+ `sales_channels.lifecycle_changed` pub/sub, so a channel goes offline on every
65
+ surface within the cache TTL (one cache, all surfaces).
66
+ - Carts/quotes are assigned the system-default channel at creation, so no
67
+ null-channel cart reaches pricing/checkout.
@@ -0,0 +1,69 @@
1
+ import type { ChannelMemberEntityType, SalesChannelCreateBody, SalesChannelDetail, SalesChannelListResponse, SalesChannelSetDefaultResponse, SalesChannelSummary, SalesChannelUpdateBody } from '@endora-commerce/contracts';
2
+ /**
3
+ * Typed wrapper around `/api/v1/admin/sales-channels/*` — feature 005 / T038.
4
+ * Source-of-truth schemas live in `@endora-commerce/contracts`.
5
+ *
6
+ * Optimistic concurrency for PATCH rides on the body's `expectedVersion`
7
+ * field (matches feature 003/004); the response's ETag is also exposed
8
+ * for completeness so a future refactor to `If-Match` is one-line away.
9
+ */
10
+ export interface ListOptions {
11
+ page?: number;
12
+ pageSize?: number;
13
+ activeOnly?: boolean;
14
+ }
15
+ export declare const salesChannelsClient: {
16
+ list(options?: ListOptions): Promise<SalesChannelListResponse>;
17
+ getByCode(code: string): Promise<SalesChannelDetail>;
18
+ create(body: SalesChannelCreateBody): Promise<SalesChannelDetail>;
19
+ update(code: string, body: SalesChannelUpdateBody & {
20
+ expectedVersion: number;
21
+ }): Promise<SalesChannelDetail>;
22
+ deactivate(code: string): Promise<SalesChannelDetail>;
23
+ activate(code: string): Promise<SalesChannelDetail>;
24
+ /**
25
+ * Move the system-default flag to this channel (D-51). Promoting the channel
26
+ * that already holds it answers 200 with `changed: false`, so a double click
27
+ * is not an error; an inactive channel is refused with 422
28
+ * `INACTIVE_SALES_CHANNEL`.
29
+ */
30
+ setDefault(code: string): Promise<SalesChannelSetDefaultResponse>;
31
+ delete(code: string, options?: {
32
+ fallbackToDefault?: boolean;
33
+ }): Promise<void>;
34
+ /** List entity ids of `entityType` that belong to `code`. */
35
+ listEntitiesInChannel(code: string, entityType: ChannelMemberEntityType, options?: {
36
+ page?: number;
37
+ pageSize?: number;
38
+ }): Promise<{
39
+ salesChannelCode: string;
40
+ entityType: ChannelMemberEntityType;
41
+ entityIds: string[];
42
+ page: number;
43
+ pageSize: number;
44
+ total: number;
45
+ }>;
46
+ /** List the channels an entity belongs to. */
47
+ listChannelsForEntity(entityType: ChannelMemberEntityType, entityId: string): Promise<{
48
+ entityType: ChannelMemberEntityType;
49
+ entityId: string;
50
+ channels: SalesChannelSummary[];
51
+ }>;
52
+ /** Idempotent — re-adding an existing membership returns `changed: false`. */
53
+ addEntityToChannel(code: string, entityType: ChannelMemberEntityType, entityId: string): Promise<{
54
+ changed: boolean;
55
+ }>;
56
+ /**
57
+ * Remove a membership. With `fallbackToDefault=false` (default), removing
58
+ * the entity's last channel returns 422 ENTITY_WOULD_HAVE_ZERO_CHANNELS;
59
+ * with `true`, the entity is rebound to the system default in one
60
+ * transaction.
61
+ */
62
+ removeEntityFromChannel(code: string, entityType: ChannelMemberEntityType, entityId: string, options?: {
63
+ fallbackToDefault?: boolean;
64
+ }): Promise<{
65
+ changed: boolean;
66
+ fallbackAppliedToDefault: boolean;
67
+ }>;
68
+ };
69
+ //# sourceMappingURL=sales-channels-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sales-channels-client.d.ts","sourceRoot":"","sources":["../../../src/admin/api/sales-channels-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;GAOG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,mBAAmB;mBAChB,WAAW,GAAQ,OAAO,CAAC,wBAAwB,CAAC;oBAWlD,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;iBAMvC,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;iBAKzD,MAAM,QACN,sBAAsB,GAAG;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE,GACzD,OAAO,CAAC,kBAAkB,CAAC;qBAOb,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;mBAOtC,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOnD;;;;;OAKG;qBACc,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC;iBAOpD,MAAM,YAAW;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAQ,OAAO,CAAC,IAAI,CAAC;IAWlF,6DAA6D;gCAErD,MAAM,cACA,uBAAuB,YAC1B;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5C,OAAO,CAAC;QACT,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,uBAAuB,CAAC;QACpC,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAUF,8CAA8C;sCAEhC,uBAAuB,YACzB,MAAM,GACf,OAAO,CAAC;QACT,UAAU,EAAE,uBAAuB,CAAC;QACpC,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;KACjC,CAAC;IAMF,8EAA8E;6BAEtE,MAAM,cACA,uBAAuB,YACzB,MAAM,GACf,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAOhC;;;;;OAKG;kCAEK,MAAM,cACA,uBAAuB,YACzB,MAAM,YACP;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GACvC,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,wBAAwB,EAAE,OAAO,CAAA;KAAE,CAAC;CAMpE,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { apiClient } from '@endora-commerce/admin-kit/lib';
2
+ export const salesChannelsClient = {
3
+ list(options = {}) {
4
+ const qs = new URLSearchParams();
5
+ if (options.page !== undefined)
6
+ qs.set('page', String(options.page));
7
+ if (options.pageSize !== undefined)
8
+ qs.set('pageSize', String(options.pageSize));
9
+ if (options.activeOnly !== undefined)
10
+ qs.set('activeOnly', String(options.activeOnly));
11
+ const tail = qs.toString();
12
+ return apiClient.get(`/api/v1/admin/sales-channels${tail ? `?${tail}` : ''}`);
13
+ },
14
+ getByCode(code) {
15
+ return apiClient.get(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}`);
16
+ },
17
+ create(body) {
18
+ return apiClient.post('/api/v1/admin/sales-channels', body);
19
+ },
20
+ update(code, body) {
21
+ return apiClient.patch(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}`, body);
22
+ },
23
+ deactivate(code) {
24
+ return apiClient.post(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/deactivate`, {});
25
+ },
26
+ activate(code) {
27
+ return apiClient.post(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/activate`, {});
28
+ },
29
+ /**
30
+ * Move the system-default flag to this channel (D-51). Promoting the channel
31
+ * that already holds it answers 200 with `changed: false`, so a double click
32
+ * is not an error; an inactive channel is refused with 422
33
+ * `INACTIVE_SALES_CHANNEL`.
34
+ */
35
+ setDefault(code) {
36
+ return apiClient.post(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/set-default`, {});
37
+ },
38
+ delete(code, options = {}) {
39
+ const qs = options.fallbackToDefault
40
+ ? `?fallbackToDefault=true`
41
+ : '';
42
+ return apiClient.delete(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}${qs}`);
43
+ },
44
+ // -- Membership routes (Phase 5b) ---------------------------------------
45
+ /** List entity ids of `entityType` that belong to `code`. */
46
+ listEntitiesInChannel(code, entityType, options = {}) {
47
+ const qs = new URLSearchParams();
48
+ if (options.page !== undefined)
49
+ qs.set('page', String(options.page));
50
+ if (options.pageSize !== undefined)
51
+ qs.set('pageSize', String(options.pageSize));
52
+ const tail = qs.toString();
53
+ return apiClient.get(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/${entityType}${tail ? `?${tail}` : ''}`);
54
+ },
55
+ /** List the channels an entity belongs to. */
56
+ listChannelsForEntity(entityType, entityId) {
57
+ return apiClient.get(`/api/v1/admin/sales-channels/by-entity/${entityType}/${encodeURIComponent(entityId)}`);
58
+ },
59
+ /** Idempotent — re-adding an existing membership returns `changed: false`. */
60
+ addEntityToChannel(code, entityType, entityId) {
61
+ return apiClient.put(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/${entityType}/${encodeURIComponent(entityId)}`, {});
62
+ },
63
+ /**
64
+ * Remove a membership. With `fallbackToDefault=false` (default), removing
65
+ * the entity's last channel returns 422 ENTITY_WOULD_HAVE_ZERO_CHANNELS;
66
+ * with `true`, the entity is rebound to the system default in one
67
+ * transaction.
68
+ */
69
+ removeEntityFromChannel(code, entityType, entityId, options = {}) {
70
+ const qs = options.fallbackToDefault ? `?fallbackToDefault=true` : '';
71
+ return apiClient.delete(`/api/v1/admin/sales-channels/${encodeURIComponent(code)}/${entityType}/${encodeURIComponent(entityId)}${qs}`);
72
+ },
73
+ };
74
+ //# sourceMappingURL=sales-channels-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sales-channels-client.js","sourceRoot":"","sources":["../../../src/admin/api/sales-channels-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type SalesChannelDetail } from '@endora-commerce/contracts';
3
+ export interface ChannelIdentityFormValue {
4
+ code: string;
5
+ name: string;
6
+ themeCode: string;
7
+ languages: string[];
8
+ defaultLanguage: string;
9
+ currencies: string[];
10
+ defaultCurrency: string;
11
+ active: boolean;
12
+ }
13
+ export interface ChannelIdentityFormProps {
14
+ mode: 'create' | 'edit';
15
+ initial?: SalesChannelDetail | null;
16
+ /** When true, the code field is read-only (renames possible later via a dedicated dialog). */
17
+ lockCode?: boolean;
18
+ errorMessage?: string | null;
19
+ saving?: boolean;
20
+ onSubmit: (value: ChannelIdentityFormValue) => void;
21
+ onCancel?: () => void;
22
+ }
23
+ export declare function ChannelIdentityForm({ mode, initial, lockCode, errorMessage, saving, onSubmit, onCancel, }: ChannelIdentityFormProps): ReactNode;
24
+ //# sourceMappingURL=ChannelIdentityForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChannelIdentityForm.d.ts","sourceRoot":"","sources":["../../../src/admin/components/ChannelIdentityForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,4BAA4B,CAAC;AAkCpC,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAOD,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAgB,EAChB,YAAY,EACZ,MAAc,EACd,QAAQ,EACR,QAAQ,GACT,EAAE,wBAAwB,GAAG,SAAS,CA+QtC"}
@@ -0,0 +1,147 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useState, } from 'react';
3
+ import {} from '@endora-commerce/contracts';
4
+ import { apiClient } from '@endora-commerce/admin-kit/lib';
5
+ import { Alert, AlertDescription, Button, Card, CardContent, CardHeader, CardTitle, Checkbox, Input, Label, Select } from '@endora-commerce/admin-kit/ui';
6
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
7
+ /**
8
+ * ChannelIdentityForm — feature 005 / T040.
9
+ *
10
+ * Captures the identity surface of a Sales Channel for both the create
11
+ * page and the edit page. Language and currency scopes are selected from
12
+ * Dictionary entries and submitted as the existing contract arrays.
13
+ *
14
+ * The i18n display name is captured as a single `en-US` string for
15
+ * v1 (matches the test-server seed). A multi-locale editor lands as
16
+ * a follow-up — the contract already supports the wider shape.
17
+ */
18
+ /**
19
+ * List dictionary entries (feature 091, P6).
20
+ *
21
+ * The requests are built here rather than through `dictionaries`' own admin
22
+ * API client: that client is another module's **code**, which is what the
23
+ * cross-module ledger recorded, while `/api/v1/admin/dictionary/*` and the
24
+ * `Dictionary*PageResponse` types are an HTTP path and
25
+ * `@endora-commerce/contracts` types that both sides already compile. That is
26
+ * the exit P2 established and `admin-kit-surface.md` R6 records.
27
+ */
28
+ function listDictionary(entry, pageSize) {
29
+ const qs = new URLSearchParams();
30
+ qs.set('pageSize', String(pageSize));
31
+ qs.set('sort', 'sortOrder');
32
+ return apiClient.get(`/api/v1/admin/dictionary/${entry}?${qs.toString()}`);
33
+ }
34
+ function pickEnglishName(name) {
35
+ if (!name)
36
+ return '';
37
+ return name['en-US'] ?? name['en'] ?? Object.values(name)[0] ?? '';
38
+ }
39
+ export function ChannelIdentityForm({ mode, initial, lockCode = false, errorMessage, saving = false, onSubmit, onCancel, }) {
40
+ const t = useTranslation('sales_channels');
41
+ const [code, setCode] = useState(initial?.code ?? '');
42
+ const [name, setName] = useState(pickEnglishName(initial?.name));
43
+ const [themeCode, setThemeCode] = useState(initial?.themeCode ?? '');
44
+ const [languages, setLanguages] = useState(initial?.languages ?? ['en-US']);
45
+ const [defaultLanguage, setDefaultLanguage] = useState(initial?.defaultLanguage ?? 'en-US');
46
+ const [currencies, setCurrencies] = useState(initial?.currencies ?? ['PLN']);
47
+ const [defaultCurrency, setDefaultCurrency] = useState(initial?.defaultCurrency ?? 'PLN');
48
+ const [active, setActive] = useState(initial?.active ?? true);
49
+ const [dictionaryLanguages, setDictionaryLanguages] = useState([]);
50
+ const [dictionaryCurrencies, setDictionaryCurrencies] = useState([]);
51
+ // Re-seed when the underlying entity changes (typical on first GET response after mount).
52
+ useEffect(() => {
53
+ if (!initial)
54
+ return;
55
+ setCode(initial.code);
56
+ setName(pickEnglishName(initial.name));
57
+ setThemeCode(initial.themeCode ?? '');
58
+ setLanguages(initial.languages);
59
+ setDefaultLanguage(initial.defaultLanguage);
60
+ setCurrencies(initial.currencies);
61
+ setDefaultCurrency(initial.defaultCurrency);
62
+ setActive(initial.active);
63
+ }, [initial]);
64
+ useEffect(() => {
65
+ let cancelled = false;
66
+ void Promise.all([
67
+ listDictionary('languages', 250),
68
+ listDictionary('currencies', 250),
69
+ ])
70
+ .then(([languagePage, currencyPage]) => {
71
+ if (cancelled)
72
+ return;
73
+ setDictionaryLanguages(languagePage.data);
74
+ setDictionaryCurrencies(currencyPage.data);
75
+ })
76
+ .catch(() => {
77
+ if (cancelled)
78
+ return;
79
+ setDictionaryLanguages([]);
80
+ setDictionaryCurrencies([]);
81
+ });
82
+ return () => {
83
+ cancelled = true;
84
+ };
85
+ }, []);
86
+ useEffect(() => {
87
+ if (languages.length > 0 && !languages.includes(defaultLanguage)) {
88
+ setDefaultLanguage(languages[0] ?? '');
89
+ }
90
+ }, [defaultLanguage, languages]);
91
+ useEffect(() => {
92
+ if (currencies.length > 0 && !currencies.includes(defaultCurrency)) {
93
+ setDefaultCurrency(currencies[0] ?? '');
94
+ }
95
+ }, [currencies, defaultCurrency]);
96
+ const languageRows = useMemo(() => mergeSelectedDictionaryRows(dictionaryLanguages, languages), [dictionaryLanguages, languages]);
97
+ const currencyRows = useMemo(() => mergeSelectedDictionaryRows(dictionaryCurrencies, currencies), [dictionaryCurrencies, currencies]);
98
+ const toggleLanguage = (language) => {
99
+ setLanguages((prev) => prev.includes(language) ? prev.filter((code) => code !== language) : [...prev, language]);
100
+ };
101
+ const toggleCurrency = (currency) => {
102
+ setCurrencies((prev) => prev.includes(currency) ? prev.filter((code) => code !== currency) : [...prev, currency]);
103
+ };
104
+ const handleSubmit = useCallback((e) => {
105
+ e.preventDefault();
106
+ onSubmit({
107
+ code: code.trim(),
108
+ name: name.trim(),
109
+ themeCode: themeCode.trim(),
110
+ languages,
111
+ defaultLanguage: defaultLanguage.trim(),
112
+ currencies,
113
+ defaultCurrency: defaultCurrency.trim(),
114
+ active,
115
+ });
116
+ }, [
117
+ onSubmit,
118
+ code,
119
+ name,
120
+ themeCode,
121
+ languages,
122
+ defaultLanguage,
123
+ currencies,
124
+ defaultCurrency,
125
+ active,
126
+ ]);
127
+ const cannotSubmit = saving || languages.length === 0 || currencies.length === 0;
128
+ return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: mode === 'create' ? t('identity.title.create') : t('identity.title.edit') }) }), _jsxs(CardContent, { children: [errorMessage && (_jsx(Alert, { variant: "destructive", className: "mb-4", children: _jsx(AlertDescription, { children: errorMessage }) })), _jsxs("form", { className: "grid gap-4", onSubmit: handleSubmit, children: [_jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-code", children: t('identity.code.label') }), _jsx(Input, { id: "sc-code", value: code, onChange: (e) => setCode(e.target.value), placeholder: "serwis-a", disabled: lockCode, required: true }), lockCode && (_jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.code.lockedHelp') }))] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-name", children: t('identity.name.label') }), _jsx(Input, { id: "sc-name", value: name, onChange: (e) => setName(e.target.value), placeholder: t('identity.name.placeholder'), required: true })] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-theme", children: t('identity.theme.label') }), _jsx(Input, { id: "sc-theme", value: themeCode, onChange: (e) => setThemeCode(e.target.value), placeholder: t('identity.theme.placeholder'), pattern: "[a-z][a-z0-9_-]*", title: t('identity.theme.pattern') }), _jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.theme.help') })] }), _jsxs("div", { className: "grid gap-2 md:grid-cols-[2fr_1fr]", children: [_jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { children: t('identity.languages.label') }), _jsx(DictionaryCheckboxList, { rows: languageRows, selected: languages, onToggle: toggleLanguage }), _jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.languages.help') })] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-default-lang", children: t('identity.defaultLanguage.label') }), _jsxs(Select, { id: "sc-default-lang", value: defaultLanguage, onChange: (e) => setDefaultLanguage(e.target.value), children: [_jsx("option", { value: "", disabled: true, children: t('identity.pickOption') }), languages.map((lang) => (_jsx("option", { value: lang, children: lang }, lang)))] })] })] }), _jsxs("div", { className: "grid gap-2 md:grid-cols-[2fr_1fr]", children: [_jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { children: t('identity.currencies.label') }), _jsx(DictionaryCheckboxList, { rows: currencyRows, selected: currencies, onToggle: toggleCurrency }), _jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.currencies.help') })] }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "sc-default-curr", children: t('identity.defaultCurrency.label') }), _jsxs(Select, { id: "sc-default-curr", value: defaultCurrency, onChange: (e) => setDefaultCurrency(e.target.value), children: [_jsx("option", { value: "", disabled: true, children: t('identity.pickOption') }), currencies.map((curr) => (_jsx("option", { value: curr, children: curr }, curr)))] })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "sc-active", checked: active, onChange: (e) => setActive(e.target.checked), disabled: initial?.systemDefault === true }), _jsx(Label, { htmlFor: "sc-active", className: "cursor-pointer", children: t('identity.active') }), initial?.systemDefault && (_jsx("span", { className: "text-xs text-muted-foreground", children: t('identity.cannotDeactivateDefault') }))] }), _jsxs("div", { className: "flex justify-end gap-2", children: [onCancel && (_jsx(Button, { type: "button", variant: "ghost", onClick: onCancel, disabled: saving, children: t('identity.action.cancel') })), _jsx(Button, { type: "submit", disabled: cannotSubmit, children: mode === 'create' ? t('identity.action.create') : t('identity.action.save') })] })] })] })] }));
129
+ }
130
+ function mergeSelectedDictionaryRows(rows, selected) {
131
+ const byCode = new Map(rows.map((row) => [row.code, row]));
132
+ const merged = [...rows];
133
+ for (const code of selected) {
134
+ if (!byCode.has(code)) {
135
+ merged.push({ code, label: code, isActive: false });
136
+ }
137
+ }
138
+ return merged;
139
+ }
140
+ function DictionaryCheckboxList({ rows, selected, onToggle, }) {
141
+ const t = useTranslation('sales_channels');
142
+ const activeRows = rows.filter((row) => row.isActive);
143
+ const inactiveSelected = rows.filter((row) => !row.isActive && selected.includes(row.code));
144
+ const visibleRows = [...activeRows, ...inactiveSelected];
145
+ return (_jsxs("div", { className: "max-h-48 overflow-auto rounded-md border p-3", children: [visibleRows.map((row) => (_jsxs("label", { className: "flex items-center gap-2 py-1 text-sm", children: [_jsx(Checkbox, { checked: selected.includes(row.code), onChange: () => onToggle(row.code) }), _jsx("span", { className: "font-mono text-xs", children: row.code }), _jsx("span", { children: row.label }), !row.isActive ? (_jsx("span", { className: "text-xs text-muted-foreground", children: t('identity.dictionary.inactive') })) : null] }, row.code))), visibleRows.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground", children: t('identity.dictionary.empty') })) : null] }));
146
+ }
147
+ //# sourceMappingURL=ChannelIdentityForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChannelIdentityForm.js","sourceRoot":"","sources":["../../../src/admin/components/ChannelIdentityForm.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,WAAW,EACX,SAAS,EACT,OAAO,EACP,QAAQ,GAGT,MAAM,OAAO,CAAC;AACf,OAAO,EAMN,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAC1J,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;;;;;;;;GAUG;AAEH;;;;;;;;;GASG;AACH,SAAS,cAAc,CAAI,KAAiC,EAAE,QAAgB;IAC5E,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;IACjC,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrC,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5B,OAAO,SAAS,CAAC,GAAG,CAAI,4BAA4B,KAAK,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAwBD,SAAS,eAAe,CAAC,IAAwC;IAC/D,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,GAAG,KAAK,EAChB,YAAY,EACZ,MAAM,GAAG,KAAK,EACd,QAAQ,EACR,QAAQ,GACiB;IACzB,MAAM,CAAC,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAC3C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IACjE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAW,OAAO,EAAE,SAAS,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACtF,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CACpD,OAAO,EAAE,eAAe,IAAI,OAAO,CACpC,CAAC;IACF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAW,OAAO,EAAE,UAAU,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACvF,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CACpD,OAAO,EAAE,eAAe,IAAI,KAAK,CAClC,CAAC;IACF,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAAuB,EAAE,CAAC,CAAC;IACzF,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GAAG,QAAQ,CAAuB,EAAE,CAAC,CAAC;IAE3F,0FAA0F;IAC1F,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACvC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACtC,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,kBAAkB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC5C,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAClC,kBAAkB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC5C,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,KAAK,OAAO,CAAC,GAAG,CAAC;YACf,cAAc,CAAkC,WAAW,EAAE,GAAG,CAAC;YACjE,cAAc,CAAmC,YAAY,EAAE,GAAG,CAAC;SACpE,CAAC;aACC,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,EAAE;YACrC,IAAI,SAAS;gBAAE,OAAO;YACtB,sBAAsB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAC1C,uBAAuB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,SAAS;gBAAE,OAAO;YACtB,sBAAsB,CAAC,EAAE,CAAC,CAAC;YAC3B,uBAAuB,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YACjE,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;IAEjC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YACnE,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;IAElC,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,2BAA2B,CAAC,mBAAmB,EAAE,SAAS,CAAC,EACjE,CAAC,mBAAmB,EAAE,SAAS,CAAC,CACjC,CAAC;IACF,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,2BAA2B,CAAC,oBAAoB,EAAE,UAAU,CAAC,EACnE,CAAC,oBAAoB,EAAE,UAAU,CAAC,CACnC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAQ,EAAE;QAChD,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CACpB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,CACzF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAQ,EAAE;QAChD,aAAa,CAAC,CAAC,IAAI,EAAE,EAAE,CACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,CACzF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,CAAY,EAAQ,EAAE;QACrB,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,QAAQ,CAAC;YACP,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;YACjB,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE;YAC3B,SAAS;YACT,eAAe,EAAE,eAAe,CAAC,IAAI,EAAE;YACvC,UAAU;YACV,eAAe,EAAE,eAAe,CAAC,IAAI,EAAE;YACvC,MAAM;SACP,CAAC,CAAC;IACL,CAAC,EACD;QACE,QAAQ;QACR,IAAI;QACJ,IAAI;QACJ,SAAS;QACT,SAAS;QACT,eAAe;QACf,UAAU;QACV,eAAe;QACf,MAAM;KACP,CACF,CAAC;IAEF,MAAM,YAAY,GAAG,MAAM,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;IAEjF,OAAO,CACL,MAAC,IAAI,eACH,KAAC,UAAU,cACT,KAAC,SAAS,IAAC,SAAS,EAAC,WAAW,YAC7B,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,GAChE,GACD,EACb,MAAC,WAAW,eACT,YAAY,IAAI,CACf,KAAC,KAAK,IAAC,OAAO,EAAC,aAAa,EAAC,SAAS,EAAC,MAAM,YAC3C,KAAC,gBAAgB,cAAE,YAAY,GAAoB,GAC7C,CACT,EACD,gBAAM,SAAS,EAAC,YAAY,EAAC,QAAQ,EAAE,YAAY,aACjD,eAAK,SAAS,EAAC,YAAY,aACzB,KAAC,KAAK,IAAC,OAAO,EAAC,SAAS,YAAE,CAAC,CAAC,qBAAqB,CAAC,GAAS,EAC3D,KAAC,KAAK,IACJ,EAAE,EAAC,SAAS,EACZ,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACxC,WAAW,EAAC,UAAU,EACtB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,SACR,EACD,QAAQ,IAAI,CACX,YAAG,SAAS,EAAC,+BAA+B,YAAE,CAAC,CAAC,0BAA0B,CAAC,GAAK,CACjF,IACG,EAEN,eAAK,SAAS,EAAC,YAAY,aACzB,KAAC,KAAK,IAAC,OAAO,EAAC,SAAS,YAAE,CAAC,CAAC,qBAAqB,CAAC,GAAS,EAC3D,KAAC,KAAK,IACJ,EAAE,EAAC,SAAS,EACZ,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACxC,WAAW,EAAE,CAAC,CAAC,2BAA2B,CAAC,EAC3C,QAAQ,SACR,IACE,EAkBN,eAAK,SAAS,EAAC,YAAY,aACzB,KAAC,KAAK,IAAC,OAAO,EAAC,UAAU,YAAE,CAAC,CAAC,sBAAsB,CAAC,GAAS,EAC7D,KAAC,KAAK,IACJ,EAAE,EAAC,UAAU,EACb,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC7C,WAAW,EAAE,CAAC,CAAC,4BAA4B,CAAC,EAC5C,OAAO,EAAC,kBAAkB,EAC1B,KAAK,EAAE,CAAC,CAAC,wBAAwB,CAAC,GAClC,EACF,YAAG,SAAS,EAAC,+BAA+B,YAAE,CAAC,CAAC,qBAAqB,CAAC,GAAK,IACvE,EAEN,eAAK,SAAS,EAAC,mCAAmC,aAChD,eAAK,SAAS,EAAC,YAAY,aACzB,KAAC,KAAK,cAAE,CAAC,CAAC,0BAA0B,CAAC,GAAS,EAC9C,KAAC,sBAAsB,IACrB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,SAAS,EACnB,QAAQ,EAAE,cAAc,GACxB,EACF,YAAG,SAAS,EAAC,+BAA+B,YAAE,CAAC,CAAC,yBAAyB,CAAC,GAAK,IAC3E,EACN,eAAK,SAAS,EAAC,YAAY,aACzB,KAAC,KAAK,IAAC,OAAO,EAAC,iBAAiB,YAAE,CAAC,CAAC,gCAAgC,CAAC,GAAS,EAC9E,MAAC,MAAM,IACL,EAAE,EAAC,iBAAiB,EACpB,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAEnD,iBAAQ,KAAK,EAAC,EAAE,EAAC,QAAQ,kBACtB,CAAC,CAAC,qBAAqB,CAAC,GAClB,EACR,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACvB,iBAAmB,KAAK,EAAE,IAAI,YAC3B,IAAI,IADM,IAAI,CAER,CACV,CAAC,IACK,IACL,IACF,EAEN,eAAK,SAAS,EAAC,mCAAmC,aAChD,eAAK,SAAS,EAAC,YAAY,aACzB,KAAC,KAAK,cAAE,CAAC,CAAC,2BAA2B,CAAC,GAAS,EAC/C,KAAC,sBAAsB,IACrB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,cAAc,GACxB,EACF,YAAG,SAAS,EAAC,+BAA+B,YAAE,CAAC,CAAC,0BAA0B,CAAC,GAAK,IAC5E,EACN,eAAK,SAAS,EAAC,YAAY,aACzB,KAAC,KAAK,IAAC,OAAO,EAAC,iBAAiB,YAAE,CAAC,CAAC,gCAAgC,CAAC,GAAS,EAC9E,MAAC,MAAM,IACL,EAAE,EAAC,iBAAiB,EACpB,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAEnD,iBAAQ,KAAK,EAAC,EAAE,EAAC,QAAQ,kBACtB,CAAC,CAAC,qBAAqB,CAAC,GAClB,EACR,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACxB,iBAAmB,KAAK,EAAE,IAAI,YAC3B,IAAI,IADM,IAAI,CAER,CACV,CAAC,IACK,IACL,IACF,EAEN,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,QAAQ,IACP,EAAE,EAAC,WAAW,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAC5C,QAAQ,EAAE,OAAO,EAAE,aAAa,KAAK,IAAI,GACzC,EACF,KAAC,KAAK,IAAC,OAAO,EAAC,WAAW,EAAC,SAAS,EAAC,gBAAgB,YAClD,CAAC,CAAC,iBAAiB,CAAC,GACf,EACP,OAAO,EAAE,aAAa,IAAI,CACzB,eAAM,SAAS,EAAC,+BAA+B,YAC5C,CAAC,CAAC,kCAAkC,CAAC,GACjC,CACR,IACG,EAEN,eAAK,SAAS,EAAC,wBAAwB,aACpC,QAAQ,IAAI,CACX,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YACtE,CAAC,CAAC,wBAAwB,CAAC,GACrB,CACV,EACD,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,YAAY,YACzC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,GACrE,IACL,IACD,IACK,IACT,CACR,CAAC;AACJ,CAAC;AAQD,SAAS,2BAA2B,CAA0B,IAAS,EAAE,QAAkB;IACzF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAO,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,sBAAsB,CAAC,EAC9B,IAAI,EACJ,QAAQ,EACR,QAAQ,GAKT;IACC,MAAM,CAAC,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5F,MAAM,WAAW,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,gBAAgB,CAAC,CAAC;IAEzD,OAAO,CACL,eAAK,SAAS,EAAC,8CAA8C,aAC1D,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACxB,iBAAsB,SAAS,EAAC,sCAAsC,aACpE,KAAC,QAAQ,IACP,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EACpC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAClC,EACF,eAAM,SAAS,EAAC,mBAAmB,YAAE,GAAG,CAAC,IAAI,GAAQ,EACrD,yBAAO,GAAG,CAAC,KAAK,GAAQ,EACvB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CACf,eAAM,SAAS,EAAC,+BAA+B,YAAE,CAAC,CAAC,8BAA8B,CAAC,GAAQ,CAC3F,CAAC,CAAC,CAAC,IAAI,KATE,GAAG,CAAC,IAAI,CAUZ,CACT,CAAC,EACD,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC1B,YAAG,SAAS,EAAC,+BAA+B,YAAE,CAAC,CAAC,2BAA2B,CAAC,GAAK,CAClF,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from 'react';
2
+ /**
3
+ * Read-only marker for the system-default Sales Channel (feature 005 / T039).
4
+ *
5
+ * The channel is identified by `systemDefault === true` (FR-002); this renders
6
+ * the visual and nothing else.
7
+ *
8
+ * **There is one copy, and this is it.** A second stood at
9
+ * `admin/src/modules/sales_channels/components/` for the length of P7a, serving
10
+ * this module's own two screens; batch 14 moved both screens into this package,
11
+ * they import this file, and the other one is deleted — which is what the note
12
+ * that stood here said would happen. `EntityChannelMembership` beside it went
13
+ * the same way one merge request earlier.
14
+ * `admin/test/modules/sales_channels/organization-channels-zone.test.tsx`
15
+ * asserts that no file remains at the old path, because nothing in this estate
16
+ * compares two copies of one component.
17
+ */
18
+ export declare function DefaultChannelBadge({ systemDefault, }: {
19
+ systemDefault: boolean;
20
+ }): ReactNode;
21
+ //# sourceMappingURL=DefaultChannelBadge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultChannelBadge.d.ts","sourceRoot":"","sources":["../../../src/admin/components/DefaultChannelBadge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,aAAa,GACd,EAAE;IACD,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,SAAS,CAQZ"}
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Badge } from '@endora-commerce/admin-kit/ui';
3
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
4
+ /**
5
+ * Read-only marker for the system-default Sales Channel (feature 005 / T039).
6
+ *
7
+ * The channel is identified by `systemDefault === true` (FR-002); this renders
8
+ * the visual and nothing else.
9
+ *
10
+ * **There is one copy, and this is it.** A second stood at
11
+ * `admin/src/modules/sales_channels/components/` for the length of P7a, serving
12
+ * this module's own two screens; batch 14 moved both screens into this package,
13
+ * they import this file, and the other one is deleted — which is what the note
14
+ * that stood here said would happen. `EntityChannelMembership` beside it went
15
+ * the same way one merge request earlier.
16
+ * `admin/test/modules/sales_channels/organization-channels-zone.test.tsx`
17
+ * asserts that no file remains at the old path, because nothing in this estate
18
+ * compares two copies of one component.
19
+ */
20
+ export function DefaultChannelBadge({ systemDefault, }) {
21
+ const t = useTranslation('sales_channels');
22
+ if (!systemDefault)
23
+ return null;
24
+ return (_jsx(Badge, { variant: "secondary", className: "ml-2 text-[10px] uppercase tracking-wider", children: t('badge.systemDefault') }));
25
+ }
26
+ //# sourceMappingURL=DefaultChannelBadge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultChannelBadge.js","sourceRoot":"","sources":["../../../src/admin/components/DefaultChannelBadge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,aAAa,GAGd;IACC,MAAM,CAAC,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAC3C,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,CACL,KAAC,KAAK,IAAC,OAAO,EAAC,WAAW,EAAC,SAAS,EAAC,2CAA2C,YAC7E,CAAC,CAAC,qBAAqB,CAAC,GACnB,CACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { ChannelMemberEntityType } from '@endora-commerce/contracts';
3
+ /**
4
+ * The channels an entity belongs to, editable from the entity's own editor
5
+ * (feature 005 / T065).
6
+ *
7
+ * Loads the entity's current channels and the platform's full channel list in
8
+ * parallel on mount. The Add control offers only channels the entity is not
9
+ * already in; Remove tries `fallbackToDefault: false` first and, on
10
+ * `ENTITY_WOULD_HAVE_ZERO_CHANNELS`, asks the operator whether to rebind to the
11
+ * system default. The mutation goes through the centralised
12
+ * `/api/v1/admin/sales-channels/:code/:entityType/:entityId` routes, so an
13
+ * entity editor never needs membership endpoints of its own.
14
+ *
15
+ * ## Why the calls are rebuilt rather than the client moved (feature 091, P7a)
16
+ *
17
+ * `catalog`'s product editor imported this file by path — one of the three
18
+ * admin keys in `backend/scripts/ledgers/cross-module-imports/catalog.ts`. It
19
+ * lives in this module's package now and reaches that screen as a
20
+ * `product.editor.channels` contribution. Its four reads and writes are HTTP
21
+ * paths whose payload types are already `@endora-commerce/contracts`', so they
22
+ * are rebuilt from the published `apiClient` here (P2's exit) rather than
23
+ * dragging that module's admin API client along, which at the time would have
24
+ * been a package reaching back into the admin application. Batch 14 moved the
25
+ * client into this package as `../api/sales-channels-client.ts`; this file goes
26
+ * on building its own requests, because a zone contribution rendered inside
27
+ * another module's screen has no business carrying a client whose only other
28
+ * readers are two screens it never renders with.
29
+ *
30
+ * **P7b deleted the copy.** One stood at
31
+ * `admin/src/modules/sales_channels/components/` for the length of P7a, serving
32
+ * `organizations`' detail screen; that screen is a zone mount now, nothing
33
+ * imported the file, and it is gone. Nothing in this estate compares two copies
34
+ * of one component, so the retiring condition was written here rather than left
35
+ * to be remembered.
36
+ *
37
+ * `DefaultChannelBadge` beside it is the other half of that copy and **went
38
+ * the same way in batch 14**, which is what the note that stood here said would
39
+ * happen: this module's own two screens moved into this package, they import the
40
+ * sibling file, and the `admin/src` copy is deleted.
41
+ *
42
+ * The `entityId` guard below is unreachable under a zone — all three mounts
43
+ * have an id before they mount — and stays as the component's own contract.
44
+ */
45
+ export interface EntityChannelMembershipProps {
46
+ entityType: ChannelMemberEntityType;
47
+ entityId: string | null | undefined;
48
+ /** When set, called after every successful add / remove / fallback so the parent can refetch. */
49
+ onChanged?: () => void;
50
+ }
51
+ export declare function EntityChannelMembership({ entityType, entityId, onChanged, }: EntityChannelMembershipProps): ReactNode;
52
+ //# sourceMappingURL=EntityChannelMembership.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityChannelMembership.d.ts","sourceRoot":"","sources":["../../../src/admin/components/EntityChannelMembership.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,KAAK,EACV,uBAAuB,EAGxB,MAAM,4BAA4B,CAAC;AAgBpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,uBAAuB,CAAC;IACpC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAUD,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACV,QAAQ,EACR,SAAS,GACV,EAAE,4BAA4B,GAAG,SAAS,CAgL1C"}