@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,154 +0,0 @@
|
|
|
1
|
-
import type React from 'react'
|
|
2
|
-
import type { Category, CreateProductEnquiryInput, Product, ProductEnquiry, ProductImage } from '@fayz-ai/shop/types'
|
|
3
|
-
import type { ProductOptionGroup, ProductOptionSelection } from './product-options'
|
|
4
|
-
import type { ResolvedStorefrontConfig, StorefrontCommerceMode } from './config'
|
|
5
|
-
import type { MediaCarouselItem } from './sections'
|
|
6
|
-
import type { CartState } from './stores/cart.store'
|
|
7
|
-
|
|
8
|
-
export interface StorefrontComponentBaseProps {
|
|
9
|
-
config: ResolvedStorefrontConfig
|
|
10
|
-
commerceMode: StorefrontCommerceMode
|
|
11
|
-
className?: string
|
|
12
|
-
testId?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface StorefrontActions {
|
|
16
|
-
navigateTo: (to: string) => void
|
|
17
|
-
addToCart: (product: Product, quantity?: number, options?: ProductOptionSelection) => void
|
|
18
|
-
openCart: () => void
|
|
19
|
-
closeCart: () => void
|
|
20
|
-
createProductEnquiry: (input: CreateProductEnquiryInput) => Promise<ProductEnquiry>
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ProductCardProps extends StorefrontComponentBaseProps {
|
|
24
|
-
product: Product
|
|
25
|
-
actions: Pick<StorefrontActions, 'navigateTo' | 'addToCart' | 'openCart'>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface ProductDetailProps extends StorefrontComponentBaseProps {
|
|
29
|
-
product: Product
|
|
30
|
-
primaryImage?: ProductImage
|
|
31
|
-
optionGroups: ProductOptionGroup[]
|
|
32
|
-
selectedOptions: ProductOptionSelection
|
|
33
|
-
setSelectedOptions: React.Dispatch<React.SetStateAction<ProductOptionSelection>>
|
|
34
|
-
quantity: number
|
|
35
|
-
setQuantity: React.Dispatch<React.SetStateAction<number>>
|
|
36
|
-
soldOut: boolean
|
|
37
|
-
lowStock: boolean
|
|
38
|
-
actions: Pick<StorefrontActions, 'addToCart' | 'createProductEnquiry' | 'navigateTo'>
|
|
39
|
-
addToCart: () => void
|
|
40
|
-
openEnquiry: () => void
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface ProductGalleryProps extends StorefrontComponentBaseProps {
|
|
44
|
-
product: Product
|
|
45
|
-
images: ProductImage[]
|
|
46
|
-
primaryImage?: ProductImage
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface ProductPriceProps extends StorefrontComponentBaseProps {
|
|
50
|
-
product: Product
|
|
51
|
-
value: number
|
|
52
|
-
compareAt?: number | null
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface ProductActionsProps extends StorefrontComponentBaseProps {
|
|
56
|
-
product: Product
|
|
57
|
-
quantity: number
|
|
58
|
-
setQuantity: React.Dispatch<React.SetStateAction<number>>
|
|
59
|
-
soldOut: boolean
|
|
60
|
-
actions: Pick<StorefrontActions, 'addToCart' | 'createProductEnquiry' | 'navigateTo'>
|
|
61
|
-
addToCart: () => void
|
|
62
|
-
openEnquiry: () => void
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface ProductEnquiryFormContractProps extends StorefrontComponentBaseProps {
|
|
66
|
-
product: Product
|
|
67
|
-
onSuccess?: () => void
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface CategoryCardProps extends StorefrontComponentBaseProps {
|
|
71
|
-
category: Category
|
|
72
|
-
actions: Pick<StorefrontActions, 'navigateTo'>
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface CollectionSectionProps extends StorefrontComponentBaseProps {
|
|
76
|
-
title: string
|
|
77
|
-
subtitle?: string
|
|
78
|
-
products: Product[]
|
|
79
|
-
category?: Category
|
|
80
|
-
children?: React.ReactNode
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export interface HeroSectionContractProps extends StorefrontComponentBaseProps {
|
|
84
|
-
title: string
|
|
85
|
-
subtitle?: string
|
|
86
|
-
eyebrow?: string
|
|
87
|
-
image?: string
|
|
88
|
-
cta?: string
|
|
89
|
-
href?: string
|
|
90
|
-
children?: React.ReactNode
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface MediaCarouselProps extends StorefrontComponentBaseProps {
|
|
94
|
-
items: MediaCarouselItem[]
|
|
95
|
-
height?: 'medium' | 'tall' | 'screen'
|
|
96
|
-
autoplayMs?: number
|
|
97
|
-
overlay?: 'dark' | 'soft' | 'none'
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface ProductSliderProps extends StorefrontComponentBaseProps {
|
|
101
|
-
title: string
|
|
102
|
-
subtitle?: string
|
|
103
|
-
eyebrow?: string
|
|
104
|
-
filter?: 'sale' | 'new' | 'all'
|
|
105
|
-
categoryName?: string
|
|
106
|
-
collection?: string
|
|
107
|
-
limit?: number
|
|
108
|
-
cta?: string
|
|
109
|
-
href?: string
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export interface StorefrontChromeProps extends StorefrontComponentBaseProps {
|
|
113
|
-
children?: React.ReactNode
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export interface StorefrontStateProps extends StorefrontComponentBaseProps {
|
|
117
|
-
title?: string
|
|
118
|
-
message?: string
|
|
119
|
-
children?: React.ReactNode
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Extra content rendered inside CartDrawer's footer, right after the
|
|
124
|
-
* "Finalizar compra" button — e.g. an alternative checkout path like
|
|
125
|
-
* "Finalizar via WhatsApp". Unlike every other entry in
|
|
126
|
-
* StorefrontComponents, this isn't a whole-component replacement:
|
|
127
|
-
* CartDrawer is always the SDK's own, this only adds optional content
|
|
128
|
-
* inside it. Only rendered when the cart has lines (same condition as the
|
|
129
|
-
* checkout button itself).
|
|
130
|
-
*/
|
|
131
|
-
export interface CartDrawerFooterExtraProps extends StorefrontComponentBaseProps {
|
|
132
|
-
cart: CartState
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export interface StorefrontComponents {
|
|
136
|
-
ProductCard?: React.ComponentType<ProductCardProps>
|
|
137
|
-
ProductDetail?: React.ComponentType<ProductDetailProps>
|
|
138
|
-
ProductGallery?: React.ComponentType<ProductGalleryProps>
|
|
139
|
-
ProductPrice?: React.ComponentType<ProductPriceProps>
|
|
140
|
-
ProductActions?: React.ComponentType<ProductActionsProps>
|
|
141
|
-
ProductEnquiryForm?: React.ComponentType<ProductEnquiryFormContractProps>
|
|
142
|
-
CategoryCard?: React.ComponentType<CategoryCardProps>
|
|
143
|
-
CollectionSection?: React.ComponentType<CollectionSectionProps>
|
|
144
|
-
HeroSection?: React.ComponentType<HeroSectionContractProps>
|
|
145
|
-
MediaCarousel?: React.ComponentType<MediaCarouselProps>
|
|
146
|
-
ProductSlider?: React.ComponentType<ProductSliderProps>
|
|
147
|
-
Header?: React.ComponentType<StorefrontChromeProps>
|
|
148
|
-
Footer?: React.ComponentType<StorefrontChromeProps>
|
|
149
|
-
Shell?: React.ComponentType<StorefrontChromeProps>
|
|
150
|
-
EmptyState?: React.ComponentType<StorefrontStateProps>
|
|
151
|
-
LoadingState?: React.ComponentType<StorefrontStateProps>
|
|
152
|
-
ErrorState?: React.ComponentType<StorefrontStateProps>
|
|
153
|
-
CartDrawerFooterExtra?: React.ComponentType<CartDrawerFooterExtraProps>
|
|
154
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { TID } from './testids'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Stable selectors that custom storefront components must preserve.
|
|
5
|
-
*
|
|
6
|
-
* Apps can fully customize the visual tree, but replacement components still
|
|
7
|
-
* need these anchors so smoke tests, QA, and agents can operate stores.
|
|
8
|
-
*/
|
|
9
|
-
export const productCardComponentContract = {
|
|
10
|
-
root: { 'data-testid': TID.productCard },
|
|
11
|
-
name: { 'data-testid': TID.productCardName },
|
|
12
|
-
priceTestId: TID.productCardPrice,
|
|
13
|
-
addButton: { 'data-testid': TID.productCardAdd },
|
|
14
|
-
} as const
|
|
15
|
-
|
|
16
|
-
export const storefrontComponentContracts = {
|
|
17
|
-
productCard: productCardComponentContract,
|
|
18
|
-
productDetail: {
|
|
19
|
-
root: { 'data-testid': TID.pdpRoot },
|
|
20
|
-
gallery: { 'data-testid': TID.pdpGallery },
|
|
21
|
-
name: { 'data-testid': TID.pdpName },
|
|
22
|
-
description: { 'data-testid': TID.pdpDescription },
|
|
23
|
-
actions: { 'data-testid': TID.pdpActions },
|
|
24
|
-
addButton: { 'data-testid': TID.pdpAddToCart },
|
|
25
|
-
enquiryButton: { 'data-testid': TID.pdpEnquiryButton },
|
|
26
|
-
enquiryForm: { 'data-testid': TID.enquiryForm },
|
|
27
|
-
},
|
|
28
|
-
} as const
|
|
29
|
-
|
|
30
|
-
export type ProductCardComponentContract = typeof productCardComponentContract
|
|
31
|
-
export type ProductDetailComponentContract = typeof storefrontComponentContracts.productDetail
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import { X, Trash2 } from 'lucide-react'
|
|
3
|
-
import {
|
|
4
|
-
useCartStore,
|
|
5
|
-
selectSubtotal,
|
|
6
|
-
selectDiscountTotal,
|
|
7
|
-
selectShipping,
|
|
8
|
-
selectTotal,
|
|
9
|
-
} from '../stores/cart.store'
|
|
10
|
-
import { useDiscountValidator } from '../hooks/useDiscountValidator'
|
|
11
|
-
import { toast } from '../stores/toast.store'
|
|
12
|
-
import { getStorefrontComponents, useStorefrontConfig } from '../config'
|
|
13
|
-
import { navigateTo } from '../router'
|
|
14
|
-
import { formatMoney } from '../format'
|
|
15
|
-
import { QuantityInput } from './QuantityInput'
|
|
16
|
-
import { formatPostalCode } from '@fayz-ai/core'
|
|
17
|
-
import { useDeliveryStore } from '../stores/delivery.store'
|
|
18
|
-
import { DeliveryEstimator } from './DeliveryEstimator'
|
|
19
|
-
import { TID } from '../testids'
|
|
20
|
-
import { SmoothImage } from './SmoothImage'
|
|
21
|
-
|
|
22
|
-
export function CartDrawer() {
|
|
23
|
-
const config = useStorefrontConfig()
|
|
24
|
-
const cart = useCartStore()
|
|
25
|
-
const components = getStorefrontComponents(config)
|
|
26
|
-
const FooterExtra = components.CartDrawerFooterExtra
|
|
27
|
-
const validate = useDiscountValidator()
|
|
28
|
-
const [code, setCode] = useState('')
|
|
29
|
-
const [discountError, setDiscountError] = useState<string | null>(null)
|
|
30
|
-
const [applying, setApplying] = useState(false)
|
|
31
|
-
|
|
32
|
-
// a11y: close on Escape while the drawer is open.
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
if (!cart.isOpen) return
|
|
35
|
-
const onKey = (e: KeyboardEvent) => {
|
|
36
|
-
if (e.key === 'Escape') cart.closeDrawer()
|
|
37
|
-
}
|
|
38
|
-
document.addEventListener('keydown', onKey)
|
|
39
|
-
return () => document.removeEventListener('keydown', onKey)
|
|
40
|
-
}, [cart.isOpen, cart.closeDrawer])
|
|
41
|
-
|
|
42
|
-
// Subscribed, not just read: selectShipping consults this store through
|
|
43
|
-
// getState(), which does not subscribe, so without this hook a fresh quote
|
|
44
|
-
// would change the price and leave the drawer showing the old one.
|
|
45
|
-
const delivery = useDeliveryStore()
|
|
46
|
-
|
|
47
|
-
const subtotal = selectSubtotal(cart)
|
|
48
|
-
const discountTotal = selectDiscountTotal(cart)
|
|
49
|
-
const shipping = selectShipping(cart, config)
|
|
50
|
-
|
|
51
|
-
const total = selectTotal(cart, config)
|
|
52
|
-
const money = (v: number) => formatMoney(v, config.currency, config.locale)
|
|
53
|
-
|
|
54
|
-
async function applyCode() {
|
|
55
|
-
setApplying(true)
|
|
56
|
-
setDiscountError(null)
|
|
57
|
-
try {
|
|
58
|
-
const result = await validate(code)
|
|
59
|
-
if (result.valid) {
|
|
60
|
-
const applied = code.trim().toUpperCase()
|
|
61
|
-
cart.applyDiscount(applied, result.percent)
|
|
62
|
-
setCode('')
|
|
63
|
-
toast.success('Cupom aplicado!', `${applied} • ${result.percent}% de desconto`)
|
|
64
|
-
} else {
|
|
65
|
-
setDiscountError(result.message ?? 'Cupom inválido.')
|
|
66
|
-
toast.error('Cupom inválido', result.message ?? 'Verifique o código e tente novamente.')
|
|
67
|
-
}
|
|
68
|
-
} finally {
|
|
69
|
-
setApplying(false)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (!cart.isOpen) return null
|
|
74
|
-
|
|
75
|
-
// Free-shipping nudge: how far from the threshold this cart is
|
|
76
|
-
const freeAbove = config.shipping.freeAbove
|
|
77
|
-
const missingForFree = freeAbove != null && subtotal < freeAbove ? freeAbove - subtotal : 0
|
|
78
|
-
const progress = freeAbove != null ? Math.min(100, (subtotal / freeAbove) * 100) : 0
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<div className="fixed inset-0 z-50">
|
|
82
|
-
<div
|
|
83
|
-
className="absolute inset-0 animate-fade-in bg-black/40"
|
|
84
|
-
aria-hidden
|
|
85
|
-
onClick={cart.closeDrawer}
|
|
86
|
-
/>
|
|
87
|
-
<div
|
|
88
|
-
data-testid={TID.cartDrawer}
|
|
89
|
-
role="dialog"
|
|
90
|
-
aria-label="Carrinho"
|
|
91
|
-
className="absolute right-0 top-0 flex h-full w-full max-w-md animate-slide-in-from-right flex-col bg-background shadow-2xl"
|
|
92
|
-
>
|
|
93
|
-
<div className="flex items-center justify-between border-b px-5 py-4">
|
|
94
|
-
<h2 className="text-lg font-semibold">Carrinho</h2>
|
|
95
|
-
<button
|
|
96
|
-
type="button"
|
|
97
|
-
aria-label="Fechar carrinho"
|
|
98
|
-
onClick={cart.closeDrawer}
|
|
99
|
-
className="rounded-full p-1.5 hover:bg-muted"
|
|
100
|
-
>
|
|
101
|
-
<X className="h-5 w-5" />
|
|
102
|
-
</button>
|
|
103
|
-
</div>
|
|
104
|
-
|
|
105
|
-
{cart.lines.length === 0 ? (
|
|
106
|
-
<div data-testid={TID.cartEmpty} className="flex flex-1 items-center justify-center p-8 text-center text-muted-foreground">
|
|
107
|
-
Seu carrinho está vazio.
|
|
108
|
-
</div>
|
|
109
|
-
) : (
|
|
110
|
-
<>
|
|
111
|
-
{freeAbove != null && (
|
|
112
|
-
<div data-testid={TID.shippingProgress} className="border-b bg-muted/40 px-5 py-3">
|
|
113
|
-
<p className="text-xs font-medium">
|
|
114
|
-
{missingForFree > 0 ? (
|
|
115
|
-
<>Faltam <strong>{money(missingForFree)}</strong> para frete grátis 🚚</>
|
|
116
|
-
) : (
|
|
117
|
-
<>🎉 Você ganhou <strong>frete grátis</strong>!</>
|
|
118
|
-
)}
|
|
119
|
-
</p>
|
|
120
|
-
<div className="mt-2 h-1.5 overflow-hidden rounded-full bg-border">
|
|
121
|
-
<div
|
|
122
|
-
className="h-full rounded-full bg-primary transition-all duration-500 ease-out"
|
|
123
|
-
style={{ width: `${progress}%` }}
|
|
124
|
-
/>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
)}
|
|
128
|
-
<div className="flex-1 space-y-4 overflow-y-auto px-5 py-4">
|
|
129
|
-
{cart.lines.map((line) => (
|
|
130
|
-
<div
|
|
131
|
-
key={line.lineId ?? line.productId}
|
|
132
|
-
data-testid={TID.cartLine}
|
|
133
|
-
data-product-id={line.productId}
|
|
134
|
-
data-line-id={line.lineId ?? line.productId}
|
|
135
|
-
className={`flex animate-fade-up gap-3 rounded-lg p-1.5 transition-all hover:bg-muted/40 ${
|
|
136
|
-
(line.lineId ?? line.productId) === cart.justAddedLineId
|
|
137
|
-
? 'bg-primary/5 ring-1 ring-primary/30'
|
|
138
|
-
: ''
|
|
139
|
-
}`}
|
|
140
|
-
>
|
|
141
|
-
{line.imageUrl && (
|
|
142
|
-
<SmoothImage src={line.imageUrl} alt={line.name} className="h-20 w-20 shrink-0 rounded-lg border object-cover" />
|
|
143
|
-
)}
|
|
144
|
-
<div className="flex flex-1 flex-col">
|
|
145
|
-
<div className="flex items-start justify-between gap-2">
|
|
146
|
-
<span className="text-sm font-medium leading-snug">{line.name}</span>
|
|
147
|
-
<button
|
|
148
|
-
type="button"
|
|
149
|
-
data-testid={TID.lineRemove}
|
|
150
|
-
aria-label={`Remover ${line.name}`}
|
|
151
|
-
onClick={() => cart.removeItem(line.lineId ?? line.productId)}
|
|
152
|
-
className="text-muted-foreground hover:text-destructive"
|
|
153
|
-
>
|
|
154
|
-
<Trash2 className="h-4 w-4" />
|
|
155
|
-
</button>
|
|
156
|
-
</div>
|
|
157
|
-
<span className="text-xs text-muted-foreground">{line.sku}</span>
|
|
158
|
-
{line.optionsLabel && (
|
|
159
|
-
<span className="text-xs text-muted-foreground">{line.optionsLabel}</span>
|
|
160
|
-
)}
|
|
161
|
-
<div className="mt-auto flex items-center justify-between pt-2">
|
|
162
|
-
<QuantityInput
|
|
163
|
-
value={line.quantity}
|
|
164
|
-
max={line.maxQuantity || undefined}
|
|
165
|
-
onChange={(n) => cart.setQuantity(line.lineId ?? line.productId, n)}
|
|
166
|
-
testId={TID.lineQty}
|
|
167
|
-
incTestId={TID.lineInc}
|
|
168
|
-
decTestId={TID.lineDec}
|
|
169
|
-
/>
|
|
170
|
-
<span
|
|
171
|
-
className="text-sm font-semibold"
|
|
172
|
-
data-price={(line.unitPrice * line.quantity).toFixed(2)}
|
|
173
|
-
>
|
|
174
|
-
{money(line.unitPrice * line.quantity)}
|
|
175
|
-
</span>
|
|
176
|
-
</div>
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
))}
|
|
180
|
-
</div>
|
|
181
|
-
|
|
182
|
-
<div className="space-y-3 border-t px-5 py-4">
|
|
183
|
-
{config.features.discounts && (
|
|
184
|
-
<div className="space-y-1">
|
|
185
|
-
<div className="flex gap-2">
|
|
186
|
-
<input
|
|
187
|
-
data-testid={TID.discountInput}
|
|
188
|
-
type="text"
|
|
189
|
-
placeholder="Cupom de desconto"
|
|
190
|
-
value={code}
|
|
191
|
-
onChange={(e) => setCode(e.target.value)}
|
|
192
|
-
className="flex-1 rounded-lg border bg-background px-3 py-2 text-sm uppercase"
|
|
193
|
-
/>
|
|
194
|
-
<button
|
|
195
|
-
type="button"
|
|
196
|
-
data-testid={TID.discountApply}
|
|
197
|
-
onClick={applyCode}
|
|
198
|
-
disabled={applying || !code.trim()}
|
|
199
|
-
className="rounded-lg border px-3 py-2 text-sm font-medium hover:bg-muted disabled:opacity-50"
|
|
200
|
-
>
|
|
201
|
-
Aplicar
|
|
202
|
-
</button>
|
|
203
|
-
</div>
|
|
204
|
-
{discountError && (
|
|
205
|
-
<p data-testid={TID.discountError} className="text-xs text-destructive">
|
|
206
|
-
{discountError}
|
|
207
|
-
</p>
|
|
208
|
-
)}
|
|
209
|
-
</div>
|
|
210
|
-
)}
|
|
211
|
-
|
|
212
|
-
{/* Second chance to give a CEP for anyone who added to cart from
|
|
213
|
-
the catalogue and never opened a product page. */}
|
|
214
|
-
<div className="mb-3">
|
|
215
|
-
<DeliveryEstimator compact />
|
|
216
|
-
</div>
|
|
217
|
-
|
|
218
|
-
<dl className="space-y-1.5 text-sm">
|
|
219
|
-
<div className="flex justify-between">
|
|
220
|
-
<dt className="text-muted-foreground">Subtotal</dt>
|
|
221
|
-
<dd data-testid={TID.cartSubtotal} data-price={subtotal.toFixed(2)}>{money(subtotal)}</dd>
|
|
222
|
-
</div>
|
|
223
|
-
{discountTotal > 0 && (
|
|
224
|
-
<div className="flex justify-between text-emerald-700" data-testid={TID.discountRow}>
|
|
225
|
-
<dt>
|
|
226
|
-
Desconto{' '}
|
|
227
|
-
<button
|
|
228
|
-
type="button"
|
|
229
|
-
onClick={cart.clearDiscount}
|
|
230
|
-
className="text-xs text-muted-foreground underline"
|
|
231
|
-
>
|
|
232
|
-
({cart.discountCode} ✕)
|
|
233
|
-
</button>
|
|
234
|
-
</dt>
|
|
235
|
-
<dd data-price={discountTotal.toFixed(2)}>−{money(discountTotal)}</dd>
|
|
236
|
-
</div>
|
|
237
|
-
)}
|
|
238
|
-
<div className="flex justify-between">
|
|
239
|
-
<dt className="text-muted-foreground">
|
|
240
|
-
Frete
|
|
241
|
-
{delivery.status === 'served' && delivery.postalCode && (
|
|
242
|
-
<span className="ml-1 text-xs">
|
|
243
|
-
· {formatPostalCode(delivery.postalCode)}
|
|
244
|
-
</span>
|
|
245
|
-
)}
|
|
246
|
-
</dt>
|
|
247
|
-
<dd data-testid={TID.cartShipping} data-price={shipping.toFixed(2)}>
|
|
248
|
-
{shipping === 0 ? 'Grátis' : money(shipping)}
|
|
249
|
-
</dd>
|
|
250
|
-
</div>
|
|
251
|
-
<div className="flex justify-between border-t pt-2 text-base font-semibold">
|
|
252
|
-
<dt>Total</dt>
|
|
253
|
-
<dd data-testid={TID.cartTotal} data-price={total.toFixed(2)}>{money(total)}</dd>
|
|
254
|
-
</div>
|
|
255
|
-
</dl>
|
|
256
|
-
|
|
257
|
-
<button
|
|
258
|
-
type="button"
|
|
259
|
-
data-testid={TID.goCheckout}
|
|
260
|
-
onClick={() => {
|
|
261
|
-
cart.closeDrawer()
|
|
262
|
-
navigateTo('/checkout')
|
|
263
|
-
}}
|
|
264
|
-
className="sf-cta w-full bg-primary py-3.5 font-semibold text-primary-foreground shadow-md transition-all hover:-translate-y-0.5 hover:shadow-lg"
|
|
265
|
-
style={{ borderRadius: 'var(--sf-radius-button)' }}
|
|
266
|
-
>
|
|
267
|
-
Finalizar compra
|
|
268
|
-
</button>
|
|
269
|
-
|
|
270
|
-
{FooterExtra && (
|
|
271
|
-
<FooterExtra cart={cart} config={config} commerceMode={config.commerceMode} />
|
|
272
|
-
)}
|
|
273
|
-
</div>
|
|
274
|
-
</>
|
|
275
|
-
)}
|
|
276
|
-
</div>
|
|
277
|
-
</div>
|
|
278
|
-
)
|
|
279
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { CreditCard, LogOut, MapPin, Package, ShieldCheck, User } from 'lucide-react'
|
|
3
|
-
import { signOutCustomer } from '../auth'
|
|
4
|
-
import { useStorefrontConfig } from '../config'
|
|
5
|
-
import { Link } from '../router'
|
|
6
|
-
import { useSessionStore } from '../stores/session.store'
|
|
7
|
-
import { TID } from '../testids'
|
|
8
|
-
|
|
9
|
-
export type AccountSection = 'profile' | 'orders' | 'addresses' | 'payments'
|
|
10
|
-
|
|
11
|
-
interface CustomerAccountShellProps {
|
|
12
|
-
title: string
|
|
13
|
-
subtitle?: string
|
|
14
|
-
active: AccountSection
|
|
15
|
-
/** Switch the active section in-place. */
|
|
16
|
-
onSelect?: (section: AccountSection) => void
|
|
17
|
-
children: React.ReactNode
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const menuItems = [
|
|
21
|
-
{ id: 'profile', label: 'Perfil', icon: User },
|
|
22
|
-
{ id: 'orders', label: 'Meus pedidos', icon: Package },
|
|
23
|
-
{ id: 'addresses', label: 'Endereços', icon: MapPin },
|
|
24
|
-
{ id: 'payments', label: 'Pagamentos', icon: CreditCard },
|
|
25
|
-
] as const
|
|
26
|
-
|
|
27
|
-
export function CustomerAccountShell({ title, subtitle, active, onSelect, children }: CustomerAccountShellProps) {
|
|
28
|
-
const config = useStorefrontConfig()
|
|
29
|
-
const session = useSessionStore()
|
|
30
|
-
const displayName = session.name || session.email?.split('@')[0] || 'Cliente'
|
|
31
|
-
const displayEmail = session.email || 'Conta criada no checkout'
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<main data-testid={TID.customerAccountShell} className="mx-auto max-w-6xl px-4 py-8 sm:px-6">
|
|
35
|
-
<div className="mb-6 flex flex-wrap items-center justify-between gap-4">
|
|
36
|
-
<div>
|
|
37
|
-
<p className="text-sm font-medium text-muted-foreground">{config.name}</p>
|
|
38
|
-
<h1 className="sf-heading text-3xl font-bold tracking-tight">{title}</h1>
|
|
39
|
-
{subtitle && <p className="mt-1 text-sm text-muted-foreground">{subtitle}</p>}
|
|
40
|
-
</div>
|
|
41
|
-
<Link to={config.catalogPath} className="rounded-lg border px-4 py-2 text-sm font-semibold hover:bg-muted">
|
|
42
|
-
Voltar à loja
|
|
43
|
-
</Link>
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
<div className="grid gap-6 lg:grid-cols-[260px_minmax(0,1fr)]">
|
|
47
|
-
<aside className="h-fit rounded-xl border bg-card p-4">
|
|
48
|
-
<div className="flex items-center gap-3 border-b pb-4">
|
|
49
|
-
<div className="flex h-11 w-11 items-center justify-center rounded-full bg-primary/10 font-bold text-primary">
|
|
50
|
-
{displayName.slice(0, 1).toUpperCase()}
|
|
51
|
-
</div>
|
|
52
|
-
<div className="min-w-0">
|
|
53
|
-
<p className="truncate font-semibold">{displayName}</p>
|
|
54
|
-
<p className="truncate text-xs text-muted-foreground">{displayEmail}</p>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
|
|
58
|
-
<nav data-testid={TID.customerAccountMenu} className="mt-4 space-y-1" aria-label="Área do cliente">
|
|
59
|
-
{menuItems.map((item) => {
|
|
60
|
-
const Icon = item.icon
|
|
61
|
-
const selected = item.id === active
|
|
62
|
-
return (
|
|
63
|
-
<button
|
|
64
|
-
key={item.id}
|
|
65
|
-
type="button"
|
|
66
|
-
aria-current={selected ? 'page' : undefined}
|
|
67
|
-
onClick={() => onSelect?.(item.id)}
|
|
68
|
-
className={`flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-left text-sm font-semibold transition ${
|
|
69
|
-
selected ? 'bg-primary/10 text-primary' : 'text-muted-foreground hover:bg-muted hover:text-foreground'
|
|
70
|
-
}`}
|
|
71
|
-
>
|
|
72
|
-
<Icon className="h-4 w-4" />
|
|
73
|
-
{item.label}
|
|
74
|
-
</button>
|
|
75
|
-
)
|
|
76
|
-
})}
|
|
77
|
-
</nav>
|
|
78
|
-
|
|
79
|
-
<div className="mt-4 rounded-lg bg-muted/40 p-3 text-xs text-muted-foreground">
|
|
80
|
-
<div className="flex items-center gap-2 font-semibold text-foreground">
|
|
81
|
-
<ShieldCheck className="h-4 w-4 text-primary" />
|
|
82
|
-
Conta protegida
|
|
83
|
-
</div>
|
|
84
|
-
<p className="mt-1">Pedidos, pagamentos e endereços ficam organizados para próximas compras.</p>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
|
-
<button
|
|
88
|
-
type="button"
|
|
89
|
-
data-testid={TID.signout}
|
|
90
|
-
onClick={() => void signOutCustomer()}
|
|
91
|
-
className="mt-4 flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-semibold text-muted-foreground transition hover:bg-muted hover:text-foreground"
|
|
92
|
-
>
|
|
93
|
-
<LogOut className="h-4 w-4" />
|
|
94
|
-
Sair
|
|
95
|
-
</button>
|
|
96
|
-
</aside>
|
|
97
|
-
|
|
98
|
-
<section className="min-w-0">{children}</section>
|
|
99
|
-
</div>
|
|
100
|
-
</main>
|
|
101
|
-
)
|
|
102
|
-
}
|