@fayz-ai/storefront 0.18.0 → 0.19.1
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-ORKXSAZ6.js → chunk-77V5ZAF5.js} +1845 -264
- 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/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 +54 -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 +7 -7
- package/dist/chunk-ORKXSAZ6.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';
|
|
@@ -232,6 +232,12 @@ function productOptionSelectionKey(selection) {
|
|
|
232
232
|
return entries.length > 0 ? JSON.stringify(entries) : "";
|
|
233
233
|
}
|
|
234
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
|
+
}
|
|
235
241
|
var EMPTY = {
|
|
236
242
|
postalCode: "",
|
|
237
243
|
address: null,
|
|
@@ -246,6 +252,17 @@ var useDeliveryStore = create()(
|
|
|
246
252
|
persist(
|
|
247
253
|
(set, get) => ({
|
|
248
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
|
+
},
|
|
249
266
|
async resolve(postalCode, subtotal) {
|
|
250
267
|
const code = normalizePostalCode(postalCode);
|
|
251
268
|
if (code.length !== 8) {
|
|
@@ -304,6 +321,37 @@ var useDeliveryStore = create()(
|
|
|
304
321
|
},
|
|
305
322
|
clear() {
|
|
306
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
|
+
}));
|
|
307
355
|
}
|
|
308
356
|
}),
|
|
309
357
|
{
|
|
@@ -311,7 +359,21 @@ var useDeliveryStore = create()(
|
|
|
311
359
|
// Deliberately NOT persisting `options`: a rehydrated
|
|
312
360
|
// price would be shown as current without anything having quoted it. The
|
|
313
361
|
// address survives, the money is asked for again.
|
|
314
|
-
|
|
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
|
+
}),
|
|
315
377
|
onRehydrateStorage: () => (state) => {
|
|
316
378
|
if (state?.address) state.status = "idle";
|
|
317
379
|
}
|
|
@@ -338,10 +400,12 @@ var useCartStore = create()(
|
|
|
338
400
|
discountFreeShipping: false,
|
|
339
401
|
isOpen: false,
|
|
340
402
|
justAddedLineId: null,
|
|
341
|
-
addItem: (product, qty = 1, options) => set((state) => {
|
|
403
|
+
addItem: (product, qty = 1, options, notes, opts) => set((state) => {
|
|
342
404
|
const normalizedOptions = normalizeProductOptionSelection(options);
|
|
343
405
|
const optionKey = productOptionSelectionKey(normalizedOptions);
|
|
344
|
-
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;
|
|
345
409
|
const variant = resolveVariantForSelection(product, normalizedOptions);
|
|
346
410
|
const unitPrice = variant?.price ?? product.price;
|
|
347
411
|
const stock = variant ? variant.inventoryCount : product.inventoryCount;
|
|
@@ -351,7 +415,7 @@ var useCartStore = create()(
|
|
|
351
415
|
return {
|
|
352
416
|
// Auto-open the cart on add — the standard premium "slide-in cart"
|
|
353
417
|
// signal — and flag the line so the drawer can highlight it.
|
|
354
|
-
isOpen: true,
|
|
418
|
+
isOpen: opts?.openDrawer ?? true,
|
|
355
419
|
justAddedLineId: lineId,
|
|
356
420
|
lines: state.lines.map(
|
|
357
421
|
(l) => (l.lineId ?? l.productId) === lineId ? { ...l, lineId, quantity: nextQty } : l
|
|
@@ -378,9 +442,14 @@ var useCartStore = create()(
|
|
|
378
442
|
heightCm: variant?.heightCm ?? product.heightCm ?? null,
|
|
379
443
|
widthCm: variant?.widthCm ?? product.widthCm ?? null,
|
|
380
444
|
lengthCm: variant?.lengthCm ?? product.lengthCm ?? null,
|
|
381
|
-
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]
|
|
382
452
|
};
|
|
383
|
-
return { isOpen: true, justAddedLineId: lineId, lines: [...state.lines, line] };
|
|
384
453
|
}),
|
|
385
454
|
setQuantity: (lineId, qty) => set((state) => {
|
|
386
455
|
if (qty <= 0) return { lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) };
|
|
@@ -743,7 +812,7 @@ function resolveConfig(config) {
|
|
|
743
812
|
const homePage = config.pages?.home ?? (config.home ? { blocks: config.home.sections } : void 0);
|
|
744
813
|
const catalogPath = homePage ? "/catalog" : "/";
|
|
745
814
|
const commerceMode = config.commerceMode ?? "checkout";
|
|
746
|
-
const checkoutEnabled = commerceMode === "checkout";
|
|
815
|
+
const checkoutEnabled = commerceMode === "checkout" || commerceMode === "delivery";
|
|
747
816
|
return {
|
|
748
817
|
...config,
|
|
749
818
|
pages: { ...config.pages, ...homePage ? { home: homePage } : {} },
|
|
@@ -759,6 +828,22 @@ function resolveConfig(config) {
|
|
|
759
828
|
terms: config.payments?.terms
|
|
760
829
|
},
|
|
761
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,
|
|
762
847
|
enquiry: {
|
|
763
848
|
label: config.enquiry?.label ?? "Contact me",
|
|
764
849
|
successMessage: config.enquiry?.successMessage ?? "Thanks. We received your enquiry.",
|
|
@@ -980,7 +1065,7 @@ function Link({ to, children, onClick, target, ...rest }) {
|
|
|
980
1065
|
event.preventDefault();
|
|
981
1066
|
adapter.navigate(to);
|
|
982
1067
|
};
|
|
983
|
-
return
|
|
1068
|
+
return React37.createElement(
|
|
984
1069
|
"a",
|
|
985
1070
|
{ href: adapter.href(to), onClick: handleClick, target, ...rest },
|
|
986
1071
|
children
|
|
@@ -1099,6 +1184,43 @@ var TID = {
|
|
|
1099
1184
|
cartTotal: "cart-total",
|
|
1100
1185
|
goCheckout: "go-checkout",
|
|
1101
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}`,
|
|
1102
1224
|
// delivery estimate (product page + cart)
|
|
1103
1225
|
deliveryEstimator: "delivery-estimator",
|
|
1104
1226
|
deliveryCepInput: "delivery-cep-input",
|
|
@@ -1183,9 +1305,9 @@ function SmoothImage({
|
|
|
1183
1305
|
const easing = resolved.easing ?? "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
1184
1306
|
const blur = resolved.blur ?? true;
|
|
1185
1307
|
const transform = resolved.transform ?? "none";
|
|
1186
|
-
const ref =
|
|
1187
|
-
const [loaded, setLoaded] =
|
|
1188
|
-
const delivered =
|
|
1308
|
+
const ref = React37.useRef(null);
|
|
1309
|
+
const [loaded, setLoaded] = React37.useState(() => mode === "none" || !clientMounted);
|
|
1310
|
+
const delivered = React37.useMemo(() => {
|
|
1189
1311
|
if (transform !== "supabase" || !src || srcSet || !isStorageImageUrl(src)) return { src, srcSet, sizes };
|
|
1190
1312
|
if (variant?.width) {
|
|
1191
1313
|
const w = variant.width;
|
|
@@ -1203,10 +1325,10 @@ function SmoothImage({
|
|
|
1203
1325
|
sizes: variant?.sizes ?? sizes ?? "100vw"
|
|
1204
1326
|
};
|
|
1205
1327
|
}, [transform, src, srcSet, sizes, variant?.width, variant?.sizes, variant?.widths, variant?.quality]);
|
|
1206
|
-
|
|
1328
|
+
React37.useEffect(() => {
|
|
1207
1329
|
clientMounted = true;
|
|
1208
1330
|
}, []);
|
|
1209
|
-
|
|
1331
|
+
React37.useEffect(() => {
|
|
1210
1332
|
if (mode === "none") {
|
|
1211
1333
|
setLoaded(true);
|
|
1212
1334
|
return;
|
|
@@ -1562,7 +1684,7 @@ async function resolvePageDataNeed(need) {
|
|
|
1562
1684
|
const data = await impl(need.params, { shop: getShopProvider() });
|
|
1563
1685
|
return { status: "ready", data };
|
|
1564
1686
|
} catch (err) {
|
|
1565
|
-
const message =
|
|
1687
|
+
const message = errorMessage(err);
|
|
1566
1688
|
console.error(`[storefront] loader "${need.loader}" failed:`, err);
|
|
1567
1689
|
return { status: "error", error: message };
|
|
1568
1690
|
}
|
|
@@ -2474,8 +2596,8 @@ var BADGE_TONE_CLASSES = {
|
|
|
2474
2596
|
warning: "bg-amber-500 text-white"
|
|
2475
2597
|
};
|
|
2476
2598
|
function useExtensionBadges(product) {
|
|
2477
|
-
const [badges, setBadges] =
|
|
2478
|
-
|
|
2599
|
+
const [badges, setBadges] = React37.useState([]);
|
|
2600
|
+
React37.useEffect(() => {
|
|
2479
2601
|
let cancelled = false;
|
|
2480
2602
|
getProductCardBadges(product).then((next) => {
|
|
2481
2603
|
if (!cancelled && next.length > 0) setBadges(next);
|
|
@@ -3671,7 +3793,7 @@ function scalarToString(value) {
|
|
|
3671
3793
|
}
|
|
3672
3794
|
function ProductSpecs({ product }) {
|
|
3673
3795
|
const config = useStorefrontConfig();
|
|
3674
|
-
const extraExcluded =
|
|
3796
|
+
const extraExcluded = React37.useMemo(
|
|
3675
3797
|
() => new Set(config.productSpecs?.exclude ?? []),
|
|
3676
3798
|
[config.productSpecs?.exclude]
|
|
3677
3799
|
);
|
|
@@ -3778,7 +3900,7 @@ function useProducts(opts) {
|
|
|
3778
3900
|
setProducts(data);
|
|
3779
3901
|
setError(null);
|
|
3780
3902
|
}).catch((e) => {
|
|
3781
|
-
if (!cancelled) setError(
|
|
3903
|
+
if (!cancelled) setError(errorMessage(e));
|
|
3782
3904
|
}).finally(() => {
|
|
3783
3905
|
if (!cancelled) setLoading(false);
|
|
3784
3906
|
});
|
|
@@ -3831,7 +3953,7 @@ function ProductEnquiryForm({ product, onSuccess }) {
|
|
|
3831
3953
|
onSuccess?.();
|
|
3832
3954
|
} catch (e) {
|
|
3833
3955
|
setStatus("error");
|
|
3834
|
-
setError(
|
|
3956
|
+
setError(errorMessage(e));
|
|
3835
3957
|
}
|
|
3836
3958
|
};
|
|
3837
3959
|
return /* @__PURE__ */ jsxs(
|
|
@@ -4543,7 +4665,7 @@ function FormBlock({
|
|
|
4543
4665
|
setValues({});
|
|
4544
4666
|
} catch (e) {
|
|
4545
4667
|
setStatus("error");
|
|
4546
|
-
setError(
|
|
4668
|
+
setError(errorMessage(e));
|
|
4547
4669
|
}
|
|
4548
4670
|
};
|
|
4549
4671
|
return /* @__PURE__ */ jsxs("section", { "data-testid": TID.formBlock, className: "mx-auto max-w-2xl px-4 py-14 sm:px-6", children: [
|
|
@@ -5323,7 +5445,7 @@ function CollectionHero({
|
|
|
5323
5445
|
{
|
|
5324
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"}`,
|
|
5325
5447
|
children: /* @__PURE__ */ jsxs(Reveal, { className: centered ? "max-w-3xl" : "max-w-2xl", children: [
|
|
5326
|
-
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: [
|
|
5327
5449
|
i > 0 && /* @__PURE__ */ jsx("span", { className: "text-2xl font-light opacity-60", "aria-hidden": true, children: "\xD7" }),
|
|
5328
5450
|
/* @__PURE__ */ jsx("img", { src: logo.src, alt: logo.alt, className: "h-10 w-auto object-contain sm:h-14" })
|
|
5329
5451
|
] }, logo.src)) }),
|
|
@@ -6080,8 +6202,8 @@ function StorefrontConfigHost({
|
|
|
6080
6202
|
config,
|
|
6081
6203
|
children
|
|
6082
6204
|
}) {
|
|
6083
|
-
const [policy, setPolicy] =
|
|
6084
|
-
|
|
6205
|
+
const [policy, setPolicy] = React37.useState(null);
|
|
6206
|
+
React37.useEffect(() => {
|
|
6085
6207
|
let cancelled = false;
|
|
6086
6208
|
let provider;
|
|
6087
6209
|
try {
|
|
@@ -6100,7 +6222,7 @@ function StorefrontConfigHost({
|
|
|
6100
6222
|
cancelled = true;
|
|
6101
6223
|
};
|
|
6102
6224
|
}, [config]);
|
|
6103
|
-
const resolved =
|
|
6225
|
+
const resolved = React37.useMemo(() => applyStoreSettings(config, policy), [config, policy]);
|
|
6104
6226
|
return /* @__PURE__ */ jsx(StorefrontConfigProvider, { value: resolved, children });
|
|
6105
6227
|
}
|
|
6106
6228
|
var RADIUS_MAP = {
|
|
@@ -6220,7 +6342,7 @@ function StorefrontThemeStyle({
|
|
|
6220
6342
|
document.getElementById(linkId)?.remove();
|
|
6221
6343
|
};
|
|
6222
6344
|
}, [fontsHref, linkId, selector]);
|
|
6223
|
-
return
|
|
6345
|
+
return React37.createElement(
|
|
6224
6346
|
"style",
|
|
6225
6347
|
{ "data-sf-theme": theme.name },
|
|
6226
6348
|
themeToCss(theme, { selector })
|
|
@@ -6319,7 +6441,7 @@ function SearchOverlay({ onClose }) {
|
|
|
6319
6441
|
"\u201D."
|
|
6320
6442
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6321
6443
|
/* @__PURE__ */ jsx("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4", children: suggestions.map(
|
|
6322
|
-
(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)
|
|
6323
6445
|
) }),
|
|
6324
6446
|
/* @__PURE__ */ jsx(
|
|
6325
6447
|
"button",
|
|
@@ -6525,11 +6647,11 @@ function HeaderActions({ onMenuClick }) {
|
|
|
6525
6647
|
const openDrawer = useCartStore((s2) => s2.openDrawer);
|
|
6526
6648
|
const session = useSessionStore();
|
|
6527
6649
|
const [accountOpen, setAccountOpen] = useState(false);
|
|
6528
|
-
const accountRef =
|
|
6650
|
+
const accountRef = React37.useRef(null);
|
|
6529
6651
|
const pop = usePopOnChange(count);
|
|
6530
6652
|
const firstName = session.name?.split(/\s+/)[0];
|
|
6531
6653
|
const initial2 = (firstName ?? session.email ?? "C").slice(0, 1).toUpperCase();
|
|
6532
|
-
|
|
6654
|
+
React37.useEffect(() => {
|
|
6533
6655
|
if (!accountOpen) return;
|
|
6534
6656
|
const onPointerDown = (event) => {
|
|
6535
6657
|
if (!accountRef.current?.contains(event.target)) setAccountOpen(false);
|
|
@@ -6696,7 +6818,7 @@ function MobileMenuDrawer({ open, onClose }) {
|
|
|
6696
6818
|
navigateTo(config.catalogPath);
|
|
6697
6819
|
onClose();
|
|
6698
6820
|
};
|
|
6699
|
-
|
|
6821
|
+
React37.useEffect(() => {
|
|
6700
6822
|
if (!open) return;
|
|
6701
6823
|
const onKey = (e) => {
|
|
6702
6824
|
if (e.key === "Escape") onClose();
|
|
@@ -6766,8 +6888,9 @@ function MobileMenuDrawer({ open, onClose }) {
|
|
|
6766
6888
|
)
|
|
6767
6889
|
] });
|
|
6768
6890
|
}
|
|
6769
|
-
function StorefrontHeader() {
|
|
6891
|
+
function StorefrontHeader({ chrome } = {}) {
|
|
6770
6892
|
const config = useStorefrontConfig();
|
|
6893
|
+
const compact2 = chrome === "minimal";
|
|
6771
6894
|
const variant = config.theme?.header?.variant ?? "classic";
|
|
6772
6895
|
const scrolled = useScrolled();
|
|
6773
6896
|
const showSearch = config.theme?.header?.showSearch !== false;
|
|
@@ -6781,8 +6904,27 @@ function StorefrontHeader() {
|
|
|
6781
6904
|
style: headerStyle,
|
|
6782
6905
|
children: [
|
|
6783
6906
|
/* @__PURE__ */ jsx(AnnouncementBar, {}),
|
|
6784
|
-
/* @__PURE__ */ jsx(UtilityBar, {}),
|
|
6785
|
-
|
|
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" ? (
|
|
6786
6928
|
// Rio/Flex pattern: centered logo row, nav row below
|
|
6787
6929
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6788
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: [
|
|
@@ -7002,7 +7144,8 @@ var useToastStore = create((set) => ({
|
|
|
7002
7144
|
title: input.title,
|
|
7003
7145
|
description: input.description,
|
|
7004
7146
|
variant: input.variant ?? "info",
|
|
7005
|
-
durationMs: input.durationMs ?? 3400
|
|
7147
|
+
durationMs: input.durationMs ?? 3400,
|
|
7148
|
+
action: input.action
|
|
7006
7149
|
};
|
|
7007
7150
|
set((s2) => ({ toasts: [...s2.toasts, toast2] }));
|
|
7008
7151
|
return id;
|
|
@@ -7133,7 +7276,7 @@ function CartDrawer() {
|
|
|
7133
7276
|
"div",
|
|
7134
7277
|
{
|
|
7135
7278
|
"data-testid": TID.cartLinesList,
|
|
7136
|
-
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",
|
|
7137
7280
|
style: { scrollbarGutter: "stable" },
|
|
7138
7281
|
children: [
|
|
7139
7282
|
/* @__PURE__ */ jsx(Slot, { area: "cart", name: "beforeLines", context: cartSlotContext }),
|
|
@@ -7163,6 +7306,11 @@ function CartDrawer() {
|
|
|
7163
7306
|
] }),
|
|
7164
7307
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: line.sku }),
|
|
7165
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
|
+
] }),
|
|
7166
7314
|
/* @__PURE__ */ jsx(CartLineAnnotations, { line }),
|
|
7167
7315
|
/* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between pt-2", children: [
|
|
7168
7316
|
/* @__PURE__ */ jsx(
|
|
@@ -7197,7 +7345,7 @@ function CartDrawer() {
|
|
|
7197
7345
|
"div",
|
|
7198
7346
|
{
|
|
7199
7347
|
"data-testid": TID.cartFooter,
|
|
7200
|
-
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",
|
|
7201
7349
|
children: [
|
|
7202
7350
|
config.features.discounts && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
7203
7351
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
@@ -7340,6 +7488,7 @@ function resolveStorefrontRoute(config, rawPath) {
|
|
|
7340
7488
|
if (matchPath("/checkout", path)) return { kind: "checkout" };
|
|
7341
7489
|
if (matchPath("/account", path)) return { kind: "account" };
|
|
7342
7490
|
if (matchPath("/catalog", path)) return { kind: "catalog" };
|
|
7491
|
+
if (resolved.delivery && matchPath(resolved.delivery.menuPath, path)) return { kind: "menu" };
|
|
7343
7492
|
if (resolved.search.mode === "overlay" && matchPath(resolved.search.resultsPath, path)) {
|
|
7344
7493
|
return { kind: "searchResults" };
|
|
7345
7494
|
}
|
|
@@ -7354,7 +7503,7 @@ function resolveStorefrontRoute(config, rawPath) {
|
|
|
7354
7503
|
function isKnownPath(config, path) {
|
|
7355
7504
|
return resolveStorefrontRoute(config, path).kind !== "notFound";
|
|
7356
7505
|
}
|
|
7357
|
-
var STATIC_PATTERNS = ["/", "/catalog", "/privacy", "/terms", "/refunds"];
|
|
7506
|
+
var STATIC_PATTERNS = ["/", "/catalog", "/menu", "/privacy", "/terms", "/refunds"];
|
|
7358
7507
|
function ensureResolved(config) {
|
|
7359
7508
|
return "features" in config && "pages" in config ? config : resolveConfig(config);
|
|
7360
7509
|
}
|
|
@@ -7408,7 +7557,7 @@ function listLocalOrderIds() {
|
|
|
7408
7557
|
}
|
|
7409
7558
|
|
|
7410
7559
|
// src/lib/errors.ts
|
|
7411
|
-
function
|
|
7560
|
+
function errorMessage5(err) {
|
|
7412
7561
|
if (err instanceof Error) return err.message;
|
|
7413
7562
|
if (err && typeof err === "object" && typeof err.message === "string") {
|
|
7414
7563
|
return err.message;
|
|
@@ -7425,7 +7574,7 @@ function formatDeliveryNotes(address, shippingAddress) {
|
|
|
7425
7574
|
return parts.length > 0 ? `Entrega: ${parts.join(", ")}` : void 0;
|
|
7426
7575
|
}
|
|
7427
7576
|
function isStaleCustomerError(err) {
|
|
7428
|
-
const message =
|
|
7577
|
+
const message = errorMessage5(err).toLowerCase();
|
|
7429
7578
|
return message.includes("customer email mismatch") || message.includes("customer does not belong to this store") || message.includes("customer belongs to another account");
|
|
7430
7579
|
}
|
|
7431
7580
|
async function placeStorefrontOrder({
|
|
@@ -7435,6 +7584,8 @@ async function placeStorefrontOrder({
|
|
|
7435
7584
|
customer,
|
|
7436
7585
|
address,
|
|
7437
7586
|
shippingAddress,
|
|
7587
|
+
fulfillmentType,
|
|
7588
|
+
scheduledFor,
|
|
7438
7589
|
paymentMethod,
|
|
7439
7590
|
markPaid = false
|
|
7440
7591
|
}) {
|
|
@@ -7453,9 +7604,12 @@ async function placeStorefrontOrder({
|
|
|
7453
7604
|
// from it and decrements ITS stock, so two sizes never share a counter.
|
|
7454
7605
|
variantId: line.variantId || void 0,
|
|
7455
7606
|
quantity: line.quantity,
|
|
7456
|
-
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
|
|
7457
7611
|
}));
|
|
7458
|
-
const shippingTotal = selectShipping(cart, config);
|
|
7612
|
+
const shippingTotal = fulfillmentType === "pickup" ? 0 : selectShipping(cart, config);
|
|
7459
7613
|
const replaced = await runBeforePlaceOrderValve({
|
|
7460
7614
|
items,
|
|
7461
7615
|
customer: { name, email },
|
|
@@ -7488,6 +7642,8 @@ async function placeStorefrontOrder({
|
|
|
7488
7642
|
shippingAddress,
|
|
7489
7643
|
paymentMethod,
|
|
7490
7644
|
metadata,
|
|
7645
|
+
fulfillmentType,
|
|
7646
|
+
scheduledFor,
|
|
7491
7647
|
items
|
|
7492
7648
|
});
|
|
7493
7649
|
let order;
|
|
@@ -7656,47 +7812,61 @@ var LABELS2 = {
|
|
|
7656
7812
|
3: "Pagamento",
|
|
7657
7813
|
4: "Pronto"
|
|
7658
7814
|
};
|
|
7659
|
-
function CheckoutSteps({ current, onGoBackTo }) {
|
|
7660
|
-
const steps = [1, 2, 3, 4];
|
|
7815
|
+
function CheckoutSteps({ current, onGoBackTo, omit }) {
|
|
7816
|
+
const steps = [1, 2, 3, 4].filter((s2) => !omit?.includes(s2));
|
|
7661
7817
|
return /* @__PURE__ */ jsxs("nav", { "data-testid": TID.checkoutSteps, "aria-label": "Etapas do checkout", className: "mb-8", children: [
|
|
7662
7818
|
/* @__PURE__ */ jsx("ol", { className: "flex items-center gap-1.5 sm:gap-2", children: steps.map((step, index) => {
|
|
7663
7819
|
const done = step < current;
|
|
7664
7820
|
const active2 = step === current;
|
|
7665
7821
|
const canGoBack = done && !!onGoBackTo;
|
|
7666
7822
|
const Tag = canGoBack ? "button" : "div";
|
|
7667
|
-
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.
|
|
7668
7829
|
/* @__PURE__ */ jsxs(
|
|
7669
|
-
|
|
7830
|
+
"li",
|
|
7670
7831
|
{
|
|
7671
|
-
|
|
7672
|
-
"data-testid": TID.checkoutStep(step),
|
|
7673
|
-
"data-state": done ? "done" : active2 ? "current" : "pending",
|
|
7674
|
-
"aria-current": active2 ? "step" : void 0,
|
|
7675
|
-
className: [
|
|
7676
|
-
"flex min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 text-left transition",
|
|
7677
|
-
canGoBack ? "hover:bg-muted" : "",
|
|
7678
|
-
active2 ? "text-foreground" : done ? "text-foreground" : "text-muted-foreground"
|
|
7679
|
-
].join(" "),
|
|
7832
|
+
className: `flex min-w-0 items-center gap-1.5 sm:gap-2 ${index < steps.length - 1 ? "flex-1" : ""}`,
|
|
7680
7833
|
children: [
|
|
7681
|
-
/* @__PURE__ */
|
|
7682
|
-
|
|
7834
|
+
/* @__PURE__ */ jsxs(
|
|
7835
|
+
Tag,
|
|
7683
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,
|
|
7684
7841
|
className: [
|
|
7685
|
-
"
|
|
7686
|
-
|
|
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"
|
|
7687
7845
|
].join(" "),
|
|
7688
|
-
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
|
+
]
|
|
7689
7859
|
}
|
|
7690
7860
|
),
|
|
7691
|
-
/* @__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"}` })
|
|
7692
7862
|
]
|
|
7693
|
-
}
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7863
|
+
},
|
|
7864
|
+
step
|
|
7865
|
+
)
|
|
7866
|
+
);
|
|
7697
7867
|
}) }),
|
|
7698
7868
|
/* @__PURE__ */ jsxs("p", { className: "mt-2 text-sm font-semibold sm:hidden", children: [
|
|
7699
|
-
current,
|
|
7869
|
+
steps.indexOf(current) + 1,
|
|
7700
7870
|
". ",
|
|
7701
7871
|
LABELS2[current]
|
|
7702
7872
|
] })
|
|
@@ -7851,13 +8021,13 @@ function CardBrick({ publicKey, amount, email, onSubmit, onError }) {
|
|
|
7851
8021
|
var POLL_MS = 3e3;
|
|
7852
8022
|
var RESUME_KEY = "fz.checkout.resume";
|
|
7853
8023
|
function useExpiry(expiresAt) {
|
|
7854
|
-
const target =
|
|
8024
|
+
const target = React37.useMemo(() => {
|
|
7855
8025
|
if (!expiresAt) return null;
|
|
7856
8026
|
const t = new Date(expiresAt).getTime();
|
|
7857
8027
|
return Number.isFinite(t) ? t : null;
|
|
7858
8028
|
}, [expiresAt]);
|
|
7859
|
-
const [now, setNow] =
|
|
7860
|
-
|
|
8029
|
+
const [now, setNow] = React37.useState(() => Date.now());
|
|
8030
|
+
React37.useEffect(() => {
|
|
7861
8031
|
if (target === null) return;
|
|
7862
8032
|
const id = setInterval(() => setNow(Date.now()), 1e3);
|
|
7863
8033
|
return () => clearInterval(id);
|
|
@@ -8403,7 +8573,7 @@ var PAYMENT_LABELS = {
|
|
|
8403
8573
|
other: { label: "Combinar com a loja", hint: "A loja entra em contato para acertar o pagamento" }
|
|
8404
8574
|
};
|
|
8405
8575
|
function placeOrderMessage(err) {
|
|
8406
|
-
const message =
|
|
8576
|
+
const message = errorMessage5(err);
|
|
8407
8577
|
if (/customer (email mismatch|does not belong|belongs to another)/i.test(message)) {
|
|
8408
8578
|
return "Sua sess\xE3o ficou presa a outro cadastro. Recarregue a p\xE1gina e tente de novo.";
|
|
8409
8579
|
}
|
|
@@ -8415,9 +8585,16 @@ function placeOrderMessage(err) {
|
|
|
8415
8585
|
}
|
|
8416
8586
|
return message.replace(/^shop_[a-z_]+:\s*/i, "") || "N\xE3o foi poss\xEDvel concluir o pedido.";
|
|
8417
8587
|
}
|
|
8588
|
+
var DEV_BUILD = (() => {
|
|
8589
|
+
try {
|
|
8590
|
+
return import.meta.env?.DEV === true;
|
|
8591
|
+
} catch {
|
|
8592
|
+
return false;
|
|
8593
|
+
}
|
|
8594
|
+
})();
|
|
8418
8595
|
function field(label, testId, value, onChange, props) {
|
|
8419
8596
|
return /* @__PURE__ */ jsxs("label", { className: "block", children: [
|
|
8420
|
-
/* @__PURE__ */ jsx("span", { className: "
|
|
8597
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-xs font-medium text-muted-foreground", children: label }),
|
|
8421
8598
|
/* @__PURE__ */ jsx(
|
|
8422
8599
|
"input",
|
|
8423
8600
|
{
|
|
@@ -8477,7 +8654,7 @@ function CheckoutPage() {
|
|
|
8477
8654
|
district: "",
|
|
8478
8655
|
state: ""
|
|
8479
8656
|
});
|
|
8480
|
-
|
|
8657
|
+
React37.useEffect(() => {
|
|
8481
8658
|
if (!known.ready) return;
|
|
8482
8659
|
setForm((current) => ({
|
|
8483
8660
|
...current,
|
|
@@ -8493,6 +8670,26 @@ function CheckoutPage() {
|
|
|
8493
8670
|
}));
|
|
8494
8671
|
}, [known.ready, known.phone, known.document, known.address]);
|
|
8495
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;
|
|
8496
8693
|
const [paidOrderId, setPaidOrderId] = useState(null);
|
|
8497
8694
|
const [error, setError] = useState(null);
|
|
8498
8695
|
const [discountCode, setDiscountCode] = useState("");
|
|
@@ -8501,14 +8698,15 @@ function CheckoutPage() {
|
|
|
8501
8698
|
const [applyingDiscount, setApplyingDiscount] = useState(false);
|
|
8502
8699
|
const [showSignin, setShowSignin] = useState(false);
|
|
8503
8700
|
const [placing, setPlacing] = useState(false);
|
|
8504
|
-
const leaving =
|
|
8701
|
+
const leaving = React37.useRef(false);
|
|
8505
8702
|
const [zipLookup, setZipLookup] = useState("idle");
|
|
8506
8703
|
const subtotal = selectSubtotal(cart);
|
|
8507
8704
|
const discountTotal = selectDiscountTotal(cart);
|
|
8508
|
-
const
|
|
8509
|
-
const
|
|
8705
|
+
const shippingRaw = selectShipping(cart, config);
|
|
8706
|
+
const shipping = isPickup ? 0 : shippingRaw;
|
|
8707
|
+
const total = selectTotal(cart, config) - (isPickup ? shippingRaw : 0);
|
|
8510
8708
|
const checkoutSlotContext = { subtotal, total };
|
|
8511
|
-
const checkoutSessionInput =
|
|
8709
|
+
const checkoutSessionInput = React37.useMemo(() => ({
|
|
8512
8710
|
items: cart.lines.map((line) => ({
|
|
8513
8711
|
productId: line.productId,
|
|
8514
8712
|
variantId: line.variantId ?? null,
|
|
@@ -8658,10 +8856,23 @@ function CheckoutPage() {
|
|
|
8658
8856
|
}, [session.customerId]);
|
|
8659
8857
|
useEffect(() => {
|
|
8660
8858
|
if (addressMode !== "new") return;
|
|
8859
|
+
const kept = delivery.savedAddresses.find((a) => a.id === delivery.selectedAddressId);
|
|
8661
8860
|
const looked = delivery.address;
|
|
8662
|
-
if (!looked) return;
|
|
8861
|
+
if (!kept && !looked) return;
|
|
8663
8862
|
setForm((current) => {
|
|
8664
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
|
+
}
|
|
8665
8876
|
return {
|
|
8666
8877
|
...current,
|
|
8667
8878
|
zip: formatPostalCode(looked.postalCode),
|
|
@@ -8671,7 +8882,7 @@ function CheckoutPage() {
|
|
|
8671
8882
|
state: looked.state
|
|
8672
8883
|
};
|
|
8673
8884
|
});
|
|
8674
|
-
}, [delivery.address, addressMode]);
|
|
8885
|
+
}, [delivery.address, delivery.savedAddresses, delivery.selectedAddressId, addressMode]);
|
|
8675
8886
|
function applySavedAddress(address) {
|
|
8676
8887
|
setAddressMode("saved");
|
|
8677
8888
|
setSelectedAddressId(address.id);
|
|
@@ -8731,6 +8942,7 @@ function CheckoutPage() {
|
|
|
8731
8942
|
}
|
|
8732
8943
|
function validateDelivery() {
|
|
8733
8944
|
setError(null);
|
|
8945
|
+
if (isPickup) return true;
|
|
8734
8946
|
if (!selectRequiresShipping(cart)) return true;
|
|
8735
8947
|
if (!form.street.trim() || !form.city.trim() || !form.zip.trim() || !form.district.trim()) {
|
|
8736
8948
|
return fail("Preencha ou selecione o endere\xE7o de entrega.", TID.checkoutStreet);
|
|
@@ -8755,13 +8967,33 @@ function CheckoutPage() {
|
|
|
8755
8967
|
setStep(next);
|
|
8756
8968
|
if (typeof window !== "undefined") window.scrollTo({ top: 0, behavior: "smooth" });
|
|
8757
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
|
+
}
|
|
8758
8990
|
function advance() {
|
|
8759
8991
|
if (step === 1 && validateContact()) {
|
|
8760
8992
|
void getShopProvider().saveCustomerContact?.({
|
|
8761
8993
|
phone: form.phone.trim() || null,
|
|
8762
8994
|
document: documentDigits(form.document) || null
|
|
8763
8995
|
});
|
|
8764
|
-
goToStep(2);
|
|
8996
|
+
goToStep(isPickup ? 3 : 2);
|
|
8765
8997
|
} else if (step === 2 && validateDelivery()) goToStep(3);
|
|
8766
8998
|
}
|
|
8767
8999
|
async function confirmWithoutCharge() {
|
|
@@ -8773,21 +9005,26 @@ function CheckoutPage() {
|
|
|
8773
9005
|
cart,
|
|
8774
9006
|
session,
|
|
8775
9007
|
customer: { email: form.email, name: form.name },
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
state: form.state.trim().toUpperCase(),
|
|
8785
|
-
phone: form.phone.trim() || void 0,
|
|
8786
|
-
// Viaja no endereço porque a assinatura do shop_place_order não pode
|
|
8787
|
-
// ganhar parâmetro sem DROP (0050); uma trigger o levanta para a
|
|
8788
|
-
// coluna e o tira do jsonb, então nunca vira linha de endereço.
|
|
8789
|
-
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
|
|
8790
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,
|
|
8791
9028
|
paymentMethod
|
|
8792
9029
|
});
|
|
8793
9030
|
if (customerId) session.setSession({ customerId, email: form.email, name: form.name });
|
|
@@ -8820,6 +9057,7 @@ function CheckoutPage() {
|
|
|
8820
9057
|
TID.checkoutDocument
|
|
8821
9058
|
);
|
|
8822
9059
|
}
|
|
9060
|
+
if (isPickup) return true;
|
|
8823
9061
|
if (!form.street.trim() || !form.city.trim() || !form.zip.trim() || !form.district.trim()) {
|
|
8824
9062
|
return fail("Preencha ou selecione o endere\xE7o de entrega.", TID.checkoutStreet);
|
|
8825
9063
|
}
|
|
@@ -8867,7 +9105,8 @@ function CheckoutPage() {
|
|
|
8867
9105
|
CheckoutSteps,
|
|
8868
9106
|
{
|
|
8869
9107
|
current: step,
|
|
8870
|
-
|
|
9108
|
+
omit: isPickup ? [2] : void 0,
|
|
9109
|
+
onGoBackTo: step === 4 ? void 0 : (target) => goToStep(isPickup && target === 2 ? 1 : target)
|
|
8871
9110
|
}
|
|
8872
9111
|
),
|
|
8873
9112
|
/* @__PURE__ */ jsxs(
|
|
@@ -9099,6 +9338,27 @@ function CheckoutPage() {
|
|
|
9099
9338
|
}
|
|
9100
9339
|
),
|
|
9101
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
|
+
] })
|
|
9102
9362
|
] })
|
|
9103
9363
|
] }),
|
|
9104
9364
|
step === 4 && paidOrderId && /* @__PURE__ */ jsxs("section", { "data-testid": TID.checkoutDone, className: "rounded-xl border bg-card p-8 text-center", children: [
|
|
@@ -9123,7 +9383,7 @@ function CheckoutPage() {
|
|
|
9123
9383
|
type: "submit",
|
|
9124
9384
|
"data-testid": TID.checkoutContinue,
|
|
9125
9385
|
className: "min-h-12 rounded-lg bg-primary px-6 py-4 text-sm font-bold text-primary-foreground transition hover:opacity-90",
|
|
9126
|
-
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)}`
|
|
9127
9387
|
}
|
|
9128
9388
|
),
|
|
9129
9389
|
step === 2 && /* @__PURE__ */ jsx(
|
|
@@ -9140,12 +9400,7 @@ function CheckoutPage() {
|
|
|
9140
9400
|
] })
|
|
9141
9401
|
]
|
|
9142
9402
|
}
|
|
9143
|
-
)
|
|
9144
|
-
/* @__PURE__ */ jsxs("footer", { className: "mt-10 flex flex-wrap gap-4 border-t pt-5 text-xs text-muted-foreground", children: [
|
|
9145
|
-
/* @__PURE__ */ jsx(Link, { to: "/privacy", className: "hover:text-foreground", children: "Privacidade" }),
|
|
9146
|
-
/* @__PURE__ */ jsx(Link, { to: "/terms", className: "hover:text-foreground", children: "Termos" }),
|
|
9147
|
-
/* @__PURE__ */ jsx(Link, { to: "/refunds", className: "hover:text-foreground", children: "Trocas e devolu\xE7\xF5es" })
|
|
9148
|
-
] })
|
|
9403
|
+
)
|
|
9149
9404
|
] }),
|
|
9150
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: [
|
|
9151
9406
|
/* @__PURE__ */ jsx("h2", { className: "sr-only", children: "Resumo do pedido" }),
|
|
@@ -9157,7 +9412,12 @@ function CheckoutPage() {
|
|
|
9157
9412
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
9158
9413
|
/* @__PURE__ */ jsx("p", { className: "truncate font-medium", children: line.name }),
|
|
9159
9414
|
line.sku && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: line.sku }),
|
|
9160
|
-
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
|
+
] })
|
|
9161
9421
|
] }),
|
|
9162
9422
|
/* @__PURE__ */ jsx("span", { "data-price": (line.unitPrice * line.quantity).toFixed(2), children: money(line.unitPrice * line.quantity) })
|
|
9163
9423
|
] }, line.lineId ?? line.productId)) }),
|
|
@@ -9223,7 +9483,7 @@ function CheckoutPage() {
|
|
|
9223
9483
|
] }),
|
|
9224
9484
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
9225
9485
|
/* @__PURE__ */ jsxs("dt", { className: cart.discountFreeShipping ? "text-emerald-700" : "text-muted-foreground", children: [
|
|
9226
|
-
"Entrega",
|
|
9486
|
+
isPickup ? "Retirada na loja" : "Entrega",
|
|
9227
9487
|
cart.discountFreeShipping && /* @__PURE__ */ jsxs(
|
|
9228
9488
|
"button",
|
|
9229
9489
|
{
|
|
@@ -9238,7 +9498,7 @@ function CheckoutPage() {
|
|
|
9238
9498
|
}
|
|
9239
9499
|
)
|
|
9240
9500
|
] }),
|
|
9241
|
-
/* @__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) })
|
|
9242
9502
|
] }),
|
|
9243
9503
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between border-t pt-5 text-lg font-bold", children: [
|
|
9244
9504
|
/* @__PURE__ */ jsx("dt", { children: "Total" }),
|
|
@@ -9250,163 +9510,1451 @@ function CheckoutPage() {
|
|
|
9250
9510
|
"Compra protegida e dados criptografados."
|
|
9251
9511
|
] }),
|
|
9252
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" })
|
|
9253
9518
|
] })
|
|
9254
9519
|
] })
|
|
9255
9520
|
] });
|
|
9256
9521
|
}
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
paid: { label: "Pago", tone: "positive" },
|
|
9262
|
-
partially_paid: { label: "Parcialmente pago", tone: "pending" },
|
|
9263
|
-
partially_refunded: { label: "Parcialmente reembolsado", tone: "negative" },
|
|
9264
|
-
refunded: { label: "Reembolsado", tone: "negative" },
|
|
9265
|
-
voided: { label: "Cancelado", tone: "negative" }
|
|
9266
|
-
};
|
|
9267
|
-
var TONE_CLASS = {
|
|
9268
|
-
positive: "bg-emerald-100 text-emerald-800",
|
|
9269
|
-
pending: "bg-amber-100 text-amber-800",
|
|
9270
|
-
negative: "bg-rose-100 text-rose-800"
|
|
9271
|
-
};
|
|
9272
|
-
function financialStatusBadge(status) {
|
|
9273
|
-
const entry = FINANCIAL[status] ?? { label: status, tone: "pending" };
|
|
9274
|
-
return { label: entry.label, className: TONE_CLASS[entry.tone] };
|
|
9275
|
-
}
|
|
9276
|
-
function isPaid(status) {
|
|
9277
|
-
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;
|
|
9278
9526
|
}
|
|
9279
|
-
function
|
|
9280
|
-
return
|
|
9527
|
+
function selectShowsHours(state) {
|
|
9528
|
+
return Boolean(state.service?.configured);
|
|
9281
9529
|
}
|
|
9282
|
-
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
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
|
+
}
|
|
9295
9544
|
}
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
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",
|
|
9300
9575
|
{
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
icon: RotateCcw
|
|
9576
|
+
src: cover,
|
|
9577
|
+
alt: "",
|
|
9578
|
+
"aria-hidden": true,
|
|
9579
|
+
className: "absolute inset-0 -z-10 h-full w-full object-cover"
|
|
9306
9580
|
}
|
|
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
|
-
|
|
9342
|
-
}
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
"data-testid": TID.orderTracking,
|
|
9349
|
-
className: `grid ${compact2 ? "gap-2" : "gap-3"} ${GRID_COLS[steps.length] ?? "sm:grid-cols-4"}`,
|
|
9350
|
-
"aria-label": "Acompanhamento do pedido",
|
|
9351
|
-
children: steps.map((step) => {
|
|
9352
|
-
const Icon2 = step.icon;
|
|
9353
|
-
const cancelled = step.state === "cancelled";
|
|
9354
|
-
const done = step.state === "complete";
|
|
9355
|
-
const current = step.state === "current";
|
|
9356
|
-
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;
|
|
9357
9622
|
return /* @__PURE__ */ jsx(
|
|
9358
|
-
"
|
|
9623
|
+
"button",
|
|
9359
9624
|
{
|
|
9360
|
-
"
|
|
9361
|
-
"data-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
].join(" "),
|
|
9367
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
9368
|
-
/* @__PURE__ */ jsx(
|
|
9369
|
-
"span",
|
|
9370
|
-
{
|
|
9371
|
-
className: [
|
|
9372
|
-
"grid h-7 w-7 shrink-0 place-items-center rounded-full border",
|
|
9373
|
-
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"
|
|
9374
|
-
].join(" "),
|
|
9375
|
-
"aria-hidden": true,
|
|
9376
|
-
children: /* @__PURE__ */ jsx(Icon2, { className: "h-3.5 w-3.5" })
|
|
9377
|
-
}
|
|
9378
|
-
),
|
|
9379
|
-
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
9380
|
-
/* @__PURE__ */ jsx("span", { className: "block font-semibold leading-snug text-foreground", children: step.label }),
|
|
9381
|
-
/* @__PURE__ */ jsx("span", { className: "mt-0.5 block leading-snug text-muted-foreground", children: step.description })
|
|
9382
|
-
] })
|
|
9383
|
-
] })
|
|
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"
|
|
9384
9631
|
},
|
|
9385
|
-
|
|
9632
|
+
mode
|
|
9386
9633
|
);
|
|
9387
|
-
})
|
|
9388
|
-
}
|
|
9389
|
-
);
|
|
9634
|
+
}) })
|
|
9635
|
+
] })
|
|
9636
|
+
] });
|
|
9390
9637
|
}
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
"
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
];
|
|
9399
|
-
var DEFAULT_ACCOUNT_SECTION = "orders";
|
|
9400
|
-
function isAccountSection(value) {
|
|
9401
|
-
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
|
+
] });
|
|
9402
9645
|
}
|
|
9403
|
-
function
|
|
9404
|
-
const
|
|
9405
|
-
if (!
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
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;
|
|
10954
|
+
for (const pair of query.split("&")) {
|
|
10955
|
+
const [key, raw = ""] = pair.split("=");
|
|
10956
|
+
if (key !== "section") continue;
|
|
10957
|
+
const value = decodeURIComponent(raw);
|
|
9410
10958
|
return isAccountSection(value) ? value : DEFAULT_ACCOUNT_SECTION;
|
|
9411
10959
|
}
|
|
9412
10960
|
return DEFAULT_ACCOUNT_SECTION;
|
|
@@ -9516,7 +11064,7 @@ function OrderConfirmationPage({ orderId }) {
|
|
|
9516
11064
|
const [loading, setLoading] = useState(true);
|
|
9517
11065
|
const money = (v) => formatMoney(v, config.currency, config.locale);
|
|
9518
11066
|
useStorefrontHead({ title: order ? `Pedido #${order.orderNumber} \u2014 ${config.name}` : config.name });
|
|
9519
|
-
const reload =
|
|
11067
|
+
const reload = React37.useCallback(() => {
|
|
9520
11068
|
let cancelled = false;
|
|
9521
11069
|
getShopProvider().getOrder(orderId).then((o) => {
|
|
9522
11070
|
if (!cancelled) setOrder(o);
|
|
@@ -9545,7 +11093,7 @@ function OrderConfirmationPage({ orderId }) {
|
|
|
9545
11093
|
] }, column)) }),
|
|
9546
11094
|
/* @__PURE__ */ jsxs("div", { className: "mt-6", children: [
|
|
9547
11095
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-32" }),
|
|
9548
|
-
/* @__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: [
|
|
9549
11097
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-7 shrink-0 rounded-full" }),
|
|
9550
11098
|
node < 3 && /* @__PURE__ */ jsx(Skeleton, { className: "h-px flex-1" })
|
|
9551
11099
|
] }, node)) })
|
|
@@ -9832,7 +11380,7 @@ function OrdersPanel() {
|
|
|
9832
11380
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-24 rounded-full" })
|
|
9833
11381
|
] }),
|
|
9834
11382
|
/* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-3 w-20" }),
|
|
9835
|
-
/* @__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: [
|
|
9836
11384
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-6 shrink-0 rounded-full" }),
|
|
9837
11385
|
node < 3 && /* @__PURE__ */ jsx(Skeleton, { className: "h-px flex-1" })
|
|
9838
11386
|
] }, node)) }),
|
|
@@ -10088,7 +11636,7 @@ function PolicyPage({ kind }) {
|
|
|
10088
11636
|
] }) })
|
|
10089
11637
|
] });
|
|
10090
11638
|
}
|
|
10091
|
-
var StorefrontErrorBoundary = class extends
|
|
11639
|
+
var StorefrontErrorBoundary = class extends React37.Component {
|
|
10092
11640
|
constructor() {
|
|
10093
11641
|
super(...arguments);
|
|
10094
11642
|
this.state = { error: null };
|
|
@@ -10145,7 +11693,19 @@ function ToastCard({ toast: toast2 }) {
|
|
|
10145
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" }) }),
|
|
10146
11694
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
10147
11695
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold leading-tight", children: toast2.title }),
|
|
10148
|
-
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
|
+
)
|
|
10149
11709
|
] }),
|
|
10150
11710
|
/* @__PURE__ */ jsx(
|
|
10151
11711
|
"button",
|
|
@@ -10164,14 +11724,29 @@ function ToastCard({ toast: toast2 }) {
|
|
|
10164
11724
|
function Toaster() {
|
|
10165
11725
|
const toasts = useToastStore((s2) => s2.toasts);
|
|
10166
11726
|
if (toasts.length === 0) return null;
|
|
10167
|
-
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
|
+
);
|
|
10168
11740
|
}
|
|
10169
|
-
function
|
|
11741
|
+
function routeChrome(config, path) {
|
|
10170
11742
|
const match = resolveStorefrontRoute(config, path);
|
|
10171
11743
|
if (match.kind === "custom") {
|
|
10172
|
-
|
|
11744
|
+
if (match.route.chrome) return match.route.chrome;
|
|
11745
|
+
return match.route.kind === "checkout" ? "focused" : "default";
|
|
10173
11746
|
}
|
|
10174
|
-
|
|
11747
|
+
if (match.kind === "checkout") return "focused";
|
|
11748
|
+
if (match.kind === "menu") return "minimal";
|
|
11749
|
+
return "default";
|
|
10175
11750
|
}
|
|
10176
11751
|
function RouteSwitch({ path }) {
|
|
10177
11752
|
const config = useStorefrontConfig();
|
|
@@ -10191,6 +11766,11 @@ function RouteSwitch({ path }) {
|
|
|
10191
11766
|
return config.features.checkout ? /* @__PURE__ */ jsx(CheckoutPage, {}) : /* @__PURE__ */ jsx(NotFoundPage, {});
|
|
10192
11767
|
case "account":
|
|
10193
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, {});
|
|
10194
11774
|
case "catalog":
|
|
10195
11775
|
// The search results page IS the catalog, filtered — where the overlay's
|
|
10196
11776
|
// CTA lands, carrying `?q=`.
|
|
@@ -10294,9 +11874,10 @@ function StorefrontShellBody({ pathOverride }) {
|
|
|
10294
11874
|
const livePath = useRoutePath();
|
|
10295
11875
|
const path = pathOverride ?? livePath;
|
|
10296
11876
|
useScrollToTopOnNavigate(path);
|
|
10297
|
-
const
|
|
11877
|
+
const chrome = routeChrome(config, path);
|
|
11878
|
+
const focused = chrome === "focused";
|
|
10298
11879
|
const components = getStorefrontComponents(config);
|
|
10299
|
-
const chromeProps = { config, commerceMode: config.commerceMode };
|
|
11880
|
+
const chromeProps = { config, commerceMode: config.commerceMode, chrome };
|
|
10300
11881
|
const header = resolveOverride(components.Header, StorefrontHeader);
|
|
10301
11882
|
const footer = resolveOverride(components.Footer, StorefrontFooter);
|
|
10302
11883
|
const Shell = overrideComponent(components.Shell);
|
|
@@ -10341,7 +11922,7 @@ function createStorefront(options) {
|
|
|
10341
11922
|
|
|
10342
11923
|
// src/document/sections.ts
|
|
10343
11924
|
var STORE_DOCUMENT_KIND = "fayz.store";
|
|
10344
|
-
var STORE_COMMERCE_MODES = ["checkout", "catalog", "enquiry"];
|
|
11925
|
+
var STORE_COMMERCE_MODES = ["checkout", "catalog", "enquiry", "delivery"];
|
|
10345
11926
|
var STORE_PAYMENT_MODES = ["mock", "pix-mercadopago", "gateway"];
|
|
10346
11927
|
var STORE_PAYMENT_METHOD_KINDS = [
|
|
10347
11928
|
"pix",
|
|
@@ -10361,7 +11942,7 @@ var STORE_ROUTE_KINDS = [
|
|
|
10361
11942
|
"order",
|
|
10362
11943
|
"custom"
|
|
10363
11944
|
];
|
|
10364
|
-
var STORE_ROUTE_CHROMES = ["default", "focused"];
|
|
11945
|
+
var STORE_ROUTE_CHROMES = ["default", "minimal", "focused"];
|
|
10365
11946
|
var STORE_THEME_RADII = ["none", "soft", "round", "pill"];
|
|
10366
11947
|
var f = (type, description, extra = {}) => ({ type, description, ...extra });
|
|
10367
11948
|
var STORE_SECTIONS = {
|
|
@@ -11558,7 +13139,7 @@ ${formatErrors(report.errors)}`;
|
|
|
11558
13139
|
return resolveHandle(name);
|
|
11559
13140
|
} catch (err) {
|
|
11560
13141
|
if (onError === "throw") throw err;
|
|
11561
|
-
console.error(`[storefront] dropping ${path}: ${
|
|
13142
|
+
console.error(`[storefront] dropping ${path}: ${errorMessage(err)}`);
|
|
11562
13143
|
return void 0;
|
|
11563
13144
|
}
|
|
11564
13145
|
};
|
|
@@ -11667,6 +13248,6 @@ ${formatErrors(report.errors)}`;
|
|
|
11667
13248
|
return config;
|
|
11668
13249
|
}
|
|
11669
13250
|
|
|
11670
|
-
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 };
|
|
11671
|
-
//# sourceMappingURL=chunk-
|
|
11672
|
-
//# 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
|