@fayz-ai/plugin-shop 0.9.1 → 0.11.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 (124) hide show
  1. package/dist/ShopPage-YB5ZWECJ.js +2926 -0
  2. package/dist/ShopPage-YB5ZWECJ.js.map +1 -0
  3. package/dist/analytics/cards.d.ts +3 -0
  4. package/dist/analytics/cards.d.ts.map +1 -0
  5. package/dist/chunk-HAKXHHAG.js +882 -0
  6. package/dist/chunk-HAKXHHAG.js.map +1 -0
  7. package/dist/data/productDataProvider.d.ts.map +1 -1
  8. package/dist/data/registries.d.ts +53 -0
  9. package/dist/data/registries.d.ts.map +1 -0
  10. package/dist/data/registry-routes.d.ts +21 -0
  11. package/dist/data/registry-routes.d.ts.map +1 -0
  12. package/dist/data/shared.d.ts +12 -2
  13. package/dist/data/shared.d.ts.map +1 -1
  14. package/dist/data/shippingProfileDataProvider.d.ts +19 -0
  15. package/dist/data/shippingProfileDataProvider.d.ts.map +1 -0
  16. package/dist/data/stockLocationDataProvider.d.ts +13 -0
  17. package/dist/data/stockLocationDataProvider.d.ts.map +1 -0
  18. package/dist/index.d.ts +16 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +4650 -508
  21. package/dist/index.js.map +1 -1
  22. package/dist/integrations/abacatepay/connectorDef.d.ts +41 -0
  23. package/dist/integrations/abacatepay/connectorDef.d.ts.map +1 -0
  24. package/dist/integrations/appmax/connectorDef.d.ts +28 -0
  25. package/dist/integrations/appmax/connectorDef.d.ts.map +1 -0
  26. package/dist/integrations/bling/connectorDef.d.ts +10 -0
  27. package/dist/integrations/bling/connectorDef.d.ts.map +1 -0
  28. package/dist/integrations/bling/data.d.ts +61 -0
  29. package/dist/integrations/bling/data.d.ts.map +1 -0
  30. package/dist/integrations/bling/inbound.d.ts +97 -0
  31. package/dist/integrations/bling/inbound.d.ts.map +1 -0
  32. package/dist/integrations/bling/index.d.ts +9 -0
  33. package/dist/integrations/bling/index.d.ts.map +1 -0
  34. package/dist/integrations/bling/limits.d.ts +33 -0
  35. package/dist/integrations/bling/limits.d.ts.map +1 -0
  36. package/dist/integrations/bling/mapping.d.ts +10 -0
  37. package/dist/integrations/bling/mapping.d.ts.map +1 -0
  38. package/dist/integrations/bling/sync.d.ts +70 -0
  39. package/dist/integrations/bling/sync.d.ts.map +1 -0
  40. package/dist/integrations/bling/types.d.ts +59 -0
  41. package/dist/integrations/bling/types.d.ts.map +1 -0
  42. package/dist/integrations/melhor-envio/connectorDef.d.ts +38 -0
  43. package/dist/integrations/melhor-envio/connectorDef.d.ts.map +1 -0
  44. package/dist/integrations/melhor-envio/labelProvider.d.ts +4 -0
  45. package/dist/integrations/melhor-envio/labelProvider.d.ts.map +1 -0
  46. package/dist/integrations/stripe-connect/connectorDef.d.ts +17 -0
  47. package/dist/integrations/stripe-connect/connectorDef.d.ts.map +1 -0
  48. package/dist/integrations/vindi/connectorDef.d.ts +76 -0
  49. package/dist/integrations/vindi/connectorDef.d.ts.map +1 -0
  50. package/dist/settings/CheckoutSettings.d.ts +17 -0
  51. package/dist/settings/CheckoutSettings.d.ts.map +1 -0
  52. package/dist/settings/ChoiceCards.d.ts +23 -0
  53. package/dist/settings/ChoiceCards.d.ts.map +1 -0
  54. package/dist/settings/FulfillmentSettings.d.ts +23 -0
  55. package/dist/settings/FulfillmentSettings.d.ts.map +1 -0
  56. package/dist/settings/HandlingSettings.d.ts +17 -0
  57. package/dist/settings/HandlingSettings.d.ts.map +1 -0
  58. package/dist/settings/PackagesSettings.d.ts +22 -0
  59. package/dist/settings/PackagesSettings.d.ts.map +1 -0
  60. package/dist/settings/PaymentProviderRow.d.ts +28 -0
  61. package/dist/settings/PaymentProviderRow.d.ts.map +1 -0
  62. package/dist/settings/PaymentsSettings.d.ts +7 -0
  63. package/dist/settings/PaymentsSettings.d.ts.map +1 -0
  64. package/dist/settings/SettingsState.d.ts +27 -0
  65. package/dist/settings/SettingsState.d.ts.map +1 -0
  66. package/dist/settings/ShippingSettings.d.ts +27 -0
  67. package/dist/settings/ShippingSettings.d.ts.map +1 -0
  68. package/dist/settings/StoreGeneralSettings.d.ts +19 -0
  69. package/dist/settings/StoreGeneralSettings.d.ts.map +1 -0
  70. package/dist/settings/error-message.d.ts +2 -0
  71. package/dist/settings/error-message.d.ts.map +1 -0
  72. package/dist/settings/index.d.ts +12 -0
  73. package/dist/settings/index.d.ts.map +1 -0
  74. package/dist/settings/payment-provider.d.ts +13 -0
  75. package/dist/settings/payment-provider.d.ts.map +1 -0
  76. package/dist/settings/useStoreSettings.d.ts +30 -0
  77. package/dist/settings/useStoreSettings.d.ts.map +1 -0
  78. package/dist/views/AgencySelect.d.ts +17 -0
  79. package/dist/views/AgencySelect.d.ts.map +1 -0
  80. package/dist/views/ContentPage.d.ts.map +1 -1
  81. package/dist/views/FulfillmentProviderSelect.d.ts +14 -0
  82. package/dist/views/FulfillmentProviderSelect.d.ts.map +1 -0
  83. package/dist/views/NewOrderCharge.d.ts +17 -0
  84. package/dist/views/NewOrderCharge.d.ts.map +1 -0
  85. package/dist/views/NewOrderPage.d.ts +9 -0
  86. package/dist/views/NewOrderPage.d.ts.map +1 -0
  87. package/dist/views/OrderDetailView.d.ts +2 -0
  88. package/dist/views/OrderDetailView.d.ts.map +1 -1
  89. package/dist/views/OrderPaymentDetail.d.ts +5 -0
  90. package/dist/views/OrderPaymentDetail.d.ts.map +1 -0
  91. package/dist/views/OrderProviderLinks.d.ts +5 -0
  92. package/dist/views/OrderProviderLinks.d.ts.map +1 -0
  93. package/dist/views/PackageSelect.d.ts +20 -0
  94. package/dist/views/PackageSelect.d.ts.map +1 -0
  95. package/dist/views/ProductImagesTab.d.ts.map +1 -1
  96. package/dist/views/ProductVariantsTab.d.ts +29 -0
  97. package/dist/views/ProductVariantsTab.d.ts.map +1 -0
  98. package/dist/views/SenderLocationModal.d.ts +20 -0
  99. package/dist/views/SenderLocationModal.d.ts.map +1 -0
  100. package/dist/views/ShipOrderForm.d.ts +10 -0
  101. package/dist/views/ShipOrderForm.d.ts.map +1 -0
  102. package/dist/views/ShipWithCarrier.d.ts +18 -0
  103. package/dist/views/ShipWithCarrier.d.ts.map +1 -0
  104. package/dist/views/ShipmentActions.d.ts +11 -0
  105. package/dist/views/ShipmentActions.d.ts.map +1 -0
  106. package/dist/views/ShippingProfileSelect.d.ts +13 -0
  107. package/dist/views/ShippingProfileSelect.d.ts.map +1 -0
  108. package/dist/views/ShopPage.d.ts.map +1 -1
  109. package/dist/views/customerEntity.d.ts.map +1 -1
  110. package/dist/views/eta-label.d.ts +6 -0
  111. package/dist/views/eta-label.d.ts.map +1 -0
  112. package/dist/views/media-links.d.ts +12 -0
  113. package/dist/views/media-links.d.ts.map +1 -0
  114. package/dist/views/new-order-rules.d.ts +55 -0
  115. package/dist/views/new-order-rules.d.ts.map +1 -0
  116. package/dist/views/order-actions.d.ts +4 -0
  117. package/dist/views/order-actions.d.ts.map +1 -0
  118. package/dist/views/productEntity.d.ts.map +1 -1
  119. package/dist/views/shippingZoneEntity.d.ts.map +1 -1
  120. package/package.json +10 -7
  121. package/dist/ShopPage-PVHFKDF3.js +0 -690
  122. package/dist/ShopPage-PVHFKDF3.js.map +0 -1
  123. package/dist/components/ShopSettings.d.ts +0 -15
  124. package/dist/components/ShopSettings.d.ts.map +0 -1
@@ -1,690 +0,0 @@
1
- import { useState, useEffect, useCallback, useMemo } from 'react';
2
- import { DataTable } from '@fayz-ai/ui';
3
- import { getShopProvider } from '@fayz-ai/shop';
4
- import { useAdminPath, adminNavigateTo, OrderDetailSkeleton, OrderDetailBlock, OrderDetailRow, PersonLink, OrderDetailView as OrderDetailView$1 } from '@fayz-ai/admin';
5
- import { getSupabaseClientOptional } from '@fayz-ai/core';
6
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
-
8
- // src/views/ShopPage.tsx
9
-
10
- // src/views/customerLookup.ts
11
- function shopCustomerLookup(provider) {
12
- return {
13
- async getById(id) {
14
- const c = await provider().getCustomer(id);
15
- if (!c) return null;
16
- const name = [c.firstName, c.lastName].filter(Boolean).join(" ");
17
- return {
18
- id: c.id,
19
- label: name || c.email || "Cliente",
20
- subtitle: c.email ?? void 0,
21
- group: "shop_customer",
22
- // PersonLink reads contact fields off `data`, so the keys must match the
23
- // shape it expects (email/phone), not our camelCase type.
24
- data: {
25
- email: c.email ?? void 0,
26
- phone: c.phone ?? void 0,
27
- kind: "shop_customer",
28
- orders_count: c.ordersCount,
29
- total_spent: c.totalSpent
30
- }
31
- };
32
- }
33
- };
34
- }
35
- var money = (v, currency2 = "BRL") => new Intl.NumberFormat("pt-BR", { style: "currency", currency: currency2 }).format(Number(v) || 0);
36
- var dateTime = (iso) => new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" }).format(new Date(iso));
37
- var dateOnly = (iso) => new Date(iso).toLocaleDateString("pt-BR");
38
- var PAYMENT_LABEL = {
39
- pix: "Pix",
40
- credit_card: "Cart\xE3o de cr\xE9dito",
41
- debit_card: "Cart\xE3o de d\xE9bito",
42
- boleto: "Boleto",
43
- cash: "Dinheiro",
44
- other: "Outro"
45
- };
46
- var LABEL = {
47
- paid: "Pago",
48
- pending: "Aguardando pagamento",
49
- refunded: "Estornado",
50
- partially_refunded: "Estorno parcial",
51
- voided: "Cancelado",
52
- fulfilled: "Enviado",
53
- unfulfilled: "N\xE3o enviado",
54
- partially_fulfilled: "Envio parcial",
55
- open: "Aberto",
56
- cancelled: "Cancelado",
57
- archived: "Arquivado"
58
- };
59
- var RECEIVABLE_LABEL = {
60
- open: "Em aberto",
61
- partial: "Parcialmente recebido",
62
- paid: "Recebido",
63
- overdue: "Vencido",
64
- cancelled: "Cancelado"
65
- };
66
- var SHIPMENT_LABEL = {
67
- pending: "Aguardando coleta",
68
- in_transit: "Em tr\xE2nsito",
69
- delivered: "Entregue",
70
- failed: "Falhou",
71
- returned: "Devolvido",
72
- cancelled: "Cancelado"
73
- };
74
- function toneOf(value) {
75
- switch (value) {
76
- case "paid":
77
- case "fulfilled":
78
- case "delivered":
79
- return "success";
80
- case "pending":
81
- case "partial":
82
- case "partially_fulfilled":
83
- case "open":
84
- case "in_transit":
85
- return "warning";
86
- case "refunded":
87
- case "partially_refunded":
88
- case "voided":
89
- case "cancelled":
90
- case "overdue":
91
- case "failed":
92
- case "returned":
93
- return "destructive";
94
- default:
95
- return "muted";
96
- }
97
- }
98
- function InlineBadge({ value }) {
99
- const tone = toneOf(value);
100
- const cls = {
101
- success: "bg-emerald-100 text-emerald-800",
102
- warning: "bg-amber-100 text-amber-800",
103
- destructive: "bg-red-100 text-red-700",
104
- info: "bg-sky-100 text-sky-800",
105
- muted: "bg-muted text-muted-foreground"
106
- };
107
- return /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${cls[tone]}`, children: LABEL[value] ?? value });
108
- }
109
- function deliveryFromNotes(notes) {
110
- if (!notes) return null;
111
- const match = notes.match(/entrega:\s*(.+)/i);
112
- return (match?.[1] ?? "").trim() || null;
113
- }
114
- var shopOrderCache = /* @__PURE__ */ new Map();
115
- var shopShipmentsCache = /* @__PURE__ */ new Map();
116
- var shopReceivableCache = /* @__PURE__ */ new Map();
117
- function OrderDetailView({ orderId, provider, onBack }) {
118
- const [order, setOrder] = useState(() => shopOrderCache.get(orderId) ?? null);
119
- const [shipments, setShipments] = useState(() => shopShipmentsCache.get(orderId) ?? []);
120
- const [loading, setLoading] = useState(() => !shopOrderCache.has(orderId));
121
- const [error, setError] = useState(null);
122
- const [confirming, setConfirming] = useState(false);
123
- const [confirmError, setConfirmError] = useState(null);
124
- const [receivable, setReceivable] = useState(() => shopReceivableCache.get(orderId) ?? null);
125
- useEffect(() => {
126
- let cancelled = false;
127
- const cached = shopOrderCache.get(orderId);
128
- if (cached) {
129
- setOrder(cached);
130
- setLoading(false);
131
- return () => {
132
- cancelled = true;
133
- };
134
- }
135
- setLoading(true);
136
- setError(null);
137
- provider().getOrder(orderId).then((o) => {
138
- if (!cancelled) {
139
- if (o) shopOrderCache.set(orderId, o);
140
- setOrder(o);
141
- }
142
- }).catch((err) => {
143
- if (!cancelled) setError(err instanceof Error ? err.message : String(err));
144
- }).finally(() => {
145
- if (!cancelled) setLoading(false);
146
- });
147
- return () => {
148
- cancelled = true;
149
- };
150
- }, [orderId, provider]);
151
- useEffect(() => {
152
- let cancelled = false;
153
- const db = getSupabaseClientOptional();
154
- if (!db) return;
155
- if (shopShipmentsCache.has(orderId)) return () => {
156
- cancelled = true;
157
- };
158
- db.from("fulfillments").select("*").eq("order_id", orderId).order("created_at", { ascending: false }).then(({ data: data2 }) => {
159
- if (!cancelled) {
160
- shopShipmentsCache.set(orderId, data2 ?? []);
161
- setShipments(data2 ?? []);
162
- }
163
- });
164
- return () => {
165
- cancelled = true;
166
- };
167
- }, [orderId]);
168
- useEffect(() => {
169
- let cancelled = false;
170
- const db = getSupabaseClientOptional();
171
- if (!db) return;
172
- if (shopReceivableCache.has(orderId)) {
173
- setReceivable(shopReceivableCache.get(orderId) ?? null);
174
- return () => {
175
- cancelled = true;
176
- };
177
- }
178
- void (async () => {
179
- const [balance, bills] = await Promise.all([
180
- db.from("v_invoice_balances").select("*").eq("invoice_id", orderId).maybeSingle(),
181
- db.from("plg_financial_movements").select("*").eq("invoice_id", orderId).eq("movement_kind", "bill").order("installment_number", { ascending: true })
182
- ]);
183
- if (cancelled || !balance?.data) return;
184
- const rec = { balance: balance.data, bills: bills?.data ?? [] };
185
- shopReceivableCache.set(orderId, rec);
186
- setReceivable(rec);
187
- })();
188
- return () => {
189
- cancelled = true;
190
- };
191
- }, [orderId, confirming]);
192
- if (loading) return /* @__PURE__ */ jsx(OrderDetailSkeleton, {});
193
- if (error) {
194
- return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800", children: [
195
- /* @__PURE__ */ jsx("p", { className: "font-medium", children: "N\xE3o foi poss\xEDvel carregar o pedido." }),
196
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-red-700", children: error })
197
- ] });
198
- }
199
- if (!order) return /* @__PURE__ */ jsx("div", { className: "py-12 text-center text-sm text-muted-foreground", children: "Pedido n\xE3o encontrado." });
200
- const cur = order.currency;
201
- const delivery = deliveryFromNotes(order.notes);
202
- const addr = order.shippingAddress;
203
- async function registerReceipt() {
204
- if (!order) return;
205
- shopReceivableCache.delete(order.id);
206
- setConfirming(true);
207
- setConfirmError(null);
208
- try {
209
- const fresh = await provider().confirmPayment?.(order.id) ?? await provider().getOrder(order.id);
210
- if (fresh) {
211
- shopOrderCache.set(order.id, fresh);
212
- setOrder(fresh);
213
- }
214
- } catch (err) {
215
- setConfirmError(err instanceof Error ? err.message : String(err));
216
- } finally {
217
- setConfirming(false);
218
- }
219
- }
220
- const installments = receivable && receivable.bills.length > 1 ? receivable.bills.map((b) => ({
221
- number: b.installment_number ?? 0,
222
- amount: `${money(Number(b.paid_amount ?? 0), cur)} / ${money(Number(b.amount), cur)}`,
223
- status: RECEIVABLE_LABEL[b.status] ?? b.status,
224
- statusTone: toneOf(b.status),
225
- dueDate: `vence ${dateOnly(b.due_date)}`
226
- })) : [];
227
- const data = {
228
- title: `Pedido #${order.orderNumber}`,
229
- subtitle: dateTime(order.createdAt),
230
- badges: [
231
- { label: LABEL[order.financialStatus] ?? order.financialStatus, tone: toneOf(order.financialStatus) },
232
- { label: LABEL[order.fulfillmentStatus] ?? order.fulfillmentStatus, tone: toneOf(order.fulfillmentStatus) }
233
- ],
234
- customer: { name: order.customerName, email: order.customerEmail },
235
- customerNode: /* @__PURE__ */ jsxs("div", { className: "space-y-1 text-sm", children: [
236
- order.customerId ? /* @__PURE__ */ jsx(
237
- PersonLink,
238
- {
239
- personId: order.customerId,
240
- name: order.customerName ?? order.customerEmail ?? "Cliente",
241
- lookup: shopCustomerLookup(provider),
242
- profileHref: `#/customers/${order.customerId}`,
243
- className: "font-medium"
244
- }
245
- ) : /* @__PURE__ */ jsx("p", { className: "font-medium", children: order.customerName ?? "\u2014" }),
246
- order.customerEmail && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: order.customerEmail }),
247
- !order.customerId && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Compra sem cadastro \u2014 n\xE3o h\xE1 ficha de cliente para abrir." })
248
- ] }),
249
- items: order.items.map((it) => ({
250
- id: it.id,
251
- name: it.name,
252
- description: it.sku,
253
- imageUrl: it.imageUrl,
254
- quantity: it.quantity,
255
- unitPrice: money(it.unitPrice, cur),
256
- total: money(it.total, cur)
257
- })),
258
- totals: [
259
- { label: "Subtotal", value: money(order.subtotal, cur) },
260
- ...order.discountTotal > 0 ? [{ label: `Desconto${order.discountCode ? ` (${order.discountCode})` : ""}`, value: `\u2212 ${money(order.discountTotal, cur)}`, muted: true }] : [],
261
- { label: "Entrega", value: money(order.shippingTotal, cur) },
262
- { label: "Impostos", value: money(order.taxTotal, cur) },
263
- { label: "Total", value: money(order.total, cur), strong: true }
264
- ],
265
- paymentMethod: order.paymentMethodKind ? PAYMENT_LABEL[order.paymentMethodKind] ?? order.paymentMethodKind : void 0,
266
- paidAt: order.paidAt ? dateTime(order.paidAt) : void 0,
267
- receivable: receivable ? {
268
- referenceNumber: receivable.balance.reference_number ?? void 0,
269
- statusBadge: { label: RECEIVABLE_LABEL[receivable.balance.status] ?? receivable.balance.status, tone: toneOf(receivable.balance.status) },
270
- rows: [
271
- { label: "Faturado", value: money(receivable.balance.amount, cur) },
272
- { label: "Recebido", value: money(receivable.balance.paid, cur) },
273
- { label: "Saldo", value: money(receivable.balance.balance, cur), strong: true }
274
- ],
275
- installments,
276
- actions: /* @__PURE__ */ jsxs(Fragment, { children: [
277
- receivable.balance.balance > 0 && receivable.balance.status !== "cancelled" && /* @__PURE__ */ jsx(
278
- "button",
279
- {
280
- type: "button",
281
- onClick: registerReceipt,
282
- disabled: confirming,
283
- "data-testid": "order-register-receipt",
284
- className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition hover:opacity-90 disabled:opacity-60",
285
- children: confirming ? "Registrando\u2026" : "Registrar recebimento"
286
- }
287
- ),
288
- /* @__PURE__ */ jsx(
289
- "button",
290
- {
291
- type: "button",
292
- onClick: () => adminNavigateTo("/financial"),
293
- className: "rounded-md border px-3 py-1.5 text-sm font-medium transition hover:bg-muted",
294
- children: "Abrir no Financeiro"
295
- }
296
- ),
297
- confirmError && /* @__PURE__ */ jsx("p", { className: "mt-2 w-full rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-800", children: confirmError })
298
- ] }),
299
- emptyLabel: "Sem conta a receber para este pedido."
300
- } : { rows: [], installments: [], emptyLabel: "Sem conta a receber para este pedido." },
301
- extraSections: /* @__PURE__ */ jsxs(Fragment, { children: [
302
- /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Entrega", hint: "O que a log\xEDstica precisa", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-sm", children: [
303
- addr ? /* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
304
- /* @__PURE__ */ jsxs("p", { children: [
305
- [addr.street, addr.number].filter(Boolean).join(", "),
306
- addr.complement ? ` \u2014 ${addr.complement}` : ""
307
- ] }),
308
- addr.district && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: addr.district }),
309
- /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
310
- [addr.city, addr.state].filter((v) => v && v !== "\u2014").join("/"),
311
- addr.postal_code ? ` \xB7 ${addr.postal_code}` : ""
312
- ] }),
313
- (addr.recipient || addr.phone) && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: [addr.recipient, addr.phone].filter(Boolean).join(" \xB7 ") })
314
- ] }) : /* @__PURE__ */ jsx("p", { className: delivery ? "" : "text-muted-foreground", children: delivery ?? "Nenhum endere\xE7o registrado neste pedido." }),
315
- /* @__PURE__ */ jsxs("div", { className: "border-t pt-2", children: [
316
- /* @__PURE__ */ jsx(OrderDetailRow, { label: "Status", value: /* @__PURE__ */ jsx(InlineBadge, { value: order.fulfillmentStatus }) }),
317
- shipments.length === 0 ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Nenhum envio registrado." }) : /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: shipments.map((s) => /* @__PURE__ */ jsxs("div", { className: "rounded-md border px-2 py-1.5", children: [
318
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
319
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: [s.carrier, s.service].filter(Boolean).join(" \xB7 ") || "Envio" }),
320
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: SHIPMENT_LABEL[s.status] ?? s.status })
321
- ] }),
322
- s.tracking_code && /* @__PURE__ */ jsx("p", { className: "mt-0.5 font-mono text-xs", children: s.tracking_url ? /* @__PURE__ */ jsx("a", { href: s.tracking_url, target: "_blank", rel: "noreferrer", className: "text-primary hover:underline", children: s.tracking_code }) : s.tracking_code }),
323
- /* @__PURE__ */ jsxs("div", { className: "mt-1 space-y-0.5 text-[11px] text-muted-foreground", children: [
324
- s.shipped_at && /* @__PURE__ */ jsxs("p", { children: [
325
- "Despachado em ",
326
- dateTime(s.shipped_at)
327
- ] }),
328
- s.estimated_delivery_at && /* @__PURE__ */ jsxs("p", { children: [
329
- "Previs\xE3o: ",
330
- dateTime(s.estimated_delivery_at)
331
- ] }),
332
- s.delivered_at && /* @__PURE__ */ jsxs("p", { children: [
333
- "Entregue em ",
334
- dateTime(s.delivered_at)
335
- ] })
336
- ] })
337
- ] }, s.id)) })
338
- ] })
339
- ] }) }),
340
- /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Hist\xF3rico", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1 text-sm", children: [
341
- /* @__PURE__ */ jsx(OrderDetailRow, { label: "Criado", value: dateTime(order.createdAt) }),
342
- /* @__PURE__ */ jsx(OrderDetailRow, { label: "Atualizado", value: dateTime(order.updatedAt) }),
343
- /* @__PURE__ */ jsx(OrderDetailRow, { label: "Situa\xE7\xE3o", value: /* @__PURE__ */ jsx(InlineBadge, { value: order.status }) })
344
- ] }) }),
345
- order.notes && /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Observa\xE7\xF5es", children: /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap text-sm text-muted-foreground", children: order.notes }) })
346
- ] }),
347
- onBack,
348
- backLabel: "Pedidos"
349
- };
350
- return /* @__PURE__ */ jsx(OrderDetailView$1, { ...data });
351
- }
352
- function currency(value, code = "BRL", locale = "pt-BR") {
353
- return new Intl.NumberFormat(locale, { style: "currency", currency: code }).format(value);
354
- }
355
- function badge(label, color) {
356
- return /* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${color}`, children: label });
357
- }
358
- var statusColors = {
359
- active: "bg-emerald-100 text-emerald-800",
360
- draft: "bg-gray-100 text-gray-700",
361
- archived: "bg-orange-100 text-orange-700",
362
- open: "bg-blue-100 text-blue-800",
363
- cancelled: "bg-red-100 text-red-700",
364
- paid: "bg-emerald-100 text-emerald-800",
365
- pending: "bg-yellow-100 text-yellow-800",
366
- fulfilled: "bg-emerald-100 text-emerald-800",
367
- unfulfilled: "bg-gray-100 text-gray-700",
368
- "partially_fulfilled": "bg-blue-100 text-blue-800"
369
- };
370
- function resolveShopProvider(provider) {
371
- return typeof provider === "function" ? provider() : provider ?? getShopProvider();
372
- }
373
- function useShopList(load, deps) {
374
- const [items, setItems] = useState([]);
375
- const [loading, setLoading] = useState(true);
376
- const [error, setError] = useState(null);
377
- useEffect(() => {
378
- let cancelled = false;
379
- setLoading(true);
380
- setError(null);
381
- load().then((data) => {
382
- if (!cancelled) setItems(data);
383
- }).catch((err) => {
384
- if (!cancelled) setError(err instanceof Error ? err.message : String(err));
385
- }).finally(() => {
386
- if (!cancelled) setLoading(false);
387
- });
388
- return () => {
389
- cancelled = true;
390
- };
391
- }, deps);
392
- return { items, loading, error };
393
- }
394
- function ErrorState({ message }) {
395
- return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800", children: [
396
- /* @__PURE__ */ jsx("p", { className: "font-medium", children: "N\xE3o foi poss\xEDvel carregar estes dados." }),
397
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-red-700", children: message })
398
- ] });
399
- }
400
- function ProductsTab({ provider }) {
401
- const [products, setProducts] = useState([]);
402
- const [loading, setLoading] = useState(true);
403
- const [search, setSearch] = useState("");
404
- const [error, setError] = useState(null);
405
- const load = useCallback(async (opts) => {
406
- setLoading(true);
407
- setError(null);
408
- try {
409
- const data = await resolveShopProvider(provider).listProducts(opts);
410
- setProducts(data);
411
- } catch (err) {
412
- setError(err instanceof Error ? err.message : String(err));
413
- } finally {
414
- setLoading(false);
415
- }
416
- }, [provider]);
417
- useEffect(() => {
418
- load();
419
- }, [load]);
420
- const handleSearch = (e) => {
421
- const q = e.target.value;
422
- setSearch(q);
423
- load(q ? { search: q } : void 0);
424
- };
425
- const columns = useMemo(() => [
426
- { accessorKey: "name", header: "Produto", cell: ({ getValue }) => /* @__PURE__ */ jsx("span", { className: "font-medium", children: getValue() }) },
427
- { accessorKey: "sku", header: "SKU", cell: ({ getValue }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: getValue() ?? "\u2014" }) },
428
- {
429
- accessorKey: "price",
430
- header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Pre\xE7o" }),
431
- cell: ({ getValue, row }) => /* @__PURE__ */ jsx("div", { className: "text-right", children: currency(getValue(), row.original.currency) })
432
- },
433
- {
434
- accessorKey: "inventoryCount",
435
- header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Estoque" }),
436
- cell: ({ getValue }) => {
437
- const count = getValue();
438
- return /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx("span", { className: count === 0 ? "text-red-600 font-medium" : "", children: count }) });
439
- }
440
- },
441
- {
442
- accessorKey: "status",
443
- header: "Status",
444
- cell: ({ getValue }) => {
445
- const status = getValue();
446
- return badge(status, statusColors[status] ?? "bg-gray-100 text-gray-700");
447
- }
448
- }
449
- ], []);
450
- return /* @__PURE__ */ jsxs("div", { children: [
451
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
452
- /* @__PURE__ */ jsx(
453
- "input",
454
- {
455
- type: "search",
456
- value: search,
457
- onChange: handleSearch,
458
- placeholder: "Buscar produtos...",
459
- className: "border rounded-lg px-3 py-2 text-sm w-64 focus:outline-none focus:ring-2 focus:ring-primary/50"
460
- }
461
- ),
462
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
463
- products.length,
464
- " produtos"
465
- ] })
466
- ] }),
467
- error ? /* @__PURE__ */ jsx(ErrorState, { message: error }) : /* @__PURE__ */ jsx(
468
- DataTable,
469
- {
470
- loading,
471
- columns,
472
- data: products,
473
- variant: "card",
474
- emptyMessage: "Nenhum produto encontrado."
475
- }
476
- )
477
- ] });
478
- }
479
- function OrdersTab({ provider }) {
480
- const { items: orders, loading, error } = useShopList(
481
- () => resolveShopProvider(provider).listOrders({ limit: 50 }),
482
- [provider]
483
- );
484
- const columns = useMemo(() => [
485
- { accessorKey: "orderNumber", header: "Pedido", cell: ({ getValue }) => /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
486
- "#",
487
- getValue()
488
- ] }) },
489
- {
490
- id: "customer",
491
- accessorFn: (o) => o.customerName ?? o.customerEmail ?? "\u2014",
492
- header: "Cliente",
493
- // Links to the customer record. stopPropagation because the row itself
494
- // opens the order — without it the click would do both.
495
- cell: ({ getValue, row }) => {
496
- const label = getValue();
497
- const id = row.original.customerId;
498
- if (!id) return /* @__PURE__ */ jsx("span", { children: label });
499
- return /* @__PURE__ */ jsx(
500
- PersonLink,
501
- {
502
- personId: id,
503
- name: label,
504
- lookup: shopCustomerLookup(() => resolveShopProvider(provider)),
505
- profileHref: `#/customers/${id}`
506
- }
507
- );
508
- }
509
- },
510
- {
511
- accessorKey: "total",
512
- header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Total" }),
513
- cell: ({ getValue, row }) => /* @__PURE__ */ jsx("div", { className: "text-right font-medium", children: currency(getValue(), row.original.currency) })
514
- },
515
- {
516
- accessorKey: "financialStatus",
517
- header: "Pagamento",
518
- cell: ({ getValue }) => {
519
- const status = getValue();
520
- return badge(status, statusColors[status] ?? "bg-gray-100 text-gray-700");
521
- }
522
- },
523
- {
524
- accessorKey: "fulfillmentStatus",
525
- header: "Entrega",
526
- cell: ({ getValue }) => {
527
- const status = getValue();
528
- return badge(status, statusColors[status] ?? "bg-gray-100 text-gray-700");
529
- }
530
- },
531
- {
532
- accessorKey: "createdAt",
533
- header: "Data",
534
- cell: ({ getValue }) => {
535
- const d = new Date(getValue());
536
- return /* @__PURE__ */ jsxs("span", { className: "whitespace-nowrap text-muted-foreground", children: [
537
- d.toLocaleDateString("pt-BR"),
538
- /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs opacity-70", children: d.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" }) })
539
- ] });
540
- }
541
- }
542
- ], []);
543
- return /* @__PURE__ */ jsx("div", { children: error ? /* @__PURE__ */ jsx(ErrorState, { message: error }) : /* @__PURE__ */ jsx(
544
- DataTable,
545
- {
546
- loading,
547
- columns,
548
- data: orders,
549
- variant: "card",
550
- emptyMessage: "Nenhum pedido ainda.",
551
- onRowClick: (row) => adminNavigateTo(`/orders/${row.id}`)
552
- }
553
- ) });
554
- }
555
- function CustomersTab({ provider }) {
556
- const { items: customers, loading, error } = useShopList(
557
- () => resolveShopProvider(provider).listCustomers({ limit: 50 }),
558
- [provider]
559
- );
560
- const columns = useMemo(() => [
561
- {
562
- id: "name",
563
- accessorFn: (c) => `${c.firstName} ${c.lastName}`,
564
- header: "Nome",
565
- cell: ({ row }) => /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
566
- row.original.firstName,
567
- " ",
568
- row.original.lastName
569
- ] })
570
- },
571
- { accessorKey: "email", header: "Email", cell: ({ getValue }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: getValue() ?? "\u2014" }) },
572
- { accessorKey: "phone", header: "Telefone", cell: ({ getValue }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: getValue() ?? "\u2014" }) },
573
- {
574
- accessorKey: "ordersCount",
575
- header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Pedidos" }),
576
- cell: ({ getValue }) => /* @__PURE__ */ jsx("div", { className: "text-right", children: getValue() })
577
- },
578
- {
579
- accessorKey: "totalSpent",
580
- header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Total Gasto" }),
581
- cell: ({ getValue }) => /* @__PURE__ */ jsx("div", { className: "text-right", children: currency(getValue()) })
582
- }
583
- ], []);
584
- return /* @__PURE__ */ jsx("div", { children: error ? /* @__PURE__ */ jsx(ErrorState, { message: error }) : /* @__PURE__ */ jsx(
585
- DataTable,
586
- {
587
- loading,
588
- columns,
589
- data: customers,
590
- variant: "card",
591
- emptyMessage: "Nenhum cliente ainda."
592
- }
593
- ) });
594
- }
595
- function DiscountsTab({ provider }) {
596
- const { items: discounts, loading, error } = useShopList(
597
- () => resolveShopProvider(provider).listDiscounts({ limit: 50 }),
598
- [provider]
599
- );
600
- const columns = useMemo(() => [
601
- { accessorKey: "title", header: "T\xEDtulo", cell: ({ getValue }) => /* @__PURE__ */ jsx("span", { className: "font-medium", children: getValue() }) },
602
- { accessorKey: "code", header: "C\xF3digo", cell: ({ getValue }) => /* @__PURE__ */ jsx("span", { className: "font-mono text-sm", children: getValue() ?? "\u2014" }) },
603
- { accessorKey: "type", header: "Tipo", cell: ({ getValue }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: getValue() }) },
604
- {
605
- accessorKey: "value",
606
- header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Valor" }),
607
- cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: "text-right", children: row.original.type === "percentage" ? `${row.original.value}%` : currency(row.original.value) })
608
- },
609
- {
610
- id: "usos",
611
- accessorKey: "timesUsed",
612
- header: () => /* @__PURE__ */ jsx("span", { className: "block text-right", children: "Usos" }),
613
- cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
614
- row.original.timesUsed,
615
- row.original.usageLimit ? ` / ${row.original.usageLimit}` : ""
616
- ] })
617
- },
618
- {
619
- accessorKey: "status",
620
- header: "Status",
621
- cell: ({ getValue }) => {
622
- const status = getValue();
623
- return badge(status, statusColors[status] ?? "bg-gray-100 text-gray-700");
624
- }
625
- }
626
- ], []);
627
- return /* @__PURE__ */ jsx("div", { children: error ? /* @__PURE__ */ jsx(ErrorState, { message: error }) : /* @__PURE__ */ jsx(
628
- DataTable,
629
- {
630
- loading,
631
- columns,
632
- data: discounts,
633
- variant: "card",
634
- emptyMessage: "Nenhum desconto cadastrado."
635
- }
636
- ) });
637
- }
638
- var TABS = [
639
- { id: "products", label: "Produtos" },
640
- { id: "orders", label: "Pedidos" },
641
- { id: "customers", label: "Clientes" },
642
- { id: "discounts", label: "Descontos" }
643
- ];
644
- var TAB_COPY = {
645
- products: { title: "Produtos", subtitle: "Cat\xE1logo da loja: pre\xE7o, estoque e status." },
646
- orders: { title: "Pedidos", subtitle: "Pedidos recebidos, pagamento e entrega." },
647
- customers: { title: "Clientes", subtitle: "Quem comprou, quanto e com que frequ\xEAncia." },
648
- discounts: { title: "Descontos", subtitle: "Cupons, regras de uso e desempenho." }
649
- };
650
- var ShopPage = ({ provider, section }) => {
651
- const [tab, setTab] = useState(section ?? "products");
652
- const active = section ?? tab;
653
- const path = useAdminPath();
654
- const orderId = section === "orders" ? path.match(/^\/orders\/([^/]+)$/)?.[1] : void 0;
655
- if (orderId) {
656
- return /* @__PURE__ */ jsx("div", { className: "p-6 max-w-7xl mx-auto", children: /* @__PURE__ */ jsx(
657
- OrderDetailView,
658
- {
659
- orderId,
660
- provider: () => resolveShopProvider(provider),
661
- onBack: () => adminNavigateTo("/orders")
662
- }
663
- ) });
664
- }
665
- const copy = section ? TAB_COPY[section] : { title: "Loja", subtitle: "Gerencie produtos, pedidos, clientes e descontos." };
666
- return /* @__PURE__ */ jsxs("div", { className: "p-6 max-w-7xl mx-auto", children: [
667
- /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
668
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold", children: copy.title }),
669
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1", children: copy.subtitle })
670
- ] }),
671
- !section && /* @__PURE__ */ jsx("div", { className: "border-b mb-6", children: /* @__PURE__ */ jsx("nav", { className: "flex gap-1", children: TABS.map((t) => /* @__PURE__ */ jsx(
672
- "button",
673
- {
674
- onClick: () => setTab(t.id),
675
- className: `px-4 py-2 text-sm font-medium border-b-2 transition-colors ${tab === t.id ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground"}`,
676
- children: t.label
677
- },
678
- t.id
679
- )) }) }),
680
- active === "products" && /* @__PURE__ */ jsx(ProductsTab, { provider }),
681
- active === "orders" && /* @__PURE__ */ jsx(OrdersTab, { provider }),
682
- active === "customers" && /* @__PURE__ */ jsx(CustomersTab, { provider }),
683
- active === "discounts" && /* @__PURE__ */ jsx(DiscountsTab, { provider })
684
- ] });
685
- };
686
- ShopPage.displayName = "ShopPage";
687
-
688
- export { ShopPage };
689
- //# sourceMappingURL=ShopPage-PVHFKDF3.js.map
690
- //# sourceMappingURL=ShopPage-PVHFKDF3.js.map