@fayz-ai/plugin-shop 0.8.1 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ShopPage-HCLXMN7Q.js → ShopPage-JP27MZS2.js} +232 -285
- package/dist/ShopPage-JP27MZS2.js.map +1 -0
- package/dist/{ShopPage-JF2SQBKO.cjs → ShopPage-NK6FSPJ5.cjs} +230 -283
- package/dist/ShopPage-NK6FSPJ5.cjs.map +1 -0
- package/dist/index.cjs +253 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +248 -20
- package/dist/index.js.map +1 -1
- package/dist/views/ChannelsPage.d.ts +7 -0
- package/dist/views/ChannelsPage.d.ts.map +1 -0
- package/dist/views/OrderDetailView.d.ts +1 -1
- package/dist/views/OrderDetailView.d.ts.map +1 -1
- package/dist/views/discountEntity.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/ShopPage.tsx +1 -1
- package/src/index.ts +47 -2
- package/src/views/ChannelsPage.tsx +274 -0
- package/src/views/OrderDetailView.tsx +205 -461
- package/src/views/discountEntity.tsx +7 -0
- package/dist/ShopPage-HCLXMN7Q.js.map +0 -1
- package/dist/ShopPage-JF2SQBKO.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/views/customerLookup.ts","../src/views/OrderDetailView.tsx","../src/ShopPage.tsx"],"names":["currency","jsx","useState","useEffect","getSupabaseClientOptional","data","OrderDetailSkeleton","jsxs","PersonLink","Fragment","adminNavigateTo","OrderDetailBlock","OrderDetailRow","SharedOrderDetailView","getShopProvider","useCallback","useMemo","DataTable","useAdminPath"],"mappings":"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","file":"ShopPage-NK6FSPJ5.cjs","sourcesContent":["import type { ShopProvider } from '@fayz-ai/shop'\n\n/**\n * Feeds the shared PersonLink popover from the shop's own customer table.\n * The default lookup reads the `person` archetype (`people`), where a shop\n * customer does not exist — so without this the card would come up empty.\n */\nexport function shopCustomerLookup(provider: () => ShopProvider) {\n return {\n async getById(id: string) {\n const c = await provider().getCustomer(id)\n if (!c) return null\n const name = [c.firstName, c.lastName].filter(Boolean).join(' ')\n return {\n id: c.id,\n label: name || c.email || 'Cliente',\n subtitle: c.email ?? undefined,\n group: 'shop_customer',\n // PersonLink reads contact fields off `data`, so the keys must match the\n // shape it expects (email/phone), not our camelCase type.\n data: {\n email: c.email ?? undefined,\n phone: c.phone ?? undefined,\n kind: 'shop_customer',\n orders_count: c.ordersCount,\n total_spent: c.totalSpent,\n },\n }\n },\n }\n}\n","import React, { useEffect, useState } from 'react'\nimport {\n adminNavigateTo, PersonLink,\n OrderDetailView as SharedOrderDetailView, OrderDetailSkeleton, OrderDetailBlock, OrderDetailRow,\n type OrderDetailData, type OrderDetailInstallment, type OrderDetailTone,\n} from '@fayz-ai/saas'\nimport { shopCustomerLookup } from './customerLookup'\nimport type { Order, ShopProvider } from '@fayz-ai/shop'\nimport { getSupabaseClientOptional } from '@fayz-ai/core'\n\n/** A shipment as stored in public.fulfillments (0018). */\ntype Fulfillment = {\n id: string\n status: string\n carrier: string | null\n service: string | null\n tracking_code: string | null\n tracking_url: string | null\n shipped_at: string | null\n estimated_delivery_at: string | null\n delivered_at: string | null\n}\n\ntype Bill = {\n id: string\n amount: number\n paid_amount: number | null\n status: string\n due_date: string\n installment_number: number | null\n}\ntype Receivable = {\n balance: { amount: number; paid: number; balance: number; status: string; reference_number: string | null }\n bills: Bill[]\n}\n\nconst money = (v: number, currency = 'BRL') =>\n new Intl.NumberFormat('pt-BR', { style: 'currency', currency }).format(Number(v) || 0)\nconst dateTime = (iso: string) =>\n new Intl.DateTimeFormat('pt-BR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }).format(new Date(iso))\nconst dateOnly = (iso: string) => new Date(iso).toLocaleDateString('pt-BR')\n\nconst PAYMENT_LABEL: Record<string, string> = {\n pix: 'Pix', credit_card: 'Cartão de crédito', debit_card: 'Cartão de débito',\n boleto: 'Boleto', cash: 'Dinheiro', other: 'Outro',\n}\nconst LABEL: Record<string, string> = {\n paid: 'Pago', pending: 'Aguardando pagamento', refunded: 'Estornado',\n partially_refunded: 'Estorno parcial', voided: 'Cancelado',\n fulfilled: 'Enviado', unfulfilled: 'Não enviado', partially_fulfilled: 'Envio parcial',\n open: 'Aberto', cancelled: 'Cancelado', archived: 'Arquivado',\n}\nconst RECEIVABLE_LABEL: Record<string, string> = {\n open: 'Em aberto', partial: 'Parcialmente recebido', paid: 'Recebido', overdue: 'Vencido', cancelled: 'Cancelado',\n}\nconst SHIPMENT_LABEL: Record<string, string> = {\n pending: 'Aguardando coleta', in_transit: 'Em trânsito', delivered: 'Entregue',\n failed: 'Falhou', returned: 'Devolvido', cancelled: 'Cancelado',\n}\n\n/** Map a shop/receivable status string to the shared component's tone. */\nfunction toneOf(value: string): OrderDetailTone {\n switch (value) {\n case 'paid': case 'fulfilled': case 'delivered': return 'success'\n case 'pending': case 'partial': case 'partially_fulfilled': case 'open': case 'in_transit': return 'warning'\n case 'refunded': case 'partially_refunded': case 'voided': case 'cancelled': case 'overdue': case 'failed': case 'returned': return 'destructive'\n default: return 'muted'\n }\n}\n\n/** Small inline badge for the shop-specific blocks (Entrega/Histórico). */\nfunction InlineBadge({ value }: { value: string }) {\n const tone = toneOf(value)\n const cls: Record<OrderDetailTone, string> = {\n success: 'bg-emerald-100 text-emerald-800', warning: 'bg-amber-100 text-amber-800',\n destructive: 'bg-red-100 text-red-700', info: 'bg-sky-100 text-sky-800', muted: 'bg-muted text-muted-foreground',\n }\n return <span className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${cls[tone]}`}>{LABEL[value] ?? value}</span>\n}\n\nfunction deliveryFromNotes(notes: string | null): string | null {\n if (!notes) return null\n const match = notes.match(/entrega:\\s*(.+)/i)\n return (match?.[1] ?? '').trim() || null\n}\n\n// Cache por id (fora do componente) — trocar de aba remonta a view; sem cache\n// isso refaz o getOrder (skeleton + request) toda vez. Cache-first evita o refetch;\n// \"Registrar recebimento\" atualiza o cache.\nconst shopOrderCache = new Map<string, Order>()\nconst shopShipmentsCache = new Map<string, Fulfillment[]>()\nconst shopReceivableCache = new Map<string, Receivable | null>()\n\nexport function OrderDetailView({ orderId, provider, onBack }: {\n orderId: string\n provider: () => ShopProvider\n onBack: () => void\n}) {\n const [order, setOrder] = useState<Order | null>(() => shopOrderCache.get(orderId) ?? null)\n const [shipments, setShipments] = useState<Fulfillment[]>(() => shopShipmentsCache.get(orderId) ?? [])\n const [loading, setLoading] = useState(() => !shopOrderCache.has(orderId))\n const [error, setError] = useState<string | null>(null)\n const [confirming, setConfirming] = useState(false)\n const [confirmError, setConfirmError] = useState<string | null>(null)\n const [receivable, setReceivable] = useState<Receivable | null>(() => shopReceivableCache.get(orderId) ?? null)\n\n useEffect(() => {\n let cancelled = false\n const cached = shopOrderCache.get(orderId)\n if (cached) { setOrder(cached); setLoading(false); return () => { cancelled = true } } // cache hit → sem request\n setLoading(true); setError(null)\n provider().getOrder(orderId)\n .then((o) => { if (!cancelled) { if (o) shopOrderCache.set(orderId, o); setOrder(o) } })\n .catch((err: unknown) => { if (!cancelled) setError(err instanceof Error ? err.message : String(err)) })\n .finally(() => { if (!cancelled) setLoading(false) })\n return () => { cancelled = true }\n }, [orderId, provider])\n\n useEffect(() => {\n let cancelled = false\n const db = getSupabaseClientOptional() as unknown as { from: (t: string) => any } | null\n if (!db) return\n if (shopShipmentsCache.has(orderId)) return () => { cancelled = true } // cache hit → sem request\n db.from('fulfillments').select('*').eq('order_id', orderId).order('created_at', { ascending: false })\n .then(({ data }: { data: Fulfillment[] | null }) => { if (!cancelled) { shopShipmentsCache.set(orderId, data ?? []); setShipments(data ?? []) } })\n return () => { cancelled = true }\n }, [orderId])\n\n // The order does not decide whether it was paid — the receivable does. Keep this\n // hook ABOVE the early returns (hook order must be stable).\n useEffect(() => {\n let cancelled = false\n const db = getSupabaseClientOptional() as unknown as { from: (t: string) => any } | null\n if (!db) return\n if (shopReceivableCache.has(orderId)) { setReceivable(shopReceivableCache.get(orderId) ?? null); return () => { cancelled = true } } // cache hit → sem request\n void (async () => {\n const [balance, bills] = await Promise.all([\n db.from('v_invoice_balances').select('*').eq('invoice_id', orderId).maybeSingle(),\n db.from('plg_financial_movements').select('*').eq('invoice_id', orderId).eq('movement_kind', 'bill').order('installment_number', { ascending: true }),\n ])\n if (cancelled || !balance?.data) return\n const rec = { balance: balance.data, bills: bills?.data ?? [] }\n shopReceivableCache.set(orderId, rec)\n setReceivable(rec)\n })()\n return () => { cancelled = true }\n }, [orderId, confirming])\n\n if (loading) return <OrderDetailSkeleton />\n if (error) {\n return (\n <div className=\"rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800\">\n <p className=\"font-medium\">Não foi possível carregar o pedido.</p>\n <p className=\"mt-1 text-red-700\">{error}</p>\n </div>\n )\n }\n if (!order) return <div className=\"py-12 text-center text-sm text-muted-foreground\">Pedido não encontrado.</div>\n\n const cur = order.currency\n const delivery = deliveryFromNotes(order.notes)\n const addr = order.shippingAddress\n\n async function registerReceipt() {\n if (!order) return\n shopReceivableCache.delete(order.id) // pagamento muda o recebível → força refetch\n setConfirming(true); setConfirmError(null)\n try {\n const fresh = (await provider().confirmPayment?.(order.id)) ?? (await provider().getOrder(order.id))\n if (fresh) { shopOrderCache.set(order.id, fresh); setOrder(fresh) } // atualiza o cache\n } catch (err: unknown) {\n setConfirmError(err instanceof Error ? err.message : String(err))\n } finally { setConfirming(false) }\n }\n\n const installments: OrderDetailInstallment[] = (receivable && receivable.bills.length > 1)\n ? receivable.bills.map((b) => ({\n number: b.installment_number ?? 0,\n amount: `${money(Number(b.paid_amount ?? 0), cur)} / ${money(Number(b.amount), cur)}`,\n status: RECEIVABLE_LABEL[b.status] ?? b.status,\n statusTone: toneOf(b.status),\n dueDate: `vence ${dateOnly(b.due_date)}`,\n }))\n : []\n\n const data: OrderDetailData = {\n title: `Pedido #${order.orderNumber}`,\n subtitle: dateTime(order.createdAt),\n badges: [\n { label: LABEL[order.financialStatus] ?? order.financialStatus, tone: toneOf(order.financialStatus) },\n { label: LABEL[order.fulfillmentStatus] ?? order.fulfillmentStatus, tone: toneOf(order.fulfillmentStatus) },\n ],\n customer: { name: order.customerName, email: order.customerEmail },\n customerNode: (\n <div className=\"space-y-1 text-sm\">\n {order.customerId ? (\n <PersonLink\n personId={order.customerId}\n name={order.customerName ?? order.customerEmail ?? 'Cliente'}\n lookup={shopCustomerLookup(provider)}\n profileHref={`#/customers/${order.customerId}`}\n className=\"font-medium\"\n />\n ) : (\n <p className=\"font-medium\">{order.customerName ?? '—'}</p>\n )}\n {order.customerEmail && <p className=\"text-muted-foreground\">{order.customerEmail}</p>}\n {!order.customerId && <p className=\"text-xs text-muted-foreground\">Compra sem cadastro — não há ficha de cliente para abrir.</p>}\n </div>\n ),\n items: order.items.map((it) => ({\n id: it.id, name: it.name, description: it.sku, imageUrl: it.imageUrl,\n quantity: it.quantity, unitPrice: money(it.unitPrice, cur), total: money(it.total, cur),\n })),\n totals: [\n { label: 'Subtotal', value: money(order.subtotal, cur) },\n ...(order.discountTotal > 0 ? [{ label: `Desconto${order.discountCode ? ` (${order.discountCode})` : ''}`, value: `− ${money(order.discountTotal, cur)}`, muted: true }] : []),\n { label: 'Entrega', value: money(order.shippingTotal, cur) },\n { label: 'Impostos', value: money(order.taxTotal, cur) },\n { label: 'Total', value: money(order.total, cur), strong: true },\n ],\n paymentMethod: order.paymentMethodKind ? (PAYMENT_LABEL[order.paymentMethodKind] ?? order.paymentMethodKind) : undefined,\n paidAt: order.paidAt ? dateTime(order.paidAt) : undefined,\n receivable: receivable ? {\n referenceNumber: receivable.balance.reference_number ?? undefined,\n statusBadge: { label: RECEIVABLE_LABEL[receivable.balance.status] ?? receivable.balance.status, tone: toneOf(receivable.balance.status) },\n rows: [\n { label: 'Faturado', value: money(receivable.balance.amount, cur) },\n { label: 'Recebido', value: money(receivable.balance.paid, cur) },\n { label: 'Saldo', value: money(receivable.balance.balance, cur), strong: true },\n ],\n installments,\n actions: (\n <>\n {receivable.balance.balance > 0 && receivable.balance.status !== 'cancelled' && (\n <button type=\"button\" onClick={registerReceipt} disabled={confirming} data-testid=\"order-register-receipt\"\n className=\"rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition hover:opacity-90 disabled:opacity-60\">\n {confirming ? 'Registrando…' : 'Registrar recebimento'}\n </button>\n )}\n <button type=\"button\" onClick={() => adminNavigateTo('/financial')}\n className=\"rounded-md border px-3 py-1.5 text-sm font-medium transition hover:bg-muted\">\n Abrir no Financeiro\n </button>\n {confirmError && <p className=\"mt-2 w-full rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-800\">{confirmError}</p>}\n </>\n ),\n emptyLabel: 'Sem conta a receber para este pedido.',\n } : { rows: [], installments: [], emptyLabel: 'Sem conta a receber para este pedido.' },\n extraSections: (\n <>\n <OrderDetailBlock title=\"Entrega\" hint=\"O que a logística precisa\">\n <div className=\"space-y-2 text-sm\">\n {addr ? (\n <div className=\"space-y-0.5\">\n <p>{[addr.street, addr.number].filter(Boolean).join(', ')}{addr.complement ? ` — ${addr.complement}` : ''}</p>\n {addr.district && <p className=\"text-muted-foreground\">{addr.district}</p>}\n <p className=\"text-muted-foreground\">\n {[addr.city, addr.state].filter((v) => v && v !== '—').join('/')}{addr.postal_code ? ` · ${addr.postal_code}` : ''}\n </p>\n {(addr.recipient || addr.phone) && <p className=\"text-xs text-muted-foreground\">{[addr.recipient, addr.phone].filter(Boolean).join(' · ')}</p>}\n </div>\n ) : (\n <p className={delivery ? '' : 'text-muted-foreground'}>{delivery ?? 'Nenhum endereço registrado neste pedido.'}</p>\n )}\n <div className=\"border-t pt-2\">\n <OrderDetailRow label=\"Status\" value={<InlineBadge value={order.fulfillmentStatus} />} />\n {shipments.length === 0 ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">Nenhum envio registrado.</p>\n ) : (\n <div className=\"mt-2 space-y-2\">\n {shipments.map((s) => (\n <div key={s.id} className=\"rounded-md border px-2 py-1.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium\">{[s.carrier, s.service].filter(Boolean).join(' · ') || 'Envio'}</span>\n <span className=\"text-[10px] text-muted-foreground\">{SHIPMENT_LABEL[s.status] ?? s.status}</span>\n </div>\n {s.tracking_code && (\n <p className=\"mt-0.5 font-mono text-xs\">\n {s.tracking_url ? <a href={s.tracking_url} target=\"_blank\" rel=\"noreferrer\" className=\"text-primary hover:underline\">{s.tracking_code}</a> : s.tracking_code}\n </p>\n )}\n <div className=\"mt-1 space-y-0.5 text-[11px] text-muted-foreground\">\n {s.shipped_at && <p>Despachado em {dateTime(s.shipped_at)}</p>}\n {s.estimated_delivery_at && <p>Previsão: {dateTime(s.estimated_delivery_at)}</p>}\n {s.delivered_at && <p>Entregue em {dateTime(s.delivered_at)}</p>}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </OrderDetailBlock>\n\n <OrderDetailBlock title=\"Histórico\">\n <div className=\"space-y-1 text-sm\">\n <OrderDetailRow label=\"Criado\" value={dateTime(order.createdAt)} />\n <OrderDetailRow label=\"Atualizado\" value={dateTime(order.updatedAt)} />\n <OrderDetailRow label=\"Situação\" value={<InlineBadge value={order.status} />} />\n </div>\n </OrderDetailBlock>\n\n {order.notes && (\n <OrderDetailBlock title=\"Observações\">\n <p className=\"whitespace-pre-wrap text-sm text-muted-foreground\">{order.notes}</p>\n </OrderDetailBlock>\n )}\n </>\n ),\n onBack,\n backLabel: 'Pedidos',\n }\n\n return <SharedOrderDetailView {...data} />\n}\n\nexport const orderDetailPath = (id: string) => `/shop/orders/${id}`\nexport const goToOrder = (id: string) => adminNavigateTo(orderDetailPath(id))\n","import React, { useEffect, useState, useCallback, useMemo } from 'react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { DataTable } from '@fayz-ai/ui'\nimport { getShopProvider } from '@fayz-ai/shop'\nimport { useAdminPath, adminNavigateTo } from '@fayz-ai/saas'\nimport { PersonLink } from '@fayz-ai/saas'\nimport { shopCustomerLookup } from './views/customerLookup'\nimport { OrderDetailView } from './views/OrderDetailView'\nimport type { Product, Order, ShopCustomer, Discount, ListProductsOptions, ShopProvider } from '@fayz-ai/shop'\n\nexport type ShopProviderResolver = ShopProvider | (() => ShopProvider)\n\nexport interface ShopPageProps {\n provider?: ShopProviderResolver\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction currency(value: number, code = 'BRL', locale = 'pt-BR') {\n return new Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(value)\n}\n\nfunction badge(label: string, color: string) {\n return (\n <span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${color}`}>\n {label}\n </span>\n )\n}\n\nconst statusColors: Record<string, string> = {\n active: 'bg-emerald-100 text-emerald-800',\n draft: 'bg-gray-100 text-gray-700',\n archived: 'bg-orange-100 text-orange-700',\n open: 'bg-blue-100 text-blue-800',\n cancelled: 'bg-red-100 text-red-700',\n paid: 'bg-emerald-100 text-emerald-800',\n pending: 'bg-yellow-100 text-yellow-800',\n fulfilled: 'bg-emerald-100 text-emerald-800',\n unfulfilled: 'bg-gray-100 text-gray-700',\n 'partially_fulfilled': 'bg-blue-100 text-blue-800',\n}\n\nfunction resolveShopProvider(provider?: ShopProviderResolver): ShopProvider {\n return typeof provider === 'function' ? provider() : provider ?? getShopProvider()\n}\n\n/**\n * Every tab used to load with `.then(setState).finally(stopLoading)` and no\n * catch. Against a pool where the shop provider reads as `anon`, listOrders and\n * listCustomers reject with \"permission denied\" — the rejection escaped React\n * and blanked the whole admin, so a permissions problem looked like a crash.\n * The tab now reports what actually failed and the rest of the shell survives.\n */\nfunction useShopList<T>(load: () => Promise<T[]>, deps: React.DependencyList) {\n const [items, setItems] = useState<T[]>([])\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n let cancelled = false\n setLoading(true)\n setError(null)\n load()\n .then((data) => { if (!cancelled) setItems(data) })\n .catch((err: unknown) => {\n if (!cancelled) setError(err instanceof Error ? err.message : String(err))\n })\n .finally(() => { if (!cancelled) setLoading(false) })\n return () => { cancelled = true }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n\n return { items, loading, error }\n}\n\nfunction ErrorState({ message }: { message: string }) {\n return (\n <div className=\"rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800\">\n <p className=\"font-medium\">Não foi possível carregar estes dados.</p>\n <p className=\"mt-1 text-red-700\">{message}</p>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Products tab\n// ---------------------------------------------------------------------------\n\nfunction ProductsTab({ provider }: ShopPageProps) {\n const [products, setProducts] = useState<Product[]>([])\n const [loading, setLoading] = useState(true)\n const [search, setSearch] = useState('')\n\n const [error, setError] = useState<string | null>(null)\n\n const load = useCallback(async (opts?: ListProductsOptions) => {\n setLoading(true)\n setError(null)\n try {\n const data = await resolveShopProvider(provider).listProducts(opts)\n setProducts(data)\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setLoading(false)\n }\n }, [provider])\n\n useEffect(() => { load() }, [load])\n\n const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {\n const q = e.target.value\n setSearch(q)\n load(q ? { search: q } : undefined)\n }\n\n const columns = useMemo<ColumnDef<Product, any>[]>(() => [\n { accessorKey: 'name', header: 'Produto', cell: ({ getValue }) => <span className=\"font-medium\">{getValue() as string}</span> },\n { accessorKey: 'sku', header: 'SKU', cell: ({ getValue }) => <span className=\"text-muted-foreground\">{(getValue() as string | undefined) ?? '—'}</span> },\n {\n accessorKey: 'price', header: () => <span className=\"block text-right\">Preço</span>,\n cell: ({ getValue, row }) => <div className=\"text-right\">{currency(getValue() as number, row.original.currency)}</div>,\n },\n {\n accessorKey: 'inventoryCount', header: () => <span className=\"block text-right\">Estoque</span>,\n cell: ({ getValue }) => {\n const count = getValue() as number\n return <div className=\"text-right\"><span className={count === 0 ? 'text-red-600 font-medium' : ''}>{count}</span></div>\n },\n },\n {\n accessorKey: 'status', header: 'Status',\n cell: ({ getValue }) => {\n const status = getValue() as string\n return badge(status, statusColors[status] ?? 'bg-gray-100 text-gray-700')\n },\n },\n ], [])\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-4\">\n <input\n type=\"search\" value={search} onChange={handleSearch}\n placeholder=\"Buscar produtos...\"\n className=\"border rounded-lg px-3 py-2 text-sm w-64 focus:outline-none focus:ring-2 focus:ring-primary/50\"\n />\n <span className=\"text-sm text-muted-foreground\">{products.length} produtos</span>\n </div>\n\n {error ? (\n <ErrorState message={error} />\n ) : (\n <DataTable\n loading={loading}\n columns={columns}\n data={products}\n variant=\"card\"\n emptyMessage=\"Nenhum produto encontrado.\"\n />\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Orders tab\n// ---------------------------------------------------------------------------\n\nfunction OrdersTab({ provider }: ShopPageProps) {\n const { items: orders, loading, error } = useShopList<Order>(\n () => resolveShopProvider(provider).listOrders({ limit: 50 }),\n [provider],\n )\n\n const columns = useMemo<ColumnDef<Order, any>[]>(() => [\n { accessorKey: 'orderNumber', header: 'Pedido', cell: ({ getValue }) => <span className=\"font-medium\">#{getValue() as string}</span> },\n {\n id: 'customer', accessorFn: (o) => o.customerName ?? o.customerEmail ?? '—', header: 'Cliente',\n // Links to the customer record. stopPropagation because the row itself\n // opens the order — without it the click would do both.\n cell: ({ getValue, row }) => {\n const label = getValue() as string\n const id = row.original.customerId\n if (!id) return <span>{label}</span>\n return (\n <PersonLink\n personId={id}\n name={label}\n lookup={shopCustomerLookup(() => resolveShopProvider(provider))}\n profileHref={`#/customers/${id}`}\n />\n )\n },\n },\n {\n accessorKey: 'total', header: () => <span className=\"block text-right\">Total</span>,\n cell: ({ getValue, row }) => <div className=\"text-right font-medium\">{currency(getValue() as number, row.original.currency)}</div>,\n },\n {\n accessorKey: 'financialStatus', header: 'Pagamento',\n cell: ({ getValue }) => {\n const status = getValue() as string\n return badge(status, statusColors[status] ?? 'bg-gray-100 text-gray-700')\n },\n },\n {\n accessorKey: 'fulfillmentStatus', header: 'Entrega',\n cell: ({ getValue }) => {\n const status = getValue() as string\n return badge(status, statusColors[status] ?? 'bg-gray-100 text-gray-700')\n },\n },\n {\n accessorKey: 'createdAt', header: 'Data',\n cell: ({ getValue }) => {\n // Time matters operationally: two orders on the same day are picked,\n // packed and settled in the order they arrived.\n const d = new Date(getValue() as string)\n return (\n <span className=\"whitespace-nowrap text-muted-foreground\">\n {d.toLocaleDateString('pt-BR')}\n <span className=\"ml-1.5 text-xs opacity-70\">{d.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })}</span>\n </span>\n )\n },\n },\n ], [])\n\n return (\n <div>\n {error ? (\n <ErrorState message={error} />\n ) : (\n <DataTable\n loading={loading}\n columns={columns}\n data={orders}\n variant=\"card\"\n emptyMessage=\"Nenhum pedido ainda.\"\n onRowClick={(row: Order) => adminNavigateTo(`/shop/orders/${row.id}`)}\n />\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Customers tab\n// ---------------------------------------------------------------------------\n\nfunction CustomersTab({ provider }: ShopPageProps) {\n const { items: customers, loading, error } = useShopList<ShopCustomer>(\n () => resolveShopProvider(provider).listCustomers({ limit: 50 }),\n [provider],\n )\n\n const columns = useMemo<ColumnDef<ShopCustomer, any>[]>(() => [\n {\n id: 'name', accessorFn: (c) => `${c.firstName} ${c.lastName}`, header: 'Nome',\n cell: ({ row }) => <span className=\"font-medium\">{row.original.firstName} {row.original.lastName}</span>,\n },\n { accessorKey: 'email', header: 'Email', cell: ({ getValue }) => <span className=\"text-muted-foreground\">{(getValue() as string | undefined) ?? '—'}</span> },\n { accessorKey: 'phone', header: 'Telefone', cell: ({ getValue }) => <span className=\"text-muted-foreground\">{(getValue() as string | undefined) ?? '—'}</span> },\n {\n accessorKey: 'ordersCount', header: () => <span className=\"block text-right\">Pedidos</span>,\n cell: ({ getValue }) => <div className=\"text-right\">{getValue() as number}</div>,\n },\n {\n accessorKey: 'totalSpent', header: () => <span className=\"block text-right\">Total Gasto</span>,\n cell: ({ getValue }) => <div className=\"text-right\">{currency(getValue() as number)}</div>,\n },\n ], [])\n\n return (\n <div>\n {error ? (\n <ErrorState message={error} />\n ) : (\n <DataTable\n loading={loading}\n columns={columns}\n data={customers}\n variant=\"card\"\n emptyMessage=\"Nenhum cliente ainda.\"\n />\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Discounts tab\n// ---------------------------------------------------------------------------\n\nfunction DiscountsTab({ provider }: ShopPageProps) {\n const { items: discounts, loading, error } = useShopList<Discount>(\n () => resolveShopProvider(provider).listDiscounts({ limit: 50 }),\n [provider],\n )\n\n const columns = useMemo<ColumnDef<Discount, any>[]>(() => [\n { accessorKey: 'title', header: 'Título', cell: ({ getValue }) => <span className=\"font-medium\">{getValue() as string}</span> },\n { accessorKey: 'code', header: 'Código', cell: ({ getValue }) => <span className=\"font-mono text-sm\">{(getValue() as string | undefined) ?? '—'}</span> },\n { accessorKey: 'type', header: 'Tipo', cell: ({ getValue }) => <span className=\"text-muted-foreground\">{getValue() as string}</span> },\n {\n accessorKey: 'value', header: () => <span className=\"block text-right\">Valor</span>,\n cell: ({ row }) => <div className=\"text-right\">{row.original.type === 'percentage' ? `${row.original.value}%` : currency(row.original.value)}</div>,\n },\n {\n id: 'usos', accessorKey: 'timesUsed', header: () => <span className=\"block text-right\">Usos</span>,\n cell: ({ row }) => <div className=\"text-right\">{row.original.timesUsed}{row.original.usageLimit ? ` / ${row.original.usageLimit}` : ''}</div>,\n },\n {\n accessorKey: 'status', header: 'Status',\n cell: ({ getValue }) => {\n const status = getValue() as string\n return badge(status, statusColors[status] ?? 'bg-gray-100 text-gray-700')\n },\n },\n ], [])\n\n return (\n <div>\n {error ? (\n <ErrorState message={error} />\n ) : (\n <DataTable\n loading={loading}\n columns={columns}\n data={discounts}\n variant=\"card\"\n emptyMessage=\"Nenhum desconto cadastrado.\"\n />\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Main page\n// ---------------------------------------------------------------------------\n\nconst TABS = [\n { id: 'products', label: 'Produtos' },\n { id: 'orders', label: 'Pedidos' },\n { id: 'customers', label: 'Clientes' },\n { id: 'discounts', label: 'Descontos' },\n] as const\n\ntype TabId = typeof TABS[number]['id']\n\nconst TAB_COPY: Record<TabId, { title: string; subtitle: string }> = {\n products: { title: 'Produtos', subtitle: 'Catálogo da loja: preço, estoque e status.' },\n orders: { title: 'Pedidos', subtitle: 'Pedidos recebidos, pagamento e entrega.' },\n customers: { title: 'Clientes', subtitle: 'Quem comprou, quanto e com que frequência.' },\n discounts: { title: 'Descontos', subtitle: 'Cupons, regras de uso e desempenho.' },\n}\n\n/**\n * `section` pins the page to one area, which is how the sidebar routes\n * /shop/products, /shop/orders, … as separate entries. Without it the page\n * keeps its own tab bar — the single-route behaviour, still used by /shop.\n */\nexport const ShopPage: React.FC<ShopPageProps & { section?: TabId }> = ({ provider, section }) => {\n const [tab, setTab] = useState<TabId>(section ?? 'products')\n const active = section ?? tab\n\n // /shop/orders/<id> renders the detail. Orders deliberately do not go through\n // createCrudPage: an order is not an editable record, it is a document with\n // items, money and a shipment attached.\n const path = useAdminPath()\n const orderId = section === 'orders' ? path.match(/^\\/shop\\/orders\\/([^/]+)$/)?.[1] : undefined\n if (orderId) {\n return (\n <div className=\"p-6 max-w-7xl mx-auto\">\n <OrderDetailView\n orderId={orderId}\n provider={() => resolveShopProvider(provider)}\n onBack={() => adminNavigateTo('/shop/orders')}\n />\n </div>\n )\n }\n const copy = section ? TAB_COPY[section] : { title: 'Loja', subtitle: 'Gerencie produtos, pedidos, clientes e descontos.' }\n\n return (\n <div className=\"p-6 max-w-7xl mx-auto\">\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold\">{copy.title}</h1>\n <p className=\"text-muted-foreground mt-1\">{copy.subtitle}</p>\n </div>\n\n {!section && (\n <div className=\"border-b mb-6\">\n <nav className=\"flex gap-1\">\n {TABS.map(t => (\n <button\n key={t.id}\n onClick={() => setTab(t.id)}\n className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${\n tab === t.id\n ? 'border-primary text-primary'\n : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n >\n {t.label}\n </button>\n ))}\n </nav>\n </div>\n )}\n\n {active === 'products' && <ProductsTab provider={provider} />}\n {active === 'orders' && <OrdersTab provider={provider} />}\n {active === 'customers' && <CustomersTab provider={provider} />}\n {active === 'discounts' && <DiscountsTab provider={provider} />}\n </div>\n )\n}\n\nShopPage.displayName = 'ShopPage'\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React3 = require('react');
|
|
4
4
|
var shop = require('@fayz-ai/shop');
|
|
5
5
|
var saas = require('@fayz-ai/saas');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var lucideReact = require('lucide-react');
|
|
8
|
+
var ui = require('@fayz-ai/ui');
|
|
7
9
|
|
|
8
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
11
|
|
|
10
|
-
var
|
|
12
|
+
var React3__default = /*#__PURE__*/_interopDefault(React3);
|
|
11
13
|
|
|
12
14
|
// src/index.ts
|
|
13
15
|
function ProductImagesTab({ item, getProvider }) {
|
|
14
16
|
const product = item;
|
|
15
|
-
const [images, setImages] =
|
|
16
|
-
const [busy, setBusy] =
|
|
17
|
-
const [error, setError] =
|
|
18
|
-
const fileRef =
|
|
17
|
+
const [images, setImages] = React3.useState([]);
|
|
18
|
+
const [busy, setBusy] = React3.useState(false);
|
|
19
|
+
const [error, setError] = React3.useState(null);
|
|
20
|
+
const fileRef = React3.useRef(null);
|
|
19
21
|
async function reload() {
|
|
20
22
|
const fresh = await getProvider().getProduct(product.id);
|
|
21
23
|
setImages(sortImages(fresh?.images ?? []));
|
|
22
24
|
}
|
|
23
|
-
|
|
25
|
+
React3.useEffect(() => {
|
|
24
26
|
void reload().catch(() => {
|
|
25
27
|
});
|
|
26
28
|
}, [product.id]);
|
|
@@ -565,6 +567,19 @@ function buildShopDiscountEntity() {
|
|
|
565
567
|
renderCell: (_v, row) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-right font-medium", children: row.type === "percentage" ? `${row.value}%` : row.type === "free_shipping" ? "\u2014" : new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(Number(row.value) || 0) })
|
|
566
568
|
},
|
|
567
569
|
// — Limites —
|
|
570
|
+
{
|
|
571
|
+
key: "minSubtotal",
|
|
572
|
+
label: "Pedido m\xEDnimo",
|
|
573
|
+
type: "currency",
|
|
574
|
+
group: "limits",
|
|
575
|
+
min: 0,
|
|
576
|
+
currency: "BRL",
|
|
577
|
+
currencySymbol: "R$",
|
|
578
|
+
currencyLocale: "pt-BR",
|
|
579
|
+
placeholder: "sem m\xEDnimo",
|
|
580
|
+
hint: "Valor m\xEDnimo do pedido para o cupom valer. Deixe vazio para n\xE3o exigir m\xEDnimo.",
|
|
581
|
+
showInTable: false
|
|
582
|
+
},
|
|
568
583
|
{
|
|
569
584
|
key: "usageLimit",
|
|
570
585
|
label: "Limite de usos",
|
|
@@ -926,15 +941,15 @@ var LOCALES = [
|
|
|
926
941
|
{ value: "es-ES", label: "Espa\xF1ol" }
|
|
927
942
|
];
|
|
928
943
|
function ShopSettings({ currency }) {
|
|
929
|
-
const [code, setCode] =
|
|
930
|
-
const [locale, setLocale] =
|
|
931
|
-
const [showOutOfStock, setShowOutOfStock] =
|
|
932
|
-
const [trackInventory, setTrackInventory] =
|
|
933
|
-
const [requireSku, setRequireSku] =
|
|
934
|
-
const [guestCheckout, setGuestCheckout] =
|
|
935
|
-
const [enableDiscounts, setEnableDiscounts] =
|
|
936
|
-
const [orderEmails, setOrderEmails] =
|
|
937
|
-
const [lowStockAlerts, setLowStockAlerts] =
|
|
944
|
+
const [code, setCode] = React3__default.default.useState(currency?.code ?? "BRL");
|
|
945
|
+
const [locale, setLocale] = React3__default.default.useState(currency?.locale ?? "pt-BR");
|
|
946
|
+
const [showOutOfStock, setShowOutOfStock] = React3__default.default.useState(true);
|
|
947
|
+
const [trackInventory, setTrackInventory] = React3__default.default.useState(true);
|
|
948
|
+
const [requireSku, setRequireSku] = React3__default.default.useState(false);
|
|
949
|
+
const [guestCheckout, setGuestCheckout] = React3__default.default.useState(true);
|
|
950
|
+
const [enableDiscounts, setEnableDiscounts] = React3__default.default.useState(true);
|
|
951
|
+
const [orderEmails, setOrderEmails] = React3__default.default.useState(true);
|
|
952
|
+
const [lowStockAlerts, setLowStockAlerts] = React3__default.default.useState(false);
|
|
938
953
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
939
954
|
/* @__PURE__ */ jsxRuntime.jsxs(saas.SettingsGroup, { title: "Loja", description: "Moeda e formata\xE7\xE3o da vitrine.", children: [
|
|
940
955
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1029,18 +1044,197 @@ function ShopSettings({ currency }) {
|
|
|
1029
1044
|
] })
|
|
1030
1045
|
] });
|
|
1031
1046
|
}
|
|
1047
|
+
var KIND_META = {
|
|
1048
|
+
online_store: { label: "Loja Online", icon: lucideReact.Globe, hint: "Seu storefront fayz \u2014 a vitrine p\xFAblica da loja.", placeholder: "https://minhaloja.com.br/" },
|
|
1049
|
+
whatsapp: { label: "WhatsApp", icon: lucideReact.MessageCircle, hint: "Link direto para o WhatsApp Business.", placeholder: "https://wa.me/5521999999999" },
|
|
1050
|
+
instagram: { label: "Instagram", icon: lucideReact.Camera, hint: "Perfil ou loja no Instagram.", placeholder: "https://instagram.com/sualoja" },
|
|
1051
|
+
tiktok_shop: { label: "TikTok Shop", icon: lucideReact.Music, hint: "Sua vitrine no TikTok Shop.", placeholder: "https://shop.tiktok.com/@sualoja" },
|
|
1052
|
+
marketplace: { label: "Marketplace", icon: lucideReact.ShoppingBag, hint: "Mercado Livre, Amazon, Shopee\u2026", placeholder: "https://\u2026" },
|
|
1053
|
+
physical: { label: "Loja F\xEDsica", icon: lucideReact.MapPin, hint: "Endere\xE7o ou ponto de venda f\xEDsico.", placeholder: "https://maps.google.com/\u2026" },
|
|
1054
|
+
custom: { label: "Outro canal", icon: lucideReact.Link2, hint: "Qualquer outro ponto de venda com um link.", placeholder: "https://\u2026" }
|
|
1055
|
+
};
|
|
1056
|
+
var ADDABLE_KINDS = ["whatsapp", "instagram", "tiktok_shop", "marketplace", "physical", "custom"];
|
|
1057
|
+
function resolve2(resolver) {
|
|
1058
|
+
return typeof resolver === "function" ? resolver() : resolver ?? shop.getShopProvider();
|
|
1059
|
+
}
|
|
1060
|
+
function notifyChannelsChanged() {
|
|
1061
|
+
if (typeof window !== "undefined") window.dispatchEvent(new Event("fayz:channels-changed"));
|
|
1062
|
+
}
|
|
1063
|
+
function ChannelsPage({ resolveProvider }) {
|
|
1064
|
+
const provider = React3__default.default.useMemo(() => resolve2(resolveProvider), [resolveProvider]);
|
|
1065
|
+
const supported = typeof provider.listSalesChannels === "function";
|
|
1066
|
+
const [channels, setChannels] = React3__default.default.useState([]);
|
|
1067
|
+
const [loading, setLoading] = React3__default.default.useState(true);
|
|
1068
|
+
const [adding, setAdding] = React3__default.default.useState(null);
|
|
1069
|
+
const reload = React3__default.default.useCallback(async () => {
|
|
1070
|
+
if (!provider.listSalesChannels) {
|
|
1071
|
+
setLoading(false);
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
setLoading(true);
|
|
1075
|
+
try {
|
|
1076
|
+
const rows = await provider.listSalesChannels();
|
|
1077
|
+
if (!rows.some((c) => c.kind === "online_store") && provider.createSalesChannel) {
|
|
1078
|
+
await provider.createSalesChannel({ kind: "online_store", label: "Loja Online", enabled: true, position: 0 });
|
|
1079
|
+
setChannels(await provider.listSalesChannels());
|
|
1080
|
+
} else {
|
|
1081
|
+
setChannels(rows);
|
|
1082
|
+
}
|
|
1083
|
+
} finally {
|
|
1084
|
+
setLoading(false);
|
|
1085
|
+
}
|
|
1086
|
+
}, [provider]);
|
|
1087
|
+
React3__default.default.useEffect(() => {
|
|
1088
|
+
void reload();
|
|
1089
|
+
}, [reload]);
|
|
1090
|
+
const patch = async (id, input) => {
|
|
1091
|
+
if (!provider.updateSalesChannel) return;
|
|
1092
|
+
const updated = await provider.updateSalesChannel(id, input);
|
|
1093
|
+
setChannels((prev) => prev.map((c) => c.id === id ? updated : c));
|
|
1094
|
+
notifyChannelsChanged();
|
|
1095
|
+
};
|
|
1096
|
+
const remove = async (id) => {
|
|
1097
|
+
if (!provider.deleteSalesChannel) return;
|
|
1098
|
+
await provider.deleteSalesChannel(id);
|
|
1099
|
+
setChannels((prev) => prev.filter((c) => c.id !== id));
|
|
1100
|
+
notifyChannelsChanged();
|
|
1101
|
+
};
|
|
1102
|
+
const add = async (kind, label, url) => {
|
|
1103
|
+
if (!provider.createSalesChannel) return;
|
|
1104
|
+
const created = await provider.createSalesChannel({ kind, label: label || KIND_META[kind].label, url: url || null, enabled: true, position: channels.length });
|
|
1105
|
+
setChannels((prev) => [...prev, created]);
|
|
1106
|
+
setAdding(null);
|
|
1107
|
+
notifyChannelsChanged();
|
|
1108
|
+
};
|
|
1109
|
+
if (!supported) {
|
|
1110
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-4xl p-6", children: [
|
|
1111
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Canais de venda" }),
|
|
1112
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Este provedor de loja ainda n\xE3o exp\xF5e canais de venda." })
|
|
1113
|
+
] });
|
|
1114
|
+
}
|
|
1115
|
+
const online = channels.find((c) => c.kind === "online_store");
|
|
1116
|
+
const others = channels.filter((c) => c.kind !== "online_store");
|
|
1117
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-4xl p-6", children: [
|
|
1118
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6", children: [
|
|
1119
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Canais de venda" }),
|
|
1120
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Onde sua loja vende. A Loja Online \xE9 o seu storefront fayz; os demais s\xE3o links que aparecem no menu lateral." })
|
|
1121
|
+
] }),
|
|
1122
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Carregando\u2026" }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
1123
|
+
online && /* @__PURE__ */ jsxRuntime.jsx(OnlineStoreCard, { channel: online, onSave: (url) => patch(online.id, { url }), onToggle: (enabled) => patch(online.id, { enabled }) }),
|
|
1124
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1125
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm font-semibold text-foreground", children: "Outros canais" }) }),
|
|
1126
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
1127
|
+
others.map((c) => /* @__PURE__ */ jsxRuntime.jsx(ChannelRow, { channel: c, onSave: (url) => patch(c.id, { url }), onToggle: (enabled) => patch(c.id, { enabled }), onRemove: () => remove(c.id) }, c.id)),
|
|
1128
|
+
others.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rounded-card border border-dashed border-border p-4 text-sm text-muted-foreground", children: "Nenhum canal adicional ainda. Adicione WhatsApp, Instagram, TikTok Shop e outros pontos de venda." })
|
|
1129
|
+
] }),
|
|
1130
|
+
adding ? /* @__PURE__ */ jsxRuntime.jsx(AddChannelForm, { kind: adding, onCancel: () => setAdding(null), onAdd: (label, url) => add(adding, label, url), onKind: setAdding }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: ADDABLE_KINDS.map((k) => {
|
|
1131
|
+
const Icon = KIND_META[k].icon;
|
|
1132
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "outline", size: "sm", onClick: () => setAdding(k), children: [
|
|
1133
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
1134
|
+
" ",
|
|
1135
|
+
KIND_META[k].label
|
|
1136
|
+
] }, k);
|
|
1137
|
+
}) })
|
|
1138
|
+
] })
|
|
1139
|
+
] })
|
|
1140
|
+
] });
|
|
1141
|
+
}
|
|
1142
|
+
function OnlineStoreCard({ channel, onSave, onToggle }) {
|
|
1143
|
+
const [url, setUrl] = React3__default.default.useState(channel.url ?? "");
|
|
1144
|
+
const dirty = (channel.url ?? "") !== url;
|
|
1145
|
+
const meta = KIND_META.online_store;
|
|
1146
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-card border border-border bg-card p-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
1147
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(meta.icon, { className: "h-5 w-5 text-primary" }) }),
|
|
1148
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1149
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1150
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: "Loja Online" }),
|
|
1151
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${channel.enabled ? "bg-emerald-100 text-emerald-800" : "bg-muted text-muted-foreground"}`, children: channel.enabled ? "Ativa" : "Inativa" })
|
|
1152
|
+
] }),
|
|
1153
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-sm text-muted-foreground", children: meta.hint }),
|
|
1154
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-col gap-2 sm:flex-row sm:items-center", children: [
|
|
1155
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: url, placeholder: meta.placeholder, onChange: (e) => setUrl(e.target.value), className: "flex-1" }),
|
|
1156
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
1157
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "sm", disabled: !dirty, onClick: () => onSave(url.trim() || null), children: "Salvar" }),
|
|
1158
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "sm", variant: "outline", disabled: !channel.url, onClick: () => channel.url && window.open(channel.url, "_blank", "noopener,noreferrer"), children: [
|
|
1159
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
1160
|
+
" Ver loja"
|
|
1161
|
+
] })
|
|
1162
|
+
] })
|
|
1163
|
+
] }),
|
|
1164
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onToggle(!channel.enabled), className: "text-xs font-medium text-muted-foreground hover:text-foreground", children: channel.enabled ? "Desativar canal" : "Ativar canal" }) })
|
|
1165
|
+
] })
|
|
1166
|
+
] }) });
|
|
1167
|
+
}
|
|
1168
|
+
function ChannelRow({ channel, onSave, onToggle, onRemove }) {
|
|
1169
|
+
const [url, setUrl] = React3__default.default.useState(channel.url ?? "");
|
|
1170
|
+
const [editing, setEditing] = React3__default.default.useState(false);
|
|
1171
|
+
const meta = KIND_META[channel.kind] ?? KIND_META.custom;
|
|
1172
|
+
const Icon = meta.icon;
|
|
1173
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-card border border-border bg-card p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1174
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-9 w-9 shrink-0 items-center justify-center rounded-full ${channel.enabled ? "bg-primary/10" : "bg-muted"}`, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: `h-4 w-4 ${channel.enabled ? "text-primary" : "text-muted-foreground"}` }) }),
|
|
1175
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1176
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-medium text-foreground", children: channel.label }),
|
|
1177
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: url, placeholder: meta.placeholder, onChange: (e) => setUrl(e.target.value), className: "mt-1 h-8" }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-muted-foreground", children: channel.url || "Sem link configurado" })
|
|
1178
|
+
] }),
|
|
1179
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-1", children: editing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1180
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "sm", variant: "ghost", onClick: () => {
|
|
1181
|
+
onSave(url.trim() || null);
|
|
1182
|
+
setEditing(false);
|
|
1183
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" }) }),
|
|
1184
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "sm", variant: "ghost", onClick: () => {
|
|
1185
|
+
setUrl(channel.url ?? "");
|
|
1186
|
+
setEditing(false);
|
|
1187
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }) })
|
|
1188
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1189
|
+
channel.url && /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "sm", variant: "ghost", onClick: () => window.open(channel.url, "_blank", "noopener,noreferrer"), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4" }) }),
|
|
1190
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onToggle(!channel.enabled), title: channel.enabled ? "Desativar" : "Ativar", className: `rounded-full px-2 py-0.5 text-xs font-medium ${channel.enabled ? "bg-emerald-100 text-emerald-800" : "bg-muted text-muted-foreground"}`, children: channel.enabled ? "Ativo" : "Inativo" }),
|
|
1191
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "sm", variant: "ghost", onClick: () => setEditing(true), children: "Editar" }),
|
|
1192
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "sm", variant: "ghost", onClick: onRemove, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4 text-red-500" }) })
|
|
1193
|
+
] }) })
|
|
1194
|
+
] }) });
|
|
1195
|
+
}
|
|
1196
|
+
function AddChannelForm({ kind, onKind, onCancel, onAdd }) {
|
|
1197
|
+
const meta = KIND_META[kind];
|
|
1198
|
+
const [label, setLabel] = React3__default.default.useState(meta.label);
|
|
1199
|
+
const [url, setUrl] = React3__default.default.useState("");
|
|
1200
|
+
React3__default.default.useEffect(() => {
|
|
1201
|
+
setLabel(KIND_META[kind].label);
|
|
1202
|
+
}, [kind]);
|
|
1203
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 rounded-card border border-border bg-card p-4", children: [
|
|
1204
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-3 flex flex-wrap gap-2", children: ADDABLE_KINDS.map((k) => {
|
|
1205
|
+
const Icon = KIND_META[k].icon;
|
|
1206
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: () => onKind(k), className: `flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-medium ${k === kind ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"}`, children: [
|
|
1207
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3.5 w-3.5" }),
|
|
1208
|
+
" ",
|
|
1209
|
+
KIND_META[k].label
|
|
1210
|
+
] }, k);
|
|
1211
|
+
}) }),
|
|
1212
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-muted-foreground", children: meta.hint }),
|
|
1213
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [
|
|
1214
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: label, placeholder: "Nome do canal", onChange: (e) => setLabel(e.target.value), className: "sm:w-48" }),
|
|
1215
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: url, placeholder: meta.placeholder, onChange: (e) => setUrl(e.target.value), className: "flex-1" })
|
|
1216
|
+
] }),
|
|
1217
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex gap-2", children: [
|
|
1218
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "sm", onClick: () => onAdd(label, url), children: [
|
|
1219
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
1220
|
+
" Adicionar"
|
|
1221
|
+
] }),
|
|
1222
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "sm", variant: "outline", onClick: onCancel, children: "Cancelar" })
|
|
1223
|
+
] })
|
|
1224
|
+
] });
|
|
1225
|
+
}
|
|
1032
1226
|
|
|
1033
1227
|
// src/index.ts
|
|
1034
|
-
var ShopPage =
|
|
1228
|
+
var ShopPage = React3__default.default.lazy(() => import('./ShopPage-NK6FSPJ5.cjs').then((m) => ({ default: m.ShopPage })));
|
|
1035
1229
|
function createShopPlugin(options) {
|
|
1036
1230
|
const curr = { code: "BRL", locale: "pt-BR", symbol: "R$", ...options?.currency };
|
|
1037
1231
|
shop.setShopTenantResolver(() => saas.useOrganizationStore.getState().currentOrg?.id);
|
|
1038
|
-
saas.registerEntityPath("shop_customer", "/
|
|
1232
|
+
saas.registerEntityPath("shop_customer", "/customers");
|
|
1039
1233
|
const pageFor = (section) => {
|
|
1040
|
-
const Wrapped = () =>
|
|
1041
|
-
|
|
1234
|
+
const Wrapped = () => React3__default.default.createElement(
|
|
1235
|
+
React3__default.default.Suspense,
|
|
1042
1236
|
{ fallback: null },
|
|
1043
|
-
|
|
1237
|
+
React3__default.default.createElement(
|
|
1044
1238
|
ShopPage,
|
|
1045
1239
|
{ provider: options?.provider, section }
|
|
1046
1240
|
)
|
|
@@ -1074,10 +1268,12 @@ function createShopPlugin(options) {
|
|
|
1074
1268
|
const SECTIONS = [
|
|
1075
1269
|
{ id: "products", label: options?.sectionLabels?.products ?? "Produtos", icon: "Package" },
|
|
1076
1270
|
{ id: "orders", label: options?.sectionLabels?.orders ?? "Pedidos", icon: "ShoppingCart" },
|
|
1077
|
-
{ id: "customers", label: options?.sectionLabels?.customers ?? "Clientes", icon: "Users" },
|
|
1078
1271
|
{ id: "discounts", label: options?.sectionLabels?.discounts ?? "Descontos", icon: "Tag" },
|
|
1079
1272
|
{ id: "shipping", label: options?.sectionLabels?.shipping ?? "Entrega", icon: "Truck" }
|
|
1080
1273
|
];
|
|
1274
|
+
const CustomersNavLabel = options?.sectionLabels?.customers ?? "Clientes";
|
|
1275
|
+
const ChannelsPageWrapped = () => React3__default.default.createElement(ChannelsPage, { resolveProvider: options?.provider });
|
|
1276
|
+
ChannelsPageWrapped.displayName = "ChannelsPage";
|
|
1081
1277
|
const navSection = options?.navSection ?? "main";
|
|
1082
1278
|
const navPosition = options?.navPosition ?? 6;
|
|
1083
1279
|
return {
|
|
@@ -1110,7 +1306,27 @@ function createShopPlugin(options) {
|
|
|
1110
1306
|
route: `/shop/${s.id}`,
|
|
1111
1307
|
icon: s.icon,
|
|
1112
1308
|
permission: { feature: "shop", action: "read" }
|
|
1113
|
-
}))
|
|
1309
|
+
})),
|
|
1310
|
+
// Clientes — top-level (route not under /shop, so it leaves the accordion).
|
|
1311
|
+
// Fractional position keeps it right below "Loja", above other plugins.
|
|
1312
|
+
{
|
|
1313
|
+
section: navSection,
|
|
1314
|
+
position: navPosition + 0.5,
|
|
1315
|
+
label: CustomersNavLabel,
|
|
1316
|
+
route: "/customers",
|
|
1317
|
+
icon: "Users",
|
|
1318
|
+
permission: { feature: "shop", action: "read" }
|
|
1319
|
+
},
|
|
1320
|
+
// Canais de venda — inside the "Loja" group (route under /shop nests it in
|
|
1321
|
+
// the accordion). The store's points of sale (Loja Online, WhatsApp, …).
|
|
1322
|
+
{
|
|
1323
|
+
section: navSection,
|
|
1324
|
+
position: navPosition + SECTIONS.length + 1,
|
|
1325
|
+
label: "Canais de venda",
|
|
1326
|
+
route: "/shop/channels",
|
|
1327
|
+
icon: "Radio",
|
|
1328
|
+
permission: { feature: "shop", action: "read" }
|
|
1329
|
+
}
|
|
1114
1330
|
],
|
|
1115
1331
|
routes: [
|
|
1116
1332
|
{
|
|
@@ -1123,7 +1339,19 @@ function createShopPlugin(options) {
|
|
|
1123
1339
|
path: `/shop/${s.id}`,
|
|
1124
1340
|
component: CRUD_PAGES[s.id] ?? pageFor(s.id),
|
|
1125
1341
|
permission: { feature: "shop", action: "read" }
|
|
1126
|
-
}))
|
|
1342
|
+
})),
|
|
1343
|
+
// Clientes at the top level, same CRUD page as before.
|
|
1344
|
+
{
|
|
1345
|
+
path: "/customers",
|
|
1346
|
+
component: CustomersCrudPage,
|
|
1347
|
+
permission: { feature: "shop", action: "read" }
|
|
1348
|
+
},
|
|
1349
|
+
// Canais de venda management page (under the Loja group).
|
|
1350
|
+
{
|
|
1351
|
+
path: "/shop/channels",
|
|
1352
|
+
component: ChannelsPageWrapped,
|
|
1353
|
+
permission: { feature: "shop", action: "read" }
|
|
1354
|
+
}
|
|
1127
1355
|
],
|
|
1128
1356
|
widgets: [],
|
|
1129
1357
|
aiTools: [
|
|
@@ -1172,7 +1400,7 @@ function createShopPlugin(options) {
|
|
|
1172
1400
|
label: "Shop",
|
|
1173
1401
|
icon: "ShoppingBag",
|
|
1174
1402
|
component: (() => {
|
|
1175
|
-
const ShopSettingsTab = () =>
|
|
1403
|
+
const ShopSettingsTab = () => React3__default.default.createElement(ShopSettings, { currency: curr });
|
|
1176
1404
|
ShopSettingsTab.displayName = "ShopSettingsTab";
|
|
1177
1405
|
return ShopSettingsTab;
|
|
1178
1406
|
})(),
|