@fayz-ai/plugin-shop 0.2.5 → 0.8.1

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 (55) hide show
  1. package/dist/ShopPage-HCLXMN7Q.js +743 -0
  2. package/dist/ShopPage-HCLXMN7Q.js.map +1 -0
  3. package/dist/ShopPage-JF2SQBKO.cjs +745 -0
  4. package/dist/ShopPage-JF2SQBKO.cjs.map +1 -0
  5. package/dist/ShopPage.d.ts +23 -1
  6. package/dist/ShopPage.d.ts.map +1 -1
  7. package/dist/data/customerDataProvider.d.ts +5 -0
  8. package/dist/data/customerDataProvider.d.ts.map +1 -0
  9. package/dist/data/discountDataProvider.d.ts +5 -0
  10. package/dist/data/discountDataProvider.d.ts.map +1 -0
  11. package/dist/data/productDataProvider.d.ts +6 -0
  12. package/dist/data/productDataProvider.d.ts.map +1 -0
  13. package/dist/data/shared.d.ts +12 -0
  14. package/dist/data/shared.d.ts.map +1 -0
  15. package/dist/data/shippingZoneDataProvider.d.ts +13 -0
  16. package/dist/data/shippingZoneDataProvider.d.ts.map +1 -0
  17. package/dist/index.cjs +986 -26
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +987 -27
  22. package/dist/index.js.map +1 -1
  23. package/dist/views/OrderDetailView.d.ts +10 -0
  24. package/dist/views/OrderDetailView.d.ts.map +1 -0
  25. package/dist/views/ProductImagesTab.d.ts +19 -0
  26. package/dist/views/ProductImagesTab.d.ts.map +1 -0
  27. package/dist/views/customerEntity.d.ts +4 -0
  28. package/dist/views/customerEntity.d.ts.map +1 -0
  29. package/dist/views/customerLookup.d.ts +22 -0
  30. package/dist/views/customerLookup.d.ts.map +1 -0
  31. package/dist/views/discountEntity.d.ts +4 -0
  32. package/dist/views/discountEntity.d.ts.map +1 -0
  33. package/dist/views/productEntity.d.ts +6 -0
  34. package/dist/views/productEntity.d.ts.map +1 -0
  35. package/dist/views/shippingZoneEntity.d.ts +4 -0
  36. package/dist/views/shippingZoneEntity.d.ts.map +1 -0
  37. package/package.json +8 -5
  38. package/src/ShopPage.tsx +156 -54
  39. package/src/data/customerDataProvider.ts +31 -0
  40. package/src/data/discountDataProvider.ts +42 -0
  41. package/src/data/productDataProvider.ts +54 -0
  42. package/src/data/shared.ts +42 -0
  43. package/src/data/shippingZoneDataProvider.ts +49 -0
  44. package/src/index.ts +104 -12
  45. package/src/views/OrderDetailView.tsx +575 -0
  46. package/src/views/ProductImagesTab.tsx +183 -0
  47. package/src/views/customerEntity.tsx +110 -0
  48. package/src/views/customerLookup.ts +31 -0
  49. package/src/views/discountEntity.tsx +137 -0
  50. package/src/views/productEntity.tsx +229 -0
  51. package/src/views/shippingZoneEntity.tsx +123 -0
  52. package/dist/ShopPage-65PPVKBD.js +0 -271
  53. package/dist/ShopPage-65PPVKBD.js.map +0 -1
  54. package/dist/ShopPage-PG5GKOZU.cjs +0 -273
  55. package/dist/ShopPage-PG5GKOZU.cjs.map +0 -1
package/src/index.ts CHANGED
@@ -1,7 +1,15 @@
1
1
  import React from 'react'
2
2
  import type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'
3
- import { setShopTenantResolver } from '@fayz-ai/shop'
4
- import { useOrganizationStore } from '@fayz-ai/saas'
3
+ import { setShopTenantResolver, getShopProvider } from '@fayz-ai/shop'
4
+ import { useOrganizationStore, createCrudPage, registerEntityPath } from '@fayz-ai/saas'
5
+ import { buildShopProductEntity } from './views/productEntity'
6
+ import { buildShopCustomerEntity } from './views/customerEntity'
7
+ import { buildShopDiscountEntity } from './views/discountEntity'
8
+ import { buildShopShippingZoneEntity } from './views/shippingZoneEntity'
9
+ import { createShopProductDataProvider } from './data/productDataProvider'
10
+ import { createShopCustomerDataProvider } from './data/customerDataProvider'
11
+ import { createShopDiscountDataProvider } from './data/discountDataProvider'
12
+ import { createShopShippingZoneDataProvider } from './data/shippingZoneDataProvider'
5
13
  import type { ShopProviderResolver } from './ShopPage'
6
14
  import { ShopSettings } from './components/ShopSettings'
7
15
 
@@ -15,6 +23,8 @@ export interface ShopPluginOptions {
15
23
  navPosition?: number
16
24
  navSection?: 'main' | 'secondary' | 'settings'
17
25
  navLabel?: string
26
+ /** Override the accordion child labels (Produtos / Pedidos / Clientes / Descontos). */
27
+ sectionLabels?: Partial<Record<'products' | 'orders' | 'customers' | 'discounts' | 'shipping', string>>
18
28
  scope?: PluginScope
19
29
  verticalId?: VerticalId
20
30
  currency?: { code?: string; locale?: string; symbol?: string }
@@ -32,13 +42,76 @@ export function createShopPlugin(options?: ShopPluginOptions): PluginManifest {
32
42
  // provider when they want SDK-owned data access instead of the global runtime.
33
43
  setShopTenantResolver(() => useOrganizationStore.getState().currentOrg?.id)
34
44
 
35
- const PageComponent: React.ComponentType<unknown> = () =>
36
- React.createElement(React.Suspense, { fallback: null },
37
- React.createElement(ShopPage as React.ComponentType<{ provider?: ShopProviderResolver }>, {
38
- provider: options?.provider,
39
- })
40
- )
41
- PageComponent.displayName = 'ShopPageWrapper'
45
+ // Teach the shared person-path registry where a SHOP customer lives. The
46
+ // built-in map ships veterinary defaults (customer → /registry/tutors), so
47
+ // without this PersonLink would resolve a shop customer to the wrong module.
48
+ registerEntityPath('shop_customer', '/shop/customers')
49
+
50
+ type ShopSection = 'products' | 'orders' | 'customers' | 'discounts' | 'shipping'
51
+
52
+ // One component per section so each gets its own route. The shell nests any
53
+ // entry whose route is a sub-path of another (same rule the courses modules
54
+ // use), so /shop/products … /shop/discounts render as an accordion under
55
+ // "Loja" instead of one link with everything hidden behind tabs.
56
+ const pageFor = (section?: ShopSection): React.ComponentType<unknown> => {
57
+ const Wrapped: React.ComponentType<unknown> = () =>
58
+ React.createElement(React.Suspense, { fallback: null },
59
+ React.createElement(
60
+ ShopPage as React.ComponentType<{ provider?: ShopProviderResolver; section?: ShopSection }>,
61
+ { provider: options?.provider, section },
62
+ )
63
+ )
64
+ Wrapped.displayName = section ? `ShopPage:${section}` : 'ShopPageWrapper'
65
+ return Wrapped
66
+ }
67
+
68
+ // Products, customers and discounts all get the full generic CRUD (list +
69
+ // form + detail + delete) from their EntityDef, rather than three bespoke
70
+ // read-only tables. Orders stay on the custom page: an order is not a CRUD
71
+ // record — it needs fulfilment, refunds and a line-item view, which is its
72
+ // own screen.
73
+ const resolveProvider = () =>
74
+ typeof options?.provider === 'function'
75
+ ? options.provider()
76
+ : options?.provider ?? getShopProvider()
77
+
78
+ const ProductsCrudPage = createCrudPage(buildShopProductEntity(curr.code, resolveProvider), {
79
+ dataProvider: createShopProductDataProvider(resolveProvider),
80
+ feature: 'shop',
81
+ })
82
+
83
+ const CustomersCrudPage = createCrudPage(buildShopCustomerEntity(), {
84
+ dataProvider: createShopCustomerDataProvider(resolveProvider),
85
+ feature: 'shop',
86
+ })
87
+
88
+ const DiscountsCrudPage = createCrudPage(buildShopDiscountEntity(), {
89
+ dataProvider: createShopDiscountDataProvider(resolveProvider),
90
+ feature: 'shop',
91
+ })
92
+
93
+ const ShippingZonesCrudPage = createCrudPage(buildShopShippingZoneEntity(curr.code), {
94
+ dataProvider: createShopShippingZoneDataProvider(resolveProvider),
95
+ feature: 'shop',
96
+ })
97
+
98
+ const CRUD_PAGES: Partial<Record<ShopSection, React.ComponentType<unknown>>> = {
99
+ products: ProductsCrudPage as React.ComponentType<unknown>,
100
+ customers: CustomersCrudPage as React.ComponentType<unknown>,
101
+ discounts: DiscountsCrudPage as React.ComponentType<unknown>,
102
+ shipping: ShippingZonesCrudPage as React.ComponentType<unknown>,
103
+ }
104
+
105
+ const SECTIONS: Array<{ id: ShopSection; label: string; icon: string }> = [
106
+ { id: 'products', label: options?.sectionLabels?.products ?? 'Produtos', icon: 'Package' },
107
+ { id: 'orders', label: options?.sectionLabels?.orders ?? 'Pedidos', icon: 'ShoppingCart' },
108
+ { id: 'customers', label: options?.sectionLabels?.customers ?? 'Clientes', icon: 'Users' },
109
+ { id: 'discounts', label: options?.sectionLabels?.discounts ?? 'Descontos', icon: 'Tag' },
110
+ { id: 'shipping', label: options?.sectionLabels?.shipping ?? 'Entrega', icon: 'Truck' },
111
+ ]
112
+
113
+ const navSection = options?.navSection ?? 'main'
114
+ const navPosition = options?.navPosition ?? 6
42
115
 
43
116
  return {
44
117
  id: 'shop',
@@ -47,24 +120,43 @@ export function createShopPlugin(options?: ShopPluginOptions): PluginManifest {
47
120
  version: '1.0.0',
48
121
  scope: options?.scope ?? 'vertical',
49
122
  verticalId: options?.verticalId,
123
+ // Storefront/commerce-operator-console surface — targets the ecommerce
124
+ // Panel world, not a saas admin app.
125
+ scaffolds: ['ecommerce'],
50
126
  defaultEnabled: true,
51
127
  dependencies: [],
52
128
  navigation: [
53
129
  {
54
- section: options?.navSection ?? 'main',
55
- position: options?.navPosition ?? 6,
130
+ section: navSection,
131
+ position: navPosition,
56
132
  label: options?.navLabel ?? 'Shop',
57
133
  route: '/shop',
58
134
  icon: 'ShoppingBag',
59
135
  permission: { feature: 'shop', action: 'read' as const },
136
+ // "Loja" and "Produtos" are the same screen — don't list both.
137
+ indexChild: false,
60
138
  },
139
+ ...SECTIONS.map((s, i) => ({
140
+ section: navSection,
141
+ position: navPosition + i + 1,
142
+ label: s.label,
143
+ route: `/shop/${s.id}`,
144
+ icon: s.icon,
145
+ permission: { feature: 'shop', action: 'read' as const },
146
+ })),
61
147
  ],
62
148
  routes: [
63
149
  {
150
+ // Kept so existing links to /shop still resolve; renders the tabbed page.
64
151
  path: '/shop',
65
- component: PageComponent,
152
+ component: pageFor(),
66
153
  permission: { feature: 'shop', action: 'read' as const },
67
154
  },
155
+ ...SECTIONS.map((s) => ({
156
+ path: `/shop/${s.id}`,
157
+ component: CRUD_PAGES[s.id] ?? pageFor(s.id),
158
+ permission: { feature: 'shop', action: 'read' as const },
159
+ })),
68
160
  ],
69
161
  widgets: [],
70
162
  aiTools: [