@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/index.js CHANGED
@@ -1,7 +1,9 @@
1
- import React2, { useState, useRef, useEffect } from 'react';
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] = React2.useState(currency?.code ?? "BRL");
924
- const [locale, setLocale] = React2.useState(currency?.locale ?? "pt-BR");
925
- const [showOutOfStock, setShowOutOfStock] = React2.useState(true);
926
- const [trackInventory, setTrackInventory] = React2.useState(true);
927
- const [requireSku, setRequireSku] = React2.useState(false);
928
- const [guestCheckout, setGuestCheckout] = React2.useState(true);
929
- const [enableDiscounts, setEnableDiscounts] = React2.useState(true);
930
- const [orderEmails, setOrderEmails] = React2.useState(true);
931
- const [lowStockAlerts, setLowStockAlerts] = React2.useState(false);
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 = React2.lazy(() => import('./ShopPage-HCLXMN7Q.js').then((m) => ({ default: m.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", "/shop/customers");
1226
+ registerEntityPath("shop_customer", "/customers");
1033
1227
  const pageFor = (section) => {
1034
- const Wrapped = () => React2.createElement(
1035
- React2.Suspense,
1228
+ const Wrapped = () => React3.createElement(
1229
+ React3.Suspense,
1036
1230
  { fallback: null },
1037
- React2.createElement(
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 = () => React2.createElement(ShopSettings, { currency: curr });
1397
+ const ShopSettingsTab = () => React3.createElement(ShopSettings, { currency: curr });
1170
1398
  ShopSettingsTab.displayName = "ShopSettingsTab";
1171
1399
  return ShopSettingsTab;
1172
1400
  })(),