@fayz-ai/storefront 0.17.0 → 0.19.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/app/createStorefrontApp.d.ts.map +1 -1
- package/dist/app/prerender.d.ts.map +1 -1
- package/dist/app/serving.d.ts +2 -0
- package/dist/app/serving.d.ts.map +1 -1
- package/dist/blocks/page-data.d.ts.map +1 -1
- package/dist/{chunk-STL6MATQ.js → chunk-77V5ZAF5.js} +1861 -273
- package/dist/chunk-77V5ZAF5.js.map +1 -0
- package/dist/components/cart/CartDrawer.d.ts.map +1 -1
- package/dist/components/checkout/CheckoutSteps.d.ts +10 -1
- package/dist/components/checkout/CheckoutSteps.d.ts.map +1 -1
- package/dist/components/checkout/DeliveryEstimator.d.ts.map +1 -1
- package/dist/components/delivery/AddressSheet.d.ts +22 -0
- package/dist/components/delivery/AddressSheet.d.ts.map +1 -0
- package/dist/components/delivery/AddressStrip.d.ts +18 -0
- package/dist/components/delivery/AddressStrip.d.ts.map +1 -0
- package/dist/components/delivery/ItemSheet.d.ts +42 -0
- package/dist/components/delivery/ItemSheet.d.ts.map +1 -0
- package/dist/components/delivery/MenuItemRow.d.ts +29 -0
- package/dist/components/delivery/MenuItemRow.d.ts.map +1 -0
- package/dist/components/delivery/MenuToolbar.d.ts +29 -0
- package/dist/components/delivery/MenuToolbar.d.ts.map +1 -0
- package/dist/components/delivery/ScheduleSheet.d.ts +14 -0
- package/dist/components/delivery/ScheduleSheet.d.ts.map +1 -0
- package/dist/components/delivery/ServiceStatus.d.ts +15 -0
- package/dist/components/delivery/ServiceStatus.d.ts.map +1 -0
- package/dist/components/delivery/StoreCover.d.ts +22 -0
- package/dist/components/delivery/StoreCover.d.ts.map +1 -0
- package/dist/components/delivery/store-time.d.ts +15 -0
- package/dist/components/delivery/store-time.d.ts.map +1 -0
- package/dist/components/layout/StorefrontHeader.d.ts +4 -1
- package/dist/components/layout/StorefrontHeader.d.ts.map +1 -1
- package/dist/components/layout/Toaster.d.ts.map +1 -1
- package/dist/components/marketing/FormBlock.d.ts.map +1 -1
- package/dist/components/product/ProductEnquiryForm.d.ts.map +1 -1
- package/dist/document/config.d.ts +101 -2
- package/dist/document/config.d.ts.map +1 -1
- package/dist/document/round-trip.d.ts.map +1 -1
- package/dist/document/sections.d.ts +2 -2
- package/dist/document/sections.d.ts.map +1 -1
- package/dist/document/upgrade.d.ts.map +1 -1
- package/dist/extend/component-contracts.d.ts +7 -1
- package/dist/extend/component-contracts.d.ts.map +1 -1
- package/dist/hooks/use-address.d.ts.map +1 -1
- package/dist/hooks/use-checkout.d.ts.map +1 -1
- package/dist/hooks/use-order.d.ts.map +1 -1
- package/dist/hooks/use-products.d.ts.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -17
- package/dist/index.js.map +1 -1
- package/dist/lib/testids.d.ts +36 -0
- package/dist/lib/testids.d.ts.map +1 -1
- package/dist/render.js +3 -3
- package/dist/render.js.map +1 -1
- package/dist/stores/cart.store.d.ts +22 -1
- package/dist/stores/cart.store.d.ts.map +1 -1
- package/dist/stores/delivery.store.d.ts +64 -1
- package/dist/stores/delivery.store.d.ts.map +1 -1
- package/dist/stores/service.store.d.ts +35 -0
- package/dist/stores/service.store.d.ts.map +1 -0
- package/dist/stores/toast.store.d.ts +14 -0
- package/dist/stores/toast.store.d.ts.map +1 -1
- package/dist/views/CheckoutPage.d.ts.map +1 -1
- package/dist/views/MenuPage.d.ts +23 -0
- package/dist/views/MenuPage.d.ts.map +1 -0
- package/dist/workflows/checkout.d.ts +15 -2
- package/dist/workflows/checkout.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/chunk-STL6MATQ.js.map +0 -1
|
@@ -3,11 +3,11 @@ import { persist } from 'zustand/middleware';
|
|
|
3
3
|
import { createAuthRuntime, createMockAuthAdapter } from '@fayz-ai/plugin-auth';
|
|
4
4
|
import { getShopProvider, setShopProvider } from '@fayz-ai/shop/runtime';
|
|
5
5
|
import { setShopCarrierQuotesResolver, setShopAccessTokenResolver, setShopShippingItemsResolver } from '@fayz-ai/sdk/shop';
|
|
6
|
-
import { normalizePostalCode, lookupPostalCode, defaultRouterAdapter, defineLoader, staticRouterAdapter, isLoaderParamRef, isLoaderPropRef, resolveLoader, dataNeedKey, getBlockMeta, defaultPropsFromSettings, getBlockErrorVisibility, isBlockEnabledOn, checkBlockConstraints, checkBlockContext, repairBlockTree, renderBlocks, clearExtensionPoints, defineExtensionPoint, runExtensionPoint, runEscapeValve, breadcrumbJsonLd, hasEntityDeclaration, resolveEntityDeclaration, defineBlock, formatPostalCode, defineEntity, listEntityDeclarations, resolveHandle, seoOrigin, RESERVED_ENTITY_FIELDS, ENTITY_FIELD_TYPES, handleNameFor, registerHandle, hasHandle, listHandles, blockRegistry, loaderRegistry, listLoaders } from '@fayz-ai/core';
|
|
7
|
-
import
|
|
6
|
+
import { normalizePostalCode, lookupPostalCode, defaultRouterAdapter, defineLoader, staticRouterAdapter, isLoaderParamRef, isLoaderPropRef, resolveLoader, errorMessage, dataNeedKey, getBlockMeta, defaultPropsFromSettings, getBlockErrorVisibility, isBlockEnabledOn, checkBlockConstraints, checkBlockContext, repairBlockTree, renderBlocks, clearExtensionPoints, defineExtensionPoint, runExtensionPoint, runEscapeValve, breadcrumbJsonLd, hasEntityDeclaration, resolveEntityDeclaration, defineBlock, formatPostalCode, defineEntity, listEntityDeclarations, resolveHandle, seoOrigin, RESERVED_ENTITY_FIELDS, ENTITY_FIELD_TYPES, handleNameFor, registerHandle, hasHandle, listHandles, blockRegistry, loaderRegistry, listLoaders } from '@fayz-ai/core';
|
|
7
|
+
import React37, { createContext, useContext, useEffect, useRef, useState, useSyncExternalStore, useMemo, useCallback } from 'react';
|
|
8
8
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
9
9
|
import { isStorageImageUrl, imageVariantUrl, imageSrcSet, IMAGE_SRCSET_WIDTHS, validateDiscount, documentDigits, isChargeableProvider, supportsCard, formatDocument, isValidDocument, gatewayLabel } from '@fayz-ai/shop';
|
|
10
|
-
import { ChevronLeft, ChevronRight, ShoppingBag, X, Minus, Plus, Send, MessageCircle, Mail, Truck, RefreshCcw, ShieldCheck, ChevronDown, Check, Search, Trash2, Lock, CreditCard,
|
|
10
|
+
import { ChevronLeft, ChevronRight, ShoppingBag, X, Minus, Plus, Send, MessageCircle, Mail, Truck, RefreshCcw, ShieldCheck, ChevronDown, Check, Search, Menu, Trash2, Lock, CreditCard, Store, Bike, Clock, MapPin, Star, Phone, User, UserCircle, Package, LogOut, QrCode, Copy, XCircle, RotateCcw, PackageCheck, Info, AlertCircle } from 'lucide-react';
|
|
11
11
|
import { getLucideIcon } from '@fayz-ai/ui/icons';
|
|
12
12
|
import { storefrontDiscountToPromotion, previewCouponPercent, discountToPromotion, PROMOTION_TYPES, PROMOTION_STATUSES, APPLICATION_METHOD_TYPES, APPLICATION_METHOD_TARGET_TYPES, APPLICATION_METHOD_ALLOCATIONS, hasRuleAttribute, listRuleAttributeKeys, RULE_OPERATORS, resolveRuleAttribute } from '@fayz-ai/shop/rules';
|
|
13
13
|
import { createMockShopProvider } from '@fayz-ai/shop/mock';
|
|
@@ -231,6 +231,13 @@ function productOptionSelectionKey(selection) {
|
|
|
231
231
|
const entries = Object.entries(normalized);
|
|
232
232
|
return entries.length > 0 ? JSON.stringify(entries) : "";
|
|
233
233
|
}
|
|
234
|
+
var HINT_TIMEOUT_MS = 1200;
|
|
235
|
+
var MAX_SAVED_ADDRESSES = 8;
|
|
236
|
+
function newAddressId() {
|
|
237
|
+
const c = globalThis.crypto;
|
|
238
|
+
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
239
|
+
return `addr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
240
|
+
}
|
|
234
241
|
var EMPTY = {
|
|
235
242
|
postalCode: "",
|
|
236
243
|
address: null,
|
|
@@ -238,12 +245,24 @@ var EMPTY = {
|
|
|
238
245
|
selectedZoneId: null,
|
|
239
246
|
status: "idle",
|
|
240
247
|
error: null,
|
|
241
|
-
refusedZone: null
|
|
248
|
+
refusedZone: null,
|
|
249
|
+
reviewZone: null
|
|
242
250
|
};
|
|
243
251
|
var useDeliveryStore = create()(
|
|
244
252
|
persist(
|
|
245
253
|
(set, get) => ({
|
|
246
254
|
...EMPTY,
|
|
255
|
+
// 'delivery' é o default porque é o que toda loja anterior à 0094 é, e o
|
|
256
|
+
// que uma loja sem retirada continua sendo.
|
|
257
|
+
fulfillmentType: "delivery",
|
|
258
|
+
scheduledFor: null,
|
|
259
|
+
setFulfillmentType(type) {
|
|
260
|
+
if (get().fulfillmentType === type) return;
|
|
261
|
+
set({ fulfillmentType: type, scheduledFor: null });
|
|
262
|
+
},
|
|
263
|
+
setScheduledFor(startsAt) {
|
|
264
|
+
set({ scheduledFor: startsAt });
|
|
265
|
+
},
|
|
247
266
|
async resolve(postalCode, subtotal) {
|
|
248
267
|
const code = normalizePostalCode(postalCode);
|
|
249
268
|
if (code.length !== 8) {
|
|
@@ -252,10 +271,17 @@ var useDeliveryStore = create()(
|
|
|
252
271
|
}
|
|
253
272
|
set({ postalCode: code, status: "loading", error: null });
|
|
254
273
|
const shop = getShopProvider();
|
|
255
|
-
const
|
|
274
|
+
const addressPromise = lookupPostalCode(code).catch(() => null);
|
|
275
|
+
const hint = await Promise.race([
|
|
276
|
+
addressPromise.then((a) => a ? { district: a.district, city: a.city, state: a.state, cityCode: a.cityCode } : void 0),
|
|
277
|
+
new Promise((resolve) => {
|
|
278
|
+
setTimeout(() => resolve(void 0), HINT_TIMEOUT_MS);
|
|
279
|
+
})
|
|
280
|
+
]);
|
|
281
|
+
const checkPromise = shop.checkDelivery ? shop.checkDelivery(code, hint).catch(() => null) : Promise.resolve(null);
|
|
256
282
|
let options = [];
|
|
257
283
|
try {
|
|
258
|
-
options = await shop.quoteShipping?.(code, subtotal) ?? [];
|
|
284
|
+
options = await shop.quoteShipping?.(code, subtotal, hint) ?? [];
|
|
259
285
|
} catch {
|
|
260
286
|
set({
|
|
261
287
|
...EMPTY,
|
|
@@ -265,22 +291,19 @@ var useDeliveryStore = create()(
|
|
|
265
291
|
});
|
|
266
292
|
return;
|
|
267
293
|
}
|
|
268
|
-
const
|
|
294
|
+
const check = await checkPromise;
|
|
295
|
+
const refusedZone = check?.refused ? check.refusedZone || "Regi\xE3o n\xE3o atendida" : null;
|
|
296
|
+
const reviewZone = !refusedZone && check?.outcome === "review" ? check.zoneName || "Regi\xE3o a confirmar" : null;
|
|
269
297
|
if (refusedZone) options = [];
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
try {
|
|
273
|
-
address = await lookupPostalCode(code);
|
|
274
|
-
notFound = address === null;
|
|
275
|
-
} catch {
|
|
276
|
-
address = null;
|
|
277
|
-
}
|
|
298
|
+
const address = await addressPromise;
|
|
299
|
+
const notFound = address === null;
|
|
278
300
|
set({
|
|
279
301
|
postalCode: code,
|
|
280
302
|
address,
|
|
281
303
|
options,
|
|
282
304
|
selectedZoneId: options[0]?.zoneId ?? null,
|
|
283
305
|
refusedZone,
|
|
306
|
+
reviewZone,
|
|
284
307
|
// A store with no zones configured quotes nothing, and that must NOT
|
|
285
308
|
// read as "we don't deliver here" — it falls back to the store-wide
|
|
286
309
|
// flat rate, which the cart already knows how to show.
|
|
@@ -298,6 +321,37 @@ var useDeliveryStore = create()(
|
|
|
298
321
|
},
|
|
299
322
|
clear() {
|
|
300
323
|
set({ ...EMPTY });
|
|
324
|
+
},
|
|
325
|
+
savedAddresses: [],
|
|
326
|
+
selectedAddressId: null,
|
|
327
|
+
saveAddress(input) {
|
|
328
|
+
const id = newAddressId();
|
|
329
|
+
const entry = { ...input, id, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
330
|
+
set((state) => ({
|
|
331
|
+
// Mesmo CEP + mesmo número é o MESMO endereço com o complemento
|
|
332
|
+
// corrigido, não um segundo. Sem isto, três tentativas de acertar o
|
|
333
|
+
// apartamento viram três linhas idênticas na lista.
|
|
334
|
+
savedAddresses: [
|
|
335
|
+
entry,
|
|
336
|
+
...state.savedAddresses.filter(
|
|
337
|
+
(a) => normalizePostalCode(a.postalCode) !== normalizePostalCode(entry.postalCode) || a.number.trim().toLowerCase() !== entry.number.trim().toLowerCase()
|
|
338
|
+
)
|
|
339
|
+
].slice(0, MAX_SAVED_ADDRESSES),
|
|
340
|
+
selectedAddressId: id
|
|
341
|
+
}));
|
|
342
|
+
return id;
|
|
343
|
+
},
|
|
344
|
+
async selectAddress(id, subtotal) {
|
|
345
|
+
const entry = get().savedAddresses.find((a) => a.id === id);
|
|
346
|
+
if (!entry) return;
|
|
347
|
+
set({ selectedAddressId: id });
|
|
348
|
+
await get().resolve(entry.postalCode, subtotal);
|
|
349
|
+
},
|
|
350
|
+
removeAddress(id) {
|
|
351
|
+
set((state) => ({
|
|
352
|
+
savedAddresses: state.savedAddresses.filter((a) => a.id !== id),
|
|
353
|
+
selectedAddressId: state.selectedAddressId === id ? null : state.selectedAddressId
|
|
354
|
+
}));
|
|
301
355
|
}
|
|
302
356
|
}),
|
|
303
357
|
{
|
|
@@ -305,7 +359,21 @@ var useDeliveryStore = create()(
|
|
|
305
359
|
// Deliberately NOT persisting `options`: a rehydrated
|
|
306
360
|
// price would be shown as current without anything having quoted it. The
|
|
307
361
|
// address survives, the money is asked for again.
|
|
308
|
-
|
|
362
|
+
// `fulfillmentType` acompanha o endereço e pela mesma razão: é uma
|
|
363
|
+
// preferência ("eu sempre busco na loja"), e ela vale amanhã.
|
|
364
|
+
// `scheduledFor` NÃO acompanha, pela mesma razão de `options`: um horário
|
|
365
|
+
// escolhido ontem é um horário que já passou, e restaurá-lo mandaria o
|
|
366
|
+
// comprador ao checkout com uma janela que o servidor vai recusar.
|
|
367
|
+
partialize: (state) => ({
|
|
368
|
+
postalCode: state.postalCode,
|
|
369
|
+
address: state.address,
|
|
370
|
+
fulfillmentType: state.fulfillmentType,
|
|
371
|
+
// O caderno é o ponto: número e complemento são o que o comprador
|
|
372
|
+
// digita de novo a cada visita, e o que nenhuma consulta de CEP
|
|
373
|
+
// devolve. Sem persistir, salvar endereço não salva nada.
|
|
374
|
+
savedAddresses: state.savedAddresses,
|
|
375
|
+
selectedAddressId: state.selectedAddressId
|
|
376
|
+
}),
|
|
309
377
|
onRehydrateStorage: () => (state) => {
|
|
310
378
|
if (state?.address) state.status = "idle";
|
|
311
379
|
}
|
|
@@ -332,10 +400,12 @@ var useCartStore = create()(
|
|
|
332
400
|
discountFreeShipping: false,
|
|
333
401
|
isOpen: false,
|
|
334
402
|
justAddedLineId: null,
|
|
335
|
-
addItem: (product, qty = 1, options) => set((state) => {
|
|
403
|
+
addItem: (product, qty = 1, options, notes, opts) => set((state) => {
|
|
336
404
|
const normalizedOptions = normalizeProductOptionSelection(options);
|
|
337
405
|
const optionKey = productOptionSelectionKey(normalizedOptions);
|
|
338
|
-
const
|
|
406
|
+
const cleanNotes = notes?.trim().slice(0, 250) || void 0;
|
|
407
|
+
const baseId = optionKey ? `${product.id}:${optionKey}` : product.id;
|
|
408
|
+
const lineId = cleanNotes ? `${baseId}#${cleanNotes}` : baseId;
|
|
339
409
|
const variant = resolveVariantForSelection(product, normalizedOptions);
|
|
340
410
|
const unitPrice = variant?.price ?? product.price;
|
|
341
411
|
const stock = variant ? variant.inventoryCount : product.inventoryCount;
|
|
@@ -345,7 +415,7 @@ var useCartStore = create()(
|
|
|
345
415
|
return {
|
|
346
416
|
// Auto-open the cart on add — the standard premium "slide-in cart"
|
|
347
417
|
// signal — and flag the line so the drawer can highlight it.
|
|
348
|
-
isOpen: true,
|
|
418
|
+
isOpen: opts?.openDrawer ?? true,
|
|
349
419
|
justAddedLineId: lineId,
|
|
350
420
|
lines: state.lines.map(
|
|
351
421
|
(l) => (l.lineId ?? l.productId) === lineId ? { ...l, lineId, quantity: nextQty } : l
|
|
@@ -372,9 +442,14 @@ var useCartStore = create()(
|
|
|
372
442
|
heightCm: variant?.heightCm ?? product.heightCm ?? null,
|
|
373
443
|
widthCm: variant?.widthCm ?? product.widthCm ?? null,
|
|
374
444
|
lengthCm: variant?.lengthCm ?? product.lengthCm ?? null,
|
|
375
|
-
packageId: product.packageId ?? null
|
|
445
|
+
packageId: product.packageId ?? null,
|
|
446
|
+
notes: cleanNotes
|
|
447
|
+
};
|
|
448
|
+
return {
|
|
449
|
+
isOpen: opts?.openDrawer ?? true,
|
|
450
|
+
justAddedLineId: lineId,
|
|
451
|
+
lines: [...state.lines, line]
|
|
376
452
|
};
|
|
377
|
-
return { isOpen: true, justAddedLineId: lineId, lines: [...state.lines, line] };
|
|
378
453
|
}),
|
|
379
454
|
setQuantity: (lineId, qty) => set((state) => {
|
|
380
455
|
if (qty <= 0) return { lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) };
|
|
@@ -737,7 +812,7 @@ function resolveConfig(config) {
|
|
|
737
812
|
const homePage = config.pages?.home ?? (config.home ? { blocks: config.home.sections } : void 0);
|
|
738
813
|
const catalogPath = homePage ? "/catalog" : "/";
|
|
739
814
|
const commerceMode = config.commerceMode ?? "checkout";
|
|
740
|
-
const checkoutEnabled = commerceMode === "checkout";
|
|
815
|
+
const checkoutEnabled = commerceMode === "checkout" || commerceMode === "delivery";
|
|
741
816
|
return {
|
|
742
817
|
...config,
|
|
743
818
|
pages: { ...config.pages, ...homePage ? { home: homePage } : {} },
|
|
@@ -753,6 +828,22 @@ function resolveConfig(config) {
|
|
|
753
828
|
terms: config.payments?.terms
|
|
754
829
|
},
|
|
755
830
|
commerceMode,
|
|
831
|
+
// Só existe no modo delivery. Fora dele o objeto inteiro é undefined, e é
|
|
832
|
+
// isso que a rota /menu consulta para decidir se existe.
|
|
833
|
+
delivery: commerceMode === "delivery" ? {
|
|
834
|
+
menuPath: config.delivery?.menuPath ?? "/menu",
|
|
835
|
+
coverImage: config.delivery?.coverImage,
|
|
836
|
+
logoImage: config.delivery?.logoImage,
|
|
837
|
+
locality: config.delivery?.locality,
|
|
838
|
+
highlightSlugs: config.delivery?.highlightSlugs,
|
|
839
|
+
// A ORDEM é a do seletor na tela. Um Set aqui perderia isso.
|
|
840
|
+
fulfillmentModes: config.delivery?.fulfillmentModes?.length ? config.delivery.fulfillmentModes : ["delivery"].slice(),
|
|
841
|
+
// Agendamento é opt-in duas vezes: aqui e na loja (0094 devolve zero
|
|
842
|
+
// slots quando scheduling_enabled é falso). A tela só oferece quando
|
|
843
|
+
// as duas concordam.
|
|
844
|
+
scheduling: config.delivery?.scheduling ?? false,
|
|
845
|
+
pickupAddress: config.delivery?.pickupAddress
|
|
846
|
+
} : void 0,
|
|
756
847
|
enquiry: {
|
|
757
848
|
label: config.enquiry?.label ?? "Contact me",
|
|
758
849
|
successMessage: config.enquiry?.successMessage ?? "Thanks. We received your enquiry.",
|
|
@@ -974,7 +1065,7 @@ function Link({ to, children, onClick, target, ...rest }) {
|
|
|
974
1065
|
event.preventDefault();
|
|
975
1066
|
adapter.navigate(to);
|
|
976
1067
|
};
|
|
977
|
-
return
|
|
1068
|
+
return React37.createElement(
|
|
978
1069
|
"a",
|
|
979
1070
|
{ href: adapter.href(to), onClick: handleClick, target, ...rest },
|
|
980
1071
|
children
|
|
@@ -1093,6 +1184,43 @@ var TID = {
|
|
|
1093
1184
|
cartTotal: "cart-total",
|
|
1094
1185
|
goCheckout: "go-checkout",
|
|
1095
1186
|
cartEmpty: "cart-empty",
|
|
1187
|
+
// menu / delivery mode (0094)
|
|
1188
|
+
menuPage: "menu-page",
|
|
1189
|
+
menuSection: (slug) => `menu-section-${slug}`,
|
|
1190
|
+
menuItem: (slug) => `menu-item-${slug}`,
|
|
1191
|
+
menuQuickAdd: (slug) => `menu-quick-add-${slug}`,
|
|
1192
|
+
devPlaceOrderWithoutCharge: "dev-place-order-without-charge",
|
|
1193
|
+
menuCartBar: "menu-cart-bar",
|
|
1194
|
+
menuItemSoldOut: "menu-sold-out",
|
|
1195
|
+
itemSheet: "item-sheet",
|
|
1196
|
+
itemSheetNotes: "item-sheet-notes",
|
|
1197
|
+
itemSheetNotesCount: "item-sheet-notes-count",
|
|
1198
|
+
itemSheetQty: "item-sheet-qty",
|
|
1199
|
+
itemSheetAdd: "item-sheet-add",
|
|
1200
|
+
serviceStatus: "service-status",
|
|
1201
|
+
serviceHoursModal: "service-hours-modal",
|
|
1202
|
+
serviceClosedGate: "service-closed-gate",
|
|
1203
|
+
fulfillmentMode: (mode) => `fulfillment-mode-${mode}`,
|
|
1204
|
+
scheduleSheet: "schedule-sheet",
|
|
1205
|
+
scheduleSlot: (iso) => `schedule-slot-${iso}`,
|
|
1206
|
+
storeCover: "store-cover",
|
|
1207
|
+
menuSearch: "menu-search",
|
|
1208
|
+
menuCategoryNav: "menu-category-nav",
|
|
1209
|
+
menuCategoryLink: (slug) => `menu-category-link-${slug}`,
|
|
1210
|
+
menuHighlights: "menu-highlights",
|
|
1211
|
+
menuItemBadge: (slug) => `menu-item-badge-${slug}`,
|
|
1212
|
+
deliveryTabBar: "delivery-tab-bar",
|
|
1213
|
+
deliveryTab: (key) => `delivery-tab-${key}`,
|
|
1214
|
+
addressStrip: "address-strip",
|
|
1215
|
+
addressSheet: "address-sheet",
|
|
1216
|
+
addressCep: "address-cep",
|
|
1217
|
+
addressNumber: "address-number",
|
|
1218
|
+
addressComplement: "address-complement",
|
|
1219
|
+
addressReference: "address-reference",
|
|
1220
|
+
addressSave: "address-save",
|
|
1221
|
+
addressAddNew: "address-add-new",
|
|
1222
|
+
savedAddress: (id) => `saved-address-${id}`,
|
|
1223
|
+
itemSheetGroup: (label) => `item-sheet-group-${label}`,
|
|
1096
1224
|
// delivery estimate (product page + cart)
|
|
1097
1225
|
deliveryEstimator: "delivery-estimator",
|
|
1098
1226
|
deliveryCepInput: "delivery-cep-input",
|
|
@@ -1177,9 +1305,9 @@ function SmoothImage({
|
|
|
1177
1305
|
const easing = resolved.easing ?? "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
1178
1306
|
const blur = resolved.blur ?? true;
|
|
1179
1307
|
const transform = resolved.transform ?? "none";
|
|
1180
|
-
const ref =
|
|
1181
|
-
const [loaded, setLoaded] =
|
|
1182
|
-
const delivered =
|
|
1308
|
+
const ref = React37.useRef(null);
|
|
1309
|
+
const [loaded, setLoaded] = React37.useState(() => mode === "none" || !clientMounted);
|
|
1310
|
+
const delivered = React37.useMemo(() => {
|
|
1183
1311
|
if (transform !== "supabase" || !src || srcSet || !isStorageImageUrl(src)) return { src, srcSet, sizes };
|
|
1184
1312
|
if (variant?.width) {
|
|
1185
1313
|
const w = variant.width;
|
|
@@ -1197,10 +1325,10 @@ function SmoothImage({
|
|
|
1197
1325
|
sizes: variant?.sizes ?? sizes ?? "100vw"
|
|
1198
1326
|
};
|
|
1199
1327
|
}, [transform, src, srcSet, sizes, variant?.width, variant?.sizes, variant?.widths, variant?.quality]);
|
|
1200
|
-
|
|
1328
|
+
React37.useEffect(() => {
|
|
1201
1329
|
clientMounted = true;
|
|
1202
1330
|
}, []);
|
|
1203
|
-
|
|
1331
|
+
React37.useEffect(() => {
|
|
1204
1332
|
if (mode === "none") {
|
|
1205
1333
|
setLoaded(true);
|
|
1206
1334
|
return;
|
|
@@ -1556,7 +1684,7 @@ async function resolvePageDataNeed(need) {
|
|
|
1556
1684
|
const data = await impl(need.params, { shop: getShopProvider() });
|
|
1557
1685
|
return { status: "ready", data };
|
|
1558
1686
|
} catch (err) {
|
|
1559
|
-
const message =
|
|
1687
|
+
const message = errorMessage(err);
|
|
1560
1688
|
console.error(`[storefront] loader "${need.loader}" failed:`, err);
|
|
1561
1689
|
return { status: "error", error: message };
|
|
1562
1690
|
}
|
|
@@ -2468,8 +2596,8 @@ var BADGE_TONE_CLASSES = {
|
|
|
2468
2596
|
warning: "bg-amber-500 text-white"
|
|
2469
2597
|
};
|
|
2470
2598
|
function useExtensionBadges(product) {
|
|
2471
|
-
const [badges, setBadges] =
|
|
2472
|
-
|
|
2599
|
+
const [badges, setBadges] = React37.useState([]);
|
|
2600
|
+
React37.useEffect(() => {
|
|
2473
2601
|
let cancelled = false;
|
|
2474
2602
|
getProductCardBadges(product).then((next) => {
|
|
2475
2603
|
if (!cancelled && next.length > 0) setBadges(next);
|
|
@@ -3665,7 +3793,7 @@ function scalarToString(value) {
|
|
|
3665
3793
|
}
|
|
3666
3794
|
function ProductSpecs({ product }) {
|
|
3667
3795
|
const config = useStorefrontConfig();
|
|
3668
|
-
const extraExcluded =
|
|
3796
|
+
const extraExcluded = React37.useMemo(
|
|
3669
3797
|
() => new Set(config.productSpecs?.exclude ?? []),
|
|
3670
3798
|
[config.productSpecs?.exclude]
|
|
3671
3799
|
);
|
|
@@ -3772,7 +3900,7 @@ function useProducts(opts) {
|
|
|
3772
3900
|
setProducts(data);
|
|
3773
3901
|
setError(null);
|
|
3774
3902
|
}).catch((e) => {
|
|
3775
|
-
if (!cancelled) setError(
|
|
3903
|
+
if (!cancelled) setError(errorMessage(e));
|
|
3776
3904
|
}).finally(() => {
|
|
3777
3905
|
if (!cancelled) setLoading(false);
|
|
3778
3906
|
});
|
|
@@ -3825,7 +3953,7 @@ function ProductEnquiryForm({ product, onSuccess }) {
|
|
|
3825
3953
|
onSuccess?.();
|
|
3826
3954
|
} catch (e) {
|
|
3827
3955
|
setStatus("error");
|
|
3828
|
-
setError(
|
|
3956
|
+
setError(errorMessage(e));
|
|
3829
3957
|
}
|
|
3830
3958
|
};
|
|
3831
3959
|
return /* @__PURE__ */ jsxs(
|
|
@@ -4201,7 +4329,8 @@ function DeliveryEstimator({ compact: compact2 = false }) {
|
|
|
4201
4329
|
}
|
|
4202
4330
|
) }, option.zoneId);
|
|
4203
4331
|
}) }),
|
|
4204
|
-
delivery.status === "unserved" && /* @__PURE__ */ jsx("p", { "data-testid": TID.deliveryUnserved, className: "mt-3 text-sm text-destructive", children: "Ainda n\xE3o entregamos nesse CEP." }),
|
|
4332
|
+
delivery.status === "unserved" && /* @__PURE__ */ jsx("p", { "data-testid": TID.deliveryUnserved, className: "mt-3 text-sm text-destructive", children: delivery.refusedZone ? "Esta loja n\xE3o entrega nesse endere\xE7o." : "Ainda n\xE3o entregamos nesse CEP." }),
|
|
4333
|
+
delivery.reviewZone && delivery.status === "served" && /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm text-amber-600 dark:text-amber-500", children: "Entregamos nessa regi\xE3o, mas confirmamos com voc\xEA antes de sair." }),
|
|
4205
4334
|
delivery.postalCode && /* @__PURE__ */ jsx(
|
|
4206
4335
|
"button",
|
|
4207
4336
|
{
|
|
@@ -4536,7 +4665,7 @@ function FormBlock({
|
|
|
4536
4665
|
setValues({});
|
|
4537
4666
|
} catch (e) {
|
|
4538
4667
|
setStatus("error");
|
|
4539
|
-
setError(
|
|
4668
|
+
setError(errorMessage(e));
|
|
4540
4669
|
}
|
|
4541
4670
|
};
|
|
4542
4671
|
return /* @__PURE__ */ jsxs("section", { "data-testid": TID.formBlock, className: "mx-auto max-w-2xl px-4 py-14 sm:px-6", children: [
|
|
@@ -5316,7 +5445,7 @@ function CollectionHero({
|
|
|
5316
5445
|
{
|
|
5317
5446
|
className: `absolute inset-0 flex flex-col justify-center p-6 text-white sm:p-12 ${OVERLAY_CLASS[overlay]} ${centered ? "items-center text-center" : "items-start text-left"}`,
|
|
5318
5447
|
children: /* @__PURE__ */ jsxs(Reveal, { className: centered ? "max-w-3xl" : "max-w-2xl", children: [
|
|
5319
|
-
logos && logos.length > 0 && /* @__PURE__ */ jsx("div", { className: `mb-6 flex items-center gap-5 ${centered ? "justify-center" : ""}`, children: logos.map((logo, i) => /* @__PURE__ */ jsxs(
|
|
5448
|
+
logos && logos.length > 0 && /* @__PURE__ */ jsx("div", { className: `mb-6 flex items-center gap-5 ${centered ? "justify-center" : ""}`, children: logos.map((logo, i) => /* @__PURE__ */ jsxs(React37.Fragment, { children: [
|
|
5320
5449
|
i > 0 && /* @__PURE__ */ jsx("span", { className: "text-2xl font-light opacity-60", "aria-hidden": true, children: "\xD7" }),
|
|
5321
5450
|
/* @__PURE__ */ jsx("img", { src: logo.src, alt: logo.alt, className: "h-10 w-auto object-contain sm:h-14" })
|
|
5322
5451
|
] }, logo.src)) }),
|
|
@@ -6073,8 +6202,8 @@ function StorefrontConfigHost({
|
|
|
6073
6202
|
config,
|
|
6074
6203
|
children
|
|
6075
6204
|
}) {
|
|
6076
|
-
const [policy, setPolicy] =
|
|
6077
|
-
|
|
6205
|
+
const [policy, setPolicy] = React37.useState(null);
|
|
6206
|
+
React37.useEffect(() => {
|
|
6078
6207
|
let cancelled = false;
|
|
6079
6208
|
let provider;
|
|
6080
6209
|
try {
|
|
@@ -6093,7 +6222,7 @@ function StorefrontConfigHost({
|
|
|
6093
6222
|
cancelled = true;
|
|
6094
6223
|
};
|
|
6095
6224
|
}, [config]);
|
|
6096
|
-
const resolved =
|
|
6225
|
+
const resolved = React37.useMemo(() => applyStoreSettings(config, policy), [config, policy]);
|
|
6097
6226
|
return /* @__PURE__ */ jsx(StorefrontConfigProvider, { value: resolved, children });
|
|
6098
6227
|
}
|
|
6099
6228
|
var RADIUS_MAP = {
|
|
@@ -6213,7 +6342,7 @@ function StorefrontThemeStyle({
|
|
|
6213
6342
|
document.getElementById(linkId)?.remove();
|
|
6214
6343
|
};
|
|
6215
6344
|
}, [fontsHref, linkId, selector]);
|
|
6216
|
-
return
|
|
6345
|
+
return React37.createElement(
|
|
6217
6346
|
"style",
|
|
6218
6347
|
{ "data-sf-theme": theme.name },
|
|
6219
6348
|
themeToCss(theme, { selector })
|
|
@@ -6312,7 +6441,7 @@ function SearchOverlay({ onClose }) {
|
|
|
6312
6441
|
"\u201D."
|
|
6313
6442
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6314
6443
|
/* @__PURE__ */ jsx("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4", children: suggestions.map(
|
|
6315
|
-
(product) => searchConfig.renderSuggestion ? /* @__PURE__ */ jsx(
|
|
6444
|
+
(product) => searchConfig.renderSuggestion ? /* @__PURE__ */ jsx(React37.Fragment, { children: searchConfig.renderSuggestion(product) }, product.id) : /* @__PURE__ */ jsx(SuggestionCard, { product, onNavigate: onClose }, product.id)
|
|
6316
6445
|
) }),
|
|
6317
6446
|
/* @__PURE__ */ jsx(
|
|
6318
6447
|
"button",
|
|
@@ -6518,11 +6647,11 @@ function HeaderActions({ onMenuClick }) {
|
|
|
6518
6647
|
const openDrawer = useCartStore((s2) => s2.openDrawer);
|
|
6519
6648
|
const session = useSessionStore();
|
|
6520
6649
|
const [accountOpen, setAccountOpen] = useState(false);
|
|
6521
|
-
const accountRef =
|
|
6650
|
+
const accountRef = React37.useRef(null);
|
|
6522
6651
|
const pop = usePopOnChange(count);
|
|
6523
6652
|
const firstName = session.name?.split(/\s+/)[0];
|
|
6524
6653
|
const initial2 = (firstName ?? session.email ?? "C").slice(0, 1).toUpperCase();
|
|
6525
|
-
|
|
6654
|
+
React37.useEffect(() => {
|
|
6526
6655
|
if (!accountOpen) return;
|
|
6527
6656
|
const onPointerDown = (event) => {
|
|
6528
6657
|
if (!accountRef.current?.contains(event.target)) setAccountOpen(false);
|
|
@@ -6689,7 +6818,7 @@ function MobileMenuDrawer({ open, onClose }) {
|
|
|
6689
6818
|
navigateTo(config.catalogPath);
|
|
6690
6819
|
onClose();
|
|
6691
6820
|
};
|
|
6692
|
-
|
|
6821
|
+
React37.useEffect(() => {
|
|
6693
6822
|
if (!open) return;
|
|
6694
6823
|
const onKey = (e) => {
|
|
6695
6824
|
if (e.key === "Escape") onClose();
|
|
@@ -6759,8 +6888,9 @@ function MobileMenuDrawer({ open, onClose }) {
|
|
|
6759
6888
|
)
|
|
6760
6889
|
] });
|
|
6761
6890
|
}
|
|
6762
|
-
function StorefrontHeader() {
|
|
6891
|
+
function StorefrontHeader({ chrome } = {}) {
|
|
6763
6892
|
const config = useStorefrontConfig();
|
|
6893
|
+
const compact2 = chrome === "minimal";
|
|
6764
6894
|
const variant = config.theme?.header?.variant ?? "classic";
|
|
6765
6895
|
const scrolled = useScrolled();
|
|
6766
6896
|
const showSearch = config.theme?.header?.showSearch !== false;
|
|
@@ -6774,8 +6904,27 @@ function StorefrontHeader() {
|
|
|
6774
6904
|
style: headerStyle,
|
|
6775
6905
|
children: [
|
|
6776
6906
|
/* @__PURE__ */ jsx(AnnouncementBar, {}),
|
|
6777
|
-
/* @__PURE__ */ jsx(UtilityBar, {}),
|
|
6778
|
-
|
|
6907
|
+
!compact2 && /* @__PURE__ */ jsx(UtilityBar, {}),
|
|
6908
|
+
compact2 ? (
|
|
6909
|
+
// O cabeçalho de um app de pedido: marca, busca, carrinho — e o resto da
|
|
6910
|
+
// navegação atrás do menu, alcançável e fora do caminho.
|
|
6911
|
+
/* @__PURE__ */ jsxs("div", { className: "mx-auto flex h-14 max-w-7xl items-center gap-3 px-4 sm:px-6", children: [
|
|
6912
|
+
/* @__PURE__ */ jsx(
|
|
6913
|
+
"button",
|
|
6914
|
+
{
|
|
6915
|
+
type: "button",
|
|
6916
|
+
"aria-label": "Abrir menu",
|
|
6917
|
+
"aria-expanded": mobileMenuOpen,
|
|
6918
|
+
onClick: () => setMobileMenuOpen((v) => !v),
|
|
6919
|
+
className: "-ml-2 grid h-11 w-11 shrink-0 place-items-center rounded-full",
|
|
6920
|
+
children: /* @__PURE__ */ jsx(Menu, { className: "h-5 w-5" })
|
|
6921
|
+
}
|
|
6922
|
+
),
|
|
6923
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 truncate", children: logo }),
|
|
6924
|
+
showSearch && /* @__PURE__ */ jsx(SearchInput, { iconOnly: true, className: "shrink-0" }),
|
|
6925
|
+
/* @__PURE__ */ jsx(HeaderActions, {})
|
|
6926
|
+
] })
|
|
6927
|
+
) : variant === "centered" ? (
|
|
6779
6928
|
// Rio/Flex pattern: centered logo row, nav row below
|
|
6780
6929
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6781
6930
|
/* @__PURE__ */ jsxs("div", { className: "mx-auto grid h-16 max-w-7xl grid-cols-[1fr_auto_1fr] items-center px-4 sm:px-6", children: [
|
|
@@ -6995,7 +7144,8 @@ var useToastStore = create((set) => ({
|
|
|
6995
7144
|
title: input.title,
|
|
6996
7145
|
description: input.description,
|
|
6997
7146
|
variant: input.variant ?? "info",
|
|
6998
|
-
durationMs: input.durationMs ?? 3400
|
|
7147
|
+
durationMs: input.durationMs ?? 3400,
|
|
7148
|
+
action: input.action
|
|
6999
7149
|
};
|
|
7000
7150
|
set((s2) => ({ toasts: [...s2.toasts, toast2] }));
|
|
7001
7151
|
return id;
|
|
@@ -7126,7 +7276,7 @@ function CartDrawer() {
|
|
|
7126
7276
|
"div",
|
|
7127
7277
|
{
|
|
7128
7278
|
"data-testid": TID.cartLinesList,
|
|
7129
|
-
className: "flex-1 space-y-4 overflow-y-auto py-4 pl-5 pr-6",
|
|
7279
|
+
className: "min-h-0 flex-1 space-y-4 overflow-y-auto py-4 pl-5 pr-6",
|
|
7130
7280
|
style: { scrollbarGutter: "stable" },
|
|
7131
7281
|
children: [
|
|
7132
7282
|
/* @__PURE__ */ jsx(Slot, { area: "cart", name: "beforeLines", context: cartSlotContext }),
|
|
@@ -7156,6 +7306,11 @@ function CartDrawer() {
|
|
|
7156
7306
|
] }),
|
|
7157
7307
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: line.sku }),
|
|
7158
7308
|
line.optionsLabel && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: line.optionsLabel }),
|
|
7309
|
+
line.notes && /* @__PURE__ */ jsxs("span", { className: "text-xs italic text-muted-foreground", children: [
|
|
7310
|
+
"\u201C",
|
|
7311
|
+
line.notes,
|
|
7312
|
+
"\u201D"
|
|
7313
|
+
] }),
|
|
7159
7314
|
/* @__PURE__ */ jsx(CartLineAnnotations, { line }),
|
|
7160
7315
|
/* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between pt-2", children: [
|
|
7161
7316
|
/* @__PURE__ */ jsx(
|
|
@@ -7190,7 +7345,7 @@ function CartDrawer() {
|
|
|
7190
7345
|
"div",
|
|
7191
7346
|
{
|
|
7192
7347
|
"data-testid": TID.cartFooter,
|
|
7193
|
-
className: "space-y-3 border-t px-5 py-4",
|
|
7348
|
+
className: "max-h-[55%] shrink-0 space-y-3 overflow-y-auto border-t px-5 py-4",
|
|
7194
7349
|
children: [
|
|
7195
7350
|
config.features.discounts && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
7196
7351
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
@@ -7333,6 +7488,7 @@ function resolveStorefrontRoute(config, rawPath) {
|
|
|
7333
7488
|
if (matchPath("/checkout", path)) return { kind: "checkout" };
|
|
7334
7489
|
if (matchPath("/account", path)) return { kind: "account" };
|
|
7335
7490
|
if (matchPath("/catalog", path)) return { kind: "catalog" };
|
|
7491
|
+
if (resolved.delivery && matchPath(resolved.delivery.menuPath, path)) return { kind: "menu" };
|
|
7336
7492
|
if (resolved.search.mode === "overlay" && matchPath(resolved.search.resultsPath, path)) {
|
|
7337
7493
|
return { kind: "searchResults" };
|
|
7338
7494
|
}
|
|
@@ -7347,7 +7503,7 @@ function resolveStorefrontRoute(config, rawPath) {
|
|
|
7347
7503
|
function isKnownPath(config, path) {
|
|
7348
7504
|
return resolveStorefrontRoute(config, path).kind !== "notFound";
|
|
7349
7505
|
}
|
|
7350
|
-
var STATIC_PATTERNS = ["/", "/catalog", "/privacy", "/terms", "/refunds"];
|
|
7506
|
+
var STATIC_PATTERNS = ["/", "/catalog", "/menu", "/privacy", "/terms", "/refunds"];
|
|
7351
7507
|
function ensureResolved(config) {
|
|
7352
7508
|
return "features" in config && "pages" in config ? config : resolveConfig(config);
|
|
7353
7509
|
}
|
|
@@ -7401,7 +7557,7 @@ function listLocalOrderIds() {
|
|
|
7401
7557
|
}
|
|
7402
7558
|
|
|
7403
7559
|
// src/lib/errors.ts
|
|
7404
|
-
function
|
|
7560
|
+
function errorMessage5(err) {
|
|
7405
7561
|
if (err instanceof Error) return err.message;
|
|
7406
7562
|
if (err && typeof err === "object" && typeof err.message === "string") {
|
|
7407
7563
|
return err.message;
|
|
@@ -7418,7 +7574,7 @@ function formatDeliveryNotes(address, shippingAddress) {
|
|
|
7418
7574
|
return parts.length > 0 ? `Entrega: ${parts.join(", ")}` : void 0;
|
|
7419
7575
|
}
|
|
7420
7576
|
function isStaleCustomerError(err) {
|
|
7421
|
-
const message =
|
|
7577
|
+
const message = errorMessage5(err).toLowerCase();
|
|
7422
7578
|
return message.includes("customer email mismatch") || message.includes("customer does not belong to this store") || message.includes("customer belongs to another account");
|
|
7423
7579
|
}
|
|
7424
7580
|
async function placeStorefrontOrder({
|
|
@@ -7428,6 +7584,8 @@ async function placeStorefrontOrder({
|
|
|
7428
7584
|
customer,
|
|
7429
7585
|
address,
|
|
7430
7586
|
shippingAddress,
|
|
7587
|
+
fulfillmentType,
|
|
7588
|
+
scheduledFor,
|
|
7431
7589
|
paymentMethod,
|
|
7432
7590
|
markPaid = false
|
|
7433
7591
|
}) {
|
|
@@ -7446,9 +7604,12 @@ async function placeStorefrontOrder({
|
|
|
7446
7604
|
// from it and decrements ITS stock, so two sizes never share a counter.
|
|
7447
7605
|
variantId: line.variantId || void 0,
|
|
7448
7606
|
quantity: line.quantity,
|
|
7449
|
-
optionsLabel: line.optionsLabel || void 0
|
|
7607
|
+
optionsLabel: line.optionsLabel || void 0,
|
|
7608
|
+
// A observação da linha (0094). Vai por item porque é por item: duas
|
|
7609
|
+
// unidades do mesmo prato com pedidos diferentes são duas linhas.
|
|
7610
|
+
notes: line.notes || void 0
|
|
7450
7611
|
}));
|
|
7451
|
-
const shippingTotal = selectShipping(cart, config);
|
|
7612
|
+
const shippingTotal = fulfillmentType === "pickup" ? 0 : selectShipping(cart, config);
|
|
7452
7613
|
const replaced = await runBeforePlaceOrderValve({
|
|
7453
7614
|
items,
|
|
7454
7615
|
customer: { name, email },
|
|
@@ -7481,6 +7642,8 @@ async function placeStorefrontOrder({
|
|
|
7481
7642
|
shippingAddress,
|
|
7482
7643
|
paymentMethod,
|
|
7483
7644
|
metadata,
|
|
7645
|
+
fulfillmentType,
|
|
7646
|
+
scheduledFor,
|
|
7484
7647
|
items
|
|
7485
7648
|
});
|
|
7486
7649
|
let order;
|
|
@@ -7649,47 +7812,61 @@ var LABELS2 = {
|
|
|
7649
7812
|
3: "Pagamento",
|
|
7650
7813
|
4: "Pronto"
|
|
7651
7814
|
};
|
|
7652
|
-
function CheckoutSteps({ current, onGoBackTo }) {
|
|
7653
|
-
const steps = [1, 2, 3, 4];
|
|
7815
|
+
function CheckoutSteps({ current, onGoBackTo, omit }) {
|
|
7816
|
+
const steps = [1, 2, 3, 4].filter((s2) => !omit?.includes(s2));
|
|
7654
7817
|
return /* @__PURE__ */ jsxs("nav", { "data-testid": TID.checkoutSteps, "aria-label": "Etapas do checkout", className: "mb-8", children: [
|
|
7655
7818
|
/* @__PURE__ */ jsx("ol", { className: "flex items-center gap-1.5 sm:gap-2", children: steps.map((step, index) => {
|
|
7656
7819
|
const done = step < current;
|
|
7657
7820
|
const active2 = step === current;
|
|
7658
7821
|
const canGoBack = done && !!onGoBackTo;
|
|
7659
7822
|
const Tag = canGoBack ? "button" : "div";
|
|
7660
|
-
return
|
|
7823
|
+
return (
|
|
7824
|
+
// `flex-1` só em quem TEM traço. O último passo não tem, e com
|
|
7825
|
+
// flex-1 ele reservava uma fatia inteira para desenhar apenas a
|
|
7826
|
+
// bolinha — que então parava no começo da fatia em vez do fim, e a
|
|
7827
|
+
// régua saía torta. Sem flex-1, o traço absorve a sobra e as
|
|
7828
|
+
// bolinhas encostam nas pontas.
|
|
7661
7829
|
/* @__PURE__ */ jsxs(
|
|
7662
|
-
|
|
7830
|
+
"li",
|
|
7663
7831
|
{
|
|
7664
|
-
|
|
7665
|
-
"data-testid": TID.checkoutStep(step),
|
|
7666
|
-
"data-state": done ? "done" : active2 ? "current" : "pending",
|
|
7667
|
-
"aria-current": active2 ? "step" : void 0,
|
|
7668
|
-
className: [
|
|
7669
|
-
"flex min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 text-left transition",
|
|
7670
|
-
canGoBack ? "hover:bg-muted" : "",
|
|
7671
|
-
active2 ? "text-foreground" : done ? "text-foreground" : "text-muted-foreground"
|
|
7672
|
-
].join(" "),
|
|
7832
|
+
className: `flex min-w-0 items-center gap-1.5 sm:gap-2 ${index < steps.length - 1 ? "flex-1" : ""}`,
|
|
7673
7833
|
children: [
|
|
7674
|
-
/* @__PURE__ */
|
|
7675
|
-
|
|
7834
|
+
/* @__PURE__ */ jsxs(
|
|
7835
|
+
Tag,
|
|
7676
7836
|
{
|
|
7837
|
+
...canGoBack ? { type: "button", onClick: () => onGoBackTo(step) } : {},
|
|
7838
|
+
"data-testid": TID.checkoutStep(step),
|
|
7839
|
+
"data-state": done ? "done" : active2 ? "current" : "pending",
|
|
7840
|
+
"aria-current": active2 ? "step" : void 0,
|
|
7677
7841
|
className: [
|
|
7678
|
-
"
|
|
7679
|
-
|
|
7842
|
+
"flex min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 text-left transition",
|
|
7843
|
+
canGoBack ? "hover:bg-muted" : "",
|
|
7844
|
+
active2 ? "text-foreground" : done ? "text-foreground" : "text-muted-foreground"
|
|
7680
7845
|
].join(" "),
|
|
7681
|
-
children:
|
|
7846
|
+
children: [
|
|
7847
|
+
/* @__PURE__ */ jsx(
|
|
7848
|
+
"span",
|
|
7849
|
+
{
|
|
7850
|
+
className: [
|
|
7851
|
+
"grid h-7 w-7 shrink-0 place-items-center rounded-full border text-xs font-semibold",
|
|
7852
|
+
done ? "border-primary bg-primary text-primary-foreground" : active2 ? "border-primary bg-background text-primary" : "border-muted-foreground/30 bg-background"
|
|
7853
|
+
].join(" "),
|
|
7854
|
+
children: done ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" }) : index + 1
|
|
7855
|
+
}
|
|
7856
|
+
),
|
|
7857
|
+
/* @__PURE__ */ jsx("span", { className: `hidden truncate text-sm sm:inline ${active2 ? "font-semibold" : ""}`, children: LABELS2[step] })
|
|
7858
|
+
]
|
|
7682
7859
|
}
|
|
7683
7860
|
),
|
|
7684
|
-
/* @__PURE__ */ jsx("span", { className: `
|
|
7861
|
+
index < steps.length - 1 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: `h-px flex-1 ${done ? "bg-primary" : "bg-border"}` })
|
|
7685
7862
|
]
|
|
7686
|
-
}
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7863
|
+
},
|
|
7864
|
+
step
|
|
7865
|
+
)
|
|
7866
|
+
);
|
|
7690
7867
|
}) }),
|
|
7691
7868
|
/* @__PURE__ */ jsxs("p", { className: "mt-2 text-sm font-semibold sm:hidden", children: [
|
|
7692
|
-
current,
|
|
7869
|
+
steps.indexOf(current) + 1,
|
|
7693
7870
|
". ",
|
|
7694
7871
|
LABELS2[current]
|
|
7695
7872
|
] })
|
|
@@ -7844,13 +8021,13 @@ function CardBrick({ publicKey, amount, email, onSubmit, onError }) {
|
|
|
7844
8021
|
var POLL_MS = 3e3;
|
|
7845
8022
|
var RESUME_KEY = "fz.checkout.resume";
|
|
7846
8023
|
function useExpiry(expiresAt) {
|
|
7847
|
-
const target =
|
|
8024
|
+
const target = React37.useMemo(() => {
|
|
7848
8025
|
if (!expiresAt) return null;
|
|
7849
8026
|
const t = new Date(expiresAt).getTime();
|
|
7850
8027
|
return Number.isFinite(t) ? t : null;
|
|
7851
8028
|
}, [expiresAt]);
|
|
7852
|
-
const [now, setNow] =
|
|
7853
|
-
|
|
8029
|
+
const [now, setNow] = React37.useState(() => Date.now());
|
|
8030
|
+
React37.useEffect(() => {
|
|
7854
8031
|
if (target === null) return;
|
|
7855
8032
|
const id = setInterval(() => setNow(Date.now()), 1e3);
|
|
7856
8033
|
return () => clearInterval(id);
|
|
@@ -8396,7 +8573,7 @@ var PAYMENT_LABELS = {
|
|
|
8396
8573
|
other: { label: "Combinar com a loja", hint: "A loja entra em contato para acertar o pagamento" }
|
|
8397
8574
|
};
|
|
8398
8575
|
function placeOrderMessage(err) {
|
|
8399
|
-
const message =
|
|
8576
|
+
const message = errorMessage5(err);
|
|
8400
8577
|
if (/customer (email mismatch|does not belong|belongs to another)/i.test(message)) {
|
|
8401
8578
|
return "Sua sess\xE3o ficou presa a outro cadastro. Recarregue a p\xE1gina e tente de novo.";
|
|
8402
8579
|
}
|
|
@@ -8408,9 +8585,16 @@ function placeOrderMessage(err) {
|
|
|
8408
8585
|
}
|
|
8409
8586
|
return message.replace(/^shop_[a-z_]+:\s*/i, "") || "N\xE3o foi poss\xEDvel concluir o pedido.";
|
|
8410
8587
|
}
|
|
8588
|
+
var DEV_BUILD = (() => {
|
|
8589
|
+
try {
|
|
8590
|
+
return import.meta.env?.DEV === true;
|
|
8591
|
+
} catch {
|
|
8592
|
+
return false;
|
|
8593
|
+
}
|
|
8594
|
+
})();
|
|
8411
8595
|
function field(label, testId, value, onChange, props) {
|
|
8412
8596
|
return /* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
8413
|
-
/* @__PURE__ */ jsx("span", { className: "
|
|
8597
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-xs font-medium text-muted-foreground", children: label }),
|
|
8414
8598
|
/* @__PURE__ */ jsx(
|
|
8415
8599
|
"input",
|
|
8416
8600
|
{
|
|
@@ -8470,7 +8654,7 @@ function CheckoutPage() {
|
|
|
8470
8654
|
district: "",
|
|
8471
8655
|
state: ""
|
|
8472
8656
|
});
|
|
8473
|
-
|
|
8657
|
+
React37.useEffect(() => {
|
|
8474
8658
|
if (!known.ready) return;
|
|
8475
8659
|
setForm((current) => ({
|
|
8476
8660
|
...current,
|
|
@@ -8486,6 +8670,26 @@ function CheckoutPage() {
|
|
|
8486
8670
|
}));
|
|
8487
8671
|
}, [known.ready, known.phone, known.document, known.address]);
|
|
8488
8672
|
const [step, setStep] = useState(resume ? 3 : 1);
|
|
8673
|
+
const fulfillmentType = useDeliveryStore((s2) => s2.fulfillmentType);
|
|
8674
|
+
const scheduledFor = useDeliveryStore((s2) => s2.scheduledFor);
|
|
8675
|
+
const deliveryReference = useDeliveryStore((s2) => {
|
|
8676
|
+
const kept = s2.savedAddresses.find((a) => a.id === s2.selectedAddressId);
|
|
8677
|
+
return kept?.reference?.trim() || "";
|
|
8678
|
+
});
|
|
8679
|
+
const isPickup = fulfillmentType === "pickup";
|
|
8680
|
+
const [dbPickup, setDbPickup] = useState(null);
|
|
8681
|
+
useEffect(() => {
|
|
8682
|
+
if (!isPickup) return;
|
|
8683
|
+
let alive = true;
|
|
8684
|
+
void (async () => {
|
|
8685
|
+
const settings = await getShopProvider().getPublicStoreSettings?.().catch(() => null);
|
|
8686
|
+
if (alive && settings?.pickupAddress) setDbPickup(settings.pickupAddress);
|
|
8687
|
+
})();
|
|
8688
|
+
return () => {
|
|
8689
|
+
alive = false;
|
|
8690
|
+
};
|
|
8691
|
+
}, [isPickup]);
|
|
8692
|
+
const pickupAddress = dbPickup ?? config.delivery?.pickupAddress ?? null;
|
|
8489
8693
|
const [paidOrderId, setPaidOrderId] = useState(null);
|
|
8490
8694
|
const [error, setError] = useState(null);
|
|
8491
8695
|
const [discountCode, setDiscountCode] = useState("");
|
|
@@ -8494,14 +8698,15 @@ function CheckoutPage() {
|
|
|
8494
8698
|
const [applyingDiscount, setApplyingDiscount] = useState(false);
|
|
8495
8699
|
const [showSignin, setShowSignin] = useState(false);
|
|
8496
8700
|
const [placing, setPlacing] = useState(false);
|
|
8497
|
-
const leaving =
|
|
8701
|
+
const leaving = React37.useRef(false);
|
|
8498
8702
|
const [zipLookup, setZipLookup] = useState("idle");
|
|
8499
8703
|
const subtotal = selectSubtotal(cart);
|
|
8500
8704
|
const discountTotal = selectDiscountTotal(cart);
|
|
8501
|
-
const
|
|
8502
|
-
const
|
|
8705
|
+
const shippingRaw = selectShipping(cart, config);
|
|
8706
|
+
const shipping = isPickup ? 0 : shippingRaw;
|
|
8707
|
+
const total = selectTotal(cart, config) - (isPickup ? shippingRaw : 0);
|
|
8503
8708
|
const checkoutSlotContext = { subtotal, total };
|
|
8504
|
-
const checkoutSessionInput =
|
|
8709
|
+
const checkoutSessionInput = React37.useMemo(() => ({
|
|
8505
8710
|
items: cart.lines.map((line) => ({
|
|
8506
8711
|
productId: line.productId,
|
|
8507
8712
|
variantId: line.variantId ?? null,
|
|
@@ -8651,10 +8856,23 @@ function CheckoutPage() {
|
|
|
8651
8856
|
}, [session.customerId]);
|
|
8652
8857
|
useEffect(() => {
|
|
8653
8858
|
if (addressMode !== "new") return;
|
|
8859
|
+
const kept = delivery.savedAddresses.find((a) => a.id === delivery.selectedAddressId);
|
|
8654
8860
|
const looked = delivery.address;
|
|
8655
|
-
if (!looked) return;
|
|
8861
|
+
if (!kept && !looked) return;
|
|
8656
8862
|
setForm((current) => {
|
|
8657
8863
|
if (current.zip.trim() || current.street.trim()) return current;
|
|
8864
|
+
if (kept) {
|
|
8865
|
+
return {
|
|
8866
|
+
...current,
|
|
8867
|
+
zip: formatPostalCode(kept.postalCode),
|
|
8868
|
+
street: kept.street,
|
|
8869
|
+
number: kept.number,
|
|
8870
|
+
complement: kept.complement ?? "",
|
|
8871
|
+
district: kept.district,
|
|
8872
|
+
city: kept.city,
|
|
8873
|
+
state: kept.state
|
|
8874
|
+
};
|
|
8875
|
+
}
|
|
8658
8876
|
return {
|
|
8659
8877
|
...current,
|
|
8660
8878
|
zip: formatPostalCode(looked.postalCode),
|
|
@@ -8664,7 +8882,7 @@ function CheckoutPage() {
|
|
|
8664
8882
|
state: looked.state
|
|
8665
8883
|
};
|
|
8666
8884
|
});
|
|
8667
|
-
}, [delivery.address, addressMode]);
|
|
8885
|
+
}, [delivery.address, delivery.savedAddresses, delivery.selectedAddressId, addressMode]);
|
|
8668
8886
|
function applySavedAddress(address) {
|
|
8669
8887
|
setAddressMode("saved");
|
|
8670
8888
|
setSelectedAddressId(address.id);
|
|
@@ -8724,6 +8942,7 @@ function CheckoutPage() {
|
|
|
8724
8942
|
}
|
|
8725
8943
|
function validateDelivery() {
|
|
8726
8944
|
setError(null);
|
|
8945
|
+
if (isPickup) return true;
|
|
8727
8946
|
if (!selectRequiresShipping(cart)) return true;
|
|
8728
8947
|
if (!form.street.trim() || !form.city.trim() || !form.zip.trim() || !form.district.trim()) {
|
|
8729
8948
|
return fail("Preencha ou selecione o endere\xE7o de entrega.", TID.checkoutStreet);
|
|
@@ -8748,13 +8967,33 @@ function CheckoutPage() {
|
|
|
8748
8967
|
setStep(next);
|
|
8749
8968
|
if (typeof window !== "undefined") window.scrollTo({ top: 0, behavior: "smooth" });
|
|
8750
8969
|
}
|
|
8970
|
+
function orderAddress() {
|
|
8971
|
+
if (isPickup && pickupAddress) {
|
|
8972
|
+
return {
|
|
8973
|
+
...pickupAddress,
|
|
8974
|
+
phone: form.phone.trim() || void 0,
|
|
8975
|
+
document: documentDigits(form.document) || void 0
|
|
8976
|
+
};
|
|
8977
|
+
}
|
|
8978
|
+
return {
|
|
8979
|
+
postalCode: form.zip.trim(),
|
|
8980
|
+
street: form.street.trim(),
|
|
8981
|
+
number: form.number.trim() || void 0,
|
|
8982
|
+
complement: form.complement.trim() || void 0,
|
|
8983
|
+
district: form.district.trim() || void 0,
|
|
8984
|
+
city: form.city.trim(),
|
|
8985
|
+
state: form.state.trim().toUpperCase(),
|
|
8986
|
+
phone: form.phone.trim() || void 0,
|
|
8987
|
+
document: documentDigits(form.document) || void 0
|
|
8988
|
+
};
|
|
8989
|
+
}
|
|
8751
8990
|
function advance() {
|
|
8752
8991
|
if (step === 1 && validateContact()) {
|
|
8753
8992
|
void getShopProvider().saveCustomerContact?.({
|
|
8754
8993
|
phone: form.phone.trim() || null,
|
|
8755
8994
|
document: documentDigits(form.document) || null
|
|
8756
8995
|
});
|
|
8757
|
-
goToStep(2);
|
|
8996
|
+
goToStep(isPickup ? 3 : 2);
|
|
8758
8997
|
} else if (step === 2 && validateDelivery()) goToStep(3);
|
|
8759
8998
|
}
|
|
8760
8999
|
async function confirmWithoutCharge() {
|
|
@@ -8766,21 +9005,26 @@ function CheckoutPage() {
|
|
|
8766
9005
|
cart,
|
|
8767
9006
|
session,
|
|
8768
9007
|
customer: { email: form.email, name: form.name },
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
state: form.state.trim().toUpperCase(),
|
|
8778
|
-
phone: form.phone.trim() || void 0,
|
|
8779
|
-
// Viaja no endereço porque a assinatura do shop_place_order não pode
|
|
8780
|
-
// ganhar parâmetro sem DROP (0050); uma trigger o levanta para a
|
|
8781
|
-
// coluna e o tira do jsonb, então nunca vira linha de endereço.
|
|
8782
|
-
document: documentDigits(form.document) || void 0
|
|
9008
|
+
// `notes` é o recado do comprador para a loja, e o ponto de referência
|
|
9009
|
+
// é exatamente isso: "portão azul, ao lado da padaria" não cabe em
|
|
9010
|
+
// nenhum campo estruturado do endereço e é o que o entregador lê.
|
|
9011
|
+
address: {
|
|
9012
|
+
street: form.street,
|
|
9013
|
+
city: form.city,
|
|
9014
|
+
zip: form.zip,
|
|
9015
|
+
notes: deliveryReference || void 0
|
|
8783
9016
|
},
|
|
9017
|
+
// Viaja com o `document` dentro: a assinatura do shop_place_order não
|
|
9018
|
+
// pode ganhar parâmetro sem DROP (0050), e uma trigger o levanta para a
|
|
9019
|
+
// coluna. Na retirada este endereço é o balcão — ver orderAddress().
|
|
9020
|
+
shippingAddress: orderAddress(),
|
|
9021
|
+
// Entrega/retirada e agendamento (0094) vão AQUI porque esta tela chama
|
|
9022
|
+
// placeStorefrontOrder direto, sem passar pelo useCheckout — e sem esta
|
|
9023
|
+
// linha o pedido nascia sem `fulfillment_type`, com a retirada
|
|
9024
|
+
// indistinguível de uma entrega e o frete cobrado assim mesmo. Foi um
|
|
9025
|
+
// pedido de teste real (#1379) que mostrou isso.
|
|
9026
|
+
fulfillmentType,
|
|
9027
|
+
scheduledFor: scheduledFor ?? void 0,
|
|
8784
9028
|
paymentMethod
|
|
8785
9029
|
});
|
|
8786
9030
|
if (customerId) session.setSession({ customerId, email: form.email, name: form.name });
|
|
@@ -8813,6 +9057,7 @@ function CheckoutPage() {
|
|
|
8813
9057
|
TID.checkoutDocument
|
|
8814
9058
|
);
|
|
8815
9059
|
}
|
|
9060
|
+
if (isPickup) return true;
|
|
8816
9061
|
if (!form.street.trim() || !form.city.trim() || !form.zip.trim() || !form.district.trim()) {
|
|
8817
9062
|
return fail("Preencha ou selecione o endere\xE7o de entrega.", TID.checkoutStreet);
|
|
8818
9063
|
}
|
|
@@ -8860,7 +9105,8 @@ function CheckoutPage() {
|
|
|
8860
9105
|
CheckoutSteps,
|
|
8861
9106
|
{
|
|
8862
9107
|
current: step,
|
|
8863
|
-
|
|
9108
|
+
omit: isPickup ? [2] : void 0,
|
|
9109
|
+
onGoBackTo: step === 4 ? void 0 : (target) => goToStep(isPickup && target === 2 ? 1 : target)
|
|
8864
9110
|
}
|
|
8865
9111
|
),
|
|
8866
9112
|
/* @__PURE__ */ jsxs(
|
|
@@ -9092,6 +9338,27 @@ function CheckoutPage() {
|
|
|
9092
9338
|
}
|
|
9093
9339
|
),
|
|
9094
9340
|
/* @__PURE__ */ jsx("p", { className: "mt-2 text-center text-xs text-muted-foreground", children: "O pedido fica aguardando pagamento at\xE9 a loja confirmar." })
|
|
9341
|
+
] }),
|
|
9342
|
+
DEV_BUILD && chargesOnline && /* @__PURE__ */ jsxs("div", { className: "mt-6 rounded-xl border border-dashed border-amber-500/60 bg-amber-500/5 p-4", children: [
|
|
9343
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-amber-600", children: "Somente em desenvolvimento" }),
|
|
9344
|
+
/* @__PURE__ */ jsx(
|
|
9345
|
+
"button",
|
|
9346
|
+
{
|
|
9347
|
+
type: "button",
|
|
9348
|
+
"data-testid": TID.devPlaceOrderWithoutCharge,
|
|
9349
|
+
disabled: placing,
|
|
9350
|
+
onClick: () => {
|
|
9351
|
+
void confirmWithoutCharge();
|
|
9352
|
+
},
|
|
9353
|
+
className: "mt-2 min-h-11 w-full rounded-lg border border-amber-500/60 px-4 py-2.5 text-sm font-medium text-amber-700 transition hover:bg-amber-500/10 disabled:opacity-60",
|
|
9354
|
+
children: `Criar pedido sem cobrar \u2014 ${money(total)}`
|
|
9355
|
+
}
|
|
9356
|
+
),
|
|
9357
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-2 text-xs text-muted-foreground", children: [
|
|
9358
|
+
"Pula o adquirente e grava o pedido como ",
|
|
9359
|
+
/* @__PURE__ */ jsx("code", { children: "pending" }),
|
|
9360
|
+
", igual a uma loja que confirma o pagamento \xE0 m\xE3o. Este bloco n\xE3o vai para produ\xE7\xE3o."
|
|
9361
|
+
] })
|
|
9095
9362
|
] })
|
|
9096
9363
|
] }),
|
|
9097
9364
|
step === 4 && paidOrderId && /* @__PURE__ */ jsxs("section", { "data-testid": TID.checkoutDone, className: "rounded-xl border bg-card p-8 text-center", children: [
|
|
@@ -9116,7 +9383,7 @@ function CheckoutPage() {
|
|
|
9116
9383
|
type: "submit",
|
|
9117
9384
|
"data-testid": TID.checkoutContinue,
|
|
9118
9385
|
className: "min-h-12 rounded-lg bg-primary px-6 py-4 text-sm font-bold text-primary-foreground transition hover:opacity-90",
|
|
9119
|
-
children: step === 1 ? "Continuar para a entrega" : `Ir para o pagamento - ${money(total)}`
|
|
9386
|
+
children: step === 1 ? isPickup ? `Ir para o pagamento - ${money(total)}` : "Continuar para a entrega" : `Ir para o pagamento - ${money(total)}`
|
|
9120
9387
|
}
|
|
9121
9388
|
),
|
|
9122
9389
|
step === 2 && /* @__PURE__ */ jsx(
|
|
@@ -9133,12 +9400,7 @@ function CheckoutPage() {
|
|
|
9133
9400
|
] })
|
|
9134
9401
|
]
|
|
9135
9402
|
}
|
|
9136
|
-
)
|
|
9137
|
-
/* @__PURE__ */ jsxs("footer", { className: "mt-10 flex flex-wrap gap-4 border-t pt-5 text-xs text-muted-foreground", children: [
|
|
9138
|
-
/* @__PURE__ */ jsx(Link, { to: "/privacy", className: "hover:text-foreground", children: "Privacidade" }),
|
|
9139
|
-
/* @__PURE__ */ jsx(Link, { to: "/terms", className: "hover:text-foreground", children: "Termos" }),
|
|
9140
|
-
/* @__PURE__ */ jsx(Link, { to: "/refunds", className: "hover:text-foreground", children: "Trocas e devolu\xE7\xF5es" })
|
|
9141
|
-
] })
|
|
9403
|
+
)
|
|
9142
9404
|
] }),
|
|
9143
9405
|
/* @__PURE__ */ jsxs("aside", { className: "rounded-xl border bg-muted/20 p-5 lg:sticky lg:top-6 lg:col-span-2 lg:self-start", children: [
|
|
9144
9406
|
/* @__PURE__ */ jsx("h2", { className: "sr-only", children: "Resumo do pedido" }),
|
|
@@ -9150,7 +9412,12 @@ function CheckoutPage() {
|
|
|
9150
9412
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
9151
9413
|
/* @__PURE__ */ jsx("p", { className: "truncate font-medium", children: line.name }),
|
|
9152
9414
|
line.sku && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: line.sku }),
|
|
9153
|
-
line.optionsLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: line.optionsLabel })
|
|
9415
|
+
line.optionsLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: line.optionsLabel }),
|
|
9416
|
+
line.notes && /* @__PURE__ */ jsxs("p", { className: "text-xs italic text-muted-foreground", children: [
|
|
9417
|
+
"\u201C",
|
|
9418
|
+
line.notes,
|
|
9419
|
+
"\u201D"
|
|
9420
|
+
] })
|
|
9154
9421
|
] }),
|
|
9155
9422
|
/* @__PURE__ */ jsx("span", { "data-price": (line.unitPrice * line.quantity).toFixed(2), children: money(line.unitPrice * line.quantity) })
|
|
9156
9423
|
] }, line.lineId ?? line.productId)) }),
|
|
@@ -9216,7 +9483,7 @@ function CheckoutPage() {
|
|
|
9216
9483
|
] }),
|
|
9217
9484
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
9218
9485
|
/* @__PURE__ */ jsxs("dt", { className: cart.discountFreeShipping ? "text-emerald-700" : "text-muted-foreground", children: [
|
|
9219
|
-
"Entrega",
|
|
9486
|
+
isPickup ? "Retirada na loja" : "Entrega",
|
|
9220
9487
|
cart.discountFreeShipping && /* @__PURE__ */ jsxs(
|
|
9221
9488
|
"button",
|
|
9222
9489
|
{
|
|
@@ -9231,7 +9498,7 @@ function CheckoutPage() {
|
|
|
9231
9498
|
}
|
|
9232
9499
|
)
|
|
9233
9500
|
] }),
|
|
9234
|
-
/* @__PURE__ */ jsx("dd", { "data-price": shipping.toFixed(2), children: shipping === 0 ? "Gr\xE1tis" : money(shipping) })
|
|
9501
|
+
/* @__PURE__ */ jsx("dd", { "data-price": shipping.toFixed(2), children: isPickup ? "Sem taxa" : shipping === 0 ? "Gr\xE1tis" : money(shipping) })
|
|
9235
9502
|
] }),
|
|
9236
9503
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between border-t pt-5 text-lg font-bold", children: [
|
|
9237
9504
|
/* @__PURE__ */ jsx("dt", { children: "Total" }),
|
|
@@ -9243,159 +9510,1447 @@ function CheckoutPage() {
|
|
|
9243
9510
|
"Compra protegida e dados criptografados."
|
|
9244
9511
|
] }),
|
|
9245
9512
|
/* @__PURE__ */ jsx("div", { className: "mt-6 border-t pt-5", children: /* @__PURE__ */ jsx(Slot, { area: "checkout", name: "afterForm", context: checkoutSlotContext }) })
|
|
9513
|
+
] }),
|
|
9514
|
+
/* @__PURE__ */ jsxs("footer", { className: "flex flex-wrap gap-4 border-t pt-5 text-xs text-muted-foreground lg:col-span-5", children: [
|
|
9515
|
+
/* @__PURE__ */ jsx(Link, { to: "/privacy", className: "hover:text-foreground", children: "Privacidade" }),
|
|
9516
|
+
/* @__PURE__ */ jsx(Link, { to: "/terms", className: "hover:text-foreground", children: "Termos" }),
|
|
9517
|
+
/* @__PURE__ */ jsx(Link, { to: "/refunds", className: "hover:text-foreground", children: "Trocas e devolu\xE7\xF5es" })
|
|
9246
9518
|
] })
|
|
9247
9519
|
] })
|
|
9248
9520
|
] });
|
|
9249
9521
|
}
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
paid: { label: "Pago", tone: "positive" },
|
|
9255
|
-
partially_paid: { label: "Parcialmente pago", tone: "pending" },
|
|
9256
|
-
partially_refunded: { label: "Parcialmente reembolsado", tone: "negative" },
|
|
9257
|
-
refunded: { label: "Reembolsado", tone: "negative" },
|
|
9258
|
-
voided: { label: "Cancelado", tone: "negative" }
|
|
9259
|
-
};
|
|
9260
|
-
var TONE_CLASS = {
|
|
9261
|
-
positive: "bg-emerald-100 text-emerald-800",
|
|
9262
|
-
pending: "bg-amber-100 text-amber-800",
|
|
9263
|
-
negative: "bg-rose-100 text-rose-800"
|
|
9264
|
-
};
|
|
9265
|
-
function financialStatusBadge(status) {
|
|
9266
|
-
const entry = FINANCIAL[status] ?? { label: status, tone: "pending" };
|
|
9267
|
-
return { label: entry.label, className: TONE_CLASS[entry.tone] };
|
|
9268
|
-
}
|
|
9269
|
-
function isPaid(status) {
|
|
9270
|
-
return status === "paid" || status === "partially_paid";
|
|
9522
|
+
function selectIsOpen(state) {
|
|
9523
|
+
if (!state.service) return true;
|
|
9524
|
+
if (!state.service.configured) return true;
|
|
9525
|
+
return state.service.open;
|
|
9271
9526
|
}
|
|
9272
|
-
function
|
|
9273
|
-
return
|
|
9527
|
+
function selectShowsHours(state) {
|
|
9528
|
+
return Boolean(state.service?.configured);
|
|
9274
9529
|
}
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9287
|
-
|
|
9530
|
+
var useServiceStore = create()((set, get) => ({
|
|
9531
|
+
status: "idle",
|
|
9532
|
+
service: null,
|
|
9533
|
+
fulfillmentType: "delivery",
|
|
9534
|
+
async refresh(fulfillmentType) {
|
|
9535
|
+
const type = fulfillmentType ?? get().fulfillmentType;
|
|
9536
|
+
set({ status: "loading", fulfillmentType: type });
|
|
9537
|
+
try {
|
|
9538
|
+
const shop = getShopProvider();
|
|
9539
|
+
const service = await shop?.getServiceStatus?.(type) ?? null;
|
|
9540
|
+
set({ service, status: "ready" });
|
|
9541
|
+
} catch {
|
|
9542
|
+
set({ service: null, status: "ready" });
|
|
9543
|
+
}
|
|
9288
9544
|
}
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9545
|
+
}));
|
|
9546
|
+
|
|
9547
|
+
// src/components/delivery/store-time.ts
|
|
9548
|
+
function storeTime(iso, timeZone, options = {}) {
|
|
9549
|
+
return new Intl.DateTimeFormat("pt-BR", {
|
|
9550
|
+
...options.weekday ? { weekday: "short" } : {},
|
|
9551
|
+
hour: "2-digit",
|
|
9552
|
+
minute: "2-digit",
|
|
9553
|
+
timeZone
|
|
9554
|
+
}).format(new Date(iso));
|
|
9555
|
+
}
|
|
9556
|
+
function StoreCover({ onShowHours }) {
|
|
9557
|
+
const config = useStorefrontConfig();
|
|
9558
|
+
const cover = config.delivery?.coverImage;
|
|
9559
|
+
const logo = config.delivery?.logoImage;
|
|
9560
|
+
const locality = config.delivery?.locality;
|
|
9561
|
+
const modes = config.delivery?.fulfillmentModes ?? ["delivery"];
|
|
9562
|
+
const type = useDeliveryStore((s2) => s2.fulfillmentType);
|
|
9563
|
+
const setFulfillmentType = useDeliveryStore((s2) => s2.setFulfillmentType);
|
|
9564
|
+
const refreshService = useServiceStore((s2) => s2.refresh);
|
|
9565
|
+
const service = useServiceStore();
|
|
9566
|
+
const showsHours = selectShowsHours(service);
|
|
9567
|
+
const open = selectIsOpen(service);
|
|
9568
|
+
function choose(next) {
|
|
9569
|
+
setFulfillmentType(next);
|
|
9570
|
+
void refreshService(next);
|
|
9571
|
+
}
|
|
9572
|
+
return /* @__PURE__ */ jsxs("header", { "data-testid": TID.storeCover, className: "relative isolate bg-neutral-900 text-white", children: [
|
|
9573
|
+
cover && /* @__PURE__ */ jsx(
|
|
9574
|
+
"img",
|
|
9293
9575
|
{
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
icon: RotateCcw
|
|
9576
|
+
src: cover,
|
|
9577
|
+
alt: "",
|
|
9578
|
+
"aria-hidden": true,
|
|
9579
|
+
className: "absolute inset-0 -z-10 h-full w-full object-cover"
|
|
9299
9580
|
}
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
}
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
}
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
"data-testid": TID.orderTracking,
|
|
9342
|
-
className: `grid ${compact2 ? "gap-2" : "gap-3"} ${GRID_COLS[steps.length] ?? "sm:grid-cols-4"}`,
|
|
9343
|
-
"aria-label": "Acompanhamento do pedido",
|
|
9344
|
-
children: steps.map((step) => {
|
|
9345
|
-
const Icon2 = step.icon;
|
|
9346
|
-
const cancelled = step.state === "cancelled";
|
|
9347
|
-
const done = step.state === "complete";
|
|
9348
|
-
const current = step.state === "current";
|
|
9349
|
-
const active2 = done || current;
|
|
9581
|
+
),
|
|
9582
|
+
/* @__PURE__ */ jsx(
|
|
9583
|
+
"div",
|
|
9584
|
+
{
|
|
9585
|
+
"aria-hidden": true,
|
|
9586
|
+
className: "absolute inset-0 -z-10 bg-gradient-to-b from-black/30 via-black/45 to-black/75"
|
|
9587
|
+
}
|
|
9588
|
+
),
|
|
9589
|
+
/* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-3xl px-4 pb-4 pt-8", children: [
|
|
9590
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 [text-shadow:0_1px_3px_rgb(0_0_0_/_0.7)]", children: [
|
|
9591
|
+
/* @__PURE__ */ jsx("div", { className: "grid h-14 w-14 shrink-0 place-items-center overflow-hidden rounded-xl bg-white/10 ring-1 ring-white/20", children: logo ? /* @__PURE__ */ jsx("img", { src: logo, alt: "", "aria-hidden": true, className: "h-full w-full object-cover" }) : /* @__PURE__ */ jsx("span", { className: "text-xl font-bold", children: config.name.slice(0, 1) }) }),
|
|
9592
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
9593
|
+
/* @__PURE__ */ jsx("h1", { className: "truncate text-xl font-bold leading-tight", children: config.name }),
|
|
9594
|
+
locality && /* @__PURE__ */ jsx("p", { className: "truncate text-sm text-white/70", children: locality }),
|
|
9595
|
+
showsHours && service.service && // O estado é o botão que abre a placa da porta. Um selo que diz
|
|
9596
|
+
// "Fechado" e não leva a lugar nenhum deixa a pessoa sem a única
|
|
9597
|
+
// pergunta seguinte que ela tem: então quando abre?
|
|
9598
|
+
/* @__PURE__ */ jsxs(
|
|
9599
|
+
"button",
|
|
9600
|
+
{
|
|
9601
|
+
type: "button",
|
|
9602
|
+
"data-testid": TID.serviceStatus,
|
|
9603
|
+
"data-open": open ? "true" : "false",
|
|
9604
|
+
onClick: onShowHours,
|
|
9605
|
+
className: "mt-0.5 flex items-center gap-1.5 text-sm font-semibold underline-offset-2 hover:underline",
|
|
9606
|
+
children: [
|
|
9607
|
+
/* @__PURE__ */ jsx(
|
|
9608
|
+
"span",
|
|
9609
|
+
{
|
|
9610
|
+
"aria-hidden": true,
|
|
9611
|
+
className: `h-2 w-2 rounded-full ${open ? "bg-emerald-400" : "bg-red-400"}`
|
|
9612
|
+
}
|
|
9613
|
+
),
|
|
9614
|
+
open ? /* @__PURE__ */ jsx(OpenUntil, {}) : /* @__PURE__ */ jsx(ClosedUntil, {})
|
|
9615
|
+
]
|
|
9616
|
+
}
|
|
9617
|
+
)
|
|
9618
|
+
] })
|
|
9619
|
+
] }),
|
|
9620
|
+
modes.length > 1 && /* @__PURE__ */ jsx("div", { className: "mt-4 flex gap-1", children: modes.map((mode) => {
|
|
9621
|
+
const active2 = type === mode;
|
|
9350
9622
|
return /* @__PURE__ */ jsx(
|
|
9351
|
-
"
|
|
9623
|
+
"button",
|
|
9352
9624
|
{
|
|
9353
|
-
"
|
|
9354
|
-
"data-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
].join(" "),
|
|
9360
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
9361
|
-
/* @__PURE__ */ jsx(
|
|
9362
|
-
"span",
|
|
9363
|
-
{
|
|
9364
|
-
className: [
|
|
9365
|
-
"grid h-7 w-7 shrink-0 place-items-center rounded-full border",
|
|
9366
|
-
cancelled ? "border-rose-300 bg-rose-500 text-white" : done ? "border-primary bg-primary text-primary-foreground" : current ? "border-primary bg-background text-primary" : "border-muted-foreground/30 bg-background"
|
|
9367
|
-
].join(" "),
|
|
9368
|
-
"aria-hidden": true,
|
|
9369
|
-
children: /* @__PURE__ */ jsx(Icon2, { className: "h-3.5 w-3.5" })
|
|
9370
|
-
}
|
|
9371
|
-
),
|
|
9372
|
-
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
9373
|
-
/* @__PURE__ */ jsx("span", { className: "block font-semibold leading-snug text-foreground", children: step.label }),
|
|
9374
|
-
/* @__PURE__ */ jsx("span", { className: "mt-0.5 block leading-snug text-muted-foreground", children: step.description })
|
|
9375
|
-
] })
|
|
9376
|
-
] })
|
|
9625
|
+
type: "button",
|
|
9626
|
+
"data-testid": TID.fulfillmentMode(mode),
|
|
9627
|
+
"aria-pressed": active2,
|
|
9628
|
+
onClick: () => choose(mode),
|
|
9629
|
+
className: `rounded-full px-5 py-2 text-sm font-semibold transition ${active2 ? "bg-white text-neutral-900" : "text-white/80"}`,
|
|
9630
|
+
children: mode === "pickup" ? "Retirada" : "Entrega"
|
|
9377
9631
|
},
|
|
9378
|
-
|
|
9632
|
+
mode
|
|
9379
9633
|
);
|
|
9380
|
-
})
|
|
9381
|
-
}
|
|
9382
|
-
);
|
|
9634
|
+
}) })
|
|
9635
|
+
] })
|
|
9636
|
+
] });
|
|
9383
9637
|
}
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
"
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
];
|
|
9392
|
-
var DEFAULT_ACCOUNT_SECTION = "orders";
|
|
9393
|
-
function isAccountSection(value) {
|
|
9394
|
-
return ACCOUNT_SECTIONS.includes(value);
|
|
9638
|
+
function OpenUntil() {
|
|
9639
|
+
const service = useServiceStore((s2) => s2.service);
|
|
9640
|
+
if (!service) return null;
|
|
9641
|
+
return /* @__PURE__ */ jsxs("span", { children: [
|
|
9642
|
+
"Aberto",
|
|
9643
|
+
service.closesAt ? ` at\xE9 ${storeTime(service.closesAt, service.timezone)}` : ""
|
|
9644
|
+
] });
|
|
9395
9645
|
}
|
|
9396
|
-
function
|
|
9397
|
-
const
|
|
9398
|
-
if (!
|
|
9646
|
+
function ClosedUntil() {
|
|
9647
|
+
const service = useServiceStore((s2) => s2.service);
|
|
9648
|
+
if (!service) return null;
|
|
9649
|
+
return /* @__PURE__ */ jsxs("span", { children: [
|
|
9650
|
+
"Fechado",
|
|
9651
|
+
service.nextOpenAt ? ` \u2022 abre ${storeTime(service.nextOpenAt, service.timezone, { weekday: true })}` : ""
|
|
9652
|
+
] });
|
|
9653
|
+
}
|
|
9654
|
+
function AddressStrip({
|
|
9655
|
+
onChangeAddress,
|
|
9656
|
+
onSchedule
|
|
9657
|
+
}) {
|
|
9658
|
+
const config = useStorefrontConfig();
|
|
9659
|
+
const scheduling = config.delivery?.scheduling ?? false;
|
|
9660
|
+
const timezone = useServiceStore((s2) => s2.service?.timezone) ?? "America/Sao_Paulo";
|
|
9661
|
+
const delivery = useDeliveryStore();
|
|
9662
|
+
const type = delivery.fulfillmentType;
|
|
9663
|
+
const isPickup = type === "pickup";
|
|
9664
|
+
const money = (v) => formatMoney(v, config.currency, config.locale);
|
|
9665
|
+
const option = delivery.options.find((o) => o.zoneId === delivery.selectedZoneId) ?? delivery.options[0];
|
|
9666
|
+
const chosen = delivery.savedAddresses.find((a) => a.id === delivery.selectedAddressId);
|
|
9667
|
+
const pickup = config.delivery?.pickupAddress;
|
|
9668
|
+
const feeLine = isPickup ? "Sem taxa de entrega" : option ? option.free ? "Entrega gr\xE1tis" : money(option.rate) : `A partir de ${money(config.shipping.flatRate)}`;
|
|
9669
|
+
const etaLine = option?.etaMaxDays != null ? ` \u2022 at\xE9 ${option.etaMaxDays} dia(s)` : "";
|
|
9670
|
+
return /* @__PURE__ */ jsxs("div", { "data-testid": TID.addressStrip, className: "border-b border-border bg-background", children: [
|
|
9671
|
+
/* @__PURE__ */ jsxs(
|
|
9672
|
+
"button",
|
|
9673
|
+
{
|
|
9674
|
+
type: "button",
|
|
9675
|
+
onClick: isPickup ? void 0 : onChangeAddress,
|
|
9676
|
+
disabled: isPickup,
|
|
9677
|
+
className: "mx-auto flex w-full max-w-3xl items-center gap-3 px-4 py-3 text-left disabled:cursor-default",
|
|
9678
|
+
children: [
|
|
9679
|
+
isPickup ? /* @__PURE__ */ jsx(Store, { className: "h-6 w-6 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ jsx(Bike, { className: "h-6 w-6 shrink-0 text-muted-foreground" }),
|
|
9680
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
9681
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: isPickup ? "Retirar na loja" : `Entregar em${etaLine} \u2022 ${feeLine}` }),
|
|
9682
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold", children: isPickup ? pickup ? `${pickup.street}${pickup.number ? `, ${pickup.number}` : ""}` : "Sem taxa de entrega" : chosen ? `${chosen.street}, ${chosen.number}${chosen.label ? ` \xB7 ${chosen.label}` : ""}` : delivery.address ? `${delivery.address.street}${delivery.address.district ? `, ${delivery.address.district}` : ""}` : "Selecionar endere\xE7o" })
|
|
9683
|
+
] }),
|
|
9684
|
+
!isPickup && /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5 shrink-0 text-muted-foreground" })
|
|
9685
|
+
]
|
|
9686
|
+
}
|
|
9687
|
+
),
|
|
9688
|
+
scheduling && onSchedule && /* @__PURE__ */ jsxs(
|
|
9689
|
+
"button",
|
|
9690
|
+
{
|
|
9691
|
+
type: "button",
|
|
9692
|
+
onClick: onSchedule,
|
|
9693
|
+
className: "mx-auto flex w-full max-w-3xl items-center gap-3 border-t border-border px-4 py-2.5 text-left",
|
|
9694
|
+
children: [
|
|
9695
|
+
/* @__PURE__ */ jsx(Clock, { className: "h-5 w-5 shrink-0 text-muted-foreground" }),
|
|
9696
|
+
delivery.scheduledFor ? /* @__PURE__ */ jsxs("span", { className: "text-sm font-semibold", children: [
|
|
9697
|
+
"Agendado \u2022",
|
|
9698
|
+
" ",
|
|
9699
|
+
new Intl.DateTimeFormat("pt-BR", {
|
|
9700
|
+
weekday: "short",
|
|
9701
|
+
day: "2-digit",
|
|
9702
|
+
month: "2-digit",
|
|
9703
|
+
hour: "2-digit",
|
|
9704
|
+
minute: "2-digit",
|
|
9705
|
+
timeZone: timezone
|
|
9706
|
+
}).format(new Date(delivery.scheduledFor))
|
|
9707
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Agendar para depois" }),
|
|
9708
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto h-5 w-5 shrink-0 text-muted-foreground" })
|
|
9709
|
+
]
|
|
9710
|
+
}
|
|
9711
|
+
)
|
|
9712
|
+
] });
|
|
9713
|
+
}
|
|
9714
|
+
function MenuToolbar({
|
|
9715
|
+
sections,
|
|
9716
|
+
query,
|
|
9717
|
+
onQuery,
|
|
9718
|
+
autoFocusSearch
|
|
9719
|
+
}) {
|
|
9720
|
+
const inputRef = React37.useRef(null);
|
|
9721
|
+
const [active2, setActive] = React37.useState(null);
|
|
9722
|
+
React37.useEffect(() => {
|
|
9723
|
+
setActive(
|
|
9724
|
+
(current) => current && sections.some((s2) => s2.slug === current) ? current : sections[0]?.slug ?? null
|
|
9725
|
+
);
|
|
9726
|
+
}, [sections]);
|
|
9727
|
+
React37.useEffect(() => {
|
|
9728
|
+
if (autoFocusSearch) inputRef.current?.focus();
|
|
9729
|
+
}, [autoFocusSearch]);
|
|
9730
|
+
React37.useEffect(() => {
|
|
9731
|
+
if (typeof IntersectionObserver === "undefined") return;
|
|
9732
|
+
const seen = /* @__PURE__ */ new Map();
|
|
9733
|
+
const observer = new IntersectionObserver(
|
|
9734
|
+
(entries) => {
|
|
9735
|
+
for (const entry of entries) {
|
|
9736
|
+
const slug = entry.target.getAttribute("data-section-slug");
|
|
9737
|
+
if (slug) seen.set(slug, entry.isIntersecting);
|
|
9738
|
+
}
|
|
9739
|
+
const first = sections.find((s2) => seen.get(s2.slug));
|
|
9740
|
+
if (first) setActive(first.slug);
|
|
9741
|
+
},
|
|
9742
|
+
// A faixa é a parte da tela logo abaixo da barra: uma seção "ativa" é a
|
|
9743
|
+
// que está sob os olhos, não a que encostou no rodapé.
|
|
9744
|
+
{ rootMargin: "-140px 0px -65% 0px", threshold: 0 }
|
|
9745
|
+
);
|
|
9746
|
+
for (const section of sections) {
|
|
9747
|
+
const el = document.getElementById(`menu-${section.slug}`);
|
|
9748
|
+
if (el) observer.observe(el);
|
|
9749
|
+
}
|
|
9750
|
+
return () => observer.disconnect();
|
|
9751
|
+
}, [sections]);
|
|
9752
|
+
function jumpTo(slug) {
|
|
9753
|
+
setActive(slug);
|
|
9754
|
+
document.getElementById(`menu-${slug}`)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
9755
|
+
}
|
|
9756
|
+
return /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-30 border-b border-border bg-background/95 backdrop-blur", children: [
|
|
9757
|
+
/* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-3xl px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
9758
|
+
/* @__PURE__ */ jsx(
|
|
9759
|
+
Search,
|
|
9760
|
+
{
|
|
9761
|
+
"aria-hidden": true,
|
|
9762
|
+
className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"
|
|
9763
|
+
}
|
|
9764
|
+
),
|
|
9765
|
+
/* @__PURE__ */ jsx(
|
|
9766
|
+
"input",
|
|
9767
|
+
{
|
|
9768
|
+
ref: inputRef,
|
|
9769
|
+
type: "text",
|
|
9770
|
+
inputMode: "search",
|
|
9771
|
+
autoComplete: "off",
|
|
9772
|
+
"data-testid": TID.menuSearch,
|
|
9773
|
+
value: query,
|
|
9774
|
+
onChange: (e) => onQuery(e.target.value),
|
|
9775
|
+
placeholder: "Buscar no card\xE1pio",
|
|
9776
|
+
"aria-label": "Buscar no card\xE1pio",
|
|
9777
|
+
className: "h-11 w-full rounded-full border border-border bg-muted/40 pl-9 pr-9 text-base"
|
|
9778
|
+
}
|
|
9779
|
+
),
|
|
9780
|
+
query && /* @__PURE__ */ jsx(
|
|
9781
|
+
"button",
|
|
9782
|
+
{
|
|
9783
|
+
type: "button",
|
|
9784
|
+
onClick: () => onQuery(""),
|
|
9785
|
+
"aria-label": "Limpar busca",
|
|
9786
|
+
className: "absolute right-2 top-1/2 grid h-8 w-8 -translate-y-1/2 place-items-center rounded-full",
|
|
9787
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
9788
|
+
}
|
|
9789
|
+
)
|
|
9790
|
+
] }) }),
|
|
9791
|
+
!query && sections.length > 1 && /* @__PURE__ */ jsx(
|
|
9792
|
+
"nav",
|
|
9793
|
+
{
|
|
9794
|
+
"data-testid": TID.menuCategoryNav,
|
|
9795
|
+
"aria-label": "Categorias",
|
|
9796
|
+
className: "mx-auto w-full max-w-3xl overflow-x-auto pb-3 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
9797
|
+
children: /* @__PURE__ */ jsx("ul", { className: "flex w-max gap-2 px-4", children: sections.map((section) => {
|
|
9798
|
+
const on = active2 === section.slug;
|
|
9799
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
9800
|
+
"button",
|
|
9801
|
+
{
|
|
9802
|
+
type: "button",
|
|
9803
|
+
"data-testid": TID.menuCategoryLink(section.slug),
|
|
9804
|
+
"aria-current": on ? "true" : void 0,
|
|
9805
|
+
onClick: () => jumpTo(section.slug),
|
|
9806
|
+
className: `whitespace-nowrap rounded-full px-4 py-2 text-sm font-medium transition ${on ? "bg-foreground text-background" : "border border-border text-muted-foreground"}`,
|
|
9807
|
+
children: section.name
|
|
9808
|
+
}
|
|
9809
|
+
) }, section.id);
|
|
9810
|
+
}) })
|
|
9811
|
+
}
|
|
9812
|
+
)
|
|
9813
|
+
] });
|
|
9814
|
+
}
|
|
9815
|
+
function MenuItemRow({
|
|
9816
|
+
product,
|
|
9817
|
+
onOpen,
|
|
9818
|
+
onQuickAdd,
|
|
9819
|
+
disabled,
|
|
9820
|
+
badge,
|
|
9821
|
+
accent,
|
|
9822
|
+
fromPrice
|
|
9823
|
+
}) {
|
|
9824
|
+
const config = useStorefrontConfig();
|
|
9825
|
+
const money = (v) => formatMoney(v, config.currency, config.locale);
|
|
9826
|
+
const image = product.images?.find((i) => i.isPrimary) ?? product.images?.[0];
|
|
9827
|
+
const soldOut = product.inventoryCount <= 0;
|
|
9828
|
+
const onSale = product.compareAtPrice != null && product.compareAtPrice > product.price;
|
|
9829
|
+
const off = onSale ? Math.floor((product.compareAtPrice - product.price) / product.compareAtPrice * 100) : 0;
|
|
9830
|
+
const dim = soldOut ? "opacity-45" : "";
|
|
9831
|
+
return /* @__PURE__ */ jsxs(
|
|
9832
|
+
"li",
|
|
9833
|
+
{
|
|
9834
|
+
"data-testid": TID.menuItem(product.slug),
|
|
9835
|
+
className: `relative border-b border-border last:border-b-0 ${accent ? "border-l-[3px] border-l-primary pl-3" : ""}`,
|
|
9836
|
+
children: [
|
|
9837
|
+
/* @__PURE__ */ jsx(
|
|
9838
|
+
"button",
|
|
9839
|
+
{
|
|
9840
|
+
type: "button",
|
|
9841
|
+
onClick: () => onOpen(product),
|
|
9842
|
+
"aria-label": product.name,
|
|
9843
|
+
className: "absolute inset-0 z-10"
|
|
9844
|
+
}
|
|
9845
|
+
),
|
|
9846
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-start gap-3 py-4 text-left", children: [
|
|
9847
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
9848
|
+
/* @__PURE__ */ jsx("h3", { className: `text-base font-semibold leading-snug ${dim}`, children: product.name }),
|
|
9849
|
+
product.description && // Três linhas: o suficiente para a frase que vende e curto o
|
|
9850
|
+
// bastante para a próxima linha caber na tela.
|
|
9851
|
+
/* @__PURE__ */ jsx("p", { className: `mt-1 line-clamp-3 text-sm text-muted-foreground ${dim}`, children: product.description }),
|
|
9852
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
9853
|
+
/* @__PURE__ */ jsxs("span", { className: `flex flex-wrap items-baseline gap-x-2 gap-y-1 ${dim}`, children: [
|
|
9854
|
+
fromPrice && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "A partir de" }),
|
|
9855
|
+
/* @__PURE__ */ jsx(
|
|
9856
|
+
"span",
|
|
9857
|
+
{
|
|
9858
|
+
className: onSale ? "font-bold text-emerald-600 dark:text-emerald-400" : "font-semibold",
|
|
9859
|
+
children: money(product.price)
|
|
9860
|
+
}
|
|
9861
|
+
),
|
|
9862
|
+
onSale && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground line-through", children: money(product.compareAtPrice) }),
|
|
9863
|
+
onSale && off >= 5 && // Cor sozinha não conta a promoção — o texto "-12%" conta, e é
|
|
9864
|
+
// o que um leitor de tela e um olho daltônico recebem.
|
|
9865
|
+
/* @__PURE__ */ jsxs("span", { className: "rounded bg-emerald-600 px-1.5 py-0.5 text-[11px] font-bold text-white", children: [
|
|
9866
|
+
"-",
|
|
9867
|
+
off,
|
|
9868
|
+
"%"
|
|
9869
|
+
] })
|
|
9870
|
+
] }),
|
|
9871
|
+
onQuickAdd && !soldOut && /* @__PURE__ */ jsx(
|
|
9872
|
+
"button",
|
|
9873
|
+
{
|
|
9874
|
+
type: "button",
|
|
9875
|
+
"data-testid": TID.menuQuickAdd(product.slug),
|
|
9876
|
+
onClick: () => onQuickAdd(product),
|
|
9877
|
+
disabled,
|
|
9878
|
+
"aria-label": `Adicionar ${product.name}`,
|
|
9879
|
+
className: "relative z-20 grid h-8 w-8 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground disabled:opacity-40",
|
|
9880
|
+
children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
|
|
9881
|
+
}
|
|
9882
|
+
)
|
|
9883
|
+
] }),
|
|
9884
|
+
soldOut && /* @__PURE__ */ jsx("p", { className: "mt-1.5", children: /* @__PURE__ */ jsx(
|
|
9885
|
+
"span",
|
|
9886
|
+
{
|
|
9887
|
+
"data-testid": TID.menuItemSoldOut,
|
|
9888
|
+
className: "rounded bg-muted px-2 py-0.5 text-xs uppercase tracking-wide text-muted-foreground",
|
|
9889
|
+
children: "Indispon\xEDvel"
|
|
9890
|
+
}
|
|
9891
|
+
) })
|
|
9892
|
+
] }),
|
|
9893
|
+
image && /* @__PURE__ */ jsx(
|
|
9894
|
+
SmoothImage,
|
|
9895
|
+
{
|
|
9896
|
+
src: image.url,
|
|
9897
|
+
alt: "",
|
|
9898
|
+
variant: { width: 96 },
|
|
9899
|
+
className: `h-24 w-24 shrink-0 rounded-lg object-cover ${soldOut ? "opacity-40 grayscale" : ""}`
|
|
9900
|
+
}
|
|
9901
|
+
)
|
|
9902
|
+
] })
|
|
9903
|
+
]
|
|
9904
|
+
}
|
|
9905
|
+
);
|
|
9906
|
+
}
|
|
9907
|
+
var NOTES_MAX = 250;
|
|
9908
|
+
function ItemSheet({
|
|
9909
|
+
product,
|
|
9910
|
+
onClose,
|
|
9911
|
+
onAdd,
|
|
9912
|
+
disabled,
|
|
9913
|
+
disabledReason
|
|
9914
|
+
}) {
|
|
9915
|
+
const config = useStorefrontConfig();
|
|
9916
|
+
const money = (v) => formatMoney(v, config.currency, config.locale);
|
|
9917
|
+
const groups = React37.useMemo(() => getProductOptionGroups(product), [product]);
|
|
9918
|
+
const [options, setOptions] = React37.useState({});
|
|
9919
|
+
const [notes, setNotes] = React37.useState("");
|
|
9920
|
+
const [quantity, setQuantity] = React37.useState(1);
|
|
9921
|
+
const image = product.images?.find((i) => i.isPrimary) ?? product.images?.[0];
|
|
9922
|
+
const stock = product.inventoryCount;
|
|
9923
|
+
const missing = groups.filter((g) => !options[g.label]);
|
|
9924
|
+
const ready = missing.length === 0;
|
|
9925
|
+
const unit = selectionPrice(product, options);
|
|
9926
|
+
const soldOut = stock <= 0;
|
|
9927
|
+
const blocked = disabled || soldOut;
|
|
9928
|
+
const blockedReason = soldOut ? "Este item est\xE1 indispon\xEDvel no momento." : disabledReason;
|
|
9929
|
+
return /* @__PURE__ */ jsx(
|
|
9930
|
+
"div",
|
|
9931
|
+
{
|
|
9932
|
+
"data-testid": TID.itemSheet,
|
|
9933
|
+
role: "dialog",
|
|
9934
|
+
"aria-modal": "true",
|
|
9935
|
+
"aria-label": product.name,
|
|
9936
|
+
className: "fixed inset-0 z-50 flex flex-col bg-background sm:items-center sm:justify-center sm:bg-black/50 sm:p-6",
|
|
9937
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col overflow-hidden bg-background sm:h-auto sm:max-h-[85vh] sm:max-w-lg sm:rounded-2xl", children: [
|
|
9938
|
+
/* @__PURE__ */ jsxs("div", { className: "relative shrink-0", children: [
|
|
9939
|
+
image && /* @__PURE__ */ jsx(
|
|
9940
|
+
SmoothImage,
|
|
9941
|
+
{
|
|
9942
|
+
src: image.url,
|
|
9943
|
+
alt: "",
|
|
9944
|
+
variant: { width: 640 },
|
|
9945
|
+
className: "h-56 w-full object-cover"
|
|
9946
|
+
}
|
|
9947
|
+
),
|
|
9948
|
+
/* @__PURE__ */ jsx(
|
|
9949
|
+
"button",
|
|
9950
|
+
{
|
|
9951
|
+
type: "button",
|
|
9952
|
+
onClick: onClose,
|
|
9953
|
+
"aria-label": "Fechar",
|
|
9954
|
+
className: "absolute left-3 top-3 grid h-9 w-9 place-items-center rounded-full bg-background/90 shadow",
|
|
9955
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
|
|
9956
|
+
}
|
|
9957
|
+
)
|
|
9958
|
+
] }),
|
|
9959
|
+
/* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto pb-4", children: [
|
|
9960
|
+
/* @__PURE__ */ jsxs("div", { className: "px-4 pt-4", children: [
|
|
9961
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: product.name }),
|
|
9962
|
+
stock > 0 && stock <= 20 && /* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm font-medium", children: [
|
|
9963
|
+
stock,
|
|
9964
|
+
" unidades dispon\xEDveis"
|
|
9965
|
+
] }),
|
|
9966
|
+
product.description && /* @__PURE__ */ jsx("p", { className: "mt-3 whitespace-pre-line text-sm text-muted-foreground", children: product.description })
|
|
9967
|
+
] }),
|
|
9968
|
+
groups.map((group) => /* @__PURE__ */ jsx(
|
|
9969
|
+
OptionGroup,
|
|
9970
|
+
{
|
|
9971
|
+
product,
|
|
9972
|
+
group,
|
|
9973
|
+
selection: options,
|
|
9974
|
+
onSelect: (value) => setOptions((prev) => ({ ...prev, [group.label]: value }))
|
|
9975
|
+
},
|
|
9976
|
+
group.id
|
|
9977
|
+
)),
|
|
9978
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-6 px-4", children: [
|
|
9979
|
+
/* @__PURE__ */ jsx(
|
|
9980
|
+
"label",
|
|
9981
|
+
{
|
|
9982
|
+
htmlFor: "item-sheet-notes",
|
|
9983
|
+
className: "text-xs font-medium uppercase tracking-wide text-muted-foreground",
|
|
9984
|
+
children: "Observa\xE7\xF5es do item"
|
|
9985
|
+
}
|
|
9986
|
+
),
|
|
9987
|
+
/* @__PURE__ */ jsx(
|
|
9988
|
+
"textarea",
|
|
9989
|
+
{
|
|
9990
|
+
id: "item-sheet-notes",
|
|
9991
|
+
"data-testid": TID.itemSheetNotes,
|
|
9992
|
+
value: notes,
|
|
9993
|
+
onChange: (e) => setNotes(e.target.value.slice(0, NOTES_MAX)),
|
|
9994
|
+
rows: 3,
|
|
9995
|
+
placeholder: "Ex.: sem cebola, ponto da carne\u2026",
|
|
9996
|
+
className: "mt-2 w-full resize-none rounded-lg border border-border bg-transparent p-3 text-base"
|
|
9997
|
+
}
|
|
9998
|
+
),
|
|
9999
|
+
/* @__PURE__ */ jsxs(
|
|
10000
|
+
"p",
|
|
10001
|
+
{
|
|
10002
|
+
"data-testid": TID.itemSheetNotesCount,
|
|
10003
|
+
className: "mt-1 text-right text-xs text-muted-foreground",
|
|
10004
|
+
children: [
|
|
10005
|
+
notes.length,
|
|
10006
|
+
"/",
|
|
10007
|
+
NOTES_MAX
|
|
10008
|
+
]
|
|
10009
|
+
}
|
|
10010
|
+
)
|
|
10011
|
+
] })
|
|
10012
|
+
] }),
|
|
10013
|
+
/* @__PURE__ */ jsxs("div", { className: "shrink-0 border-t border-border p-4 pb-[max(1rem,env(safe-area-inset-bottom))]", children: [
|
|
10014
|
+
blocked && blockedReason && /* @__PURE__ */ jsx("p", { className: "mb-3 text-center text-sm text-muted-foreground", children: blockedReason }),
|
|
10015
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
10016
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-full border border-border px-2 py-1", children: [
|
|
10017
|
+
/* @__PURE__ */ jsx(
|
|
10018
|
+
"button",
|
|
10019
|
+
{
|
|
10020
|
+
type: "button",
|
|
10021
|
+
"aria-label": "Menos um",
|
|
10022
|
+
onClick: () => setQuantity((q) => Math.max(1, q - 1)),
|
|
10023
|
+
className: "grid h-9 w-9 place-items-center rounded-full disabled:opacity-40",
|
|
10024
|
+
disabled: quantity <= 1,
|
|
10025
|
+
children: /* @__PURE__ */ jsx(Minus, { className: "h-4 w-4" })
|
|
10026
|
+
}
|
|
10027
|
+
),
|
|
10028
|
+
/* @__PURE__ */ jsx("span", { "data-testid": TID.itemSheetQty, className: "min-w-4 text-center tabular-nums", children: quantity }),
|
|
10029
|
+
/* @__PURE__ */ jsx(
|
|
10030
|
+
"button",
|
|
10031
|
+
{
|
|
10032
|
+
type: "button",
|
|
10033
|
+
"aria-label": "Mais um",
|
|
10034
|
+
onClick: () => setQuantity((q) => Math.min(stock || Infinity, q + 1)),
|
|
10035
|
+
className: "grid h-9 w-9 place-items-center rounded-full disabled:opacity-40",
|
|
10036
|
+
disabled: stock > 0 && quantity >= stock,
|
|
10037
|
+
children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
|
|
10038
|
+
}
|
|
10039
|
+
)
|
|
10040
|
+
] }),
|
|
10041
|
+
/* @__PURE__ */ jsx(
|
|
10042
|
+
"button",
|
|
10043
|
+
{
|
|
10044
|
+
type: "button",
|
|
10045
|
+
"data-testid": TID.itemSheetAdd,
|
|
10046
|
+
disabled: blocked || !ready,
|
|
10047
|
+
onClick: () => onAdd({ quantity, options, notes: notes.trim() || void 0 }),
|
|
10048
|
+
className: "flex h-12 flex-1 items-center justify-center rounded-full bg-primary px-6 text-sm font-bold uppercase tracking-wide text-primary-foreground disabled:opacity-40",
|
|
10049
|
+
children: ready ? `Adicionar \u2022 ${money(unit * quantity)}` : `Escolha ${missing[0].label}`
|
|
10050
|
+
}
|
|
10051
|
+
)
|
|
10052
|
+
] })
|
|
10053
|
+
] })
|
|
10054
|
+
] })
|
|
10055
|
+
}
|
|
10056
|
+
);
|
|
10057
|
+
}
|
|
10058
|
+
function OptionGroup({
|
|
10059
|
+
product,
|
|
10060
|
+
group,
|
|
10061
|
+
selection,
|
|
10062
|
+
onSelect
|
|
10063
|
+
}) {
|
|
10064
|
+
const config = useStorefrontConfig();
|
|
10065
|
+
const money = (v) => formatMoney(v, config.currency, config.locale);
|
|
10066
|
+
const chosen = selection[group.label];
|
|
10067
|
+
const prices = group.values.map(
|
|
10068
|
+
(value) => selectionPrice(product, { ...selection, [group.label]: value })
|
|
10069
|
+
);
|
|
10070
|
+
const base = Math.min(...prices);
|
|
10071
|
+
return /* @__PURE__ */ jsxs("section", { "data-testid": TID.itemSheetGroup(group.label), className: "mt-6", children: [
|
|
10072
|
+
/* @__PURE__ */ jsxs("div", { className: "border-y border-border bg-muted/40 px-4 py-3", children: [
|
|
10073
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-bold", children: group.label }),
|
|
10074
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Escolha 1 op\xE7\xE3o." })
|
|
10075
|
+
] }),
|
|
10076
|
+
/* @__PURE__ */ jsx("ul", { children: group.values.map((value, index) => {
|
|
10077
|
+
const delta = prices[index] - base;
|
|
10078
|
+
const on = chosen === value;
|
|
10079
|
+
return /* @__PURE__ */ jsx("li", { className: "border-b border-border", children: /* @__PURE__ */ jsxs(
|
|
10080
|
+
"button",
|
|
10081
|
+
{
|
|
10082
|
+
type: "button",
|
|
10083
|
+
role: "radio",
|
|
10084
|
+
"aria-checked": on,
|
|
10085
|
+
onClick: () => onSelect(value),
|
|
10086
|
+
className: "flex min-h-14 w-full items-center gap-3 px-4 py-3 text-left",
|
|
10087
|
+
children: [
|
|
10088
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
10089
|
+
/* @__PURE__ */ jsx("span", { className: "block text-sm", children: value }),
|
|
10090
|
+
delta > 0 && /* @__PURE__ */ jsxs("span", { className: "block text-sm font-semibold", children: [
|
|
10091
|
+
"+ ",
|
|
10092
|
+
money(delta)
|
|
10093
|
+
] })
|
|
10094
|
+
] }),
|
|
10095
|
+
/* @__PURE__ */ jsx(
|
|
10096
|
+
"span",
|
|
10097
|
+
{
|
|
10098
|
+
"aria-hidden": true,
|
|
10099
|
+
className: `grid h-5 w-5 shrink-0 place-items-center rounded-full border-2 ${on ? "border-primary" : "border-muted-foreground/40"}`,
|
|
10100
|
+
children: on && /* @__PURE__ */ jsx("span", { className: "h-2.5 w-2.5 rounded-full bg-primary" })
|
|
10101
|
+
}
|
|
10102
|
+
)
|
|
10103
|
+
]
|
|
10104
|
+
}
|
|
10105
|
+
) }, value);
|
|
10106
|
+
}) })
|
|
10107
|
+
] });
|
|
10108
|
+
}
|
|
10109
|
+
function ScheduleSheet({ onClose }) {
|
|
10110
|
+
const fulfillmentType = useDeliveryStore((s2) => s2.fulfillmentType);
|
|
10111
|
+
const scheduledFor = useDeliveryStore((s2) => s2.scheduledFor);
|
|
10112
|
+
const setScheduledFor = useDeliveryStore((s2) => s2.setScheduledFor);
|
|
10113
|
+
const timezone = useServiceStore((s2) => s2.service?.timezone) ?? "America/Sao_Paulo";
|
|
10114
|
+
const [slots, setSlots] = React37.useState(null);
|
|
10115
|
+
React37.useEffect(() => {
|
|
10116
|
+
let alive = true;
|
|
10117
|
+
void (async () => {
|
|
10118
|
+
const rows = await getShopProvider()?.listScheduleSlots?.(fulfillmentType) ?? [];
|
|
10119
|
+
if (alive) setSlots(rows);
|
|
10120
|
+
})();
|
|
10121
|
+
return () => {
|
|
10122
|
+
alive = false;
|
|
10123
|
+
};
|
|
10124
|
+
}, [fulfillmentType]);
|
|
10125
|
+
const days = React37.useMemo(() => {
|
|
10126
|
+
const fmtDay = new Intl.DateTimeFormat("pt-BR", {
|
|
10127
|
+
weekday: "long",
|
|
10128
|
+
day: "2-digit",
|
|
10129
|
+
month: "2-digit",
|
|
10130
|
+
timeZone: timezone
|
|
10131
|
+
});
|
|
10132
|
+
const map = /* @__PURE__ */ new Map();
|
|
10133
|
+
for (const slot of slots ?? []) {
|
|
10134
|
+
const key = fmtDay.format(new Date(slot.startsAt));
|
|
10135
|
+
const list = map.get(key) ?? [];
|
|
10136
|
+
list.push(slot);
|
|
10137
|
+
map.set(key, list);
|
|
10138
|
+
}
|
|
10139
|
+
return [...map.entries()];
|
|
10140
|
+
}, [slots, timezone]);
|
|
10141
|
+
const fmtTime = new Intl.DateTimeFormat("pt-BR", {
|
|
10142
|
+
hour: "2-digit",
|
|
10143
|
+
minute: "2-digit",
|
|
10144
|
+
timeZone: timezone
|
|
10145
|
+
});
|
|
10146
|
+
return /* @__PURE__ */ jsx(
|
|
10147
|
+
"div",
|
|
10148
|
+
{
|
|
10149
|
+
role: "dialog",
|
|
10150
|
+
"aria-modal": "true",
|
|
10151
|
+
"aria-label": "Agendar",
|
|
10152
|
+
"data-testid": TID.scheduleSheet,
|
|
10153
|
+
className: "fixed inset-0 z-50 flex flex-col justify-end bg-black/50 sm:items-center sm:justify-center sm:p-6",
|
|
10154
|
+
children: /* @__PURE__ */ jsxs("div", { className: "max-h-[80vh] w-full overflow-hidden rounded-t-2xl bg-background sm:max-w-md sm:rounded-2xl", children: [
|
|
10155
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-border p-4", children: [
|
|
10156
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: "Agendar" }),
|
|
10157
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, "aria-label": "Fechar", className: "-mr-1 -mt-1 p-1", children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" }) })
|
|
10158
|
+
] }),
|
|
10159
|
+
/* @__PURE__ */ jsxs("div", { className: "max-h-[60vh] overflow-y-auto p-4", children: [
|
|
10160
|
+
/* @__PURE__ */ jsx(
|
|
10161
|
+
"button",
|
|
10162
|
+
{
|
|
10163
|
+
type: "button",
|
|
10164
|
+
onClick: () => {
|
|
10165
|
+
setScheduledFor(null);
|
|
10166
|
+
onClose();
|
|
10167
|
+
},
|
|
10168
|
+
"aria-pressed": !scheduledFor,
|
|
10169
|
+
className: `mb-4 w-full rounded-lg border px-4 py-3 text-left text-sm ${!scheduledFor ? "border-primary font-medium" : "border-border"}`,
|
|
10170
|
+
children: "O quanto antes"
|
|
10171
|
+
}
|
|
10172
|
+
),
|
|
10173
|
+
slots === null && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Carregando hor\xE1rios\u2026" }),
|
|
10174
|
+
slots !== null && !slots.length && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "N\xE3o h\xE1 hor\xE1rios dispon\xEDveis para agendar agora." }),
|
|
10175
|
+
days.map(([day, daySlots]) => /* @__PURE__ */ jsxs("div", { className: "mb-5", children: [
|
|
10176
|
+
/* @__PURE__ */ jsx("h3", { className: "mb-2 text-sm font-semibold capitalize", children: day }),
|
|
10177
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: daySlots.map((slot) => {
|
|
10178
|
+
const active2 = scheduledFor === slot.startsAt;
|
|
10179
|
+
return /* @__PURE__ */ jsxs(
|
|
10180
|
+
"button",
|
|
10181
|
+
{
|
|
10182
|
+
type: "button",
|
|
10183
|
+
"data-testid": TID.scheduleSlot(slot.startsAt),
|
|
10184
|
+
"aria-pressed": active2,
|
|
10185
|
+
onClick: () => {
|
|
10186
|
+
setScheduledFor(slot.startsAt);
|
|
10187
|
+
onClose();
|
|
10188
|
+
},
|
|
10189
|
+
className: `rounded-lg border px-3 py-2 text-sm ${active2 ? "border-primary font-medium" : "border-border"}`,
|
|
10190
|
+
children: [
|
|
10191
|
+
fmtTime.format(new Date(slot.startsAt)),
|
|
10192
|
+
" \u2013 ",
|
|
10193
|
+
fmtTime.format(new Date(slot.endsAt))
|
|
10194
|
+
]
|
|
10195
|
+
},
|
|
10196
|
+
slot.startsAt
|
|
10197
|
+
);
|
|
10198
|
+
}) })
|
|
10199
|
+
] }, day))
|
|
10200
|
+
] })
|
|
10201
|
+
] })
|
|
10202
|
+
}
|
|
10203
|
+
);
|
|
10204
|
+
}
|
|
10205
|
+
var WEEKDAYS = ["dom", "seg", "ter", "qua", "qui", "sex", "s\xE1b"];
|
|
10206
|
+
function hhmm(time) {
|
|
10207
|
+
return time.slice(0, 5);
|
|
10208
|
+
}
|
|
10209
|
+
function ServiceHoursModal({ onClose }) {
|
|
10210
|
+
const fulfillmentType = useServiceStore((s2) => s2.fulfillmentType);
|
|
10211
|
+
const [hours, setHours] = React37.useState(null);
|
|
10212
|
+
React37.useEffect(() => {
|
|
10213
|
+
let alive = true;
|
|
10214
|
+
void (async () => {
|
|
10215
|
+
const rows = await getShopProvider()?.listServiceHours?.(fulfillmentType) ?? [];
|
|
10216
|
+
if (alive) setHours(rows);
|
|
10217
|
+
})();
|
|
10218
|
+
return () => {
|
|
10219
|
+
alive = false;
|
|
10220
|
+
};
|
|
10221
|
+
}, [fulfillmentType]);
|
|
10222
|
+
const byDay = React37.useMemo(() => {
|
|
10223
|
+
const map = /* @__PURE__ */ new Map();
|
|
10224
|
+
for (const h of hours ?? []) {
|
|
10225
|
+
const list = map.get(h.weekday) ?? [];
|
|
10226
|
+
list.push(h);
|
|
10227
|
+
map.set(h.weekday, list);
|
|
10228
|
+
}
|
|
10229
|
+
return map;
|
|
10230
|
+
}, [hours]);
|
|
10231
|
+
return /* @__PURE__ */ jsx(
|
|
10232
|
+
"div",
|
|
10233
|
+
{
|
|
10234
|
+
role: "dialog",
|
|
10235
|
+
"aria-modal": "true",
|
|
10236
|
+
"aria-label": "Hor\xE1rios de funcionamento",
|
|
10237
|
+
"data-testid": TID.serviceHoursModal,
|
|
10238
|
+
className: "fixed inset-0 z-50 grid place-items-center bg-black/50 p-4",
|
|
10239
|
+
children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm rounded-2xl bg-background p-6", children: [
|
|
10240
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
10241
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: "Hor\xE1rios de funcionamento" }),
|
|
10242
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, "aria-label": "Fechar", className: "-mr-1 -mt-1 p-1", children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" }) })
|
|
10243
|
+
] }),
|
|
10244
|
+
hours === null && /* @__PURE__ */ jsx("p", { className: "mt-4 text-sm text-muted-foreground", children: "Carregando\u2026" }),
|
|
10245
|
+
hours !== null && /* @__PURE__ */ jsx("ul", { className: "mt-4 space-y-2 text-sm", children: WEEKDAYS.map((label, day) => {
|
|
10246
|
+
const windows = byDay.get(day) ?? [];
|
|
10247
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex items-baseline justify-between gap-4", children: [
|
|
10248
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
|
|
10249
|
+
/* @__PURE__ */ jsx("span", { className: "text-right", children: windows.length ? windows.map((w) => `${hhmm(w.opensAt)} \xE0s ${hhmm(w.closesAt)}`).join(" \xB7 ") : (
|
|
10250
|
+
// Um dia sem janela não é um erro nem um vazio: é uma
|
|
10251
|
+
// informação, e escrevê-la evita que alguém volte amanhã
|
|
10252
|
+
// para descobrir o mesmo.
|
|
10253
|
+
"Fechado"
|
|
10254
|
+
) })
|
|
10255
|
+
] }, day);
|
|
10256
|
+
}) })
|
|
10257
|
+
] })
|
|
10258
|
+
}
|
|
10259
|
+
);
|
|
10260
|
+
}
|
|
10261
|
+
function ClosedStoreDialog({
|
|
10262
|
+
onClose,
|
|
10263
|
+
onShowHours
|
|
10264
|
+
}) {
|
|
10265
|
+
const state = useServiceStore();
|
|
10266
|
+
const tz = state.service?.timezone ?? "America/Sao_Paulo";
|
|
10267
|
+
const next = state.service?.nextOpenAt;
|
|
10268
|
+
return /* @__PURE__ */ jsx(
|
|
10269
|
+
"div",
|
|
10270
|
+
{
|
|
10271
|
+
role: "dialog",
|
|
10272
|
+
"aria-modal": "true",
|
|
10273
|
+
"data-testid": TID.serviceClosedGate,
|
|
10274
|
+
className: "fixed inset-0 z-[60] grid place-items-center bg-black/50 p-4",
|
|
10275
|
+
children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm rounded-2xl bg-background p-6 text-center", children: [
|
|
10276
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: "Nossa loja est\xE1 fechada no momento" }),
|
|
10277
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: next ? `Abrimos ${storeTime(next, tz, { weekday: true })}. Enquanto isso, fique \xE0 vontade para olhar o card\xE1pio.` : "Enquanto isso, fique \xE0 vontade para olhar o card\xE1pio." }),
|
|
10278
|
+
/* @__PURE__ */ jsx(
|
|
10279
|
+
"button",
|
|
10280
|
+
{
|
|
10281
|
+
type: "button",
|
|
10282
|
+
onClick: onShowHours,
|
|
10283
|
+
className: "mt-5 w-full rounded-full bg-primary px-6 py-3 font-semibold text-primary-foreground",
|
|
10284
|
+
children: "Ver hor\xE1rios de funcionamento"
|
|
10285
|
+
}
|
|
10286
|
+
),
|
|
10287
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, className: "mt-3 w-full py-2 text-sm font-medium", children: "OK, entendi" })
|
|
10288
|
+
] })
|
|
10289
|
+
}
|
|
10290
|
+
);
|
|
10291
|
+
}
|
|
10292
|
+
var LABELS3 = ["Casa", "Trabalho"];
|
|
10293
|
+
function AddressSheet({ onClose }) {
|
|
10294
|
+
const saved = useDeliveryStore((s2) => s2.savedAddresses);
|
|
10295
|
+
const selectedId = useDeliveryStore((s2) => s2.selectedAddressId);
|
|
10296
|
+
const selectAddress = useDeliveryStore((s2) => s2.selectAddress);
|
|
10297
|
+
const removeAddress = useDeliveryStore((s2) => s2.removeAddress);
|
|
10298
|
+
const subtotal = selectSubtotal(useCartStore());
|
|
10299
|
+
const [adding, setAdding] = React37.useState(saved.length === 0);
|
|
10300
|
+
return /* @__PURE__ */ jsx(
|
|
10301
|
+
"div",
|
|
10302
|
+
{
|
|
10303
|
+
role: "dialog",
|
|
10304
|
+
"aria-modal": "true",
|
|
10305
|
+
"aria-label": "Endere\xE7o de entrega",
|
|
10306
|
+
"data-testid": TID.addressSheet,
|
|
10307
|
+
className: "fixed inset-0 z-50 flex flex-col justify-end bg-black/50 sm:items-center sm:justify-center sm:p-6",
|
|
10308
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[85vh] w-full flex-col overflow-hidden rounded-t-2xl bg-background sm:max-w-md sm:rounded-2xl", children: [
|
|
10309
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-border p-4", children: [
|
|
10310
|
+
adding && saved.length > 0 && /* @__PURE__ */ jsx(
|
|
10311
|
+
"button",
|
|
10312
|
+
{
|
|
10313
|
+
type: "button",
|
|
10314
|
+
onClick: () => setAdding(false),
|
|
10315
|
+
"aria-label": "Voltar",
|
|
10316
|
+
className: "-ml-2 grid h-9 w-9 place-items-center rounded-full",
|
|
10317
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" })
|
|
10318
|
+
}
|
|
10319
|
+
),
|
|
10320
|
+
/* @__PURE__ */ jsx("h2", { className: "flex-1 text-lg font-semibold", children: adding ? "Novo endere\xE7o" : "Onde voc\xEA quer receber?" }),
|
|
10321
|
+
/* @__PURE__ */ jsx(
|
|
10322
|
+
"button",
|
|
10323
|
+
{
|
|
10324
|
+
type: "button",
|
|
10325
|
+
onClick: onClose,
|
|
10326
|
+
"aria-label": "Fechar",
|
|
10327
|
+
className: "-mr-2 grid h-9 w-9 place-items-center rounded-full",
|
|
10328
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
|
|
10329
|
+
}
|
|
10330
|
+
)
|
|
10331
|
+
] }),
|
|
10332
|
+
adding ? /* @__PURE__ */ jsx(
|
|
10333
|
+
AddressForm,
|
|
10334
|
+
{
|
|
10335
|
+
onDone: () => {
|
|
10336
|
+
setAdding(false);
|
|
10337
|
+
onClose();
|
|
10338
|
+
}
|
|
10339
|
+
}
|
|
10340
|
+
) : /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: [
|
|
10341
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-2", children: saved.map((address) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2", children: [
|
|
10342
|
+
/* @__PURE__ */ jsxs(
|
|
10343
|
+
"button",
|
|
10344
|
+
{
|
|
10345
|
+
type: "button",
|
|
10346
|
+
"data-testid": TID.savedAddress(address.id),
|
|
10347
|
+
"aria-pressed": selectedId === address.id,
|
|
10348
|
+
onClick: () => {
|
|
10349
|
+
void selectAddress(address.id, subtotal);
|
|
10350
|
+
onClose();
|
|
10351
|
+
},
|
|
10352
|
+
className: `flex min-w-0 flex-1 items-start gap-3 rounded-lg border p-3 text-left ${selectedId === address.id ? "border-primary" : "border-border"}`,
|
|
10353
|
+
children: [
|
|
10354
|
+
/* @__PURE__ */ jsx(MapPin, { className: "mt-0.5 h-5 w-5 shrink-0 text-muted-foreground" }),
|
|
10355
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
10356
|
+
address.label && /* @__PURE__ */ jsx("span", { className: "block text-sm font-semibold", children: address.label }),
|
|
10357
|
+
/* @__PURE__ */ jsxs("span", { className: "block truncate text-sm", children: [
|
|
10358
|
+
address.street,
|
|
10359
|
+
", ",
|
|
10360
|
+
address.number
|
|
10361
|
+
] }),
|
|
10362
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-muted-foreground", children: [address.complement, address.district, address.city].filter(Boolean).join(" \xB7 ") }),
|
|
10363
|
+
address.reference && /* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate text-xs text-muted-foreground", children: address.reference })
|
|
10364
|
+
] })
|
|
10365
|
+
]
|
|
10366
|
+
}
|
|
10367
|
+
),
|
|
10368
|
+
/* @__PURE__ */ jsx(
|
|
10369
|
+
"button",
|
|
10370
|
+
{
|
|
10371
|
+
type: "button",
|
|
10372
|
+
onClick: () => removeAddress(address.id),
|
|
10373
|
+
"aria-label": `Remover ${address.street}, ${address.number}`,
|
|
10374
|
+
className: "mt-1 grid h-10 w-10 shrink-0 place-items-center rounded-full text-muted-foreground",
|
|
10375
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
|
|
10376
|
+
}
|
|
10377
|
+
)
|
|
10378
|
+
] }, address.id)) }),
|
|
10379
|
+
/* @__PURE__ */ jsxs(
|
|
10380
|
+
"button",
|
|
10381
|
+
{
|
|
10382
|
+
type: "button",
|
|
10383
|
+
"data-testid": TID.addressAddNew,
|
|
10384
|
+
onClick: () => setAdding(true),
|
|
10385
|
+
className: "mt-4 flex w-full items-center justify-center gap-2 rounded-full border border-border px-4 py-3 text-sm font-semibold",
|
|
10386
|
+
children: [
|
|
10387
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
|
|
10388
|
+
"Adicionar novo endere\xE7o"
|
|
10389
|
+
]
|
|
10390
|
+
}
|
|
10391
|
+
)
|
|
10392
|
+
] })
|
|
10393
|
+
] })
|
|
10394
|
+
}
|
|
10395
|
+
);
|
|
10396
|
+
}
|
|
10397
|
+
function AddressForm({ onDone }) {
|
|
10398
|
+
const resolve = useDeliveryStore((s2) => s2.resolve);
|
|
10399
|
+
const saveAddress = useDeliveryStore((s2) => s2.saveAddress);
|
|
10400
|
+
const looked = useDeliveryStore((s2) => s2.address);
|
|
10401
|
+
const status = useDeliveryStore((s2) => s2.status);
|
|
10402
|
+
const storeError = useDeliveryStore((s2) => s2.error);
|
|
10403
|
+
const refusedZone = useDeliveryStore((s2) => s2.refusedZone);
|
|
10404
|
+
const subtotal = selectSubtotal(useCartStore());
|
|
10405
|
+
const [cep, setCep] = React37.useState("");
|
|
10406
|
+
const [number, setNumber] = React37.useState("");
|
|
10407
|
+
const [complement, setComplement] = React37.useState("");
|
|
10408
|
+
const [reference, setReference] = React37.useState("");
|
|
10409
|
+
const [label, setLabel] = React37.useState("");
|
|
10410
|
+
const [touched, setTouched] = React37.useState(false);
|
|
10411
|
+
const numberRef = React37.useRef(null);
|
|
10412
|
+
const digits = normalizePostalCode(cep);
|
|
10413
|
+
const found = Boolean(looked) && normalizePostalCode(looked.postalCode) === digits;
|
|
10414
|
+
React37.useEffect(() => {
|
|
10415
|
+
if (found) numberRef.current?.focus();
|
|
10416
|
+
}, [found]);
|
|
10417
|
+
async function lookUp() {
|
|
10418
|
+
if (digits.length !== 8) return;
|
|
10419
|
+
await resolve(digits, subtotal);
|
|
10420
|
+
}
|
|
10421
|
+
function submit(event) {
|
|
10422
|
+
event.preventDefault();
|
|
10423
|
+
setTouched(true);
|
|
10424
|
+
if (!found || !number.trim()) return;
|
|
10425
|
+
saveAddress({
|
|
10426
|
+
label: label.trim() || null,
|
|
10427
|
+
postalCode: looked.postalCode,
|
|
10428
|
+
street: looked.street,
|
|
10429
|
+
number: number.trim(),
|
|
10430
|
+
complement: complement.trim() || null,
|
|
10431
|
+
reference: reference.trim() || null,
|
|
10432
|
+
district: looked.district,
|
|
10433
|
+
city: looked.city,
|
|
10434
|
+
state: looked.state
|
|
10435
|
+
});
|
|
10436
|
+
onDone();
|
|
10437
|
+
}
|
|
10438
|
+
const numberMissing = touched && !number.trim();
|
|
10439
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "min-h-0 flex-1 overflow-y-auto p-4", children: [
|
|
10440
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "address-cep", className: "text-sm font-medium", children: "CEP" }),
|
|
10441
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex gap-2", children: [
|
|
10442
|
+
/* @__PURE__ */ jsx(
|
|
10443
|
+
"input",
|
|
10444
|
+
{
|
|
10445
|
+
id: "address-cep",
|
|
10446
|
+
"data-testid": TID.addressCep,
|
|
10447
|
+
value: cep,
|
|
10448
|
+
onChange: (e) => setCep(formatPostalCode(e.target.value)),
|
|
10449
|
+
onBlur: () => void lookUp(),
|
|
10450
|
+
inputMode: "numeric",
|
|
10451
|
+
autoComplete: "postal-code",
|
|
10452
|
+
placeholder: "00000-000",
|
|
10453
|
+
className: "h-12 flex-1 rounded-lg border border-border bg-transparent px-3 text-base"
|
|
10454
|
+
}
|
|
10455
|
+
),
|
|
10456
|
+
/* @__PURE__ */ jsx(
|
|
10457
|
+
"button",
|
|
10458
|
+
{
|
|
10459
|
+
type: "button",
|
|
10460
|
+
onClick: () => void lookUp(),
|
|
10461
|
+
disabled: digits.length !== 8 || status === "loading",
|
|
10462
|
+
className: "h-12 rounded-lg bg-primary px-4 text-sm font-semibold text-primary-foreground disabled:opacity-40",
|
|
10463
|
+
children: status === "loading" ? "Buscando\u2026" : "Buscar"
|
|
10464
|
+
}
|
|
10465
|
+
)
|
|
10466
|
+
] }),
|
|
10467
|
+
storeError && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-destructive", children: storeError }),
|
|
10468
|
+
refusedZone && /* @__PURE__ */ jsxs("p", { className: "mt-2 text-sm text-destructive", children: [
|
|
10469
|
+
"Ainda n\xE3o entregamos nessa regi\xE3o (",
|
|
10470
|
+
refusedZone,
|
|
10471
|
+
")."
|
|
10472
|
+
] }),
|
|
10473
|
+
found && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10474
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-4 rounded-lg bg-muted/40 p-3 text-sm", children: [
|
|
10475
|
+
/* @__PURE__ */ jsx("span", { className: "block font-medium", children: looked.street }),
|
|
10476
|
+
/* @__PURE__ */ jsxs("span", { className: "block text-muted-foreground", children: [
|
|
10477
|
+
looked.district,
|
|
10478
|
+
" \xB7 ",
|
|
10479
|
+
looked.city,
|
|
10480
|
+
" \u2014 ",
|
|
10481
|
+
looked.state
|
|
10482
|
+
] })
|
|
10483
|
+
] }),
|
|
10484
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-4 grid grid-cols-2 gap-3", children: [
|
|
10485
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10486
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "address-number", className: "text-sm font-medium", children: "N\xFAmero" }),
|
|
10487
|
+
/* @__PURE__ */ jsx(
|
|
10488
|
+
"input",
|
|
10489
|
+
{
|
|
10490
|
+
id: "address-number",
|
|
10491
|
+
ref: numberRef,
|
|
10492
|
+
"data-testid": TID.addressNumber,
|
|
10493
|
+
value: number,
|
|
10494
|
+
onChange: (e) => setNumber(e.target.value),
|
|
10495
|
+
inputMode: "numeric",
|
|
10496
|
+
autoComplete: "address-line2",
|
|
10497
|
+
"aria-invalid": numberMissing || void 0,
|
|
10498
|
+
"aria-describedby": numberMissing ? "address-number-error" : void 0,
|
|
10499
|
+
className: `mt-1 h-12 w-full rounded-lg border bg-transparent px-3 text-base ${numberMissing ? "border-destructive" : "border-border"}`
|
|
10500
|
+
}
|
|
10501
|
+
),
|
|
10502
|
+
numberMissing && // Junto do campo e não num resumo no topo: o erro é sobre ESTE
|
|
10503
|
+
// campo, e a pessoa está olhando para ele.
|
|
10504
|
+
/* @__PURE__ */ jsx("p", { id: "address-number-error", className: "mt-1 text-xs text-destructive", children: "Informe o n\xFAmero." })
|
|
10505
|
+
] }),
|
|
10506
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10507
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "address-complement", className: "text-sm font-medium", children: "Complemento" }),
|
|
10508
|
+
/* @__PURE__ */ jsx(
|
|
10509
|
+
"input",
|
|
10510
|
+
{
|
|
10511
|
+
id: "address-complement",
|
|
10512
|
+
"data-testid": TID.addressComplement,
|
|
10513
|
+
value: complement,
|
|
10514
|
+
onChange: (e) => setComplement(e.target.value),
|
|
10515
|
+
placeholder: "Apto, bloco\u2026",
|
|
10516
|
+
className: "mt-1 h-12 w-full rounded-lg border border-border bg-transparent px-3 text-base"
|
|
10517
|
+
}
|
|
10518
|
+
)
|
|
10519
|
+
] })
|
|
10520
|
+
] }),
|
|
10521
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-4", children: [
|
|
10522
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "address-reference", className: "text-sm font-medium", children: "Ponto de refer\xEAncia" }),
|
|
10523
|
+
/* @__PURE__ */ jsx(
|
|
10524
|
+
"input",
|
|
10525
|
+
{
|
|
10526
|
+
id: "address-reference",
|
|
10527
|
+
"data-testid": TID.addressReference,
|
|
10528
|
+
value: reference,
|
|
10529
|
+
onChange: (e) => setReference(e.target.value),
|
|
10530
|
+
placeholder: "Port\xE3o azul, ao lado da padaria",
|
|
10531
|
+
className: "mt-1 h-12 w-full rounded-lg border border-border bg-transparent px-3 text-base"
|
|
10532
|
+
}
|
|
10533
|
+
)
|
|
10534
|
+
] }),
|
|
10535
|
+
/* @__PURE__ */ jsxs("fieldset", { className: "mt-4", children: [
|
|
10536
|
+
/* @__PURE__ */ jsx("legend", { className: "text-sm font-medium", children: "Salvar como" }),
|
|
10537
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap gap-2", children: [
|
|
10538
|
+
LABELS3.map((name) => /* @__PURE__ */ jsx(
|
|
10539
|
+
"button",
|
|
10540
|
+
{
|
|
10541
|
+
type: "button",
|
|
10542
|
+
"aria-pressed": label === name,
|
|
10543
|
+
onClick: () => setLabel(label === name ? "" : name),
|
|
10544
|
+
className: `rounded-full px-4 py-2 text-sm font-medium ${label === name ? "bg-foreground text-background" : "border border-border text-muted-foreground"}`,
|
|
10545
|
+
children: name
|
|
10546
|
+
},
|
|
10547
|
+
name
|
|
10548
|
+
)),
|
|
10549
|
+
/* @__PURE__ */ jsx(
|
|
10550
|
+
"input",
|
|
10551
|
+
{
|
|
10552
|
+
value: LABELS3.includes(label) ? "" : label,
|
|
10553
|
+
onChange: (e) => setLabel(e.target.value),
|
|
10554
|
+
placeholder: "Outro",
|
|
10555
|
+
"aria-label": "Outro apelido",
|
|
10556
|
+
className: "h-10 min-w-24 flex-1 rounded-full border border-border bg-transparent px-4 text-sm"
|
|
10557
|
+
}
|
|
10558
|
+
)
|
|
10559
|
+
] })
|
|
10560
|
+
] }),
|
|
10561
|
+
/* @__PURE__ */ jsx(
|
|
10562
|
+
"button",
|
|
10563
|
+
{
|
|
10564
|
+
type: "submit",
|
|
10565
|
+
"data-testid": TID.addressSave,
|
|
10566
|
+
className: "mt-6 h-12 w-full rounded-full bg-primary font-semibold text-primary-foreground",
|
|
10567
|
+
children: "Salvar endere\xE7o"
|
|
10568
|
+
}
|
|
10569
|
+
)
|
|
10570
|
+
] })
|
|
10571
|
+
] });
|
|
10572
|
+
}
|
|
10573
|
+
var HIGHLIGHT_LIMIT = 6;
|
|
10574
|
+
function MenuPage() {
|
|
10575
|
+
const config = useStorefrontConfig();
|
|
10576
|
+
const addItem = useCartStore((s2) => s2.addItem);
|
|
10577
|
+
const [openProduct, setOpenProduct] = React37.useState(null);
|
|
10578
|
+
const [showHours, setShowHours] = React37.useState(false);
|
|
10579
|
+
const [showClosed, setShowClosed] = React37.useState(false);
|
|
10580
|
+
const [showAddress, setShowAddress] = React37.useState(false);
|
|
10581
|
+
const [showSchedule, setShowSchedule] = React37.useState(false);
|
|
10582
|
+
const [query, setQuery] = React37.useState("");
|
|
10583
|
+
const serviceState = useServiceStore();
|
|
10584
|
+
const refreshService = useServiceStore((s2) => s2.refresh);
|
|
10585
|
+
const isOpen = selectIsOpen(serviceState);
|
|
10586
|
+
React37.useEffect(() => {
|
|
10587
|
+
void refreshService();
|
|
10588
|
+
}, [refreshService]);
|
|
10589
|
+
const cart = useCartStore();
|
|
10590
|
+
const openDrawer = useCartStore((s2) => s2.openDrawer);
|
|
10591
|
+
const pushToast = useToastStore((s2) => s2.push);
|
|
10592
|
+
const count = selectCount(cart);
|
|
10593
|
+
const subtotal = selectSubtotal(cart);
|
|
10594
|
+
function guarded(run) {
|
|
10595
|
+
if (!isOpen) {
|
|
10596
|
+
setShowClosed(true);
|
|
10597
|
+
return;
|
|
10598
|
+
}
|
|
10599
|
+
run();
|
|
10600
|
+
}
|
|
10601
|
+
const products = useLoader("products.list", {});
|
|
10602
|
+
const categories = useLoader("categories.list", {});
|
|
10603
|
+
const loading = products.status === "loading" || products.status === "idle";
|
|
10604
|
+
const items = products.data ?? [];
|
|
10605
|
+
const cats = categories.data ?? [];
|
|
10606
|
+
const allSections = React37.useMemo(() => {
|
|
10607
|
+
const byCategory = /* @__PURE__ */ new Map();
|
|
10608
|
+
const loose = [];
|
|
10609
|
+
for (const p of items) {
|
|
10610
|
+
const key = p.categoryId ?? p.categoryName ?? "";
|
|
10611
|
+
if (!key) {
|
|
10612
|
+
loose.push(p);
|
|
10613
|
+
continue;
|
|
10614
|
+
}
|
|
10615
|
+
const list = byCategory.get(key) ?? [];
|
|
10616
|
+
list.push(p);
|
|
10617
|
+
byCategory.set(key, list);
|
|
10618
|
+
}
|
|
10619
|
+
const ordered = cats.map((c) => ({
|
|
10620
|
+
id: c.id,
|
|
10621
|
+
slug: c.slug ?? c.id,
|
|
10622
|
+
name: c.name,
|
|
10623
|
+
description: c.description ?? null,
|
|
10624
|
+
products: byCategory.get(c.id) ?? byCategory.get(c.name) ?? []
|
|
10625
|
+
})).filter((s2) => s2.products.length > 0);
|
|
10626
|
+
if (loose.length) {
|
|
10627
|
+
ordered.push({ id: "outros", slug: "outros", name: "Outros", description: null, products: loose });
|
|
10628
|
+
}
|
|
10629
|
+
if (!ordered.length && items.length) {
|
|
10630
|
+
return [{ id: "todos", slug: "todos", name: "Card\xE1pio", description: null, products: items }];
|
|
10631
|
+
}
|
|
10632
|
+
return ordered;
|
|
10633
|
+
}, [items, cats]);
|
|
10634
|
+
const highlights = React37.useMemo(() => {
|
|
10635
|
+
const slugs = config.delivery?.highlightSlugs;
|
|
10636
|
+
if (slugs?.length) {
|
|
10637
|
+
const bySlug = new Map(items.map((p) => [p.slug, p]));
|
|
10638
|
+
return slugs.map((slug) => bySlug.get(slug)).filter((p) => Boolean(p)).slice(0, HIGHLIGHT_LIMIT);
|
|
10639
|
+
}
|
|
10640
|
+
return items.filter((p) => p.compareAtPrice != null && p.compareAtPrice > p.price && p.inventoryCount > 0).slice(0, HIGHLIGHT_LIMIT);
|
|
10641
|
+
}, [items, config.delivery?.highlightSlugs]);
|
|
10642
|
+
const normalized = query.trim().toLowerCase();
|
|
10643
|
+
const sections = React37.useMemo(() => {
|
|
10644
|
+
if (!normalized) return allSections;
|
|
10645
|
+
return allSections.map((section) => ({
|
|
10646
|
+
...section,
|
|
10647
|
+
products: section.products.filter(
|
|
10648
|
+
(p) => p.name.toLowerCase().includes(normalized) || (p.description ?? "").toLowerCase().includes(normalized)
|
|
10649
|
+
)
|
|
10650
|
+
})).filter((section) => section.products.length > 0);
|
|
10651
|
+
}, [allSections, normalized]);
|
|
10652
|
+
const matches = sections.reduce((n, s2) => n + s2.products.length, 0);
|
|
10653
|
+
function addToCart(product, quantity, options, notes) {
|
|
10654
|
+
addItem(product, quantity, options, notes, { openDrawer: false });
|
|
10655
|
+
pushToast({
|
|
10656
|
+
title: `${quantity}\xD7 ${product.name}`,
|
|
10657
|
+
description: "Adicionado ao carrinho.",
|
|
10658
|
+
variant: "success",
|
|
10659
|
+
action: { label: "Ver carrinho", onClick: openDrawer },
|
|
10660
|
+
// Mais longo que o padrão: o aviso carrega uma decisão, e 3,4s é pouco
|
|
10661
|
+
// para ler, decidir e acertar um alvo com o polegar.
|
|
10662
|
+
durationMs: 5e3
|
|
10663
|
+
});
|
|
10664
|
+
}
|
|
10665
|
+
function quickAddable(product) {
|
|
10666
|
+
return getProductOptionGroups(product).length === 0;
|
|
10667
|
+
}
|
|
10668
|
+
function rowProps(product) {
|
|
10669
|
+
return {
|
|
10670
|
+
onOpen: setOpenProduct,
|
|
10671
|
+
onQuickAdd: quickAddable(product) ? (p) => guarded(() => addToCart(p, 1)) : void 0,
|
|
10672
|
+
// "A partir de" quando o preço mostrado é o de UMA combinação entre
|
|
10673
|
+
// várias: o número na linha não é o que a pessoa vai pagar.
|
|
10674
|
+
fromPrice: getProductOptionGroups(product).length > 0
|
|
10675
|
+
};
|
|
10676
|
+
}
|
|
10677
|
+
return (
|
|
10678
|
+
// pb-28 reserva o espaço da barra fixa do carrinho: conteúdo escondido
|
|
10679
|
+
// atrás de um elemento fixo é a falha mais comum de barra inferior.
|
|
10680
|
+
/* @__PURE__ */ jsxs("main", { "data-testid": TID.menuPage, className: "w-full pb-28", children: [
|
|
10681
|
+
/* @__PURE__ */ jsx(StoreCover, { onShowHours: () => setShowHours(true) }),
|
|
10682
|
+
/* @__PURE__ */ jsx(
|
|
10683
|
+
AddressStrip,
|
|
10684
|
+
{
|
|
10685
|
+
onChangeAddress: () => setShowAddress(true),
|
|
10686
|
+
onSchedule: () => setShowSchedule(true)
|
|
10687
|
+
}
|
|
10688
|
+
),
|
|
10689
|
+
/* @__PURE__ */ jsx(
|
|
10690
|
+
MenuToolbar,
|
|
10691
|
+
{
|
|
10692
|
+
sections: allSections,
|
|
10693
|
+
query,
|
|
10694
|
+
onQuery: setQuery
|
|
10695
|
+
}
|
|
10696
|
+
),
|
|
10697
|
+
/* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-3xl px-4", children: [
|
|
10698
|
+
loading && // Esqueleto e não "Carregando…": a lista aparece no lugar exato onde
|
|
10699
|
+
// as caixas já estavam, sem o pulo que um texto centralizado causa.
|
|
10700
|
+
/* @__PURE__ */ jsx("ul", { "aria-hidden": true, className: "animate-pulse pt-6", children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-3 border-b border-border py-4", children: [
|
|
10701
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [
|
|
10702
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-2/3 rounded bg-muted" }),
|
|
10703
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-full rounded bg-muted" }),
|
|
10704
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 rounded bg-muted" })
|
|
10705
|
+
] }),
|
|
10706
|
+
/* @__PURE__ */ jsx("div", { className: "h-24 w-24 shrink-0 rounded-lg bg-muted" })
|
|
10707
|
+
] }, i)) }),
|
|
10708
|
+
!loading && !sections.length && /* @__PURE__ */ jsx("p", { className: "py-12 text-center text-muted-foreground", children: normalized ? `Nada no card\xE1pio para "${query.trim()}".` : "Nenhum item dispon\xEDvel no momento." }),
|
|
10709
|
+
normalized && matches > 0 && /* @__PURE__ */ jsxs("p", { className: "pt-4 text-sm text-muted-foreground", children: [
|
|
10710
|
+
matches,
|
|
10711
|
+
" ",
|
|
10712
|
+
matches === 1 ? "item encontrado" : "itens encontrados"
|
|
10713
|
+
] }),
|
|
10714
|
+
!normalized && highlights.length > 0 && /* @__PURE__ */ jsxs("section", { "data-testid": TID.menuHighlights, className: "mb-10 pt-6", children: [
|
|
10715
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-bold uppercase tracking-wide", children: "Destaques" }),
|
|
10716
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-2", children: highlights.map((product) => /* @__PURE__ */ jsx(
|
|
10717
|
+
MenuItemRow,
|
|
10718
|
+
{
|
|
10719
|
+
product,
|
|
10720
|
+
badge: product.compareAtPrice != null && product.compareAtPrice > product.price ? "Em promo\xE7\xE3o" : void 0,
|
|
10721
|
+
accent: true,
|
|
10722
|
+
...rowProps(product)
|
|
10723
|
+
},
|
|
10724
|
+
product.id
|
|
10725
|
+
)) })
|
|
10726
|
+
] }),
|
|
10727
|
+
sections.map((section) => /* @__PURE__ */ jsxs(
|
|
10728
|
+
"section",
|
|
10729
|
+
{
|
|
10730
|
+
"data-testid": TID.menuSection(section.slug),
|
|
10731
|
+
"data-section-slug": section.slug,
|
|
10732
|
+
className: "mb-10 scroll-mt-32",
|
|
10733
|
+
id: `menu-${section.slug}`,
|
|
10734
|
+
children: [
|
|
10735
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-bold uppercase tracking-wide", children: section.name }),
|
|
10736
|
+
section.description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: section.description }),
|
|
10737
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-2", children: section.products.map((product) => /* @__PURE__ */ jsx(MenuItemRow, { product, ...rowProps(product) }, product.id)) })
|
|
10738
|
+
]
|
|
10739
|
+
},
|
|
10740
|
+
section.id
|
|
10741
|
+
))
|
|
10742
|
+
] }),
|
|
10743
|
+
openProduct && /* @__PURE__ */ jsx(
|
|
10744
|
+
ItemSheet,
|
|
10745
|
+
{
|
|
10746
|
+
product: openProduct,
|
|
10747
|
+
onClose: () => setOpenProduct(null),
|
|
10748
|
+
disabled: !isOpen,
|
|
10749
|
+
disabledReason: !isOpen ? "A loja est\xE1 fechada no momento." : void 0,
|
|
10750
|
+
onAdd: ({ quantity, options, notes }) => {
|
|
10751
|
+
guarded(() => {
|
|
10752
|
+
addToCart(openProduct, quantity, options, notes);
|
|
10753
|
+
setOpenProduct(null);
|
|
10754
|
+
});
|
|
10755
|
+
}
|
|
10756
|
+
}
|
|
10757
|
+
),
|
|
10758
|
+
count > 0 && /* @__PURE__ */ jsx(BottomBarSpace, {}),
|
|
10759
|
+
count > 0 && /* @__PURE__ */ jsx(
|
|
10760
|
+
"div",
|
|
10761
|
+
{
|
|
10762
|
+
"data-testid": TID.menuCartBar,
|
|
10763
|
+
className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background p-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]",
|
|
10764
|
+
children: /* @__PURE__ */ jsxs(
|
|
10765
|
+
"button",
|
|
10766
|
+
{
|
|
10767
|
+
type: "button",
|
|
10768
|
+
onClick: openDrawer,
|
|
10769
|
+
className: "mx-auto flex h-12 w-full max-w-3xl items-center justify-between rounded-full bg-primary px-5 font-semibold text-primary-foreground",
|
|
10770
|
+
children: [
|
|
10771
|
+
/* @__PURE__ */ jsx("span", { className: "grid h-7 min-w-7 place-items-center rounded-full bg-primary-foreground/20 px-2 text-sm tabular-nums", children: count }),
|
|
10772
|
+
/* @__PURE__ */ jsx("span", { children: "Ver carrinho" }),
|
|
10773
|
+
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formatMoney(subtotal, config.currency, config.locale) })
|
|
10774
|
+
]
|
|
10775
|
+
}
|
|
10776
|
+
)
|
|
10777
|
+
}
|
|
10778
|
+
),
|
|
10779
|
+
showAddress && /* @__PURE__ */ jsx(AddressSheet, { onClose: () => setShowAddress(false) }),
|
|
10780
|
+
showHours && /* @__PURE__ */ jsx(ServiceHoursModal, { onClose: () => setShowHours(false) }),
|
|
10781
|
+
showSchedule && /* @__PURE__ */ jsx(ScheduleSheet, { onClose: () => setShowSchedule(false) }),
|
|
10782
|
+
showClosed && /* @__PURE__ */ jsx(
|
|
10783
|
+
ClosedStoreDialog,
|
|
10784
|
+
{
|
|
10785
|
+
onClose: () => setShowClosed(false),
|
|
10786
|
+
onShowHours: () => {
|
|
10787
|
+
setShowClosed(false);
|
|
10788
|
+
setShowHours(true);
|
|
10789
|
+
}
|
|
10790
|
+
}
|
|
10791
|
+
)
|
|
10792
|
+
] })
|
|
10793
|
+
);
|
|
10794
|
+
}
|
|
10795
|
+
function BottomBarSpace() {
|
|
10796
|
+
React37.useEffect(() => {
|
|
10797
|
+
const root = document.documentElement;
|
|
10798
|
+
root.style.setProperty("--fayz-bottom-bar", "4.5rem");
|
|
10799
|
+
return () => {
|
|
10800
|
+
root.style.removeProperty("--fayz-bottom-bar");
|
|
10801
|
+
};
|
|
10802
|
+
}, []);
|
|
10803
|
+
return null;
|
|
10804
|
+
}
|
|
10805
|
+
|
|
10806
|
+
// src/data/order-status.ts
|
|
10807
|
+
var FINANCIAL = {
|
|
10808
|
+
pending: { label: "Pendente", tone: "pending" },
|
|
10809
|
+
paid: { label: "Pago", tone: "positive" },
|
|
10810
|
+
partially_paid: { label: "Parcialmente pago", tone: "pending" },
|
|
10811
|
+
partially_refunded: { label: "Parcialmente reembolsado", tone: "negative" },
|
|
10812
|
+
refunded: { label: "Reembolsado", tone: "negative" },
|
|
10813
|
+
voided: { label: "Cancelado", tone: "negative" }
|
|
10814
|
+
};
|
|
10815
|
+
var TONE_CLASS = {
|
|
10816
|
+
positive: "bg-emerald-100 text-emerald-800",
|
|
10817
|
+
pending: "bg-amber-100 text-amber-800",
|
|
10818
|
+
negative: "bg-rose-100 text-rose-800"
|
|
10819
|
+
};
|
|
10820
|
+
function financialStatusBadge(status) {
|
|
10821
|
+
const entry = FINANCIAL[status] ?? { label: status, tone: "pending" };
|
|
10822
|
+
return { label: entry.label, className: TONE_CLASS[entry.tone] };
|
|
10823
|
+
}
|
|
10824
|
+
function isPaid(status) {
|
|
10825
|
+
return status === "paid" || status === "partially_paid";
|
|
10826
|
+
}
|
|
10827
|
+
function isRefunded(status) {
|
|
10828
|
+
return status === "refunded" || status === "partially_refunded";
|
|
10829
|
+
}
|
|
10830
|
+
function orderTrackingSteps(order) {
|
|
10831
|
+
const received = {
|
|
10832
|
+
id: "received",
|
|
10833
|
+
label: "Pedido recebido",
|
|
10834
|
+
description: `#${order.orderNumber}`,
|
|
10835
|
+
state: "complete",
|
|
10836
|
+
icon: Check
|
|
10837
|
+
};
|
|
10838
|
+
if (order.status === "cancelled" || order.financialStatus === "voided") {
|
|
10839
|
+
return [
|
|
10840
|
+
received,
|
|
10841
|
+
{ id: "payment", label: "Pedido cancelado", description: "Este pedido foi cancelado", state: "cancelled", icon: XCircle }
|
|
10842
|
+
];
|
|
10843
|
+
}
|
|
10844
|
+
if (isRefunded(order.financialStatus)) {
|
|
10845
|
+
return [
|
|
10846
|
+
received,
|
|
10847
|
+
{ id: "payment", label: "Pagamento aprovado", description: "Compra confirmada", state: "complete", icon: Check },
|
|
10848
|
+
{
|
|
10849
|
+
id: "refund",
|
|
10850
|
+
label: order.financialStatus === "refunded" ? "Reembolsado" : "Reembolso parcial",
|
|
10851
|
+
description: "Valor devolvido ao cliente",
|
|
10852
|
+
state: "cancelled",
|
|
10853
|
+
icon: RotateCcw
|
|
10854
|
+
}
|
|
10855
|
+
];
|
|
10856
|
+
}
|
|
10857
|
+
const paid = isPaid(order.financialStatus);
|
|
10858
|
+
const partiallyFulfilled = order.fulfillmentStatus === "partially_fulfilled";
|
|
10859
|
+
const fulfilled = order.fulfillmentStatus === "fulfilled";
|
|
10860
|
+
return [
|
|
10861
|
+
received,
|
|
10862
|
+
{
|
|
10863
|
+
id: "payment",
|
|
10864
|
+
label: paid ? "Pagamento aprovado" : "Aguardando pagamento",
|
|
10865
|
+
// "Processando" descrevia um pagamento que ninguém iniciou.
|
|
10866
|
+
description: paid ? "Compra confirmada" : "Ainda n\xE3o recebemos",
|
|
10867
|
+
state: paid ? "complete" : "current",
|
|
10868
|
+
icon: paid ? Check : Clock
|
|
10869
|
+
},
|
|
10870
|
+
{
|
|
10871
|
+
id: "preparing",
|
|
10872
|
+
label: "Preparando envio",
|
|
10873
|
+
description: paid ? "Separando produtos" : "Come\xE7a ap\xF3s o pagamento",
|
|
10874
|
+
state: fulfilled || partiallyFulfilled ? "complete" : paid ? "current" : "pending",
|
|
10875
|
+
icon: PackageCheck
|
|
10876
|
+
},
|
|
10877
|
+
{
|
|
10878
|
+
id: "delivery",
|
|
10879
|
+
label: fulfilled ? "Pedido enviado" : partiallyFulfilled ? "Envio parcial" : "Entrega",
|
|
10880
|
+
description: fulfilled ? "A caminho do cliente" : partiallyFulfilled ? "Parte do pedido saiu" : "Pr\xF3xima etapa",
|
|
10881
|
+
state: fulfilled ? "complete" : partiallyFulfilled ? "current" : "pending",
|
|
10882
|
+
icon: fulfilled || partiallyFulfilled ? Truck : Clock
|
|
10883
|
+
}
|
|
10884
|
+
];
|
|
10885
|
+
}
|
|
10886
|
+
var GRID_COLS = {
|
|
10887
|
+
2: "sm:grid-cols-2",
|
|
10888
|
+
3: "sm:grid-cols-3",
|
|
10889
|
+
4: "sm:grid-cols-4"
|
|
10890
|
+
};
|
|
10891
|
+
function OrderTrackingTimeline({ order, compact: compact2 = false }) {
|
|
10892
|
+
const steps = orderTrackingSteps(order);
|
|
10893
|
+
return /* @__PURE__ */ jsx(
|
|
10894
|
+
"ol",
|
|
10895
|
+
{
|
|
10896
|
+
"data-testid": TID.orderTracking,
|
|
10897
|
+
className: `grid ${compact2 ? "gap-2" : "gap-3"} ${GRID_COLS[steps.length] ?? "sm:grid-cols-4"}`,
|
|
10898
|
+
"aria-label": "Acompanhamento do pedido",
|
|
10899
|
+
children: steps.map((step) => {
|
|
10900
|
+
const Icon2 = step.icon;
|
|
10901
|
+
const cancelled = step.state === "cancelled";
|
|
10902
|
+
const done = step.state === "complete";
|
|
10903
|
+
const current = step.state === "current";
|
|
10904
|
+
const active2 = done || current;
|
|
10905
|
+
return /* @__PURE__ */ jsx(
|
|
10906
|
+
"li",
|
|
10907
|
+
{
|
|
10908
|
+
"data-testid": TID.orderTrackingStep(step.id),
|
|
10909
|
+
"data-state": step.state,
|
|
10910
|
+
className: [
|
|
10911
|
+
"relative min-w-0 rounded-xl border p-3",
|
|
10912
|
+
cancelled ? "border-rose-200 bg-rose-50 text-rose-700" : active2 ? "border-primary/35 bg-primary/5" : "bg-muted/20 text-muted-foreground",
|
|
10913
|
+
compact2 ? "text-xs" : "text-sm"
|
|
10914
|
+
].join(" "),
|
|
10915
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
10916
|
+
/* @__PURE__ */ jsx(
|
|
10917
|
+
"span",
|
|
10918
|
+
{
|
|
10919
|
+
className: [
|
|
10920
|
+
"grid h-7 w-7 shrink-0 place-items-center rounded-full border",
|
|
10921
|
+
cancelled ? "border-rose-300 bg-rose-500 text-white" : done ? "border-primary bg-primary text-primary-foreground" : current ? "border-primary bg-background text-primary" : "border-muted-foreground/30 bg-background"
|
|
10922
|
+
].join(" "),
|
|
10923
|
+
"aria-hidden": true,
|
|
10924
|
+
children: /* @__PURE__ */ jsx(Icon2, { className: "h-3.5 w-3.5" })
|
|
10925
|
+
}
|
|
10926
|
+
),
|
|
10927
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
10928
|
+
/* @__PURE__ */ jsx("span", { className: "block font-semibold leading-snug text-foreground", children: step.label }),
|
|
10929
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 block leading-snug text-muted-foreground", children: step.description })
|
|
10930
|
+
] })
|
|
10931
|
+
] })
|
|
10932
|
+
},
|
|
10933
|
+
step.id
|
|
10934
|
+
);
|
|
10935
|
+
})
|
|
10936
|
+
}
|
|
10937
|
+
);
|
|
10938
|
+
}
|
|
10939
|
+
|
|
10940
|
+
// src/components/account/section.ts
|
|
10941
|
+
var ACCOUNT_SECTIONS = [
|
|
10942
|
+
"profile",
|
|
10943
|
+
"orders",
|
|
10944
|
+
"addresses",
|
|
10945
|
+
"payments"
|
|
10946
|
+
];
|
|
10947
|
+
var DEFAULT_ACCOUNT_SECTION = "orders";
|
|
10948
|
+
function isAccountSection(value) {
|
|
10949
|
+
return ACCOUNT_SECTIONS.includes(value);
|
|
10950
|
+
}
|
|
10951
|
+
function parseAccountSection(path) {
|
|
10952
|
+
const query = path.split("?")[1];
|
|
10953
|
+
if (!query) return DEFAULT_ACCOUNT_SECTION;
|
|
9399
10954
|
for (const pair of query.split("&")) {
|
|
9400
10955
|
const [key, raw = ""] = pair.split("=");
|
|
9401
10956
|
if (key !== "section") continue;
|
|
@@ -9509,7 +11064,7 @@ function OrderConfirmationPage({ orderId }) {
|
|
|
9509
11064
|
const [loading, setLoading] = useState(true);
|
|
9510
11065
|
const money = (v) => formatMoney(v, config.currency, config.locale);
|
|
9511
11066
|
useStorefrontHead({ title: order ? `Pedido #${order.orderNumber} \u2014 ${config.name}` : config.name });
|
|
9512
|
-
const reload =
|
|
11067
|
+
const reload = React37.useCallback(() => {
|
|
9513
11068
|
let cancelled = false;
|
|
9514
11069
|
getShopProvider().getOrder(orderId).then((o) => {
|
|
9515
11070
|
if (!cancelled) setOrder(o);
|
|
@@ -9538,7 +11093,7 @@ function OrderConfirmationPage({ orderId }) {
|
|
|
9538
11093
|
] }, column)) }),
|
|
9539
11094
|
/* @__PURE__ */ jsxs("div", { className: "mt-6", children: [
|
|
9540
11095
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-32" }),
|
|
9541
|
-
/* @__PURE__ */ jsx("div", { className: "mt-3 flex items-center gap-2", children: [0, 1, 2, 3].map((node) => /* @__PURE__ */ jsxs(
|
|
11096
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 flex items-center gap-2", children: [0, 1, 2, 3].map((node) => /* @__PURE__ */ jsxs(React37.Fragment, { children: [
|
|
9542
11097
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-7 shrink-0 rounded-full" }),
|
|
9543
11098
|
node < 3 && /* @__PURE__ */ jsx(Skeleton, { className: "h-px flex-1" })
|
|
9544
11099
|
] }, node)) })
|
|
@@ -9825,7 +11380,7 @@ function OrdersPanel() {
|
|
|
9825
11380
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-24 rounded-full" })
|
|
9826
11381
|
] }),
|
|
9827
11382
|
/* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-3 w-20" }),
|
|
9828
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex items-center gap-2", children: [0, 1, 2, 3].map((node) => /* @__PURE__ */ jsxs(
|
|
11383
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex items-center gap-2", children: [0, 1, 2, 3].map((node) => /* @__PURE__ */ jsxs(React37.Fragment, { children: [
|
|
9829
11384
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-6 shrink-0 rounded-full" }),
|
|
9830
11385
|
node < 3 && /* @__PURE__ */ jsx(Skeleton, { className: "h-px flex-1" })
|
|
9831
11386
|
] }, node)) }),
|
|
@@ -10081,7 +11636,7 @@ function PolicyPage({ kind }) {
|
|
|
10081
11636
|
] }) })
|
|
10082
11637
|
] });
|
|
10083
11638
|
}
|
|
10084
|
-
var StorefrontErrorBoundary = class extends
|
|
11639
|
+
var StorefrontErrorBoundary = class extends React37.Component {
|
|
10085
11640
|
constructor() {
|
|
10086
11641
|
super(...arguments);
|
|
10087
11642
|
this.state = { error: null };
|
|
@@ -10138,7 +11693,19 @@ function ToastCard({ toast: toast2 }) {
|
|
|
10138
11693
|
/* @__PURE__ */ jsx("span", { className: `grid h-8 w-8 shrink-0 place-items-center rounded-full ${ACCENT[toast2.variant]}`, children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4" }) }),
|
|
10139
11694
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
10140
11695
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold leading-tight", children: toast2.title }),
|
|
10141
|
-
toast2.description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: toast2.description })
|
|
11696
|
+
toast2.description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: toast2.description }),
|
|
11697
|
+
toast2.action && /* @__PURE__ */ jsx(
|
|
11698
|
+
"button",
|
|
11699
|
+
{
|
|
11700
|
+
type: "button",
|
|
11701
|
+
onClick: () => {
|
|
11702
|
+
toast2.action.onClick();
|
|
11703
|
+
dismiss(toast2.id);
|
|
11704
|
+
},
|
|
11705
|
+
className: "mt-2 text-sm font-semibold text-primary underline underline-offset-2",
|
|
11706
|
+
children: toast2.action.label
|
|
11707
|
+
}
|
|
11708
|
+
)
|
|
10142
11709
|
] }),
|
|
10143
11710
|
/* @__PURE__ */ jsx(
|
|
10144
11711
|
"button",
|
|
@@ -10157,14 +11724,29 @@ function ToastCard({ toast: toast2 }) {
|
|
|
10157
11724
|
function Toaster() {
|
|
10158
11725
|
const toasts = useToastStore((s2) => s2.toasts);
|
|
10159
11726
|
if (toasts.length === 0) return null;
|
|
10160
|
-
return
|
|
11727
|
+
return (
|
|
11728
|
+
// `--fayz-bottom-bar` é declarada por quem TEM uma barra fixa embaixo (o
|
|
11729
|
+
// cardápio, quando há carrinho). Sem isto o aviso nasce exatamente atrás
|
|
11730
|
+
// dela — e o aviso que anuncia o item some debaixo do botão que leva a ele.
|
|
11731
|
+
/* @__PURE__ */ jsx(
|
|
11732
|
+
"div",
|
|
11733
|
+
{
|
|
11734
|
+
className: "pointer-events-none fixed right-4 z-[70] flex flex-col gap-2",
|
|
11735
|
+
style: { bottom: "calc(1rem + var(--fayz-bottom-bar, 0px))" },
|
|
11736
|
+
children: toasts.map((t) => /* @__PURE__ */ jsx(ToastCard, { toast: t }, t.id))
|
|
11737
|
+
}
|
|
11738
|
+
)
|
|
11739
|
+
);
|
|
10161
11740
|
}
|
|
10162
|
-
function
|
|
11741
|
+
function routeChrome(config, path) {
|
|
10163
11742
|
const match = resolveStorefrontRoute(config, path);
|
|
10164
11743
|
if (match.kind === "custom") {
|
|
10165
|
-
|
|
11744
|
+
if (match.route.chrome) return match.route.chrome;
|
|
11745
|
+
return match.route.kind === "checkout" ? "focused" : "default";
|
|
10166
11746
|
}
|
|
10167
|
-
|
|
11747
|
+
if (match.kind === "checkout") return "focused";
|
|
11748
|
+
if (match.kind === "menu") return "minimal";
|
|
11749
|
+
return "default";
|
|
10168
11750
|
}
|
|
10169
11751
|
function RouteSwitch({ path }) {
|
|
10170
11752
|
const config = useStorefrontConfig();
|
|
@@ -10184,6 +11766,11 @@ function RouteSwitch({ path }) {
|
|
|
10184
11766
|
return config.features.checkout ? /* @__PURE__ */ jsx(CheckoutPage, {}) : /* @__PURE__ */ jsx(NotFoundPage, {});
|
|
10185
11767
|
case "account":
|
|
10186
11768
|
return config.features.accounts ? /* @__PURE__ */ jsx(MyPurchasesPage, {}) : /* @__PURE__ */ jsx(NotFoundPage, {});
|
|
11769
|
+
// O cardápio do modo delivery. A rota já só resolve dentro do modo
|
|
11770
|
+
// (serving.ts testa `resolved.delivery`), então aqui não há segundo guard —
|
|
11771
|
+
// dois lugares decidindo a mesma coisa é como eles passam a discordar.
|
|
11772
|
+
case "menu":
|
|
11773
|
+
return /* @__PURE__ */ jsx(MenuPage, {});
|
|
10187
11774
|
case "catalog":
|
|
10188
11775
|
// The search results page IS the catalog, filtered — where the overlay's
|
|
10189
11776
|
// CTA lands, carrying `?q=`.
|
|
@@ -10287,9 +11874,10 @@ function StorefrontShellBody({ pathOverride }) {
|
|
|
10287
11874
|
const livePath = useRoutePath();
|
|
10288
11875
|
const path = pathOverride ?? livePath;
|
|
10289
11876
|
useScrollToTopOnNavigate(path);
|
|
10290
|
-
const
|
|
11877
|
+
const chrome = routeChrome(config, path);
|
|
11878
|
+
const focused = chrome === "focused";
|
|
10291
11879
|
const components = getStorefrontComponents(config);
|
|
10292
|
-
const chromeProps = { config, commerceMode: config.commerceMode };
|
|
11880
|
+
const chromeProps = { config, commerceMode: config.commerceMode, chrome };
|
|
10293
11881
|
const header = resolveOverride(components.Header, StorefrontHeader);
|
|
10294
11882
|
const footer = resolveOverride(components.Footer, StorefrontFooter);
|
|
10295
11883
|
const Shell = overrideComponent(components.Shell);
|
|
@@ -10334,7 +11922,7 @@ function createStorefront(options) {
|
|
|
10334
11922
|
|
|
10335
11923
|
// src/document/sections.ts
|
|
10336
11924
|
var STORE_DOCUMENT_KIND = "fayz.store";
|
|
10337
|
-
var STORE_COMMERCE_MODES = ["checkout", "catalog", "enquiry"];
|
|
11925
|
+
var STORE_COMMERCE_MODES = ["checkout", "catalog", "enquiry", "delivery"];
|
|
10338
11926
|
var STORE_PAYMENT_MODES = ["mock", "pix-mercadopago", "gateway"];
|
|
10339
11927
|
var STORE_PAYMENT_METHOD_KINDS = [
|
|
10340
11928
|
"pix",
|
|
@@ -10354,7 +11942,7 @@ var STORE_ROUTE_KINDS = [
|
|
|
10354
11942
|
"order",
|
|
10355
11943
|
"custom"
|
|
10356
11944
|
];
|
|
10357
|
-
var STORE_ROUTE_CHROMES = ["default", "focused"];
|
|
11945
|
+
var STORE_ROUTE_CHROMES = ["default", "minimal", "focused"];
|
|
10358
11946
|
var STORE_THEME_RADII = ["none", "soft", "round", "pill"];
|
|
10359
11947
|
var f = (type, description, extra = {}) => ({ type, description, ...extra });
|
|
10360
11948
|
var STORE_SECTIONS = {
|
|
@@ -11551,7 +13139,7 @@ ${formatErrors(report.errors)}`;
|
|
|
11551
13139
|
return resolveHandle(name);
|
|
11552
13140
|
} catch (err) {
|
|
11553
13141
|
if (onError === "throw") throw err;
|
|
11554
|
-
console.error(`[storefront] dropping ${path}: ${
|
|
13142
|
+
console.error(`[storefront] dropping ${path}: ${errorMessage(err)}`);
|
|
11555
13143
|
return void 0;
|
|
11556
13144
|
}
|
|
11557
13145
|
};
|
|
@@ -11660,6 +13248,6 @@ ${formatErrors(report.errors)}`;
|
|
|
11660
13248
|
return config;
|
|
11661
13249
|
}
|
|
11662
13250
|
|
|
11663
|
-
export { BEFORE_PLACE_ORDER_VALVE, BLOCK_STRUCTURAL_KEYS, BenefitsRow, BlockDataError, CART_LINE_ANNOTATION_POINT, CATALOG_BODY_BLOCK, CHECKOUT_FIELD_POINT, CartDrawer, CatalogPage, CategoryShowcase, CheckoutPage, CollectionCta, CollectionHero, ContentPage, CountdownBand, EmailConfirmationRequiredError, EntityListBlock, FaqSection, FiltersPanel, FormBlock, HeroSection, ImageTiles, Link, ManifestoBlock, MediaCarousel, MotifStrip, MyPurchasesPage, NewsletterBand, ORDER_METADATA_POINT, OrderConfirmationPage, OrderTrackingTimeline, PAGE_DATA_SCRIPT_ID, PLACEHOLDER_ASPECTS, PRODUCT_BODY_BLOCK, PRODUCT_CARD_BADGE_POINT, PageDataScope, PaymentTerms, Price, ProductCard, ProductDetailPage, ProductEnquiryForm, ProductGallery, ProductGrid, ProductOptionSelector, ProductRail, ProductReviews, ProductSlider, ProductSpecs, ProductSpotlight, PromoBanner, QuantityInput, Reveal, STOREFRONT_COMPONENT_KEYS, STOREFRONT_PAGE_KINDS, STOREFRONT_SLOTS, STORE_BACKEND_PROVIDERS, STORE_COMMERCE_MODES, STORE_DOCUMENT_KIND, STORE_PAYMENT_METHOD_KINDS, STORE_PAYMENT_MODES, STORE_ROUTE_CHROMES, STORE_ROUTE_KINDS, STORE_SECTIONS, STORE_SECTION_NAMES, SealsBand, SearchOverlay, Slot, SmoothImage, StepsSection, StorefrontConfigHost, StorefrontConfigProvider, StorefrontFooter, StorefrontHeader, StorefrontPage, StorefrontRouterProvider, StorefrontShell, StorefrontThemeStyle, StoryQuote, THEME_SCALE_FIELDS, THEME_SCALE_VAR_PREFIX, TID, Testimonials, TierCards, applyStoreSettings, bannerPlaceholder, blockInstanceId, buildEnquiryFromForm, checkPageBlocks, collectDataNeeds, collectOrderMetadata, contentPagePath, createStorefront, createStorefrontApp, currentStaticRenderPass, defaultPageBlocks, entityListBlockMeta, establishCustomerSession, exportStore, formatMoney, formatProductOptionSelection, getCartLineAnnotations, getCheckoutFieldContributions, getCustomerAuthAdapter, getProductCardBadges, getProductOptionGroups, hydrateStoreDocument, hydratedEntriesFor, initStorefrontRuntime, isJsonValue, isKnownPath, isNestedBlockRef, isPublicPath, isRecord, listSlots, matchContentPage, matchPath, matchesFacets, mergeCollectionFacet, mergePageTheme, navigateTo, nextMilestone, normalizeProductOptionSelection, orderGalleryImages, overrideComponent, overrideProps, pageSeo, pageThemeSelector, pickProductCardImage, placeStorefrontOrder, prefersReducedMotion, primaryImageUrl, productCardComponentContract, productJsonLd, productOptionSelectionKey, productPlaceholder, productSeo, readHydratedPageData, registerStorefrontBlocks, registerStorefrontEntities, registerStorefrontExtensionPoints, registerStorefrontLoaders, resetPageDiagnostics, resetProductOptionsDeprecationWarnings, resetStorefrontExtensionPoints, resolveAuthAdapter, resolveConfig, resolveDataParams, resolveOverride, resolvePageData, resolvePageDataNeed, resolvePaymentTerms, resolveStorefrontProvider, resolveStorefrontRoute, resolveVariantForSelection, roundCents, routePathParams, runBeforePlaceOrderValve, sectionToJsonSchema, sectionsToBlocks, selectCount, selectDiscountTotal, selectRequiresShipping, selectShipping, selectSubtotal, selectTotal, selectionPrice, serializePageData, shellRouterAdapter, signInByEmail, signOutCustomer, signUpCustomer, slugifyStoreName, storefrontComponentContracts, storefrontPaths, themeToCss, toBlockNodes, toFacetMap, useBlockData, useCartStore, useCatalogStore, useCategories, useDeliveryStore, useDiscountValidator, useEnquiry, useHashPath, useInView, useLoader, useMyOrders, useNavigate, usePopOnChange, useProduct, useProducts, useRoutePath, useRouterAdapter, useScrollToTopOnNavigate, useScrolled, useSessionStore, useSlotContext, useStorefrontActions, useStorefrontConfig, useStorefrontConfigOptional, useStorefrontHead, useStorefrontPage, useStorefrontPageOptional, usedSlots, validateStore, withFacet, withStaticRenderPass };
|
|
11664
|
-
//# sourceMappingURL=chunk-
|
|
11665
|
-
//# sourceMappingURL=chunk-
|
|
13251
|
+
export { AddressSheet, AddressStrip, BEFORE_PLACE_ORDER_VALVE, BLOCK_STRUCTURAL_KEYS, BenefitsRow, BlockDataError, CART_LINE_ANNOTATION_POINT, CATALOG_BODY_BLOCK, CHECKOUT_FIELD_POINT, CartDrawer, CatalogPage, CategoryShowcase, CheckoutPage, ClosedStoreDialog, CollectionCta, CollectionHero, ContentPage, CountdownBand, EmailConfirmationRequiredError, EntityListBlock, FaqSection, FiltersPanel, FormBlock, HeroSection, ImageTiles, ItemSheet, Link, ManifestoBlock, MediaCarousel, MenuItemRow, MenuPage, MenuToolbar, MotifStrip, MyPurchasesPage, NewsletterBand, ORDER_METADATA_POINT, OrderConfirmationPage, OrderTrackingTimeline, PAGE_DATA_SCRIPT_ID, PLACEHOLDER_ASPECTS, PRODUCT_BODY_BLOCK, PRODUCT_CARD_BADGE_POINT, PageDataScope, PaymentTerms, Price, ProductCard, ProductDetailPage, ProductEnquiryForm, ProductGallery, ProductGrid, ProductOptionSelector, ProductRail, ProductReviews, ProductSlider, ProductSpecs, ProductSpotlight, PromoBanner, QuantityInput, Reveal, STOREFRONT_COMPONENT_KEYS, STOREFRONT_PAGE_KINDS, STOREFRONT_SLOTS, STORE_BACKEND_PROVIDERS, STORE_COMMERCE_MODES, STORE_DOCUMENT_KIND, STORE_PAYMENT_METHOD_KINDS, STORE_PAYMENT_MODES, STORE_ROUTE_CHROMES, STORE_ROUTE_KINDS, STORE_SECTIONS, STORE_SECTION_NAMES, ScheduleSheet, SealsBand, SearchOverlay, ServiceHoursModal, Slot, SmoothImage, StepsSection, StoreCover, StorefrontConfigHost, StorefrontConfigProvider, StorefrontFooter, StorefrontHeader, StorefrontPage, StorefrontRouterProvider, StorefrontShell, StorefrontThemeStyle, StoryQuote, THEME_SCALE_FIELDS, THEME_SCALE_VAR_PREFIX, TID, Testimonials, TierCards, applyStoreSettings, bannerPlaceholder, blockInstanceId, buildEnquiryFromForm, checkPageBlocks, collectDataNeeds, collectOrderMetadata, contentPagePath, createStorefront, createStorefrontApp, currentStaticRenderPass, defaultPageBlocks, entityListBlockMeta, establishCustomerSession, exportStore, formatMoney, formatProductOptionSelection, getCartLineAnnotations, getCheckoutFieldContributions, getCustomerAuthAdapter, getProductCardBadges, getProductOptionGroups, hydrateStoreDocument, hydratedEntriesFor, initStorefrontRuntime, isJsonValue, isKnownPath, isNestedBlockRef, isPublicPath, isRecord, listSlots, matchContentPage, matchPath, matchesFacets, mergeCollectionFacet, mergePageTheme, navigateTo, nextMilestone, normalizeProductOptionSelection, orderGalleryImages, overrideComponent, overrideProps, pageSeo, pageThemeSelector, pickProductCardImage, placeStorefrontOrder, prefersReducedMotion, primaryImageUrl, productCardComponentContract, productJsonLd, productOptionSelectionKey, productPlaceholder, productSeo, readHydratedPageData, registerStorefrontBlocks, registerStorefrontEntities, registerStorefrontExtensionPoints, registerStorefrontLoaders, resetPageDiagnostics, resetProductOptionsDeprecationWarnings, resetStorefrontExtensionPoints, resolveAuthAdapter, resolveConfig, resolveDataParams, resolveOverride, resolvePageData, resolvePageDataNeed, resolvePaymentTerms, resolveStorefrontProvider, resolveStorefrontRoute, resolveVariantForSelection, roundCents, routePathParams, runBeforePlaceOrderValve, sectionToJsonSchema, sectionsToBlocks, selectCount, selectDiscountTotal, selectIsOpen, selectRequiresShipping, selectShipping, selectShowsHours, selectSubtotal, selectTotal, selectionPrice, serializePageData, shellRouterAdapter, signInByEmail, signOutCustomer, signUpCustomer, slugifyStoreName, storefrontComponentContracts, storefrontPaths, themeToCss, toBlockNodes, toFacetMap, useBlockData, useCartStore, useCatalogStore, useCategories, useDeliveryStore, useDiscountValidator, useEnquiry, useHashPath, useInView, useLoader, useMyOrders, useNavigate, usePopOnChange, useProduct, useProducts, useRoutePath, useRouterAdapter, useScrollToTopOnNavigate, useScrolled, useServiceStore, useSessionStore, useSlotContext, useStorefrontActions, useStorefrontConfig, useStorefrontConfigOptional, useStorefrontHead, useStorefrontPage, useStorefrontPageOptional, usedSlots, validateStore, withFacet, withStaticRenderPass };
|
|
13252
|
+
//# sourceMappingURL=chunk-77V5ZAF5.js.map
|
|
13253
|
+
//# sourceMappingURL=chunk-77V5ZAF5.js.map
|