@fayz-ai/plugin-orders 0.23.0-canary.20261027164140 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DeliverySettings-2KMZ25CI.js → DeliverySettings-5ACP5XAG.js} +33 -198
- package/dist/DeliverySettings-5ACP5XAG.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -254
- package/dist/index.js.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/migrations/index.d.ts +1 -2
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/main.browser.js +2 -3
- package/dist/migrations/main.browser.js.map +1 -1
- package/dist/migrations/main.js +77 -115
- package/dist/migrations/main.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -1
- package/dist/settings/DeliverySettings.d.ts.map +1 -1
- package/dist/settings/useDeliverySettings.d.ts +0 -3
- package/dist/settings/useDeliverySettings.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/DeliverySettings-2KMZ25CI.js.map +0 -1
- package/dist/chunk-O4W3DNIC.js +0 -174
- package/dist/chunk-O4W3DNIC.js.map +0 -1
- package/dist/lib/delivery-zones.d.ts +0 -67
- package/dist/lib/delivery-zones.d.ts.map +0 -1
- package/dist/lib/onboarding.d.ts +0 -77
- package/dist/lib/onboarding.d.ts.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import React2 from 'react';
|
|
1
|
+
import React from 'react';
|
|
3
2
|
import { useConnectors, useConnectorsPanelAvailable, openConnectorsPanel, SettingsGroup, ToggleRow, AddConnectorButton, ConnectorRow, AddConnectorPanel, ConnectorDetail, TextRow } from '@fayz-ai/admin';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { AlertTriangle, Loader2, Check
|
|
3
|
+
import { Skeleton } from '@fayz-ai/ui';
|
|
4
|
+
import { usePluginRuntimeOptional, getComponent, getSupabaseClientOptional } from '@fayz-ai/core';
|
|
5
|
+
import { AlertTriangle, Loader2, Check } from 'lucide-react';
|
|
7
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
8
7
|
|
|
8
|
+
// src/settings/DeliverySettings.tsx
|
|
9
9
|
var DEBOUNCE_MS = 400;
|
|
10
10
|
var KEYS = {
|
|
11
11
|
enabled: "delivery.enabled",
|
|
@@ -13,30 +13,22 @@ var KEYS = {
|
|
|
13
13
|
freeOver: "delivery.free_over",
|
|
14
14
|
minOrder: "delivery.min_order",
|
|
15
15
|
etaMinutes: "delivery.eta_minutes",
|
|
16
|
-
radiusKm: "delivery.radius_km"
|
|
17
|
-
zones: "delivery.zones"
|
|
16
|
+
radiusKm: "delivery.radius_km"
|
|
18
17
|
};
|
|
19
|
-
function fromSetting(field, value) {
|
|
20
|
-
return field === "zones" ? zonesFromSetting(value) : value;
|
|
21
|
-
}
|
|
22
|
-
function toSetting(field, value) {
|
|
23
|
-
if (field === "zones") return zonesToSetting(value ?? []);
|
|
24
|
-
return value ?? null;
|
|
25
|
-
}
|
|
26
18
|
function message(e) {
|
|
27
19
|
if (e instanceof Error) return e.message;
|
|
28
20
|
if (typeof e === "object" && e && "message" in e) return String(e.message);
|
|
29
21
|
return String(e);
|
|
30
22
|
}
|
|
31
23
|
function useDeliverySettings(defaults = {}) {
|
|
32
|
-
const client =
|
|
24
|
+
const client = React.useMemo(() => getSupabaseClientOptional(), []);
|
|
33
25
|
const supported = !!client;
|
|
34
|
-
const [stored, setStored] =
|
|
35
|
-
const [loading, setLoading] =
|
|
36
|
-
const [saving, setSaving] =
|
|
37
|
-
const [error, setError] =
|
|
38
|
-
const [loadError, setLoadError] =
|
|
39
|
-
|
|
26
|
+
const [stored, setStored] = React.useState({});
|
|
27
|
+
const [loading, setLoading] = React.useState(supported);
|
|
28
|
+
const [saving, setSaving] = React.useState(false);
|
|
29
|
+
const [error, setError] = React.useState(null);
|
|
30
|
+
const [loadError, setLoadError] = React.useState(null);
|
|
31
|
+
React.useEffect(() => {
|
|
40
32
|
if (!client) return;
|
|
41
33
|
let cancelled = false;
|
|
42
34
|
setLoading(true);
|
|
@@ -50,7 +42,7 @@ function useDeliverySettings(defaults = {}) {
|
|
|
50
42
|
const flat = data ?? {};
|
|
51
43
|
const next = {};
|
|
52
44
|
for (const [field, key] of Object.entries(KEYS)) {
|
|
53
|
-
if (key in flat && flat[key] !== null) next[field] =
|
|
45
|
+
if (key in flat && flat[key] !== null) next[field] = flat[key];
|
|
54
46
|
else if (key in flat && flat[key] === null) next[field] = null;
|
|
55
47
|
}
|
|
56
48
|
setStored(next);
|
|
@@ -63,12 +55,12 @@ function useDeliverySettings(defaults = {}) {
|
|
|
63
55
|
cancelled = true;
|
|
64
56
|
};
|
|
65
57
|
}, [client]);
|
|
66
|
-
const pendingRef =
|
|
67
|
-
const timerRef =
|
|
68
|
-
|
|
58
|
+
const pendingRef = React.useRef({});
|
|
59
|
+
const timerRef = React.useRef(null);
|
|
60
|
+
React.useEffect(() => () => {
|
|
69
61
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
70
62
|
}, []);
|
|
71
|
-
const set =
|
|
63
|
+
const set = React.useCallback((patch) => {
|
|
72
64
|
setStored((current) => ({ ...current, ...patch }));
|
|
73
65
|
if (!client) return;
|
|
74
66
|
setError(null);
|
|
@@ -80,17 +72,14 @@ function useDeliverySettings(defaults = {}) {
|
|
|
80
72
|
pendingRef.current = {};
|
|
81
73
|
void Promise.all(
|
|
82
74
|
Object.entries(payload).map(
|
|
83
|
-
([field, value2]) => client.rpc("tenant_setting_set", {
|
|
84
|
-
p_key: KEYS[field],
|
|
85
|
-
p_value: toSetting(field, value2)
|
|
86
|
-
}).then(({ error: e }) => {
|
|
75
|
+
([field, value2]) => client.rpc("tenant_setting_set", { p_key: KEYS[field], p_value: value2 ?? null }).then(({ error: e }) => {
|
|
87
76
|
if (e) throw e;
|
|
88
77
|
})
|
|
89
78
|
)
|
|
90
|
-
).catch((e) => setError(
|
|
79
|
+
).catch((e) => setError(message(e))).finally(() => setSaving(false));
|
|
91
80
|
}, DEBOUNCE_MS);
|
|
92
81
|
}, [client]);
|
|
93
|
-
const value =
|
|
82
|
+
const value = React.useMemo(() => ({ ...defaults, ...stored }), [defaults, stored]);
|
|
94
83
|
return { value, set, loading, saving, error, loadError, supported };
|
|
95
84
|
}
|
|
96
85
|
var MARKETPLACE_CATEGORIES = ["marketplace"];
|
|
@@ -106,9 +95,9 @@ function amountText(value) {
|
|
|
106
95
|
return String(value).replace(".", ",");
|
|
107
96
|
}
|
|
108
97
|
function AmountRow({ label, description, hint, value, onCommit, pending }) {
|
|
109
|
-
const [text, setText] =
|
|
110
|
-
const [invalid, setInvalid] =
|
|
111
|
-
|
|
98
|
+
const [text, setText] = React.useState(() => amountText(value));
|
|
99
|
+
const [invalid, setInvalid] = React.useState(false);
|
|
100
|
+
React.useEffect(() => {
|
|
112
101
|
setText(amountText(value));
|
|
113
102
|
}, [value]);
|
|
114
103
|
return /* @__PURE__ */ jsx(
|
|
@@ -137,168 +126,25 @@ function AmountRow({ label, description, hint, value, onCommit, pending }) {
|
|
|
137
126
|
}
|
|
138
127
|
);
|
|
139
128
|
}
|
|
140
|
-
function ZoneRow({ zone, previousKm, onCommit, onRemove }) {
|
|
141
|
-
const t = useTranslation();
|
|
142
|
-
const [km, setKm] = React2.useState(() => amountText(zone?.maxKm));
|
|
143
|
-
const [fee, setFee] = React2.useState(() => amountText(zone?.fee));
|
|
144
|
-
const [eta, setEta] = React2.useState(() => amountText(zone?.etaMinutes));
|
|
145
|
-
const [invalid, setInvalid] = React2.useState(false);
|
|
146
|
-
React2.useEffect(() => {
|
|
147
|
-
setKm(amountText(zone?.maxKm));
|
|
148
|
-
setFee(amountText(zone?.fee));
|
|
149
|
-
setEta(amountText(zone?.etaMinutes));
|
|
150
|
-
}, [zone?.maxKm, zone?.fee, zone?.etaMinutes]);
|
|
151
|
-
const commit = () => {
|
|
152
|
-
const k = parseAmount(km);
|
|
153
|
-
const f = parseAmount(fee);
|
|
154
|
-
const e = parseAmount(eta);
|
|
155
|
-
if (k === null || f === null || Number.isNaN(k) || Number.isNaN(f) || Number.isNaN(e) || k <= 0) {
|
|
156
|
-
setInvalid(km !== "" || fee !== "");
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
setInvalid(false);
|
|
160
|
-
const next = { maxKm: k, fee: f };
|
|
161
|
-
if (e) next.etaMinutes = Math.round(e);
|
|
162
|
-
if (zone && zone.maxKm === next.maxKm && zone.fee === next.fee && zone.etaMinutes === next.etaMinutes) return;
|
|
163
|
-
onCommit(next);
|
|
164
|
-
};
|
|
165
|
-
const onKey = (ev) => {
|
|
166
|
-
if (ev.key === "Enter") ev.target.blur();
|
|
167
|
-
};
|
|
168
|
-
const label = zone ? `${amountText(zone.maxKm)} ${t("orders.zones.km")}` : "";
|
|
169
|
-
return /* @__PURE__ */ jsxs("div", { className: "py-3", children: [
|
|
170
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-2 text-sm", children: [
|
|
171
|
-
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 whitespace-nowrap", children: [
|
|
172
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: previousKm !== void 0 ? `${amountText(previousKm)} a` : t("orders.zones.upTo") }),
|
|
173
|
-
/* @__PURE__ */ jsx(
|
|
174
|
-
Input,
|
|
175
|
-
{
|
|
176
|
-
className: "h-9 w-16",
|
|
177
|
-
inputMode: "decimal",
|
|
178
|
-
value: km,
|
|
179
|
-
placeholder: "3",
|
|
180
|
-
onChange: (e) => {
|
|
181
|
-
setKm(e.target.value);
|
|
182
|
-
setInvalid(false);
|
|
183
|
-
},
|
|
184
|
-
onBlur: commit,
|
|
185
|
-
onKeyDown: onKey,
|
|
186
|
-
"aria-label": `${t("orders.zones.upTo")} ${t("orders.zones.km")}`
|
|
187
|
-
}
|
|
188
|
-
),
|
|
189
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("orders.zones.km") })
|
|
190
|
-
] }),
|
|
191
|
-
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 whitespace-nowrap", children: [
|
|
192
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "R$" }),
|
|
193
|
-
/* @__PURE__ */ jsx(
|
|
194
|
-
Input,
|
|
195
|
-
{
|
|
196
|
-
className: "h-9 w-20",
|
|
197
|
-
inputMode: "decimal",
|
|
198
|
-
value: fee,
|
|
199
|
-
placeholder: "0,00",
|
|
200
|
-
onChange: (e) => {
|
|
201
|
-
setFee(e.target.value);
|
|
202
|
-
setInvalid(false);
|
|
203
|
-
},
|
|
204
|
-
onBlur: commit,
|
|
205
|
-
onKeyDown: onKey,
|
|
206
|
-
"aria-label": t("orders.zones.fee")
|
|
207
|
-
}
|
|
208
|
-
)
|
|
209
|
-
] }),
|
|
210
|
-
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 whitespace-nowrap", children: [
|
|
211
|
-
/* @__PURE__ */ jsx(
|
|
212
|
-
Input,
|
|
213
|
-
{
|
|
214
|
-
className: "h-9 w-16",
|
|
215
|
-
inputMode: "numeric",
|
|
216
|
-
value: eta,
|
|
217
|
-
placeholder: "30",
|
|
218
|
-
onChange: (e) => {
|
|
219
|
-
setEta(e.target.value);
|
|
220
|
-
setInvalid(false);
|
|
221
|
-
},
|
|
222
|
-
onBlur: commit,
|
|
223
|
-
onKeyDown: onKey,
|
|
224
|
-
"aria-label": t("orders.zones.eta")
|
|
225
|
-
}
|
|
226
|
-
),
|
|
227
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("orders.zones.eta") })
|
|
228
|
-
] }),
|
|
229
|
-
/* @__PURE__ */ jsx(
|
|
230
|
-
Button,
|
|
231
|
-
{
|
|
232
|
-
type: "button",
|
|
233
|
-
variant: "ghost",
|
|
234
|
-
size: "icon",
|
|
235
|
-
className: "ml-auto h-9 w-9",
|
|
236
|
-
onClick: onRemove,
|
|
237
|
-
"aria-label": t("orders.zones.remove", { km: label }),
|
|
238
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
239
|
-
}
|
|
240
|
-
)
|
|
241
|
-
] }),
|
|
242
|
-
invalid && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive", children: t("orders.zones.invalid") })
|
|
243
|
-
] });
|
|
244
|
-
}
|
|
245
|
-
function ZonesGroup({ zones, onChange }) {
|
|
246
|
-
const t = useTranslation();
|
|
247
|
-
const [draft, setDraft] = React2.useState(false);
|
|
248
|
-
const sorted = React2.useMemo(() => normalizeZones(zones), [zones]);
|
|
249
|
-
return /* @__PURE__ */ jsxs(SettingsGroup, { title: t("orders.zones.title"), description: t("orders.zones.description"), children: [
|
|
250
|
-
sorted.length === 0 && !draft && /* @__PURE__ */ jsx("p", { className: "py-3 text-sm text-muted-foreground", children: t("orders.zones.empty") }),
|
|
251
|
-
sorted.map((zone, i) => /* @__PURE__ */ jsx(
|
|
252
|
-
ZoneRow,
|
|
253
|
-
{
|
|
254
|
-
zone,
|
|
255
|
-
previousKm: i > 0 ? sorted[i - 1].maxKm : void 0,
|
|
256
|
-
onCommit: (next) => onChange(normalizeZones(sorted.map((z, j) => j === i ? next : z))),
|
|
257
|
-
onRemove: () => onChange(sorted.filter((_, j) => j !== i))
|
|
258
|
-
},
|
|
259
|
-
`${zone.maxKm}-${i}`
|
|
260
|
-
)),
|
|
261
|
-
draft && /* @__PURE__ */ jsx(
|
|
262
|
-
ZoneRow,
|
|
263
|
-
{
|
|
264
|
-
previousKm: sorted.length > 0 ? sorted[sorted.length - 1].maxKm : void 0,
|
|
265
|
-
onCommit: (next) => {
|
|
266
|
-
setDraft(false);
|
|
267
|
-
onChange(normalizeZones([...sorted, next]));
|
|
268
|
-
},
|
|
269
|
-
onRemove: () => setDraft(false)
|
|
270
|
-
}
|
|
271
|
-
),
|
|
272
|
-
/* @__PURE__ */ jsx("div", { className: "py-3", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setDraft(true), disabled: draft, children: [
|
|
273
|
-
/* @__PURE__ */ jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }),
|
|
274
|
-
t("orders.zones.add")
|
|
275
|
-
] }) })
|
|
276
|
-
] });
|
|
277
|
-
}
|
|
278
129
|
function DeliverySettings() {
|
|
279
|
-
const t = useTranslation();
|
|
280
130
|
const runtime = usePluginRuntimeOptional();
|
|
281
131
|
const shopActive = (runtime?.activePlugins ?? []).some((p) => p.id === "shop");
|
|
282
132
|
const ShopDelivery = shopActive ? getComponent(SHOP_DELIVERY_COMPONENT) : void 0;
|
|
283
133
|
const settings = useDeliverySettings({ enabled: true, fee: 0, minOrder: 0, etaMinutes: 45, radiusKm: 0 });
|
|
284
134
|
const { value, set } = settings;
|
|
285
135
|
const { connectors } = useConnectors({ hostPluginId: "orders", includeGrants: false });
|
|
286
|
-
const [adding, setAdding] =
|
|
287
|
-
const [selected, setSelected] =
|
|
136
|
+
const [adding, setAdding] = React.useState(false);
|
|
137
|
+
const [selected, setSelected] = React.useState(null);
|
|
288
138
|
const panelAvailable = useConnectorsPanelAvailable();
|
|
289
|
-
const openJourney =
|
|
139
|
+
const openJourney = React.useCallback((connector) => {
|
|
290
140
|
if (panelAvailable) openConnectorsPanel(connector);
|
|
291
141
|
else setSelected(connector);
|
|
292
142
|
}, [panelAvailable]);
|
|
293
|
-
const marketplaces =
|
|
143
|
+
const marketplaces = React.useMemo(
|
|
294
144
|
() => (connectors ?? []).filter((c) => c.category && MARKETPLACE_CATEGORIES.includes(c.category)),
|
|
295
145
|
[connectors]
|
|
296
146
|
);
|
|
297
147
|
const patch = (next) => set(next);
|
|
298
|
-
const zones = value.zones ?? [];
|
|
299
|
-
React2.useEffect(() => {
|
|
300
|
-
if (settings.error) toast.error(t("orders.delivery.saveFailed"), { description: settings.error });
|
|
301
|
-
}, [settings.error, t]);
|
|
302
148
|
if (!settings.supported) {
|
|
303
149
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-amber-500/30 bg-amber-500/5 p-4 text-sm", children: [
|
|
304
150
|
/* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 font-medium text-amber-700 dark:text-amber-500", children: [
|
|
@@ -392,10 +238,7 @@ function DeliverySettings() {
|
|
|
392
238
|
onCommit: (next) => patch({ etaMinutes: next === null ? 0 : Math.round(next) })
|
|
393
239
|
}
|
|
394
240
|
),
|
|
395
|
-
|
|
396
|
-
// With bands the radius is derived: the largest band is how far the moto goes.
|
|
397
|
-
/* @__PURE__ */ jsx("p", { className: "py-3 text-sm text-muted-foreground", children: t("orders.zones.radius", { km: amountText(zones[zones.length - 1].maxKm) }) })
|
|
398
|
-
) : /* @__PURE__ */ jsx(
|
|
241
|
+
/* @__PURE__ */ jsx(
|
|
399
242
|
AmountRow,
|
|
400
243
|
{
|
|
401
244
|
pending: true,
|
|
@@ -408,13 +251,6 @@ function DeliverySettings() {
|
|
|
408
251
|
)
|
|
409
252
|
]
|
|
410
253
|
}
|
|
411
|
-
),
|
|
412
|
-
/* @__PURE__ */ jsx(
|
|
413
|
-
ZonesGroup,
|
|
414
|
-
{
|
|
415
|
-
zones,
|
|
416
|
-
onChange: (next) => patch(next.length > 0 ? { zones: next, radiusKm: next[next.length - 1].maxKm } : { zones: next })
|
|
417
|
-
}
|
|
418
254
|
)
|
|
419
255
|
] }),
|
|
420
256
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -427,10 +263,9 @@ function DeliverySettings() {
|
|
|
427
263
|
] }),
|
|
428
264
|
/* @__PURE__ */ jsx("div", { className: "rounded-card border bg-card shadow-sm", children: marketplaces.length === 0 ? /* @__PURE__ */ jsx("p", { className: "p-4 text-sm text-muted-foreground", children: "Nenhum marketplace dispon\xEDvel para este app ainda. A entrega pr\xF3pria funciona sem nenhum." }) : /* @__PURE__ */ jsx("ul", { className: "divide-y", children: marketplaces.map((connector) => /* @__PURE__ */ jsx(ConnectorRow, { connector, onOpen: openJourney }, connector.id)) }) })
|
|
429
265
|
] }),
|
|
430
|
-
/* @__PURE__ */ jsx("div", { className: "flex min-h-5 items-center gap-1.5 px-1 text-xs text-muted-foreground", children: settings.error ? /* @__PURE__ */ jsxs("span", {
|
|
266
|
+
/* @__PURE__ */ jsx("div", { className: "flex min-h-5 items-center gap-1.5 px-1 text-xs text-muted-foreground", children: settings.error ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-destructive", children: [
|
|
431
267
|
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
432
|
-
|
|
433
|
-
": ",
|
|
268
|
+
"N\xE3o foi poss\xEDvel salvar: ",
|
|
434
269
|
settings.error
|
|
435
270
|
] }) : settings.saving ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
436
271
|
/* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 shrink-0 animate-spin" }),
|
|
@@ -466,5 +301,5 @@ function DeliverySettings() {
|
|
|
466
301
|
}
|
|
467
302
|
|
|
468
303
|
export { DeliverySettings };
|
|
469
|
-
//# sourceMappingURL=DeliverySettings-
|
|
470
|
-
//# sourceMappingURL=DeliverySettings-
|
|
304
|
+
//# sourceMappingURL=DeliverySettings-5ACP5XAG.js.map
|
|
305
|
+
//# sourceMappingURL=DeliverySettings-5ACP5XAG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/settings/useDeliverySettings.ts","../src/settings/DeliverySettings.tsx"],"names":["value","React"],"mappings":"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","file":"DeliverySettings-5ACP5XAG.js","sourcesContent":["import React from 'react'\nimport { getSupabaseClientOptional } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// useDeliverySettings — a política de entrega da casa, lida e salva\n// ---------------------------------------------------------------------------\n// Mesma forma do `useStoreSettings` do plugin-shop, e pela mesma razão: cada\n// linha é UMA decisão com significado imediato (\"entrego em 45 min\"), então\n// salva sozinha, com debounce, e a tela diz \"salvando…\" em vez de pedir que\n// alguém lembre no que tocou.\n//\n// Onde mora: `tenants.settings`, pelas RPCs do spine (`tenant_settings` para\n// ler tudo de uma vez, `tenant_setting_set` para gravar chave a chave). A\n// função recusa chave não registrada — ver a migration 041 — e cobra\n// `settings.manage`, então o garçom não muda a taxa.\n\nconst DEBOUNCE_MS = 400\nconst PREFIX = 'delivery.'\n\nexport interface DeliverySettings {\n enabled?: boolean\n fee?: number\n freeOver?: number | null\n minOrder?: number\n etaMinutes?: number\n radiusKm?: number\n}\n\n/** Chave no banco ⇄ campo na tela. Uma tabela, para os dois sentidos. */\nconst KEYS: Record<keyof DeliverySettings, string> = {\n enabled: 'delivery.enabled',\n fee: 'delivery.fee',\n freeOver: 'delivery.free_over',\n minOrder: 'delivery.min_order',\n etaMinutes: 'delivery.eta_minutes',\n radiusKm: 'delivery.radius_km',\n}\n\nexport interface DeliverySettingsHandle {\n value: DeliverySettings\n set: (patch: DeliverySettings) => void\n loading: boolean\n saving: boolean\n /** A gravação foi recusada. O valor otimista continua na tela. */\n error: string | null\n /** A LEITURA falhou: o que está na tela são padrões, não as escolhas da casa. */\n loadError: string | null\n /** Sem backend montado (mock/standalone): a tela diz isso em vez de fingir. */\n supported: boolean\n}\n\nfunction message(e: unknown): string {\n if (e instanceof Error) return e.message\n if (typeof e === 'object' && e && 'message' in e) return String((e as { message: unknown }).message)\n return String(e)\n}\n\nexport function useDeliverySettings(defaults: DeliverySettings = {}): DeliverySettingsHandle {\n const client = React.useMemo(() => getSupabaseClientOptional() as any, [])\n const supported = !!client\n\n const [stored, setStored] = React.useState<DeliverySettings>({})\n const [loading, setLoading] = React.useState(supported)\n const [saving, setSaving] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [loadError, setLoadError] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n if (!client) return\n let cancelled = false\n setLoading(true)\n setLoadError(null)\n void client\n .rpc('tenant_settings')\n .then(({ data, error: e }: { data: Record<string, unknown> | null; error: unknown }) => {\n if (cancelled) return\n if (e) { setLoadError(message(e)); return }\n const flat = (data ?? {}) as Record<string, unknown>\n const next: DeliverySettings = {}\n for (const [field, key] of Object.entries(KEYS)) {\n // Só o que a casa DECIDIU. Uma chave ausente continua indefinida, e é\n // o `defaults` da tela que responde por ela — gravar o padrão de volta\n // transformaria \"não decidi\" em \"escolhi isto\".\n if (key in flat && flat[key] !== null) (next as any)[field] = flat[key]\n else if (key in flat && flat[key] === null) (next as any)[field] = null\n }\n setStored(next)\n })\n .catch((e: unknown) => { if (!cancelled) setLoadError(message(e)) })\n .finally(() => { if (!cancelled) setLoading(false) })\n return () => { cancelled = true }\n }, [client])\n\n // O patch acumula durante a janela do debounce: três cliques viram uma\n // rodada de gravações, não três corridas para ver quem grava por último.\n const pendingRef = React.useRef<DeliverySettings>({})\n const timerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n React.useEffect(() => () => { if (timerRef.current) clearTimeout(timerRef.current) }, [])\n\n const set = React.useCallback((patch: DeliverySettings) => {\n setStored((current) => ({ ...current, ...patch }))\n if (!client) return\n setError(null)\n setSaving(true)\n pendingRef.current = { ...pendingRef.current, ...patch }\n if (timerRef.current) clearTimeout(timerRef.current)\n timerRef.current = setTimeout(() => {\n const payload = pendingRef.current\n pendingRef.current = {}\n void Promise.all(\n Object.entries(payload).map(([field, value]) =>\n client.rpc('tenant_setting_set', { p_key: KEYS[field as keyof DeliverySettings], p_value: value ?? null })\n .then(({ error: e }: { error: unknown }) => { if (e) throw e }),\n ),\n )\n .catch((e: unknown) => setError(message(e)))\n .finally(() => setSaving(false))\n }, DEBOUNCE_MS)\n }, [client])\n\n const value = React.useMemo(() => ({ ...defaults, ...stored }), [defaults, stored])\n\n return { value, set, loading, saving, error, loadError, supported }\n}\n","import React from 'react'\nimport {\n SettingsGroup, ToggleRow, TextRow,\n useConnectors, ConnectorRow, ConnectorDetail, AddConnectorPanel, AddConnectorButton,\n openConnectorsPanel, useConnectorsPanelAvailable,\n type UnifiedConnector,\n} from '@fayz-ai/admin'\nimport { Skeleton } from '@fayz-ai/ui'\nimport { getComponent, usePluginRuntimeOptional } from '@fayz-ai/core'\nimport { AlertTriangle, Check, Loader2 } from 'lucide-react'\nimport { useDeliverySettings, type DeliverySettings as DeliveryValues } from './useDeliverySettings'\n\n/**\n * Entrega — o que a casa cobra para levar, e quem traz o pedido.\n *\n * Duas coisas na tela, e a distinção é o assunto (a mesma do \"Pagamentos\" da\n * loja, e por isso a mesma forma):\n *\n * • A POLÍTICA é da casa e muda com a estação: taxa, mínimo, tempo, raio.\n * Mora em `tenants.settings` (migration 041) e salva sozinha.\n *\n * • QUEM TRAZ O PEDIDO é uma conexão. iFood, 99Food, Keeta, Uber Eats já são\n * conectores declarados por este plugin; a tela FILTRA o hub por\n * `category === 'marketplace'` e reusa a mesma linha, a mesma marca e a\n * mesma jornada de conectar. Um cartão próprio aqui divergiria do hub na\n * primeira vez que qualquer um dos três mudasse.\n *\n * Entrega própria é legítima sem conector nenhum — a moto é do restaurante —\n * então nada aqui exige uma conexão para a política valer.\n */\nconst MARKETPLACE_CATEGORIES = ['marketplace']\n// A store with a SITE sets its delivery through the shop's own block\n// (`shop.delivery-settings`, shop 0130): the fee, free delivery and regions the\n// quote charges from, the minimum and the estimate the site enforces and shows.\n// Without a shop the policy rows below still save to tenants.settings (spine\n// 041) and nothing reads them yet — hence their «Em breve» mark.\nconst SHOP_DELIVERY_COMPONENT = 'shop.delivery-settings'\n\n/** Aceita \"12,90\" e \"12.90\"; devolve `null` para vazio. */\nfunction parseAmount(text: string): number | null {\n const clean = text.replace(/\\s/g, '').replace(',', '.')\n if (!clean) return null\n const n = Number(clean)\n return Number.isFinite(n) && n >= 0 ? n : NaN\n}\n\nfunction amountText(value: number | null | undefined): string {\n if (value === null || value === undefined) return ''\n return String(value).replace('.', ',')\n}\n\n/** Uma linha de dinheiro/número: texto local no input, número no banco. */\nfunction AmountRow({ label, description, hint, value, onCommit, pending }: {\n pending?: boolean\n label: string\n description?: string\n hint?: string\n value: number | null | undefined\n onCommit: (next: number | null) => void\n}) {\n const [text, setText] = React.useState(() => amountText(value))\n const [invalid, setInvalid] = React.useState(false)\n // O valor do servidor ganha quando muda por fora (carregou, ou outra aba).\n React.useEffect(() => { setText(amountText(value)) }, [value])\n\n return (\n <TextRow\n pending={pending}\n label={label}\n description={description}\n value={text}\n onChange={(next) => { setText(next); setInvalid(false) }}\n // Só no blur/Enter: salvar por tecla gravaria '1' e '19' no caminho para\n // '19,90', e cada um deles é uma taxa que a casa cobrou de verdade.\n onBlurCommit={() => {\n const parsed = parseAmount(text)\n if (Number.isNaN(parsed)) { setInvalid(true); return }\n setInvalid(false)\n onCommit(parsed)\n }}\n hint={invalid ? 'Use um número, como 9,90.' : hint}\n invalid={invalid}\n placeholder=\"0,00\"\n />\n )\n}\n\nexport function DeliverySettings() {\n const runtime = usePluginRuntimeOptional()\n const shopActive = (runtime?.activePlugins ?? []).some((p) => (p as { id?: string }).id === 'shop')\n const ShopDelivery = shopActive\n ? (getComponent(SHOP_DELIVERY_COMPONENT) as React.ComponentType<unknown> | undefined)\n : undefined\n const settings = useDeliverySettings({ enabled: true, fee: 0, minOrder: 0, etaMinutes: 45, radiusKm: 0 })\n const { value, set } = settings\n const { connectors } = useConnectors({ hostPluginId: 'orders', includeGrants: false })\n const [adding, setAdding] = React.useState(false)\n const [selected, setSelected] = React.useState<UnifiedConnector | null>(null)\n const panelAvailable = useConnectorsPanelAvailable()\n\n const openJourney = React.useCallback((connector: UnifiedConnector) => {\n // Mesma regra do hub: a gaveta do assistente é dona da jornada quando está\n // montada, e a folha é o fallback para o fluxo nunca ficar sem saída.\n if (panelAvailable) openConnectorsPanel(connector)\n else setSelected(connector)\n }, [panelAvailable])\n\n const marketplaces = React.useMemo(\n () => (connectors ?? []).filter((c) => c.category && MARKETPLACE_CATEGORIES.includes(c.category)),\n [connectors],\n )\n\n const patch = (next: DeliveryValues) => set(next)\n\n if (!settings.supported) {\n return (\n <div className=\"rounded-lg border border-amber-500/30 bg-amber-500/5 p-4 text-sm\">\n <p className=\"flex items-center gap-2 font-medium text-amber-700 dark:text-amber-500\">\n <AlertTriangle className=\"h-4 w-4 shrink-0\" />\n Este app não guarda a configuração de entrega\n </p>\n <p className=\"mt-1 text-muted-foreground\">\n Não há backend montado aqui, então nada abaixo seria salvo — e por isso não é mostrado.\n </p>\n </div>\n )\n }\n\n if (settings.loading) {\n return (\n <div className=\"space-y-4\">\n <Skeleton className=\"h-28 w-full rounded-lg\" />\n <Skeleton className=\"h-40 w-full rounded-lg\" />\n </div>\n )\n }\n\n return (\n <div className=\"space-y-4\">\n {settings.loadError && (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 p-3 text-sm\">\n <p className=\"flex items-center gap-2 font-medium text-destructive\">\n <AlertTriangle className=\"h-4 w-4 shrink-0\" />\n Não foi possível carregar a configuração de entrega\n </p>\n <p className=\"mt-1 text-muted-foreground\">\n O que aparece abaixo são os valores padrão, não as suas escolhas. Recarregue a página\n antes de alterar algo — salvar agora sobrescreveria o que não conseguimos ler.\n </p>\n <p className=\"mt-1 text-xs text-muted-foreground\">{settings.loadError}</p>\n </div>\n )}\n\n {ShopDelivery ? <ShopDelivery /> : <>\n <SettingsGroup\n title=\"Entrega\"\n description=\"Vale para o pedido que sai da casa. O quadro de despacho continua existindo com a entrega desligada — o histórico não some.\"\n >\n <ToggleRow\n pending\n label=\"A casa entrega\"\n description=\"Desligado, nenhum canal novo nasce como entrega.\"\n checked={value.enabled !== false}\n onChange={(checked) => patch({ enabled: checked })}\n />\n <AmountRow\n pending\n label=\"Taxa de entrega\"\n description=\"Cobrada por pedido, na moeda da casa.\"\n hint=\"Zero = entrega sem taxa.\"\n value={value.fee}\n onCommit={(next) => patch({ fee: next ?? 0 })}\n />\n <AmountRow\n pending\n label=\"Frete grátis acima de\"\n description=\"Acima deste valor de pedido a taxa é zerada.\"\n hint=\"Vazio = a taxa vale sempre.\"\n value={value.freeOver}\n onCommit={(next) => patch({ freeOver: next })}\n />\n <AmountRow\n pending\n label=\"Pedido mínimo\"\n description=\"Abaixo disso a casa não entrega.\"\n hint=\"Zero = sem mínimo.\"\n value={value.minOrder}\n onCommit={(next) => patch({ minOrder: next ?? 0 })}\n />\n </SettingsGroup>\n\n <SettingsGroup\n title=\"Até onde, e em quanto tempo\"\n description=\"O que o cliente ouve quando pergunta — e o que o despacho promete.\"\n >\n <AmountRow\n pending\n label=\"Tempo estimado (min)\"\n description=\"Da confirmação até a porta.\"\n value={value.etaMinutes}\n onCommit={(next) => patch({ etaMinutes: next === null ? 0 : Math.round(next) })}\n />\n <AmountRow\n pending\n label=\"Raio de entrega (km)\"\n description=\"Distância máxima a partir da casa.\"\n hint=\"Zero = sem limite declarado.\"\n value={value.radiusKm}\n onCommit={(next) => patch({ radiusKm: next ?? 0 })}\n />\n </SettingsGroup>\n </>}\n\n <div>\n <div className=\"flex items-start justify-between gap-4 px-1 pb-1 pt-4\">\n <div>\n <h3 className=\"text-sm font-semibold\">Quem traz o pedido</h3>\n <p className=\"mt-0.5 text-[10px] text-muted-foreground\">\n Marketplaces conectados entram no quadro sozinhos, cada pedido marcado com a origem.\n A credencial vai para o cofre, nunca para o banco da casa.\n </p>\n </div>\n <AddConnectorButton onClick={() => setAdding(true)} />\n </div>\n <div className=\"rounded-card border bg-card shadow-sm\">\n {marketplaces.length === 0 ? (\n <p className=\"p-4 text-sm text-muted-foreground\">\n Nenhum marketplace disponível para este app ainda. A entrega própria funciona sem nenhum.\n </p>\n ) : (\n <ul className=\"divide-y\">\n {marketplaces.map((connector) => (\n <ConnectorRow key={connector.id} connector={connector} onOpen={openJourney} />\n ))}\n </ul>\n )}\n </div>\n </div>\n\n <div className=\"flex min-h-5 items-center gap-1.5 px-1 text-xs text-muted-foreground\">\n {settings.error ? (\n <span className=\"flex items-center gap-1.5 text-destructive\">\n <AlertTriangle className=\"h-3.5 w-3.5 shrink-0\" />\n Não foi possível salvar: {settings.error}\n </span>\n ) : settings.saving ? (\n <>\n <Loader2 className=\"h-3.5 w-3.5 shrink-0 animate-spin\" />\n Salvando…\n </>\n ) : (\n <>\n <Check className=\"h-3.5 w-3.5 shrink-0\" />\n As alterações são salvas automaticamente.\n </>\n )}\n </div>\n\n <AddConnectorPanel\n open={adding}\n onOpenChange={setAdding}\n connectors={connectors}\n categories={MARKETPLACE_CATEGORIES}\n onSelect={(connector) => { setAdding(false); openJourney(connector) }}\n />\n <ConnectorDetail\n connector={selected}\n open={!!selected}\n onOpenChange={(open) => { if (!open) setSelected(null) }}\n />\n </div>\n )\n}\n"]}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAanE,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAwB,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|