@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
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React3, { useState, useRef, useEffect } from 'react';
|
|
2
2
|
import { setShopTenantResolver, getShopProvider } from '@fayz-ai/shop';
|
|
3
3
|
import { useOrganizationStore, registerEntityPath, createCrudPage, ClientOrdersTab, adminNavigateTo, createClientOrdersProvider, SettingsGroup, SelectRow, ToggleRow } from '@fayz-ai/saas';
|
|
4
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
import { Link2, MapPin, ShoppingBag, Music, Camera, MessageCircle, Globe, ExternalLink, Check, X, Trash2, Plus } from 'lucide-react';
|
|
6
|
+
import { Button, Input } from '@fayz-ai/ui';
|
|
5
7
|
|
|
6
8
|
// src/index.ts
|
|
7
9
|
function ProductImagesTab({ item, getProvider }) {
|
|
@@ -559,6 +561,19 @@ function buildShopDiscountEntity() {
|
|
|
559
561
|
renderCell: (_v, row) => /* @__PURE__ */ 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) })
|
|
560
562
|
},
|
|
561
563
|
// — Limites —
|
|
564
|
+
{
|
|
565
|
+
key: "minSubtotal",
|
|
566
|
+
label: "Pedido m\xEDnimo",
|
|
567
|
+
type: "currency",
|
|
568
|
+
group: "limits",
|
|
569
|
+
min: 0,
|
|
570
|
+
currency: "BRL",
|
|
571
|
+
currencySymbol: "R$",
|
|
572
|
+
currencyLocale: "pt-BR",
|
|
573
|
+
placeholder: "sem m\xEDnimo",
|
|
574
|
+
hint: "Valor m\xEDnimo do pedido para o cupom valer. Deixe vazio para n\xE3o exigir m\xEDnimo.",
|
|
575
|
+
showInTable: false
|
|
576
|
+
},
|
|
562
577
|
{
|
|
563
578
|
key: "usageLimit",
|
|
564
579
|
label: "Limite de usos",
|
|
@@ -920,15 +935,15 @@ var LOCALES = [
|
|
|
920
935
|
{ value: "es-ES", label: "Espa\xF1ol" }
|
|
921
936
|
];
|
|
922
937
|
function ShopSettings({ currency }) {
|
|
923
|
-
const [code, setCode] =
|
|
924
|
-
const [locale, setLocale] =
|
|
925
|
-
const [showOutOfStock, setShowOutOfStock] =
|
|
926
|
-
const [trackInventory, setTrackInventory] =
|
|
927
|
-
const [requireSku, setRequireSku] =
|
|
928
|
-
const [guestCheckout, setGuestCheckout] =
|
|
929
|
-
const [enableDiscounts, setEnableDiscounts] =
|
|
930
|
-
const [orderEmails, setOrderEmails] =
|
|
931
|
-
const [lowStockAlerts, setLowStockAlerts] =
|
|
938
|
+
const [code, setCode] = React3.useState(currency?.code ?? "BRL");
|
|
939
|
+
const [locale, setLocale] = React3.useState(currency?.locale ?? "pt-BR");
|
|
940
|
+
const [showOutOfStock, setShowOutOfStock] = React3.useState(true);
|
|
941
|
+
const [trackInventory, setTrackInventory] = React3.useState(true);
|
|
942
|
+
const [requireSku, setRequireSku] = React3.useState(false);
|
|
943
|
+
const [guestCheckout, setGuestCheckout] = React3.useState(true);
|
|
944
|
+
const [enableDiscounts, setEnableDiscounts] = React3.useState(true);
|
|
945
|
+
const [orderEmails, setOrderEmails] = React3.useState(true);
|
|
946
|
+
const [lowStockAlerts, setLowStockAlerts] = React3.useState(false);
|
|
932
947
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
933
948
|
/* @__PURE__ */ jsxs(SettingsGroup, { title: "Loja", description: "Moeda e formata\xE7\xE3o da vitrine.", children: [
|
|
934
949
|
/* @__PURE__ */ jsx(
|
|
@@ -1023,18 +1038,197 @@ function ShopSettings({ currency }) {
|
|
|
1023
1038
|
] })
|
|
1024
1039
|
] });
|
|
1025
1040
|
}
|
|
1041
|
+
var KIND_META = {
|
|
1042
|
+
online_store: { label: "Loja Online", icon: Globe, hint: "Seu storefront fayz \u2014 a vitrine p\xFAblica da loja.", placeholder: "https://minhaloja.com.br/" },
|
|
1043
|
+
whatsapp: { label: "WhatsApp", icon: MessageCircle, hint: "Link direto para o WhatsApp Business.", placeholder: "https://wa.me/5521999999999" },
|
|
1044
|
+
instagram: { label: "Instagram", icon: Camera, hint: "Perfil ou loja no Instagram.", placeholder: "https://instagram.com/sualoja" },
|
|
1045
|
+
tiktok_shop: { label: "TikTok Shop", icon: Music, hint: "Sua vitrine no TikTok Shop.", placeholder: "https://shop.tiktok.com/@sualoja" },
|
|
1046
|
+
marketplace: { label: "Marketplace", icon: ShoppingBag, hint: "Mercado Livre, Amazon, Shopee\u2026", placeholder: "https://\u2026" },
|
|
1047
|
+
physical: { label: "Loja F\xEDsica", icon: MapPin, hint: "Endere\xE7o ou ponto de venda f\xEDsico.", placeholder: "https://maps.google.com/\u2026" },
|
|
1048
|
+
custom: { label: "Outro canal", icon: Link2, hint: "Qualquer outro ponto de venda com um link.", placeholder: "https://\u2026" }
|
|
1049
|
+
};
|
|
1050
|
+
var ADDABLE_KINDS = ["whatsapp", "instagram", "tiktok_shop", "marketplace", "physical", "custom"];
|
|
1051
|
+
function resolve2(resolver) {
|
|
1052
|
+
return typeof resolver === "function" ? resolver() : resolver ?? getShopProvider();
|
|
1053
|
+
}
|
|
1054
|
+
function notifyChannelsChanged() {
|
|
1055
|
+
if (typeof window !== "undefined") window.dispatchEvent(new Event("fayz:channels-changed"));
|
|
1056
|
+
}
|
|
1057
|
+
function ChannelsPage({ resolveProvider }) {
|
|
1058
|
+
const provider = React3.useMemo(() => resolve2(resolveProvider), [resolveProvider]);
|
|
1059
|
+
const supported = typeof provider.listSalesChannels === "function";
|
|
1060
|
+
const [channels, setChannels] = React3.useState([]);
|
|
1061
|
+
const [loading, setLoading] = React3.useState(true);
|
|
1062
|
+
const [adding, setAdding] = React3.useState(null);
|
|
1063
|
+
const reload = React3.useCallback(async () => {
|
|
1064
|
+
if (!provider.listSalesChannels) {
|
|
1065
|
+
setLoading(false);
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
setLoading(true);
|
|
1069
|
+
try {
|
|
1070
|
+
const rows = await provider.listSalesChannels();
|
|
1071
|
+
if (!rows.some((c) => c.kind === "online_store") && provider.createSalesChannel) {
|
|
1072
|
+
await provider.createSalesChannel({ kind: "online_store", label: "Loja Online", enabled: true, position: 0 });
|
|
1073
|
+
setChannels(await provider.listSalesChannels());
|
|
1074
|
+
} else {
|
|
1075
|
+
setChannels(rows);
|
|
1076
|
+
}
|
|
1077
|
+
} finally {
|
|
1078
|
+
setLoading(false);
|
|
1079
|
+
}
|
|
1080
|
+
}, [provider]);
|
|
1081
|
+
React3.useEffect(() => {
|
|
1082
|
+
void reload();
|
|
1083
|
+
}, [reload]);
|
|
1084
|
+
const patch = async (id, input) => {
|
|
1085
|
+
if (!provider.updateSalesChannel) return;
|
|
1086
|
+
const updated = await provider.updateSalesChannel(id, input);
|
|
1087
|
+
setChannels((prev) => prev.map((c) => c.id === id ? updated : c));
|
|
1088
|
+
notifyChannelsChanged();
|
|
1089
|
+
};
|
|
1090
|
+
const remove = async (id) => {
|
|
1091
|
+
if (!provider.deleteSalesChannel) return;
|
|
1092
|
+
await provider.deleteSalesChannel(id);
|
|
1093
|
+
setChannels((prev) => prev.filter((c) => c.id !== id));
|
|
1094
|
+
notifyChannelsChanged();
|
|
1095
|
+
};
|
|
1096
|
+
const add = async (kind, label, url) => {
|
|
1097
|
+
if (!provider.createSalesChannel) return;
|
|
1098
|
+
const created = await provider.createSalesChannel({ kind, label: label || KIND_META[kind].label, url: url || null, enabled: true, position: channels.length });
|
|
1099
|
+
setChannels((prev) => [...prev, created]);
|
|
1100
|
+
setAdding(null);
|
|
1101
|
+
notifyChannelsChanged();
|
|
1102
|
+
};
|
|
1103
|
+
if (!supported) {
|
|
1104
|
+
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl p-6", children: [
|
|
1105
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Canais de venda" }),
|
|
1106
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Este provedor de loja ainda n\xE3o exp\xF5e canais de venda." })
|
|
1107
|
+
] });
|
|
1108
|
+
}
|
|
1109
|
+
const online = channels.find((c) => c.kind === "online_store");
|
|
1110
|
+
const others = channels.filter((c) => c.kind !== "online_store");
|
|
1111
|
+
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl p-6", children: [
|
|
1112
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
1113
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Canais de venda" }),
|
|
1114
|
+
/* @__PURE__ */ 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." })
|
|
1115
|
+
] }),
|
|
1116
|
+
loading ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Carregando\u2026" }) : /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
1117
|
+
online && /* @__PURE__ */ jsx(OnlineStoreCard, { channel: online, onSave: (url) => patch(online.id, { url }), onToggle: (enabled) => patch(online.id, { enabled }) }),
|
|
1118
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1119
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2 flex items-center justify-between", children: /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-foreground", children: "Outros canais" }) }),
|
|
1120
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1121
|
+
others.map((c) => /* @__PURE__ */ jsx(ChannelRow, { channel: c, onSave: (url) => patch(c.id, { url }), onToggle: (enabled) => patch(c.id, { enabled }), onRemove: () => remove(c.id) }, c.id)),
|
|
1122
|
+
others.length === 0 && /* @__PURE__ */ 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." })
|
|
1123
|
+
] }),
|
|
1124
|
+
adding ? /* @__PURE__ */ jsx(AddChannelForm, { kind: adding, onCancel: () => setAdding(null), onAdd: (label, url) => add(adding, label, url), onKind: setAdding }) : /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: ADDABLE_KINDS.map((k) => {
|
|
1125
|
+
const Icon = KIND_META[k].icon;
|
|
1126
|
+
return /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => setAdding(k), children: [
|
|
1127
|
+
/* @__PURE__ */ jsx(Icon, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
1128
|
+
" ",
|
|
1129
|
+
KIND_META[k].label
|
|
1130
|
+
] }, k);
|
|
1131
|
+
}) })
|
|
1132
|
+
] })
|
|
1133
|
+
] })
|
|
1134
|
+
] });
|
|
1135
|
+
}
|
|
1136
|
+
function OnlineStoreCard({ channel, onSave, onToggle }) {
|
|
1137
|
+
const [url, setUrl] = React3.useState(channel.url ?? "");
|
|
1138
|
+
const dirty = (channel.url ?? "") !== url;
|
|
1139
|
+
const meta = KIND_META.online_store;
|
|
1140
|
+
return /* @__PURE__ */ jsx("div", { className: "rounded-card border border-border bg-card p-5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
1141
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx(meta.icon, { className: "h-5 w-5 text-primary" }) }),
|
|
1142
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1143
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1144
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: "Loja Online" }),
|
|
1145
|
+
/* @__PURE__ */ 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" })
|
|
1146
|
+
] }),
|
|
1147
|
+
/* @__PURE__ */ jsx("p", { className: "mt-0.5 text-sm text-muted-foreground", children: meta.hint }),
|
|
1148
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-col gap-2 sm:flex-row sm:items-center", children: [
|
|
1149
|
+
/* @__PURE__ */ jsx(Input, { value: url, placeholder: meta.placeholder, onChange: (e) => setUrl(e.target.value), className: "flex-1" }),
|
|
1150
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
1151
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", disabled: !dirty, onClick: () => onSave(url.trim() || null), children: "Salvar" }),
|
|
1152
|
+
/* @__PURE__ */ jsxs(Button, { size: "sm", variant: "outline", disabled: !channel.url, onClick: () => channel.url && window.open(channel.url, "_blank", "noopener,noreferrer"), children: [
|
|
1153
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
1154
|
+
" Ver loja"
|
|
1155
|
+
] })
|
|
1156
|
+
] })
|
|
1157
|
+
] }),
|
|
1158
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ 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" }) })
|
|
1159
|
+
] })
|
|
1160
|
+
] }) });
|
|
1161
|
+
}
|
|
1162
|
+
function ChannelRow({ channel, onSave, onToggle, onRemove }) {
|
|
1163
|
+
const [url, setUrl] = React3.useState(channel.url ?? "");
|
|
1164
|
+
const [editing, setEditing] = React3.useState(false);
|
|
1165
|
+
const meta = KIND_META[channel.kind] ?? KIND_META.custom;
|
|
1166
|
+
const Icon = meta.icon;
|
|
1167
|
+
return /* @__PURE__ */ jsx("div", { className: "rounded-card border border-border bg-card p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1168
|
+
/* @__PURE__ */ 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__ */ jsx(Icon, { className: `h-4 w-4 ${channel.enabled ? "text-primary" : "text-muted-foreground"}` }) }),
|
|
1169
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1170
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-foreground", children: channel.label }),
|
|
1171
|
+
editing ? /* @__PURE__ */ jsx(Input, { value: url, placeholder: meta.placeholder, onChange: (e) => setUrl(e.target.value), className: "mt-1 h-8" }) : /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: channel.url || "Sem link configurado" })
|
|
1172
|
+
] }),
|
|
1173
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1", children: editing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1174
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: () => {
|
|
1175
|
+
onSave(url.trim() || null);
|
|
1176
|
+
setEditing(false);
|
|
1177
|
+
}, children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }),
|
|
1178
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: () => {
|
|
1179
|
+
setUrl(channel.url ?? "");
|
|
1180
|
+
setEditing(false);
|
|
1181
|
+
}, children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }) })
|
|
1182
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1183
|
+
channel.url && /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: () => window.open(channel.url, "_blank", "noopener,noreferrer"), children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" }) }),
|
|
1184
|
+
/* @__PURE__ */ 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" }),
|
|
1185
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: () => setEditing(true), children: "Editar" }),
|
|
1186
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: onRemove, children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4 text-red-500" }) })
|
|
1187
|
+
] }) })
|
|
1188
|
+
] }) });
|
|
1189
|
+
}
|
|
1190
|
+
function AddChannelForm({ kind, onKind, onCancel, onAdd }) {
|
|
1191
|
+
const meta = KIND_META[kind];
|
|
1192
|
+
const [label, setLabel] = React3.useState(meta.label);
|
|
1193
|
+
const [url, setUrl] = React3.useState("");
|
|
1194
|
+
React3.useEffect(() => {
|
|
1195
|
+
setLabel(KIND_META[kind].label);
|
|
1196
|
+
}, [kind]);
|
|
1197
|
+
return /* @__PURE__ */ jsxs("div", { className: "mt-3 rounded-card border border-border bg-card p-4", children: [
|
|
1198
|
+
/* @__PURE__ */ jsx("div", { className: "mb-3 flex flex-wrap gap-2", children: ADDABLE_KINDS.map((k) => {
|
|
1199
|
+
const Icon = KIND_META[k].icon;
|
|
1200
|
+
return /* @__PURE__ */ 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: [
|
|
1201
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }),
|
|
1202
|
+
" ",
|
|
1203
|
+
KIND_META[k].label
|
|
1204
|
+
] }, k);
|
|
1205
|
+
}) }),
|
|
1206
|
+
/* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-muted-foreground", children: meta.hint }),
|
|
1207
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [
|
|
1208
|
+
/* @__PURE__ */ jsx(Input, { value: label, placeholder: "Nome do canal", onChange: (e) => setLabel(e.target.value), className: "sm:w-48" }),
|
|
1209
|
+
/* @__PURE__ */ jsx(Input, { value: url, placeholder: meta.placeholder, onChange: (e) => setUrl(e.target.value), className: "flex-1" })
|
|
1210
|
+
] }),
|
|
1211
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3 flex gap-2", children: [
|
|
1212
|
+
/* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => onAdd(label, url), children: [
|
|
1213
|
+
/* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
1214
|
+
" Adicionar"
|
|
1215
|
+
] }),
|
|
1216
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: onCancel, children: "Cancelar" })
|
|
1217
|
+
] })
|
|
1218
|
+
] });
|
|
1219
|
+
}
|
|
1026
1220
|
|
|
1027
1221
|
// src/index.ts
|
|
1028
|
-
var ShopPage =
|
|
1222
|
+
var ShopPage = React3.lazy(() => import('./ShopPage-JP27MZS2.js').then((m) => ({ default: m.ShopPage })));
|
|
1029
1223
|
function createShopPlugin(options) {
|
|
1030
1224
|
const curr = { code: "BRL", locale: "pt-BR", symbol: "R$", ...options?.currency };
|
|
1031
1225
|
setShopTenantResolver(() => useOrganizationStore.getState().currentOrg?.id);
|
|
1032
|
-
registerEntityPath("shop_customer", "/
|
|
1226
|
+
registerEntityPath("shop_customer", "/customers");
|
|
1033
1227
|
const pageFor = (section) => {
|
|
1034
|
-
const Wrapped = () =>
|
|
1035
|
-
|
|
1228
|
+
const Wrapped = () => React3.createElement(
|
|
1229
|
+
React3.Suspense,
|
|
1036
1230
|
{ fallback: null },
|
|
1037
|
-
|
|
1231
|
+
React3.createElement(
|
|
1038
1232
|
ShopPage,
|
|
1039
1233
|
{ provider: options?.provider, section }
|
|
1040
1234
|
)
|
|
@@ -1068,10 +1262,12 @@ function createShopPlugin(options) {
|
|
|
1068
1262
|
const SECTIONS = [
|
|
1069
1263
|
{ id: "products", label: options?.sectionLabels?.products ?? "Produtos", icon: "Package" },
|
|
1070
1264
|
{ id: "orders", label: options?.sectionLabels?.orders ?? "Pedidos", icon: "ShoppingCart" },
|
|
1071
|
-
{ id: "customers", label: options?.sectionLabels?.customers ?? "Clientes", icon: "Users" },
|
|
1072
1265
|
{ id: "discounts", label: options?.sectionLabels?.discounts ?? "Descontos", icon: "Tag" },
|
|
1073
1266
|
{ id: "shipping", label: options?.sectionLabels?.shipping ?? "Entrega", icon: "Truck" }
|
|
1074
1267
|
];
|
|
1268
|
+
const CustomersNavLabel = options?.sectionLabels?.customers ?? "Clientes";
|
|
1269
|
+
const ChannelsPageWrapped = () => React3.createElement(ChannelsPage, { resolveProvider: options?.provider });
|
|
1270
|
+
ChannelsPageWrapped.displayName = "ChannelsPage";
|
|
1075
1271
|
const navSection = options?.navSection ?? "main";
|
|
1076
1272
|
const navPosition = options?.navPosition ?? 6;
|
|
1077
1273
|
return {
|
|
@@ -1104,7 +1300,27 @@ function createShopPlugin(options) {
|
|
|
1104
1300
|
route: `/shop/${s.id}`,
|
|
1105
1301
|
icon: s.icon,
|
|
1106
1302
|
permission: { feature: "shop", action: "read" }
|
|
1107
|
-
}))
|
|
1303
|
+
})),
|
|
1304
|
+
// Clientes — top-level (route not under /shop, so it leaves the accordion).
|
|
1305
|
+
// Fractional position keeps it right below "Loja", above other plugins.
|
|
1306
|
+
{
|
|
1307
|
+
section: navSection,
|
|
1308
|
+
position: navPosition + 0.5,
|
|
1309
|
+
label: CustomersNavLabel,
|
|
1310
|
+
route: "/customers",
|
|
1311
|
+
icon: "Users",
|
|
1312
|
+
permission: { feature: "shop", action: "read" }
|
|
1313
|
+
},
|
|
1314
|
+
// Canais de venda — inside the "Loja" group (route under /shop nests it in
|
|
1315
|
+
// the accordion). The store's points of sale (Loja Online, WhatsApp, …).
|
|
1316
|
+
{
|
|
1317
|
+
section: navSection,
|
|
1318
|
+
position: navPosition + SECTIONS.length + 1,
|
|
1319
|
+
label: "Canais de venda",
|
|
1320
|
+
route: "/shop/channels",
|
|
1321
|
+
icon: "Radio",
|
|
1322
|
+
permission: { feature: "shop", action: "read" }
|
|
1323
|
+
}
|
|
1108
1324
|
],
|
|
1109
1325
|
routes: [
|
|
1110
1326
|
{
|
|
@@ -1117,7 +1333,19 @@ function createShopPlugin(options) {
|
|
|
1117
1333
|
path: `/shop/${s.id}`,
|
|
1118
1334
|
component: CRUD_PAGES[s.id] ?? pageFor(s.id),
|
|
1119
1335
|
permission: { feature: "shop", action: "read" }
|
|
1120
|
-
}))
|
|
1336
|
+
})),
|
|
1337
|
+
// Clientes at the top level, same CRUD page as before.
|
|
1338
|
+
{
|
|
1339
|
+
path: "/customers",
|
|
1340
|
+
component: CustomersCrudPage,
|
|
1341
|
+
permission: { feature: "shop", action: "read" }
|
|
1342
|
+
},
|
|
1343
|
+
// Canais de venda management page (under the Loja group).
|
|
1344
|
+
{
|
|
1345
|
+
path: "/shop/channels",
|
|
1346
|
+
component: ChannelsPageWrapped,
|
|
1347
|
+
permission: { feature: "shop", action: "read" }
|
|
1348
|
+
}
|
|
1121
1349
|
],
|
|
1122
1350
|
widgets: [],
|
|
1123
1351
|
aiTools: [
|
|
@@ -1166,7 +1394,7 @@ function createShopPlugin(options) {
|
|
|
1166
1394
|
label: "Shop",
|
|
1167
1395
|
icon: "ShoppingBag",
|
|
1168
1396
|
component: (() => {
|
|
1169
|
-
const ShopSettingsTab = () =>
|
|
1397
|
+
const ShopSettingsTab = () => React3.createElement(ShopSettings, { currency: curr });
|
|
1170
1398
|
ShopSettingsTab.displayName = "ShopSettingsTab";
|
|
1171
1399
|
return ShopSettingsTab;
|
|
1172
1400
|
})(),
|