@fayz-ai/storefront 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/app/createStorefrontApp.d.ts +65 -0
- package/dist/app/createStorefrontApp.d.ts.map +1 -0
- package/dist/{define.d.ts → app/define.d.ts} +3 -3
- package/dist/app/define.d.ts.map +1 -0
- package/dist/app/hydration.d.ts +37 -0
- package/dist/app/hydration.d.ts.map +1 -0
- package/dist/app/prerender.d.ts +57 -0
- package/dist/app/prerender.d.ts.map +1 -0
- package/dist/{router.d.ts → app/router.d.ts} +140 -113
- package/dist/app/router.d.ts.map +1 -0
- package/dist/{scaffold.d.ts → app/scaffold.d.ts} +2 -2
- package/dist/app/scaffold.d.ts.map +1 -0
- package/dist/app/serving.d.ts +70 -0
- package/dist/app/serving.d.ts.map +1 -0
- package/dist/app/static-render.d.ts +46 -0
- package/dist/app/static-render.d.ts.map +1 -0
- package/dist/blocks/block-at-path.d.ts +59 -0
- package/dist/blocks/block-at-path.d.ts.map +1 -0
- package/dist/blocks/page-blocks.d.ts +163 -0
- package/dist/blocks/page-blocks.d.ts.map +1 -0
- package/dist/blocks/page-data.d.ts +105 -0
- package/dist/blocks/page-data.d.ts.map +1 -0
- package/dist/{blocks.d.ts → blocks/registry.d.ts} +1 -1
- package/dist/blocks/registry.d.ts.map +1 -0
- package/dist/{sections.d.ts → blocks/sections.d.ts} +40 -2
- package/dist/blocks/sections.d.ts.map +1 -0
- package/dist/chunk-6B7H3IZ6.js +10232 -0
- package/dist/chunk-6B7H3IZ6.js.map +1 -0
- package/dist/chunk-6IXTENLB.js +162 -0
- package/dist/chunk-6IXTENLB.js.map +1 -0
- package/dist/components/PaymentTerms.d.ts +34 -0
- package/dist/components/PaymentTerms.d.ts.map +1 -0
- package/dist/components/SmoothImage.d.ts +1 -1
- package/dist/components/SmoothImage.d.ts.map +1 -1
- package/dist/components/account/CustomerAccountShell.d.ts.map +1 -0
- package/dist/components/account/SignInModal.d.ts.map +1 -0
- package/dist/components/cart/CartDrawer.d.ts.map +1 -0
- package/dist/components/cart/QuantityInput.d.ts.map +1 -0
- package/dist/components/checkout/DeliveryEstimator.d.ts.map +1 -0
- package/dist/components/collection/CategoryShowcase.d.ts +44 -0
- package/dist/components/collection/CategoryShowcase.d.ts.map +1 -0
- package/dist/components/collection/FiltersPanel.d.ts +19 -0
- package/dist/components/collection/FiltersPanel.d.ts.map +1 -0
- package/dist/components/collection/ProductGrid.d.ts.map +1 -0
- package/dist/components/layout/PageBodyBlocks.d.ts +40 -0
- package/dist/components/layout/PageBodyBlocks.d.ts.map +1 -0
- package/dist/components/layout/SearchOverlay.d.ts +13 -0
- package/dist/components/layout/SearchOverlay.d.ts.map +1 -0
- package/dist/components/layout/StorefrontErrorBoundary.d.ts.map +1 -0
- package/dist/components/layout/StorefrontFooter.d.ts.map +1 -0
- package/dist/components/layout/StorefrontHeader.d.ts.map +1 -0
- package/dist/components/layout/Toaster.d.ts.map +1 -0
- package/dist/components/marketing/CollectionSections.d.ts +463 -0
- package/dist/components/marketing/CollectionSections.d.ts.map +1 -0
- package/dist/components/marketing/ConversionSections.d.ts +221 -0
- package/dist/components/marketing/ConversionSections.d.ts.map +1 -0
- package/dist/components/marketing/EditorialSections.d.ts +248 -0
- package/dist/components/marketing/EditorialSections.d.ts.map +1 -0
- package/dist/components/marketing/EntityList.d.ts +97 -0
- package/dist/components/marketing/EntityList.d.ts.map +1 -0
- package/dist/components/marketing/FormBlock.d.ts +167 -0
- package/dist/components/marketing/FormBlock.d.ts.map +1 -0
- package/dist/components/marketing/HeroSection.d.ts +125 -0
- package/dist/components/marketing/HeroSection.d.ts.map +1 -0
- package/dist/components/marketing/MediaCarousel.d.ts +135 -0
- package/dist/components/marketing/MediaCarousel.d.ts.map +1 -0
- package/dist/components/marketing/MiscSections.d.ts +252 -0
- package/dist/components/marketing/MiscSections.d.ts.map +1 -0
- package/dist/components/order/OrderTrackingTimeline.d.ts.map +1 -0
- package/dist/components/product/ProductCard.d.ts +14 -0
- package/dist/components/product/ProductCard.d.ts.map +1 -0
- package/dist/components/product/ProductEnquiryForm.d.ts.map +1 -0
- package/dist/components/product/ProductGallery.d.ts +36 -0
- package/dist/components/product/ProductGallery.d.ts.map +1 -0
- package/dist/components/{ProductOptionSelector.d.ts → product/ProductOptionSelector.d.ts} +1 -1
- package/dist/components/product/ProductOptionSelector.d.ts.map +1 -0
- package/dist/components/product/ProductRail.d.ts +93 -0
- package/dist/components/product/ProductRail.d.ts.map +1 -0
- package/dist/components/product/ProductReviews.d.ts +39 -0
- package/dist/components/product/ProductReviews.d.ts.map +1 -0
- package/dist/components/product/ProductSlider.d.ts +169 -0
- package/dist/components/product/ProductSlider.d.ts.map +1 -0
- package/dist/components/product/ProductSpecs.d.ts.map +1 -0
- package/dist/components/product/RelatedProducts.d.ts.map +1 -0
- package/dist/{auth.d.ts → data/auth.d.ts} +9 -0
- package/dist/data/auth.d.ts.map +1 -0
- package/dist/data/facets.d.ts +39 -0
- package/dist/data/facets.d.ts.map +1 -0
- package/dist/data/loaders.d.ts +56 -0
- package/dist/data/loaders.d.ts.map +1 -0
- package/dist/data/order-status.d.ts.map +1 -0
- package/dist/data/product-options.d.ts +36 -0
- package/dist/data/product-options.d.ts.map +1 -0
- package/dist/diagnostics/seo-audit.d.ts +54 -0
- package/dist/diagnostics/seo-audit.d.ts.map +1 -0
- package/dist/diagnostics/seo-audit.js +3 -0
- package/dist/diagnostics/seo-audit.js.map +1 -0
- package/dist/document/change.d.ts +100 -0
- package/dist/document/change.d.ts.map +1 -0
- package/dist/{config.d.ts → document/config.d.ts} +126 -7
- package/dist/document/config.d.ts.map +1 -0
- package/dist/document/describe.d.ts +135 -0
- package/dist/document/describe.d.ts.map +1 -0
- package/dist/document/overlay.d.ts +58 -0
- package/dist/document/overlay.d.ts.map +1 -0
- package/dist/{presets.d.ts → document/presets.d.ts} +2 -2
- package/dist/document/presets.d.ts.map +1 -0
- package/dist/document/render.d.ts +171 -0
- package/dist/document/render.d.ts.map +1 -0
- package/dist/document/round-trip.d.ts +46 -0
- package/dist/document/round-trip.d.ts.map +1 -0
- package/dist/document/sections.d.ts +194 -0
- package/dist/document/sections.d.ts.map +1 -0
- package/dist/document/upgrade.d.ts +112 -0
- package/dist/document/upgrade.d.ts.map +1 -0
- package/dist/document/validate.d.ts +24 -0
- package/dist/document/validate.d.ts.map +1 -0
- package/dist/{component-contracts.d.ts → extend/component-contracts.d.ts} +74 -22
- package/dist/extend/component-contracts.d.ts.map +1 -0
- package/dist/extend/component-override.d.ts +38 -0
- package/dist/extend/component-override.d.ts.map +1 -0
- package/dist/extend/component-selectors.d.ts.map +1 -0
- package/dist/extend/editor-bridge.d.ts +59 -0
- package/dist/extend/editor-bridge.d.ts.map +1 -0
- package/dist/extend/extension-points.d.ts +103 -0
- package/dist/extend/extension-points.d.ts.map +1 -0
- package/dist/extend/slots.d.ts +216 -0
- package/dist/extend/slots.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +25 -6
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/use-address.d.ts +26 -0
- package/dist/hooks/use-address.d.ts.map +1 -0
- package/dist/hooks/use-cart.d.ts +3 -0
- package/dist/hooks/use-cart.d.ts.map +1 -0
- package/dist/hooks/use-catalog.d.ts +24 -0
- package/dist/hooks/use-catalog.d.ts.map +1 -0
- package/dist/hooks/use-categories.d.ts +19 -0
- package/dist/hooks/use-categories.d.ts.map +1 -0
- package/dist/hooks/use-checkout.d.ts +41 -0
- package/dist/hooks/use-checkout.d.ts.map +1 -0
- package/dist/hooks/use-discount-validator.d.ts +20 -0
- package/dist/hooks/use-discount-validator.d.ts.map +1 -0
- package/dist/hooks/use-enquiry.d.ts +7 -0
- package/dist/hooks/use-enquiry.d.ts.map +1 -0
- package/dist/hooks/{useMyOrders.d.ts → use-my-orders.d.ts} +1 -1
- package/dist/hooks/use-my-orders.d.ts.map +1 -0
- package/dist/hooks/use-order.d.ts +17 -0
- package/dist/hooks/use-order.d.ts.map +1 -0
- package/dist/hooks/use-payment-methods.d.ts +19 -0
- package/dist/hooks/use-payment-methods.d.ts.map +1 -0
- package/dist/hooks/use-policies.d.ts +25 -0
- package/dist/hooks/use-policies.d.ts.map +1 -0
- package/dist/hooks/use-product.d.ts +15 -0
- package/dist/hooks/use-product.d.ts.map +1 -0
- package/dist/hooks/{useProducts.d.ts → use-products.d.ts} +1 -1
- package/dist/hooks/use-products.d.ts.map +1 -0
- package/dist/hooks/use-region.d.ts +15 -0
- package/dist/hooks/use-region.d.ts.map +1 -0
- package/dist/hooks/use-shipping.d.ts +29 -0
- package/dist/hooks/use-shipping.d.ts.map +1 -0
- package/dist/hooks/use-storefront-actions.d.ts +12 -0
- package/dist/hooks/use-storefront-actions.d.ts.map +1 -0
- package/dist/hooks/use-storefront-head.d.ts +19 -0
- package/dist/hooks/use-storefront-head.d.ts.map +1 -0
- package/dist/hooks/use-storefront.d.ts +3 -0
- package/dist/hooks/use-storefront.d.ts.map +1 -0
- package/dist/index.d.ts +123 -54
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1311 -5012
- package/dist/index.js.map +1 -1
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/motion.d.ts.map +1 -0
- package/dist/lib/seo.d.ts +26 -0
- package/dist/lib/seo.d.ts.map +1 -0
- package/dist/{testids.d.ts → lib/testids.d.ts} +21 -0
- package/dist/lib/testids.d.ts.map +1 -0
- package/dist/{theme.d.ts → lib/theme.d.ts} +41 -3
- package/dist/lib/theme.d.ts.map +1 -0
- package/dist/render.d.ts +5 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +359 -0
- package/dist/render.js.map +1 -0
- package/dist/stores/cart.store.d.ts +6 -2
- package/dist/stores/cart.store.d.ts.map +1 -1
- package/dist/stores/catalog.store.d.ts +11 -0
- package/dist/stores/catalog.store.d.ts.map +1 -1
- package/dist/views/CatalogPage.d.ts.map +1 -0
- package/dist/views/CheckoutPage.d.ts.map +1 -0
- package/dist/views/ContentPage.d.ts +11 -0
- package/dist/views/ContentPage.d.ts.map +1 -0
- package/dist/views/HomePage.d.ts +9 -0
- package/dist/views/HomePage.d.ts.map +1 -0
- package/dist/views/MyPurchasesPage.d.ts.map +1 -0
- package/dist/views/NotFoundPage.d.ts.map +1 -0
- package/dist/{pages → views}/OrderConfirmationPage.d.ts.map +1 -1
- package/dist/{pages → views}/PolicyPage.d.ts.map +1 -1
- package/dist/views/ProductDetailPage.d.ts.map +1 -0
- package/dist/views/StorefrontPage.d.ts +35 -0
- package/dist/views/StorefrontPage.d.ts.map +1 -0
- package/dist/workflows/checkout.d.ts +1 -1
- package/dist/workflows/checkout.d.ts.map +1 -1
- package/package.json +21 -14
- package/dist/auth.d.ts.map +0 -1
- package/dist/blocks.d.ts.map +0 -1
- package/dist/component-contracts.d.ts.map +0 -1
- package/dist/component-selectors.d.ts.map +0 -1
- package/dist/components/CartDrawer.d.ts.map +0 -1
- package/dist/components/CustomerAccountShell.d.ts.map +0 -1
- package/dist/components/DeliveryEstimator.d.ts.map +0 -1
- package/dist/components/FiltersPanel.d.ts +0 -3
- package/dist/components/FiltersPanel.d.ts.map +0 -1
- package/dist/components/OrderTrackingTimeline.d.ts.map +0 -1
- package/dist/components/ProductCard.d.ts +0 -4
- package/dist/components/ProductCard.d.ts.map +0 -1
- package/dist/components/ProductEnquiryForm.d.ts.map +0 -1
- package/dist/components/ProductGallery.d.ts +0 -22
- package/dist/components/ProductGallery.d.ts.map +0 -1
- package/dist/components/ProductGrid.d.ts.map +0 -1
- package/dist/components/ProductOptionSelector.d.ts.map +0 -1
- package/dist/components/ProductSpecs.d.ts.map +0 -1
- package/dist/components/QuantityInput.d.ts.map +0 -1
- package/dist/components/RelatedProducts.d.ts.map +0 -1
- package/dist/components/SignInModal.d.ts.map +0 -1
- package/dist/components/StorefrontErrorBoundary.d.ts.map +0 -1
- package/dist/components/StorefrontFooter.d.ts.map +0 -1
- package/dist/components/StorefrontHeader.d.ts.map +0 -1
- package/dist/components/Toaster.d.ts.map +0 -1
- package/dist/components/sections/CategoryShowcase.d.ts +0 -6
- package/dist/components/sections/CategoryShowcase.d.ts.map +0 -1
- package/dist/components/sections/HeroSection.d.ts +0 -9
- package/dist/components/sections/HeroSection.d.ts.map +0 -1
- package/dist/components/sections/MediaCarousel.d.ts +0 -11
- package/dist/components/sections/MediaCarousel.d.ts.map +0 -1
- package/dist/components/sections/MiscSections.d.ts +0 -33
- package/dist/components/sections/MiscSections.d.ts.map +0 -1
- package/dist/components/sections/ProductRail.d.ts +0 -9
- package/dist/components/sections/ProductRail.d.ts.map +0 -1
- package/dist/components/sections/ProductSlider.d.ts +0 -15
- package/dist/components/sections/ProductSlider.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/createStorefrontApp.d.ts +0 -28
- package/dist/createStorefrontApp.d.ts.map +0 -1
- package/dist/define.d.ts.map +0 -1
- package/dist/format.d.ts.map +0 -1
- package/dist/hooks/useCategories.d.ts +0 -6
- package/dist/hooks/useCategories.d.ts.map +0 -1
- package/dist/hooks/useDiscountValidator.d.ts +0 -14
- package/dist/hooks/useDiscountValidator.d.ts.map +0 -1
- package/dist/hooks/useMyOrders.d.ts.map +0 -1
- package/dist/hooks/useProduct.d.ts +0 -7
- package/dist/hooks/useProduct.d.ts.map +0 -1
- package/dist/hooks/useProducts.d.ts.map +0 -1
- package/dist/hooks/useStorefront.d.ts +0 -35
- package/dist/hooks/useStorefront.d.ts.map +0 -1
- package/dist/hooks/useStorefrontHead.d.ts +0 -11
- package/dist/hooks/useStorefrontHead.d.ts.map +0 -1
- package/dist/motion.d.ts.map +0 -1
- package/dist/order-status.d.ts.map +0 -1
- package/dist/pages/CatalogPage.d.ts.map +0 -1
- package/dist/pages/CheckoutPage.d.ts.map +0 -1
- package/dist/pages/HomePage.d.ts +0 -9
- package/dist/pages/HomePage.d.ts.map +0 -1
- package/dist/pages/MyPurchasesPage.d.ts.map +0 -1
- package/dist/pages/NotFoundPage.d.ts.map +0 -1
- package/dist/pages/ProductDetailPage.d.ts.map +0 -1
- package/dist/presets.d.ts.map +0 -1
- package/dist/product-options.d.ts +0 -12
- package/dist/product-options.d.ts.map +0 -1
- package/dist/router.d.ts.map +0 -1
- package/dist/scaffold.d.ts.map +0 -1
- package/dist/sections.d.ts.map +0 -1
- package/dist/testids.d.ts.map +0 -1
- package/dist/theme.d.ts.map +0 -1
- package/src/auth.ts +0 -227
- package/src/blocks.tsx +0 -51
- package/src/catalog.ts +0 -3
- package/src/component-contracts.ts +0 -154
- package/src/component-selectors.ts +0 -31
- package/src/components/CartDrawer.tsx +0 -279
- package/src/components/CustomerAccountShell.tsx +0 -102
- package/src/components/DeliveryEstimator.tsx +0 -157
- package/src/components/FiltersPanel.tsx +0 -109
- package/src/components/OrderTrackingTimeline.tsx +0 -135
- package/src/components/Price.tsx +0 -32
- package/src/components/ProductCard.tsx +0 -120
- package/src/components/ProductEnquiryForm.tsx +0 -175
- package/src/components/ProductGallery.tsx +0 -174
- package/src/components/ProductGrid.tsx +0 -43
- package/src/components/ProductOptionSelector.tsx +0 -50
- package/src/components/ProductSpecs.tsx +0 -75
- package/src/components/QuantityInput.tsx +0 -52
- package/src/components/RelatedProducts.tsx +0 -40
- package/src/components/SignInModal.tsx +0 -120
- package/src/components/SmoothImage.tsx +0 -59
- package/src/components/StorefrontErrorBoundary.tsx +0 -51
- package/src/components/StorefrontFooter.tsx +0 -110
- package/src/components/StorefrontHeader.tsx +0 -477
- package/src/components/Toaster.tsx +0 -60
- package/src/components/sections/CategoryShowcase.tsx +0 -80
- package/src/components/sections/HeroSection.tsx +0 -193
- package/src/components/sections/MediaCarousel.tsx +0 -141
- package/src/components/sections/MiscSections.tsx +0 -158
- package/src/components/sections/ProductRail.tsx +0 -81
- package/src/components/sections/ProductSlider.tsx +0 -119
- package/src/config.ts +0 -229
- package/src/createStorefrontApp.tsx +0 -247
- package/src/define.ts +0 -34
- package/src/format.ts +0 -7
- package/src/hooks/index.ts +0 -6
- package/src/hooks/useCategories.ts +0 -26
- package/src/hooks/useDiscountValidator.ts +0 -43
- package/src/hooks/useMyOrders.ts +0 -41
- package/src/hooks/useProduct.ts +0 -36
- package/src/hooks/useProducts.ts +0 -39
- package/src/hooks/useStorefront.ts +0 -58
- package/src/hooks/useStorefrontHead.ts +0 -25
- package/src/index.ts +0 -202
- package/src/motion.tsx +0 -94
- package/src/order-status.ts +0 -33
- package/src/pages/CatalogPage.tsx +0 -118
- package/src/pages/CheckoutPage.tsx +0 -689
- package/src/pages/HomePage.tsx +0 -16
- package/src/pages/MyPurchasesPage.tsx +0 -311
- package/src/pages/NotFoundPage.tsx +0 -25
- package/src/pages/OrderConfirmationPage.tsx +0 -190
- package/src/pages/PolicyPage.tsx +0 -47
- package/src/pages/ProductDetailPage.tsx +0 -264
- package/src/presets.ts +0 -324
- package/src/product-options.ts +0 -63
- package/src/router.ts +0 -49
- package/src/scaffold.tsx +0 -115
- package/src/sections.ts +0 -116
- package/src/shop.ts +0 -4
- package/src/stores/cart.store.ts +0 -185
- package/src/stores/catalog.store.ts +0 -39
- package/src/stores/delivery.store.ts +0 -152
- package/src/stores/session.store.ts +0 -28
- package/src/stores/toast.store.ts +0 -43
- package/src/testids.ts +0 -136
- package/src/theme.ts +0 -194
- package/src/ui.ts +0 -5
- package/src/workflows/checkout.ts +0 -119
- /package/dist/components/{CustomerAccountShell.d.ts → account/CustomerAccountShell.d.ts} +0 -0
- /package/dist/components/{SignInModal.d.ts → account/SignInModal.d.ts} +0 -0
- /package/dist/components/{CartDrawer.d.ts → cart/CartDrawer.d.ts} +0 -0
- /package/dist/components/{QuantityInput.d.ts → cart/QuantityInput.d.ts} +0 -0
- /package/dist/components/{DeliveryEstimator.d.ts → checkout/DeliveryEstimator.d.ts} +0 -0
- /package/dist/components/{ProductGrid.d.ts → collection/ProductGrid.d.ts} +0 -0
- /package/dist/components/{StorefrontErrorBoundary.d.ts → layout/StorefrontErrorBoundary.d.ts} +0 -0
- /package/dist/components/{StorefrontFooter.d.ts → layout/StorefrontFooter.d.ts} +0 -0
- /package/dist/components/{StorefrontHeader.d.ts → layout/StorefrontHeader.d.ts} +0 -0
- /package/dist/components/{Toaster.d.ts → layout/Toaster.d.ts} +0 -0
- /package/dist/components/{OrderTrackingTimeline.d.ts → order/OrderTrackingTimeline.d.ts} +0 -0
- /package/dist/components/{ProductEnquiryForm.d.ts → product/ProductEnquiryForm.d.ts} +0 -0
- /package/dist/components/{ProductSpecs.d.ts → product/ProductSpecs.d.ts} +0 -0
- /package/dist/components/{RelatedProducts.d.ts → product/RelatedProducts.d.ts} +0 -0
- /package/dist/{order-status.d.ts → data/order-status.d.ts} +0 -0
- /package/dist/{component-selectors.d.ts → extend/component-selectors.d.ts} +0 -0
- /package/dist/{format.d.ts → lib/format.d.ts} +0 -0
- /package/dist/{motion.d.ts → lib/motion.d.ts} +0 -0
- /package/dist/{pages → views}/CatalogPage.d.ts +0 -0
- /package/dist/{pages → views}/CheckoutPage.d.ts +0 -0
- /package/dist/{pages → views}/MyPurchasesPage.d.ts +0 -0
- /package/dist/{pages → views}/NotFoundPage.d.ts +0 -0
- /package/dist/{pages → views}/OrderConfirmationPage.d.ts +0 -0
- /package/dist/{pages → views}/PolicyPage.d.ts +0 -0
- /package/dist/{pages → views}/ProductDetailPage.d.ts +0 -0
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand'
|
|
2
|
-
import { persist } from 'zustand/middleware'
|
|
3
|
-
|
|
4
|
-
// Customer session state. Identity is established through the shared
|
|
5
|
-
// @fayz-ai/auth AuthAdapter (see ../auth.ts) — this store only mirrors the
|
|
6
|
-
// linked ShopCustomer for synchronous UI access.
|
|
7
|
-
|
|
8
|
-
export interface SessionState {
|
|
9
|
-
customerId: string | null
|
|
10
|
-
email: string | null
|
|
11
|
-
name: string | null
|
|
12
|
-
setSession(session: { customerId: string; email: string; name?: string | null }): void
|
|
13
|
-
signOut(): void
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const useSessionStore = create<SessionState>()(
|
|
17
|
-
persist(
|
|
18
|
-
(set) => ({
|
|
19
|
-
customerId: null,
|
|
20
|
-
email: null,
|
|
21
|
-
name: null,
|
|
22
|
-
setSession: ({ customerId, email, name }) =>
|
|
23
|
-
set({ customerId, email, name: name ?? null }),
|
|
24
|
-
signOut: () => set({ customerId: null, email: null, name: null }),
|
|
25
|
-
}),
|
|
26
|
-
{ name: 'fayz.storefront.session.v1' },
|
|
27
|
-
),
|
|
28
|
-
)
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand'
|
|
2
|
-
|
|
3
|
-
export type ToastVariant = 'success' | 'error' | 'info'
|
|
4
|
-
|
|
5
|
-
export interface Toast {
|
|
6
|
-
id: string
|
|
7
|
-
title: string
|
|
8
|
-
description?: string
|
|
9
|
-
variant: ToastVariant
|
|
10
|
-
durationMs: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface ToastState {
|
|
14
|
-
toasts: Toast[]
|
|
15
|
-
push(input: { title: string; description?: string; variant?: ToastVariant; durationMs?: number }): string
|
|
16
|
-
dismiss(id: string): void
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
let seq = 0
|
|
20
|
-
|
|
21
|
-
export const useToastStore = create<ToastState>((set) => ({
|
|
22
|
-
toasts: [],
|
|
23
|
-
push: (input) => {
|
|
24
|
-
const id = `toast-${++seq}-${Date.now()}`
|
|
25
|
-
const toast: Toast = {
|
|
26
|
-
id,
|
|
27
|
-
title: input.title,
|
|
28
|
-
description: input.description,
|
|
29
|
-
variant: input.variant ?? 'info',
|
|
30
|
-
durationMs: input.durationMs ?? 3400,
|
|
31
|
-
}
|
|
32
|
-
set((s) => ({ toasts: [...s.toasts, toast] }))
|
|
33
|
-
return id
|
|
34
|
-
},
|
|
35
|
-
dismiss: (id) => set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) })),
|
|
36
|
-
}))
|
|
37
|
-
|
|
38
|
-
/** Imperative toast API — callable from components, store actions, or workflows. */
|
|
39
|
-
export const toast = {
|
|
40
|
-
success: (title: string, description?: string) => useToastStore.getState().push({ title, description, variant: 'success' }),
|
|
41
|
-
error: (title: string, description?: string) => useToastStore.getState().push({ title, description, variant: 'error' }),
|
|
42
|
-
info: (title: string, description?: string) => useToastStore.getState().push({ title, description, variant: 'info' }),
|
|
43
|
-
}
|
package/src/testids.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
// Single source of truth for e2e selectors. Components import from here;
|
|
2
|
-
// Playwright specs assert against the same constants — they cannot drift.
|
|
3
|
-
export const TID = {
|
|
4
|
-
// header
|
|
5
|
-
headerSearch: 'header-search',
|
|
6
|
-
headerSearchToggle: 'header-search-toggle',
|
|
7
|
-
cartButton: 'cart-button',
|
|
8
|
-
cartCount: 'cart-count',
|
|
9
|
-
accountLink: 'account-link',
|
|
10
|
-
accountDropdown: 'account-dropdown',
|
|
11
|
-
announcementBar: 'announcement-bar',
|
|
12
|
-
navLink: (label: string) => `nav-${label.toLowerCase().replace(/\s+/g, '-')}`,
|
|
13
|
-
navCategory: (slug: string) => `nav-cat-${slug}`,
|
|
14
|
-
accountName: 'account-name',
|
|
15
|
-
// home sections
|
|
16
|
-
hero: 'home-hero',
|
|
17
|
-
heroPrev: 'hero-prev',
|
|
18
|
-
heroNext: 'hero-next',
|
|
19
|
-
mediaCarousel: 'media-carousel',
|
|
20
|
-
mediaCarouselPrev: 'media-carousel-prev',
|
|
21
|
-
mediaCarouselNext: 'media-carousel-next',
|
|
22
|
-
productSlider: 'product-slider',
|
|
23
|
-
productSliderViewport: 'product-slider-viewport',
|
|
24
|
-
productSliderPrev: 'product-slider-prev',
|
|
25
|
-
productSliderNext: 'product-slider-next',
|
|
26
|
-
categoryShowcase: 'category-showcase',
|
|
27
|
-
productRail: 'product-rail',
|
|
28
|
-
benefits: 'benefits-row',
|
|
29
|
-
promoBanner: 'promo-banner',
|
|
30
|
-
manifesto: 'manifesto',
|
|
31
|
-
testimonials: 'testimonials',
|
|
32
|
-
newsletter: 'newsletter',
|
|
33
|
-
newsletterEmail: 'newsletter-email',
|
|
34
|
-
newsletterSubmit: 'newsletter-submit',
|
|
35
|
-
newsletterDone: 'newsletter-done',
|
|
36
|
-
// catalog
|
|
37
|
-
productGrid: 'product-grid',
|
|
38
|
-
productCard: 'product-card',
|
|
39
|
-
productCardName: 'product-card-name',
|
|
40
|
-
productCardPrice: 'product-card-price',
|
|
41
|
-
productCardAdd: 'product-card-add',
|
|
42
|
-
badgeSale: 'badge-sale',
|
|
43
|
-
badgeSoldout: 'badge-soldout',
|
|
44
|
-
// filters
|
|
45
|
-
filterCategory: (slug: string) => `filter-category-${slug}`,
|
|
46
|
-
filterPriceMin: 'filter-price-min',
|
|
47
|
-
filterPriceMax: 'filter-price-max',
|
|
48
|
-
filterInstock: 'filter-instock',
|
|
49
|
-
sortSelect: 'sort-select',
|
|
50
|
-
filtersClear: 'filters-clear',
|
|
51
|
-
// product detail
|
|
52
|
-
pdpName: 'pdp-name',
|
|
53
|
-
pdpPrice: 'pdp-price',
|
|
54
|
-
pdpComparePrice: 'pdp-compare-price',
|
|
55
|
-
pdpDescription: 'pdp-description',
|
|
56
|
-
productOptionGroup: (id: string) => `product-option-${id.toLowerCase().replace(/\s+/g, '-')}`,
|
|
57
|
-
productOptionValue: (id: string, value: string) => `product-option-${id.toLowerCase().replace(/\s+/g, '-')}-${value.toLowerCase().replace(/\s+/g, '-')}`,
|
|
58
|
-
pdpQtyInput: 'pdp-qty-input',
|
|
59
|
-
pdpAddToCart: 'pdp-add-to-cart',
|
|
60
|
-
pdpRoot: 'pdp-root',
|
|
61
|
-
pdpGallery: 'pdp-gallery',
|
|
62
|
-
pdpGalleryImage: 'pdp-gallery-image',
|
|
63
|
-
pdpGalleryThumbs: 'pdp-gallery-thumbs',
|
|
64
|
-
pdpGalleryThumb: 'pdp-gallery-thumb',
|
|
65
|
-
pdpActions: 'pdp-actions',
|
|
66
|
-
pdpEnquiryButton: 'pdp-enquiry-button',
|
|
67
|
-
enquiryForm: 'enquiry-form',
|
|
68
|
-
enquiryName: 'enquiry-name',
|
|
69
|
-
enquiryEmail: 'enquiry-email',
|
|
70
|
-
enquiryPhone: 'enquiry-phone',
|
|
71
|
-
enquirySubject: 'enquiry-subject',
|
|
72
|
-
enquiryMessage: 'enquiry-message',
|
|
73
|
-
enquirySubmit: 'enquiry-submit',
|
|
74
|
-
enquirySuccess: 'enquiry-success',
|
|
75
|
-
enquiryError: 'enquiry-error',
|
|
76
|
-
// cart
|
|
77
|
-
cartDrawer: 'cart-drawer',
|
|
78
|
-
cartLine: 'cart-line',
|
|
79
|
-
lineQty: 'line-qty',
|
|
80
|
-
lineInc: 'line-inc',
|
|
81
|
-
lineDec: 'line-dec',
|
|
82
|
-
lineRemove: 'line-remove',
|
|
83
|
-
cartSubtotal: 'cart-subtotal',
|
|
84
|
-
discountInput: 'discount-input',
|
|
85
|
-
discountApply: 'discount-apply',
|
|
86
|
-
discountRow: 'discount-row',
|
|
87
|
-
discountError: 'discount-error',
|
|
88
|
-
cartShipping: 'cart-shipping',
|
|
89
|
-
shippingProgress: 'shipping-progress',
|
|
90
|
-
cartTotal: 'cart-total',
|
|
91
|
-
goCheckout: 'go-checkout',
|
|
92
|
-
cartEmpty: 'cart-empty',
|
|
93
|
-
// delivery estimate (product page + cart)
|
|
94
|
-
deliveryEstimator: 'delivery-estimator',
|
|
95
|
-
deliveryCepInput: 'delivery-cep-input',
|
|
96
|
-
deliveryCepSubmit: 'delivery-cep-submit',
|
|
97
|
-
deliveryOption: 'delivery-option',
|
|
98
|
-
deliveryUnserved: 'delivery-unserved',
|
|
99
|
-
deliveryError: 'delivery-error',
|
|
100
|
-
deliveryAddress: 'delivery-address',
|
|
101
|
-
deliveryClear: 'delivery-clear',
|
|
102
|
-
// checkout
|
|
103
|
-
checkoutEmail: 'checkout-email',
|
|
104
|
-
checkoutName: 'checkout-name',
|
|
105
|
-
checkoutStreet: 'checkout-street',
|
|
106
|
-
checkoutCity: 'checkout-city',
|
|
107
|
-
checkoutZip: 'checkout-zip',
|
|
108
|
-
checkoutCard: 'checkout-card',
|
|
109
|
-
checkoutExpiry: 'checkout-expiry',
|
|
110
|
-
checkoutCvc: 'checkout-cvc',
|
|
111
|
-
placeOrder: 'place-order',
|
|
112
|
-
checkoutError: 'checkout-error',
|
|
113
|
-
checkoutProcessing: 'checkout-processing',
|
|
114
|
-
// confirmation
|
|
115
|
-
orderNumber: 'order-number',
|
|
116
|
-
orderStatus: 'order-status',
|
|
117
|
-
orderTracking: 'order-tracking',
|
|
118
|
-
orderTrackingStep: (step: string) => `order-tracking-step-${step}`,
|
|
119
|
-
orderTotal: 'order-total',
|
|
120
|
-
viewPurchases: 'view-purchases',
|
|
121
|
-
// account
|
|
122
|
-
customerAccountShell: 'customer-account-shell',
|
|
123
|
-
customerAccountMenu: 'customer-account-menu',
|
|
124
|
-
orderDetail: 'order-detail',
|
|
125
|
-
authTabSignin: 'auth-tab-signin',
|
|
126
|
-
authTabSignup: 'auth-tab-signup',
|
|
127
|
-
signinEmail: 'signin-email',
|
|
128
|
-
signinPassword: 'signin-password',
|
|
129
|
-
signinName: 'signin-name',
|
|
130
|
-
signinSubmit: 'signin-submit',
|
|
131
|
-
authError: 'auth-error',
|
|
132
|
-
purchasesList: 'purchases-list',
|
|
133
|
-
purchaseItem: 'purchase-item',
|
|
134
|
-
purchasesEmpty: 'purchases-empty',
|
|
135
|
-
signout: 'signout',
|
|
136
|
-
} as const
|
package/src/theme.ts
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import React, { useEffect } from 'react'
|
|
2
|
-
|
|
3
|
-
// ---------------------------------------------------------------------------
|
|
4
|
-
// StorefrontTheme — the storefront counterpart of SaasTheme.
|
|
5
|
-
// Personalizes colors (HSL token triplets), typography (Google Fonts pairing),
|
|
6
|
-
// radius and layout properties via CSS custom properties, so every @fayz-ai/ui
|
|
7
|
-
// token class (bg-background, text-primary, ...) picks the brand up for free.
|
|
8
|
-
//
|
|
9
|
-
// Derived from the Nuvemshop template research (docs/storefront-templates-research.md):
|
|
10
|
-
// the personalization axes are palette, font pairing, radius, header treatment,
|
|
11
|
-
// hero style and product-card style.
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
|
-
export type StorefrontRadius = 'none' | 'soft' | 'round' | 'pill'
|
|
15
|
-
export type HeaderVariant = 'classic' | 'centered' | 'search' | 'minimal'
|
|
16
|
-
export type HeroVariant = 'banner' | 'split' | 'slider'
|
|
17
|
-
export type CardStyle = 'card' | 'editorial'
|
|
18
|
-
|
|
19
|
-
export interface StorefrontThemeColors {
|
|
20
|
-
/** HSL triplets, e.g. '40 20% 94%' — same convention as SaasTheme */
|
|
21
|
-
background?: string
|
|
22
|
-
foreground?: string
|
|
23
|
-
primary?: string
|
|
24
|
-
primaryForeground?: string
|
|
25
|
-
card?: string
|
|
26
|
-
cardForeground?: string
|
|
27
|
-
muted?: string
|
|
28
|
-
mutedForeground?: string
|
|
29
|
-
border?: string
|
|
30
|
-
/** Header treatment — dark headers (Brasília) set these */
|
|
31
|
-
headerBackground?: string
|
|
32
|
-
headerForeground?: string
|
|
33
|
-
/** Announcement bar */
|
|
34
|
-
announcementBackground?: string
|
|
35
|
-
announcementForeground?: string
|
|
36
|
-
/** Secondary brand accent (e.g. a gourmet gold beside the primary). Emitted
|
|
37
|
-
* as `--sf-accent` / `--sf-accent-foreground` and the `accent` tailwind token. */
|
|
38
|
-
accent?: string
|
|
39
|
-
accentForeground?: string
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface StorefrontThemeFont {
|
|
43
|
-
/** Display font for headings, e.g. 'Marcellus' */
|
|
44
|
-
heading: string
|
|
45
|
-
/** Body font, e.g. 'Rubik' */
|
|
46
|
-
body: string
|
|
47
|
-
/** Optional oversized display face for hero words (emitted as `--sf-font-display`). */
|
|
48
|
-
display?: string
|
|
49
|
-
/** Optional serif accent for quotes/editorial (emitted as `--sf-font-serif`). */
|
|
50
|
-
serif?: string
|
|
51
|
-
/** Google Fonts families to load (defaults to heading+body+display+serif) */
|
|
52
|
-
googleFonts?: string[]
|
|
53
|
-
/** Fallback stack — default sans-serif; use 'serif' for editorial themes */
|
|
54
|
-
fallback?: 'sans-serif' | 'serif'
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface StorefrontTheme {
|
|
58
|
-
name: string
|
|
59
|
-
colors?: StorefrontThemeColors
|
|
60
|
-
font?: StorefrontThemeFont
|
|
61
|
-
radius?: StorefrontRadius
|
|
62
|
-
/** Layout personality */
|
|
63
|
-
header?: {
|
|
64
|
-
variant?: HeaderVariant
|
|
65
|
-
/** Uppercase nav links (premium retail tone) */
|
|
66
|
-
uppercaseNav?: boolean
|
|
67
|
-
/** Show category shortcuts after primary nav links. Default true. */
|
|
68
|
-
showCategories?: boolean
|
|
69
|
-
/** Show the storefront search in the header. Default true. */
|
|
70
|
-
showSearch?: boolean
|
|
71
|
-
/** Header search presentation: a full input ('full', default) or a compact
|
|
72
|
-
* icon button that expands into an input on click ('icon'). */
|
|
73
|
-
searchStyle?: 'full' | 'icon'
|
|
74
|
-
}
|
|
75
|
-
productCard?: {
|
|
76
|
-
style?: CardStyle
|
|
77
|
-
imageAspect?: 'square' | 'portrait'
|
|
78
|
-
}
|
|
79
|
-
/** Uppercase CTA buttons with letter-spacing (Uyuni/Flex tone) */
|
|
80
|
-
uppercaseButtons?: boolean
|
|
81
|
-
/** Brand-token passthrough. Each entry is emitted verbatim as a `--<key>` CSS
|
|
82
|
-
* custom property, so a store can add gradients, glows, extra colors, or
|
|
83
|
-
* letter-spacing the fixed schema doesn't enumerate — without editing the SDK.
|
|
84
|
-
* e.g. { 'grad-ember': 'linear-gradient(...)', 'glow-ember': '0 0 0 1px ...' }. */
|
|
85
|
-
tokens?: Record<string, string>
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const RADIUS_MAP: Record<StorefrontRadius, { button: string; card: string; input: string }> = {
|
|
89
|
-
none: { button: '0px', card: '0px', input: '0px' },
|
|
90
|
-
soft: { button: '6px', card: '10px', input: '6px' },
|
|
91
|
-
round: { button: '10px', card: '16px', input: '10px' },
|
|
92
|
-
pill: { button: '999px', card: '20px', input: '999px' },
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const COLOR_VAR_MAP: Record<keyof StorefrontThemeColors, string> = {
|
|
96
|
-
background: '--background',
|
|
97
|
-
foreground: '--foreground',
|
|
98
|
-
primary: '--primary',
|
|
99
|
-
primaryForeground: '--primary-foreground',
|
|
100
|
-
card: '--card',
|
|
101
|
-
cardForeground: '--card-foreground',
|
|
102
|
-
muted: '--muted',
|
|
103
|
-
mutedForeground: '--muted-foreground',
|
|
104
|
-
border: '--border',
|
|
105
|
-
headerBackground: '--sf-header-bg',
|
|
106
|
-
headerForeground: '--sf-header-fg',
|
|
107
|
-
announcementBackground: '--sf-announcement-bg',
|
|
108
|
-
announcementForeground: '--sf-announcement-fg',
|
|
109
|
-
accent: '--sf-accent',
|
|
110
|
-
accentForeground: '--sf-accent-foreground',
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function themeToCss(theme: StorefrontTheme): string {
|
|
114
|
-
const lines: string[] = []
|
|
115
|
-
|
|
116
|
-
for (const [key, cssVar] of Object.entries(COLOR_VAR_MAP) as [keyof StorefrontThemeColors, string][]) {
|
|
117
|
-
const value = theme.colors?.[key]
|
|
118
|
-
if (value) lines.push(`${cssVar}: ${value};`)
|
|
119
|
-
}
|
|
120
|
-
// Header defaults to the page background unless the theme sets one
|
|
121
|
-
if (!theme.colors?.headerBackground && theme.colors?.background) {
|
|
122
|
-
lines.push(`--sf-header-bg: ${theme.colors.background};`)
|
|
123
|
-
}
|
|
124
|
-
if (!theme.colors?.headerForeground && theme.colors?.foreground) {
|
|
125
|
-
lines.push(`--sf-header-fg: ${theme.colors.foreground};`)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (theme.font) {
|
|
129
|
-
const fallback = theme.font.fallback ?? 'sans-serif'
|
|
130
|
-
lines.push(`--font-family: '${theme.font.body}', ${fallback};`)
|
|
131
|
-
lines.push(`--sf-font-heading: '${theme.font.heading}', ${fallback};`)
|
|
132
|
-
if (theme.font.display) lines.push(`--sf-font-display: '${theme.font.display}', ${fallback};`)
|
|
133
|
-
if (theme.font.serif) lines.push(`--sf-font-serif: '${theme.font.serif}', serif;`)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Brand-token passthrough — emit each entry as a raw CSS custom property.
|
|
137
|
-
for (const [key, value] of Object.entries(theme.tokens ?? {})) {
|
|
138
|
-
const name = key.startsWith('--') ? key : `--${key}`
|
|
139
|
-
lines.push(`${name}: ${value};`)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const radius = RADIUS_MAP[theme.radius ?? 'soft']
|
|
143
|
-
lines.push(`--button-radius: ${radius.button};`)
|
|
144
|
-
lines.push(`--card-radius: ${radius.card};`)
|
|
145
|
-
lines.push(`--input-radius: ${radius.input};`)
|
|
146
|
-
lines.push(`--sf-radius-button: ${radius.button};`)
|
|
147
|
-
lines.push(`--sf-radius-card: ${radius.card};`)
|
|
148
|
-
lines.push(`--sf-radius-input: ${radius.input};`)
|
|
149
|
-
|
|
150
|
-
let css = `:root {\n ${lines.join('\n ')}\n}\n`
|
|
151
|
-
css += `body { font-family: var(--font-family); }\n`
|
|
152
|
-
css += `h1, h2, h3, h4, .sf-heading { font-family: var(--sf-font-heading, var(--font-family)); }\n`
|
|
153
|
-
if (theme.uppercaseButtons) {
|
|
154
|
-
css += `.sf-cta { text-transform: uppercase; letter-spacing: 0.08em; }\n`
|
|
155
|
-
}
|
|
156
|
-
if (theme.header?.uppercaseNav) {
|
|
157
|
-
css += `.sf-nav-link { text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.8rem; }\n`
|
|
158
|
-
}
|
|
159
|
-
return css
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function googleFontsHref(theme: StorefrontTheme): string | null {
|
|
163
|
-
if (!theme.font) return null
|
|
164
|
-
const families =
|
|
165
|
-
theme.font.googleFonts ??
|
|
166
|
-
[theme.font.heading, theme.font.body, theme.font.display, theme.font.serif].filter(
|
|
167
|
-
(f): f is string => Boolean(f),
|
|
168
|
-
)
|
|
169
|
-
const unique = [...new Set(families)]
|
|
170
|
-
const params = unique
|
|
171
|
-
.map((f) => `family=${encodeURIComponent(f).replace(/%20/g, '+')}:wght@300;400;500;600;700`)
|
|
172
|
-
.join('&')
|
|
173
|
-
return `https://fonts.googleapis.com/css2?${params}&display=swap`
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/** Injects theme CSS variables + Google Fonts. Mount once inside the app root. */
|
|
177
|
-
export function StorefrontThemeStyle({ theme }: { theme: StorefrontTheme }) {
|
|
178
|
-
const fontsHref = googleFontsHref(theme)
|
|
179
|
-
|
|
180
|
-
useEffect(() => {
|
|
181
|
-
if (!fontsHref) return
|
|
182
|
-
const id = 'sf-theme-fonts'
|
|
183
|
-
let link = document.getElementById(id) as HTMLLinkElement | null
|
|
184
|
-
if (!link) {
|
|
185
|
-
link = document.createElement('link')
|
|
186
|
-
link.id = id
|
|
187
|
-
link.rel = 'stylesheet'
|
|
188
|
-
document.head.appendChild(link)
|
|
189
|
-
}
|
|
190
|
-
link.href = fontsHref
|
|
191
|
-
}, [fontsHref])
|
|
192
|
-
|
|
193
|
-
return React.createElement('style', { 'data-sf-theme': theme.name }, themeToCss(theme))
|
|
194
|
-
}
|
package/src/ui.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// Front-door re-export of @fayz-ai/ui for storefront apps.
|
|
2
|
-
// Import design-system primitives from `@fayz-ai/storefront/ui` instead of
|
|
3
|
-
// depending on @fayz-ai/ui directly. Own module graph keeps the UI deps out of
|
|
4
|
-
// the main storefront entry.
|
|
5
|
-
export * from '@fayz-ai/ui'
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { getShopProvider } from '@fayz-ai/shop/runtime'
|
|
2
|
-
import type { Order, ShippingAddressInput, PaymentMethodKind } from '@fayz-ai/shop/types'
|
|
3
|
-
import { establishCustomerSession } from '../auth'
|
|
4
|
-
import type { ResolvedStorefrontConfig } from '../config'
|
|
5
|
-
import type { CartState } from '../stores/cart.store'
|
|
6
|
-
import { selectShipping } from '../stores/cart.store'
|
|
7
|
-
import type { SessionState } from '../stores/session.store'
|
|
8
|
-
|
|
9
|
-
export interface StorefrontCheckoutCustomer {
|
|
10
|
-
email: string
|
|
11
|
-
name: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface StorefrontCheckoutAddress {
|
|
15
|
-
street?: string
|
|
16
|
-
city?: string
|
|
17
|
-
zip?: string
|
|
18
|
-
notes?: string
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface PlaceStorefrontOrderInput {
|
|
22
|
-
config: ResolvedStorefrontConfig
|
|
23
|
-
cart: Pick<CartState, 'lines' | 'discountCode' | 'discountPercent'>
|
|
24
|
-
session?: Pick<SessionState, 'customerId' | 'email'>
|
|
25
|
-
customer: StorefrontCheckoutCustomer
|
|
26
|
-
address?: StorefrontCheckoutAddress
|
|
27
|
-
/** Structured address; without it the order keeps only the free-text note. */
|
|
28
|
-
shippingAddress?: ShippingAddressInput
|
|
29
|
-
paymentMethod?: PaymentMethodKind
|
|
30
|
-
markPaid?: boolean
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface PlaceStorefrontOrderResult {
|
|
34
|
-
order: Order
|
|
35
|
-
customerId: string
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* `notes` is the buyer's free-text message to the store — nothing else.
|
|
40
|
-
*
|
|
41
|
-
* It used to double as the delivery address, from back when the order had
|
|
42
|
-
* nowhere structured to put one. Now that the address is a real snapshot plus a
|
|
43
|
-
* row in the address book, repeating it here only creates a second copy that
|
|
44
|
-
* can disagree with the first (it did: it dropped number and district). When a
|
|
45
|
-
* structured address is present, notes carries only what the customer wrote.
|
|
46
|
-
*/
|
|
47
|
-
function formatDeliveryNotes(
|
|
48
|
-
address: StorefrontCheckoutAddress | undefined,
|
|
49
|
-
shippingAddress?: ShippingAddressInput,
|
|
50
|
-
): string | undefined {
|
|
51
|
-
if (address?.notes?.trim()) return address.notes.trim()
|
|
52
|
-
|
|
53
|
-
// Structured address present → the order already knows where to deliver.
|
|
54
|
-
if (shippingAddress) return undefined
|
|
55
|
-
|
|
56
|
-
if (!address) return undefined
|
|
57
|
-
const parts = [address.street, address.city, address.zip]
|
|
58
|
-
.map((part) => part?.trim())
|
|
59
|
-
.filter(Boolean)
|
|
60
|
-
|
|
61
|
-
return parts.length > 0 ? `Entrega: ${parts.join(', ')}` : undefined
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Storefront checkout primitive for custom/generated checkout screens.
|
|
66
|
-
* It owns the order payload math and customer-session handshake so app-owned
|
|
67
|
-
* routes can customize UX without copying provider/business logic.
|
|
68
|
-
*/
|
|
69
|
-
export async function placeStorefrontOrder({
|
|
70
|
-
config,
|
|
71
|
-
cart,
|
|
72
|
-
session,
|
|
73
|
-
customer,
|
|
74
|
-
address,
|
|
75
|
-
shippingAddress,
|
|
76
|
-
paymentMethod,
|
|
77
|
-
markPaid = false,
|
|
78
|
-
}: PlaceStorefrontOrderInput): Promise<PlaceStorefrontOrderResult> {
|
|
79
|
-
const email = customer.email.trim().toLowerCase()
|
|
80
|
-
const name = customer.name.trim()
|
|
81
|
-
const provider = getShopProvider()
|
|
82
|
-
|
|
83
|
-
let customerId = session?.customerId ?? null
|
|
84
|
-
if (!customerId || session?.email !== email) {
|
|
85
|
-
const established = await establishCustomerSession(email, { name })
|
|
86
|
-
customerId = established.customerId
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Trusted placement: send only product ids + quantities. The provider
|
|
90
|
-
// (shop_place_order RPC on Supabase, in-memory provider in mock) re-reads
|
|
91
|
-
// prices, validates the discount, and decrements inventory server-side.
|
|
92
|
-
const order = await provider.placeOrder({
|
|
93
|
-
customerId: customerId ?? undefined,
|
|
94
|
-
customer: { name, email },
|
|
95
|
-
currency: config.currency,
|
|
96
|
-
notes: formatDeliveryNotes(address, shippingAddress),
|
|
97
|
-
discountCode: cart.discountCode ?? undefined,
|
|
98
|
-
shippingTotal: selectShipping(cart, config),
|
|
99
|
-
// Structured address + method are what populate public.addresses and the
|
|
100
|
-
// transactions ledger. `notes` stays for backwards compatibility with
|
|
101
|
-
// checkouts that have not been updated yet.
|
|
102
|
-
shippingAddress,
|
|
103
|
-
paymentMethod,
|
|
104
|
-
items: cart.lines.map((line) => ({
|
|
105
|
-
productId: line.productId,
|
|
106
|
-
quantity: line.quantity,
|
|
107
|
-
optionsLabel: line.optionsLabel || undefined,
|
|
108
|
-
})),
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
if (markPaid) {
|
|
112
|
-
// Prefer the RPC seam — anon storefronts have no UPDATE grant on the
|
|
113
|
-
// orders table, so a direct updateOrder 401s on pool backends.
|
|
114
|
-
if (provider.confirmPayment) await provider.confirmPayment(order.id)
|
|
115
|
-
else await provider.updateOrder(order.id, { financialStatus: 'paid' })
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return { order, customerId: customerId ?? order.customerId ?? '' }
|
|
119
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/components/{StorefrontErrorBoundary.d.ts → layout/StorefrontErrorBoundary.d.ts}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|