@akinon/projectzero 2.0.0-beta.2 → 2.0.0-beta.20
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/CHANGELOG.md +147 -6
- package/app-template/.env.example +8 -0
- package/app-template/.github/instructions/account.instructions.md +749 -0
- package/app-template/.github/instructions/checkout.instructions.md +678 -0
- package/app-template/.github/instructions/default.instructions.md +279 -0
- package/app-template/.github/instructions/edge-cases.instructions.md +73 -0
- package/app-template/.github/instructions/routing.instructions.md +603 -0
- package/app-template/.github/instructions/settings.instructions.md +338 -0
- package/app-template/.gitignore +5 -0
- package/app-template/AGENTS.md +7 -0
- package/app-template/CHANGELOG.md +1645 -61
- package/app-template/Procfile +1 -1
- package/app-template/README.md +6 -0
- package/app-template/akinon.json +1 -4
- package/app-template/build.sh +10 -0
- package/app-template/config/prebuild-tests.json +5 -0
- package/app-template/docs/advanced-usage.md +111 -0
- package/app-template/docs/plugins.md +60 -25
- package/app-template/docs/sentry-usage.md +35 -0
- package/app-template/jest.config.ts +2 -2
- package/app-template/next-env.d.ts +1 -0
- package/app-template/next.config.mjs +8 -5
- package/app-template/package.json +60 -50
- package/app-template/postcss.config.mjs +5 -0
- package/app-template/public/amex.svg +12 -0
- package/app-template/public/apple-pay.svg +16 -0
- package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
- package/app-template/public/google-pay.svg +16 -0
- package/app-template/public/locales/en/account.json +13 -4
- package/app-template/public/locales/en/auth.json +6 -7
- package/app-template/public/locales/en/basket.json +6 -6
- package/app-template/public/locales/en/blog.json +7 -0
- package/app-template/public/locales/en/category.json +3 -1
- package/app-template/public/locales/en/checkout.json +17 -4
- package/app-template/public/locales/en/common.json +71 -3
- package/app-template/public/locales/en/forgot_password.json +6 -7
- package/app-template/public/locales/en/product.json +84 -4
- package/app-template/public/locales/tr/account.json +13 -4
- package/app-template/public/locales/tr/auth.json +16 -17
- package/app-template/public/locales/tr/basket.json +4 -4
- package/app-template/public/locales/tr/blog.json +7 -0
- package/app-template/public/locales/tr/category.json +3 -1
- package/app-template/public/locales/tr/checkout.json +48 -36
- package/app-template/public/locales/tr/common.json +70 -2
- package/app-template/public/locales/tr/forgot_password.json +12 -13
- package/app-template/public/locales/tr/product.json +82 -0
- package/app-template/public/logo.svg +3 -27
- package/app-template/public/mastercard.svg +14 -0
- package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
- package/app-template/public/promotion-banner.jpg +0 -0
- package/app-template/public/shop-pay.svg +12 -0
- package/app-template/public/visa.svg +12 -0
- package/app-template/src/__tests__/middleware-matcher.test.ts +135 -0
- package/app-template/src/app/[commerce]/[locale]/[currency]/blog/[slug]/page.tsx +118 -0
- package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +15 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +9 -9
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +105 -13
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +136 -52
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
- package/app-template/src/app/[pz]/category/[pk]/page.tsx +27 -0
- package/app-template/src/app/[pz]/error.tsx +17 -0
- package/app-template/src/app/[pz]/flat-page/[pk]/page.tsx +23 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/forms/[pk]/generate/page.tsx +1 -2
- package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +93 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/page.tsx +2 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/layout.tsx +3 -10
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/page.tsx +2 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency]/pz-not-found/page.tsx → [pz]/not-found.tsx} +5 -7
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +7 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
- package/app-template/src/app/[pz]/product/[pk]/page.tsx +102 -0
- package/app-template/src/app/[pz]/special-page/[pk]/page.tsx +35 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/email-set-primary/[[...id]]/page.tsx +3 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/registration/account-confirm-email/[[...id]]/page.tsx +3 -3
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/reset/[[...id]]/page.tsx +41 -5
- package/app-template/src/app/[pz]/xml-sitemap/[node]/route.ts +73 -0
- package/app-template/src/app/api/auth/[...nextauth]/route.ts +3 -0
- package/app-template/src/app/api/barcode-search/route.ts +1 -0
- package/app-template/src/app/api/form/[...id]/route.ts +1 -7
- package/app-template/src/app/api/image-proxy/route.ts +1 -0
- package/app-template/src/app/api/product-categories/route.ts +1 -0
- package/app-template/src/app/api/similar-product-list/route.ts +1 -0
- package/app-template/src/app/api/similar-products/route.ts +1 -0
- package/app-template/src/app/api/theme-settings/route.ts +12 -0
- package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
- package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
- package/app-template/src/assets/fonts/pz-icon.css +211 -49
- package/app-template/src/assets/fonts/pz-icon.eot +0 -0
- package/app-template/src/assets/fonts/pz-icon.html +486 -0
- package/app-template/src/assets/fonts/pz-icon.scss +373 -49
- package/app-template/src/assets/fonts/pz-icon.svg +215 -53
- package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
- package/app-template/src/assets/fonts/pz-icon.woff +0 -0
- package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
- package/app-template/src/assets/globals.scss +37 -34
- package/app-template/src/assets/icons/arrow-right.svg +3 -0
- package/app-template/src/assets/icons/cart.svg +4 -12
- package/app-template/src/assets/icons/check.svg +2 -18
- package/app-template/src/assets/icons/chevron-down.svg +2 -7
- package/app-template/src/assets/icons/delete.svg +3 -0
- package/app-template/src/assets/icons/facebook.svg +2 -8
- package/app-template/src/assets/icons/fav-off.svg +5 -0
- package/app-template/src/assets/icons/fav-on.svg +5 -0
- package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
- package/app-template/src/assets/icons/heart.svg +3 -0
- package/app-template/src/assets/icons/instagram.svg +2 -13
- package/app-template/src/assets/icons/materials.svg +3 -0
- package/app-template/src/assets/icons/person.svg +4 -0
- package/app-template/src/assets/icons/pinterest.svg +5 -11
- package/app-template/src/assets/icons/ruler.svg +3 -0
- package/app-template/src/assets/icons/search.svg +8 -11
- package/app-template/src/assets/icons/share.svg +2 -9
- package/app-template/src/assets/icons/snapchat.svg +3 -0
- package/app-template/src/assets/icons/tiktok.svg +3 -0
- package/app-template/src/assets/icons/tumblr.svg +6 -0
- package/app-template/src/assets/icons/twitter.svg +2 -10
- package/app-template/src/assets/icons/vimeo.svg +3 -0
- package/app-template/src/assets/icons/youtube.svg +3 -0
- package/app-template/src/assets/icons/zoom.svg +8 -0
- package/app-template/src/auth.ts +3 -0
- package/app-template/src/components/__tests__/link.test.tsx +2 -0
- package/app-template/src/components/accordion.tsx +48 -23
- package/app-template/src/components/action-tooltip.tsx +160 -0
- package/app-template/src/components/button.tsx +50 -35
- package/app-template/src/components/carousel-core.tsx +4 -11
- package/app-template/src/components/checkbox.tsx +2 -1
- package/app-template/src/components/currency-select.tsx +150 -4
- package/app-template/src/components/file-input.tsx +64 -2
- package/app-template/src/components/generate-form-fields.tsx +49 -10
- package/app-template/src/components/icon.tsx +5 -6
- package/app-template/src/components/index.ts +4 -1
- package/app-template/src/components/input.tsx +8 -2
- package/app-template/src/components/language-select.tsx +88 -2
- package/app-template/src/components/modal.tsx +34 -16
- package/app-template/src/components/pagination.tsx +133 -20
- package/app-template/src/components/price.tsx +1 -1
- package/app-template/src/components/pwa-tags.tsx +1 -0
- package/app-template/src/components/quantity-input.tsx +63 -0
- package/app-template/src/components/quantity-selector.tsx +203 -0
- package/app-template/src/components/route-handler.tsx +50 -0
- package/app-template/src/components/select.tsx +86 -54
- package/app-template/src/components/tabs.tsx +2 -2
- package/app-template/src/components/types/index.ts +55 -2
- package/app-template/src/components/widget-content.tsx +323 -0
- package/app-template/src/data/server/theme.ts +70 -0
- package/app-template/src/hooks/use-fav-button.tsx +9 -10
- package/app-template/src/hooks/use-product-cart.ts +80 -0
- package/app-template/src/hooks/use-stock-alert.ts +74 -0
- package/app-template/src/hooks/use-theme-settings.ts +42 -0
- package/app-template/src/lib/fonts.ts +149 -0
- package/app-template/src/middleware.ts +1 -0
- package/app-template/src/plugins.js +13 -2
- package/app-template/src/redux/middlewares/category.ts +6 -5
- package/app-template/src/redux/reducers/category.ts +1 -1
- package/app-template/src/redux/store.ts +21 -1
- package/app-template/src/routes/index.ts +2 -1
- package/app-template/src/settings.js +5 -3
- package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
- package/app-template/src/types/index.ts +74 -3
- package/app-template/src/types/next-auth.d.ts +2 -2
- package/app-template/src/types/widget.ts +169 -0
- package/app-template/src/utils/convert-facet-search-params.ts +1 -1
- package/app-template/src/utils/formatDate.ts +48 -0
- package/app-template/src/utils/styles.ts +71 -0
- package/app-template/src/utils/variant-validation.ts +41 -0
- package/app-template/src/views/account/address-form.tsx +8 -4
- package/app-template/src/views/account/contact-form.tsx +148 -136
- package/app-template/src/views/account/content-header.tsx +2 -2
- package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
- package/app-template/src/views/account/favorite-item.tsx +1 -1
- package/app-template/src/views/account/order.tsx +10 -8
- package/app-template/src/views/account/orders/order-cancellation-item.tsx +4 -3
- package/app-template/src/views/account/orders/order-detail-header.tsx +1 -1
- package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +44 -37
- package/app-template/src/views/basket/basket-item.tsx +697 -107
- package/app-template/src/views/basket/basket-summary-context.tsx +560 -0
- package/app-template/src/views/basket/designer-context.tsx +617 -0
- package/app-template/src/views/basket/index.ts +2 -0
- package/app-template/src/views/basket/summary.tsx +497 -60
- package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +190 -0
- package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +286 -0
- package/app-template/src/views/breadcrumb/constants.ts +15 -0
- package/app-template/src/views/breadcrumb/index.tsx +127 -0
- package/app-template/src/views/breadcrumb.tsx +13 -38
- package/app-template/src/views/category/category-active-filters.tsx +1 -1
- package/app-template/src/views/category/category-banner.tsx +4 -23
- package/app-template/src/views/category/category-header.tsx +289 -60
- package/app-template/src/views/category/category-info.tsx +177 -27
- package/app-template/src/views/category/filters/filter-item.tsx +138 -42
- package/app-template/src/views/category/filters/index.tsx +209 -49
- package/app-template/src/views/category/layout.tsx +7 -4
- package/app-template/src/views/category/native-widget-context.tsx +257 -0
- package/app-template/src/views/category/product-list-registrar.tsx +665 -0
- package/app-template/src/views/checkout/auth.tsx +64 -40
- package/app-template/src/views/checkout/checkout-address-registrar.tsx +254 -0
- package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +183 -0
- package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +259 -0
- package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +253 -0
- package/app-template/src/views/checkout/checkout-summary-registrar.tsx +183 -0
- package/app-template/src/views/checkout/constants.ts +5 -0
- package/app-template/src/views/checkout/index.tsx +5 -0
- package/app-template/src/views/checkout/layout/header.tsx +9 -5
- package/app-template/src/views/checkout/steps/payment/index.tsx +5 -2
- package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +93 -6
- package/app-template/src/views/checkout/steps/payment/options/funds-transfer.tsx +25 -5
- package/app-template/src/views/checkout/steps/payment/options/loyalty.tsx +21 -2
- package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +15 -0
- package/app-template/src/views/checkout/steps/payment/options/redirection.tsx +27 -5
- package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +18 -0
- package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +464 -0
- package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +171 -40
- package/app-template/src/views/checkout/steps/shipping/address-box.tsx +104 -29
- package/app-template/src/views/checkout/steps/shipping/addresses.tsx +129 -46
- package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +232 -27
- package/app-template/src/views/checkout/summary.tsx +310 -26
- package/app-template/src/views/find-in-store/index.tsx +2 -2
- package/app-template/src/views/footer/footer-app-banner-context.tsx +326 -0
- package/app-template/src/views/footer/footer-bottom-context.tsx +215 -0
- package/app-template/src/views/footer/footer-bottom-wrapper.tsx +74 -0
- package/app-template/src/views/footer/footer-layout-constants.ts +35 -0
- package/app-template/src/views/footer/footer-layout-registrar.tsx +342 -0
- package/app-template/src/views/footer/footer-layout-switcher.tsx +110 -0
- package/app-template/src/views/footer/footer-menu-context.tsx +211 -0
- package/app-template/src/views/footer/footer-native-widgets.tsx +60 -0
- package/app-template/src/views/footer/footer-social-context.tsx +254 -0
- package/app-template/src/views/footer/footer-subscription-context.tsx +210 -0
- package/app-template/src/views/footer/footer-utils.ts +43 -0
- package/app-template/src/views/footer/footer-value-props-context.tsx +326 -0
- package/app-template/src/views/footer/logo-settings.ts +183 -0
- package/app-template/src/views/footer/native-widget-config.ts +262 -0
- package/app-template/src/views/footer/subscription-settings.ts +122 -0
- package/app-template/src/views/footer/use-footer-logo.ts +162 -0
- package/app-template/src/views/footer.tsx +415 -13
- package/app-template/src/views/guest-login/index.tsx +62 -58
- package/app-template/src/views/header/action-menu.tsx +284 -49
- package/app-template/src/views/header/band.tsx +6 -21
- package/app-template/src/views/header/designer-context.tsx +261 -0
- package/app-template/src/views/header/header-announcement-registrar.tsx +267 -0
- package/app-template/src/views/header/header-client-wrapper.tsx +496 -0
- package/app-template/src/views/header/header-content.tsx +1026 -0
- package/app-template/src/views/header/header-currency-registrar.tsx +348 -0
- package/app-template/src/views/header/header-icons-context.tsx +262 -0
- package/app-template/src/views/header/header-language-registrar.tsx +348 -0
- package/app-template/src/views/header/header-layout-context.tsx +143 -0
- package/app-template/src/views/header/header-layout-registrar.tsx +658 -0
- package/app-template/src/views/header/header-logo-context.tsx +228 -0
- package/app-template/src/views/header/header-logo.tsx +118 -0
- package/app-template/src/views/header/header-mini-basket-context.tsx +524 -0
- package/app-template/src/views/header/header-search-registrar.tsx +511 -0
- package/app-template/src/views/header/header-text-slider-registrar.tsx +382 -0
- package/app-template/src/views/header/index.tsx +110 -48
- package/app-template/src/views/header/inline-search.tsx +262 -0
- package/app-template/src/views/header/mini-basket.tsx +832 -46
- package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
- package/app-template/src/views/header/mobile-menu.tsx +12 -0
- package/app-template/src/views/header/navbar-menu-context.tsx +219 -0
- package/app-template/src/views/header/navbar.tsx +178 -111
- package/app-template/src/views/header/search/index.tsx +85 -24
- package/app-template/src/views/header/search/results.tsx +127 -65
- package/app-template/src/views/header/search/search-input.tsx +61 -0
- package/app-template/src/views/header/server-settings-parser.ts +1105 -0
- package/app-template/src/views/header/use-header-icons.ts +241 -0
- package/app-template/src/views/header/use-header-logo.ts +213 -0
- package/app-template/src/views/header/use-navbar-menu.ts +179 -0
- package/app-template/src/views/installment-options/index.tsx +1 -1
- package/app-template/src/views/login/index.tsx +89 -56
- package/app-template/src/views/otp-login/index.tsx +23 -20
- package/app-template/src/views/product/accordion-section.tsx +61 -0
- package/app-template/src/views/product/accordion-wrapper.tsx +135 -43
- package/app-template/src/views/product/custom-button-group.tsx +69 -0
- package/app-template/src/views/product/favorites-button-section.tsx +69 -0
- package/app-template/src/views/product/find-in-store-section.tsx +60 -0
- package/app-template/src/views/product/index.ts +1 -0
- package/app-template/src/views/product/layout.tsx +21 -6
- package/app-template/src/views/product/misc-buttons.tsx +339 -25
- package/app-template/src/views/product/price-wrapper.tsx +3 -24
- package/app-template/src/views/product/product-actions.tsx +294 -0
- package/app-template/src/views/product/product-info-section.tsx +140 -0
- package/app-template/src/views/product/product-info.tsx +130 -254
- package/app-template/src/views/product/product-share.tsx +61 -0
- package/app-template/src/views/product/product-variants.tsx +26 -0
- package/app-template/src/views/product/quantity-section.tsx +73 -0
- package/app-template/src/views/product/sale-tag.tsx +10 -0
- package/app-template/src/views/product/share-section.tsx +357 -0
- package/app-template/src/views/product/slider.tsx +135 -76
- package/app-template/src/views/product/variant.tsx +69 -41
- package/app-template/src/views/product/variants-section.tsx +126 -0
- package/app-template/src/views/product-detail/constants.ts +272 -0
- package/app-template/src/views/product-detail/index.ts +10 -0
- package/app-template/src/views/product-detail/product-detail-registrar.tsx +616 -0
- package/app-template/src/views/product-item/index.tsx +119 -46
- package/app-template/src/views/register/index.tsx +54 -44
- package/app-template/src/views/share/index.tsx +9 -6
- package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
- package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
- package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
- package/app-template/src/widgets/footer-app-banner.tsx +444 -0
- package/app-template/src/widgets/footer-bottom.tsx +127 -0
- package/app-template/src/widgets/footer-menu-compact.tsx +238 -0
- package/app-template/src/widgets/footer-menu-two.tsx +298 -0
- package/app-template/src/widgets/footer-menu.tsx +6 -2
- package/app-template/src/widgets/footer-social-client.tsx +251 -0
- package/app-template/src/widgets/footer-social.tsx +47 -16
- package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
- package/app-template/src/widgets/footer-subscription/index.tsx +183 -17
- package/app-template/src/widgets/footer-value-props.tsx +201 -0
- package/app-template/src/widgets/home-stories-eng.tsx +42 -34
- package/app-template/src/widgets/index.ts +7 -0
- package/app-template/src/widgets/schemas/about-us.json +46 -0
- package/app-template/src/widgets/schemas/blog-list.json +37 -0
- package/app-template/src/widgets/schemas/blog.json +29 -0
- package/app-template/tailwind.config.js +19 -7
- package/app-template/tsconfig.json +29 -11
- package/codemods/migrate-segments/index.js +591 -0
- package/codemods/sentry-9/index.js +30 -0
- package/codemods/sentry-9/remove-sentry-configs.js +14 -0
- package/codemods/sentry-9/remove-sentry-dependency.js +25 -0
- package/codemods/sentry-9/replace-error-page.js +32 -0
- package/codemods/update-tailwind-config/index.js +30 -0
- package/codemods/update-tailwind-config/transform.js +102 -0
- package/commands/codemod.ts +17 -0
- package/commands/index.ts +3 -1
- package/commands/plugins.ts +115 -46
- package/dist/codemods/sentry-9/templates/error.js +14 -0
- package/dist/commands/codemod.js +15 -0
- package/dist/commands/index.js +3 -1
- package/dist/commands/plugins.js +85 -34
- package/package.json +3 -2
- package/app-template/postcss.config.js +0 -6
- package/app-template/sentry.client.config.ts +0 -16
- package/app-template/sentry.edge.config.ts +0 -3
- package/app-template/sentry.properties +0 -4
- package/app-template/sentry.server.config.ts +0 -3
- package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
- package/app-template/src/app/[commerce]/[locale]/[currency]/error.tsx +0 -20
- package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
- package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
- package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/loading.tsx +0 -67
- package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
- package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
- package/app-template/src/app/[commerce]/[locale]/[currency]/xml-sitemap/[node]/route.ts +0 -25
- package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checkout Delivery Method Section Registrar
|
|
5
|
+
*
|
|
6
|
+
* This component registers the "Delivery Method" section for the checkout placeholder.
|
|
7
|
+
* It provides the current view type and styles to child components via context.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
createContext,
|
|
12
|
+
useContext,
|
|
13
|
+
useEffect,
|
|
14
|
+
useRef,
|
|
15
|
+
useState,
|
|
16
|
+
ReactNode
|
|
17
|
+
} from 'react';
|
|
18
|
+
|
|
19
|
+
// Constants
|
|
20
|
+
export const CHECKOUT_PLACEHOLDER_ID = 'checkout-page';
|
|
21
|
+
export const CHECKOUT_DELIVERY_METHOD_SECTION_ID = 'checkout-delivery-method';
|
|
22
|
+
|
|
23
|
+
// View types
|
|
24
|
+
export type DeliveryMethodViewType = 'radio' | 'dropdown';
|
|
25
|
+
|
|
26
|
+
// Global flag to track if registration has been done (survives component remount)
|
|
27
|
+
declare global {
|
|
28
|
+
interface Window {
|
|
29
|
+
__checkoutDeliveryMethodRegistered?: boolean;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if running inside designer iframe
|
|
35
|
+
*/
|
|
36
|
+
function isInDesignerMode(): boolean {
|
|
37
|
+
if (typeof window === 'undefined') return false;
|
|
38
|
+
return window.self !== window.top;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CheckoutDeliveryMethodProperties {
|
|
42
|
+
viewType?: DeliveryMethodViewType | Record<string, string>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface CheckoutDeliveryMethodStyles {
|
|
46
|
+
[key: string]: string | number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Context for sharing view type with other components
|
|
50
|
+
interface CheckoutDeliveryMethodContextValue {
|
|
51
|
+
viewType: DeliveryMethodViewType;
|
|
52
|
+
isDesigner: boolean;
|
|
53
|
+
sectionStyles: CheckoutDeliveryMethodStyles;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const CheckoutDeliveryMethodContext =
|
|
57
|
+
createContext<CheckoutDeliveryMethodContextValue>({
|
|
58
|
+
viewType: 'radio',
|
|
59
|
+
isDesigner: false,
|
|
60
|
+
sectionStyles: {}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export const useCheckoutDeliveryMethod = () =>
|
|
64
|
+
useContext(CheckoutDeliveryMethodContext);
|
|
65
|
+
|
|
66
|
+
interface CheckoutDeliveryMethodRegistrarProps {
|
|
67
|
+
children?: ReactNode;
|
|
68
|
+
initialViewType?: DeliveryMethodViewType;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function CheckoutDeliveryMethodRegistrar({
|
|
72
|
+
children,
|
|
73
|
+
initialViewType = 'radio'
|
|
74
|
+
}: CheckoutDeliveryMethodRegistrarProps) {
|
|
75
|
+
const isDesignerRef = useRef(false);
|
|
76
|
+
|
|
77
|
+
const [sectionProperties, setSectionProperties] =
|
|
78
|
+
useState<CheckoutDeliveryMethodProperties>({
|
|
79
|
+
viewType: initialViewType
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const [sectionStyles, setSectionStyles] =
|
|
83
|
+
useState<CheckoutDeliveryMethodStyles>({});
|
|
84
|
+
|
|
85
|
+
const [isSectionSelected, setIsSectionSelected] = useState(false);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
isDesignerRef.current = isInDesignerMode();
|
|
89
|
+
}, []);
|
|
90
|
+
|
|
91
|
+
const isDesigner = isDesignerRef.current;
|
|
92
|
+
|
|
93
|
+
// Register native widget with Theme Editor
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
const isInIframe =
|
|
96
|
+
typeof window !== 'undefined' && window.self !== window.top;
|
|
97
|
+
if (!isInIframe || !window.parent) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// If already registered, skip
|
|
102
|
+
if (
|
|
103
|
+
typeof window !== 'undefined' &&
|
|
104
|
+
window.__checkoutDeliveryMethodRegistered
|
|
105
|
+
) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const nativeWidgetConfig = {
|
|
110
|
+
placeholderId: CHECKOUT_PLACEHOLDER_ID,
|
|
111
|
+
section: {
|
|
112
|
+
id: CHECKOUT_DELIVERY_METHOD_SECTION_ID,
|
|
113
|
+
type: 'native',
|
|
114
|
+
label: 'Delivery Method',
|
|
115
|
+
blocks: []
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
window.parent.postMessage(
|
|
120
|
+
{
|
|
121
|
+
type: 'REGISTER_NATIVE_WIDGETS',
|
|
122
|
+
data: { widgets: [nativeWidgetConfig] }
|
|
123
|
+
},
|
|
124
|
+
'*'
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
window.__checkoutDeliveryMethodRegistered = true;
|
|
128
|
+
}, []);
|
|
129
|
+
|
|
130
|
+
// Listen for theme updates and selection changes from Theme Editor
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
if (typeof window === 'undefined') return;
|
|
133
|
+
|
|
134
|
+
const handleMessage = (event: MessageEvent) => {
|
|
135
|
+
const { type, data } = event.data || {};
|
|
136
|
+
|
|
137
|
+
// Handle theme updates
|
|
138
|
+
if (
|
|
139
|
+
(type === 'UPDATE_THEME' || type === 'LOAD_THEME') &&
|
|
140
|
+
data?.theme?.placeholders
|
|
141
|
+
) {
|
|
142
|
+
const placeholder = data.theme.placeholders?.find(
|
|
143
|
+
(p: { slug: string }) => p.slug === CHECKOUT_PLACEHOLDER_ID
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const section = placeholder?.sections?.find(
|
|
147
|
+
(s: { id: string }) => s.id === CHECKOUT_DELIVERY_METHOD_SECTION_ID
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
if (section) {
|
|
151
|
+
if (section.properties) {
|
|
152
|
+
setSectionProperties(section.properties);
|
|
153
|
+
}
|
|
154
|
+
if (section.styles) {
|
|
155
|
+
// Flatten responsive styles to current breakpoint (desktop by default)
|
|
156
|
+
const flatStyles: CheckoutDeliveryMethodStyles = {};
|
|
157
|
+
Object.entries(section.styles).forEach(([key, value]) => {
|
|
158
|
+
if (typeof value === 'object' && value !== null) {
|
|
159
|
+
const responsiveValue = value as Record<
|
|
160
|
+
string,
|
|
161
|
+
string | number
|
|
162
|
+
>;
|
|
163
|
+
flatStyles[key] =
|
|
164
|
+
responsiveValue.desktop ||
|
|
165
|
+
responsiveValue.mobile ||
|
|
166
|
+
responsiveValue.tablet ||
|
|
167
|
+
Object.values(responsiveValue)[0] ||
|
|
168
|
+
'';
|
|
169
|
+
} else if (
|
|
170
|
+
typeof value === 'string' ||
|
|
171
|
+
typeof value === 'number'
|
|
172
|
+
) {
|
|
173
|
+
flatStyles[key] = value;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
setSectionStyles(flatStyles);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Handle property updates
|
|
182
|
+
if (type === 'UPDATE_SECTION_PROPERTY' || type === 'UPDATE_PROPERTY') {
|
|
183
|
+
const { sectionId, placeholderId, key, value, properties } = data || {};
|
|
184
|
+
|
|
185
|
+
if (
|
|
186
|
+
sectionId === CHECKOUT_DELIVERY_METHOD_SECTION_ID ||
|
|
187
|
+
placeholderId === CHECKOUT_PLACEHOLDER_ID
|
|
188
|
+
) {
|
|
189
|
+
if (key && value !== undefined) {
|
|
190
|
+
setSectionProperties((prev) => ({
|
|
191
|
+
...prev,
|
|
192
|
+
[key]: value
|
|
193
|
+
}));
|
|
194
|
+
}
|
|
195
|
+
if (properties) {
|
|
196
|
+
setSectionProperties(properties);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Handle selection
|
|
202
|
+
if (type === 'SELECT_SECTION') {
|
|
203
|
+
const { placeholderId, sectionId } = data || {};
|
|
204
|
+
setIsSectionSelected(
|
|
205
|
+
placeholderId === CHECKOUT_PLACEHOLDER_ID &&
|
|
206
|
+
sectionId === CHECKOUT_DELIVERY_METHOD_SECTION_ID
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (type === 'DESELECT' || type === 'CLEAR_SELECTION') {
|
|
211
|
+
setIsSectionSelected(false);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
window.addEventListener('message', handleMessage);
|
|
216
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
217
|
+
}, []);
|
|
218
|
+
|
|
219
|
+
// Extraction helper
|
|
220
|
+
const extractViewType = (prop: unknown): DeliveryMethodViewType => {
|
|
221
|
+
if (!prop) return 'radio';
|
|
222
|
+
|
|
223
|
+
if (typeof prop === 'string') {
|
|
224
|
+
return prop as DeliveryMethodViewType;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (typeof prop === 'object' && prop !== null) {
|
|
228
|
+
const obj = prop as Record<string, string>;
|
|
229
|
+
return (obj.desktop ||
|
|
230
|
+
obj.mobile ||
|
|
231
|
+
Object.values(obj)[0] ||
|
|
232
|
+
'radio') as DeliveryMethodViewType;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return 'radio';
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const currentViewType = extractViewType(sectionProperties.viewType);
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<CheckoutDeliveryMethodContext.Provider
|
|
242
|
+
value={{
|
|
243
|
+
viewType: currentViewType,
|
|
244
|
+
isDesigner,
|
|
245
|
+
sectionStyles
|
|
246
|
+
}}
|
|
247
|
+
>
|
|
248
|
+
<div
|
|
249
|
+
style={
|
|
250
|
+
isSectionSelected
|
|
251
|
+
? { outline: '2px solid #3b82f6', outlineOffset: '2px' }
|
|
252
|
+
: undefined
|
|
253
|
+
}
|
|
254
|
+
>
|
|
255
|
+
{children}
|
|
256
|
+
</div>
|
|
257
|
+
</CheckoutDeliveryMethodContext.Provider>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checkout Payment Options Section Registrar
|
|
5
|
+
*
|
|
6
|
+
* This component registers the "Payment Options" section for the checkout placeholder.
|
|
7
|
+
* It provides view type and styles to child components via context.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
createContext,
|
|
12
|
+
useContext,
|
|
13
|
+
useEffect,
|
|
14
|
+
useState,
|
|
15
|
+
ReactNode
|
|
16
|
+
} from 'react';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
CHECKOUT_PLACEHOLDER_ID,
|
|
20
|
+
CHECKOUT_PAYMENT_OPTIONS_SECTION_ID
|
|
21
|
+
} from './constants';
|
|
22
|
+
|
|
23
|
+
// Global flag to track if registration has been done (survives component remount)
|
|
24
|
+
declare global {
|
|
25
|
+
interface Window {
|
|
26
|
+
__checkoutPaymentOptionsRegistered?: boolean;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if running inside designer iframe
|
|
32
|
+
*/
|
|
33
|
+
function isInDesignerMode(): boolean {
|
|
34
|
+
if (typeof window === 'undefined') return false;
|
|
35
|
+
return window.self !== window.top;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface CheckoutPaymentOptionsStyles {
|
|
39
|
+
[key: string]: string | number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Context for sharing view type and styles with other components
|
|
43
|
+
interface CheckoutPaymentOptionsContextValue {
|
|
44
|
+
isDesigner: boolean;
|
|
45
|
+
viewType: 'tab' | 'dropdown';
|
|
46
|
+
sectionStyles: CheckoutPaymentOptionsStyles;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const CheckoutPaymentOptionsContext =
|
|
50
|
+
createContext<CheckoutPaymentOptionsContextValue>({
|
|
51
|
+
isDesigner: false,
|
|
52
|
+
viewType: 'tab',
|
|
53
|
+
sectionStyles: {}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export const useCheckoutPaymentOptions = () =>
|
|
57
|
+
useContext(CheckoutPaymentOptionsContext);
|
|
58
|
+
|
|
59
|
+
interface CheckoutPaymentOptionsRegistrarProps {
|
|
60
|
+
children?: ReactNode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function CheckoutPaymentOptionsRegistrar({
|
|
64
|
+
children
|
|
65
|
+
}: CheckoutPaymentOptionsRegistrarProps) {
|
|
66
|
+
const [isDesigner, setIsDesigner] = useState(() => {
|
|
67
|
+
// Initialize from function to avoid recalculation
|
|
68
|
+
if (typeof window === 'undefined') return false;
|
|
69
|
+
return window.self !== window.top;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const [viewType, setViewType] = useState<'tab' | 'dropdown'>(() => {
|
|
73
|
+
// Try to get from localStorage first (for persistence)
|
|
74
|
+
if (typeof window !== 'undefined') {
|
|
75
|
+
const saved = localStorage.getItem('checkout-payment-view-type');
|
|
76
|
+
if (saved === 'tab' || saved === 'dropdown') return saved;
|
|
77
|
+
}
|
|
78
|
+
return 'tab';
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const [sectionStyles, setSectionStyles] =
|
|
82
|
+
useState<CheckoutPaymentOptionsStyles>({});
|
|
83
|
+
const [isSectionSelected, setIsSectionSelected] = useState(false);
|
|
84
|
+
|
|
85
|
+
// No longer need this useEffect for isDesigner
|
|
86
|
+
// useEffect(() => {
|
|
87
|
+
// setIsDesigner(isInDesignerMode());
|
|
88
|
+
// }, []);
|
|
89
|
+
|
|
90
|
+
// Register native widget with Theme Editor
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const isInIframe =
|
|
93
|
+
typeof window !== 'undefined' && window.self !== window.top;
|
|
94
|
+
if (!isInIframe || !window.parent) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// If already registered, skip
|
|
99
|
+
if (
|
|
100
|
+
typeof window !== 'undefined' &&
|
|
101
|
+
window.__checkoutPaymentOptionsRegistered
|
|
102
|
+
) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const nativeWidgetConfig = {
|
|
107
|
+
placeholderId: CHECKOUT_PLACEHOLDER_ID,
|
|
108
|
+
section: {
|
|
109
|
+
id: CHECKOUT_PAYMENT_OPTIONS_SECTION_ID,
|
|
110
|
+
type: 'native',
|
|
111
|
+
label: 'Payment Options',
|
|
112
|
+
blocks: []
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
window.parent.postMessage(
|
|
117
|
+
{
|
|
118
|
+
type: 'REGISTER_NATIVE_WIDGETS',
|
|
119
|
+
data: { widgets: [nativeWidgetConfig] }
|
|
120
|
+
},
|
|
121
|
+
'*'
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
window.__checkoutPaymentOptionsRegistered = true;
|
|
125
|
+
}, []);
|
|
126
|
+
|
|
127
|
+
// Listen for theme updates and selection changes from Theme Editor
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (typeof window === 'undefined') return;
|
|
130
|
+
|
|
131
|
+
const handleMessage = (event: MessageEvent) => {
|
|
132
|
+
const { type, data } = event.data || {};
|
|
133
|
+
|
|
134
|
+
// Handle theme updates
|
|
135
|
+
if (
|
|
136
|
+
(type === 'UPDATE_THEME' || type === 'LOAD_THEME') &&
|
|
137
|
+
data?.theme?.placeholders
|
|
138
|
+
) {
|
|
139
|
+
const placeholder = data.theme.placeholders?.find(
|
|
140
|
+
(p: { slug: string }) => p.slug === CHECKOUT_PLACEHOLDER_ID
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const section = placeholder?.sections?.find(
|
|
144
|
+
(s: { id: string }) => s.id === CHECKOUT_PAYMENT_OPTIONS_SECTION_ID
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
if (section) {
|
|
148
|
+
// Extract view type from properties - only update if value exists
|
|
149
|
+
if (
|
|
150
|
+
section.properties?.viewType !== undefined &&
|
|
151
|
+
section.properties?.viewType !== null
|
|
152
|
+
) {
|
|
153
|
+
const viewTypeValue = section.properties.viewType;
|
|
154
|
+
|
|
155
|
+
// Handle both string and responsive object formats
|
|
156
|
+
if (typeof viewTypeValue === 'string') {
|
|
157
|
+
setViewType(viewTypeValue as 'tab' | 'dropdown');
|
|
158
|
+
// Save to localStorage for persistence
|
|
159
|
+
if (typeof window !== 'undefined') {
|
|
160
|
+
localStorage.setItem(
|
|
161
|
+
'checkout-payment-view-type',
|
|
162
|
+
viewTypeValue
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
} else if (
|
|
166
|
+
typeof viewTypeValue === 'object' &&
|
|
167
|
+
viewTypeValue !== null
|
|
168
|
+
) {
|
|
169
|
+
// Extract from responsive object
|
|
170
|
+
const responsiveValue = viewTypeValue as Record<string, string>;
|
|
171
|
+
const extractedValue =
|
|
172
|
+
responsiveValue.desktop ||
|
|
173
|
+
responsiveValue.mobile ||
|
|
174
|
+
responsiveValue.tablet ||
|
|
175
|
+
Object.values(responsiveValue)[0];
|
|
176
|
+
if (extractedValue) {
|
|
177
|
+
setViewType(extractedValue as 'tab' | 'dropdown');
|
|
178
|
+
// Save to localStorage for persistence
|
|
179
|
+
if (typeof window !== 'undefined') {
|
|
180
|
+
localStorage.setItem(
|
|
181
|
+
'checkout-payment-view-type',
|
|
182
|
+
extractedValue
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Flatten responsive styles to current breakpoint (desktop by default)
|
|
190
|
+
if (section.styles) {
|
|
191
|
+
const flatStyles: CheckoutPaymentOptionsStyles = {};
|
|
192
|
+
Object.entries(section.styles).forEach(([key, value]) => {
|
|
193
|
+
if (typeof value === 'object' && value !== null) {
|
|
194
|
+
const responsiveValue = value as Record<
|
|
195
|
+
string,
|
|
196
|
+
string | number
|
|
197
|
+
>;
|
|
198
|
+
flatStyles[key] =
|
|
199
|
+
responsiveValue.desktop ||
|
|
200
|
+
responsiveValue.mobile ||
|
|
201
|
+
responsiveValue.tablet ||
|
|
202
|
+
Object.values(responsiveValue)[0] ||
|
|
203
|
+
'';
|
|
204
|
+
} else if (
|
|
205
|
+
typeof value === 'string' ||
|
|
206
|
+
typeof value === 'number'
|
|
207
|
+
) {
|
|
208
|
+
flatStyles[key] = value;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
setSectionStyles(flatStyles);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Handle section selection
|
|
217
|
+
if (type === 'SECTION_SELECTED') {
|
|
218
|
+
const isSelected =
|
|
219
|
+
data?.placeholderId === CHECKOUT_PLACEHOLDER_ID &&
|
|
220
|
+
data?.sectionId === CHECKOUT_PAYMENT_OPTIONS_SECTION_ID;
|
|
221
|
+
setIsSectionSelected(isSelected);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (type === 'SECTION_DESELECTED') {
|
|
225
|
+
setIsSectionSelected(false);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
window.addEventListener('message', handleMessage);
|
|
230
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
231
|
+
}, []);
|
|
232
|
+
|
|
233
|
+
return (
|
|
234
|
+
<CheckoutPaymentOptionsContext.Provider
|
|
235
|
+
value={{
|
|
236
|
+
isDesigner,
|
|
237
|
+
viewType,
|
|
238
|
+
sectionStyles
|
|
239
|
+
}}
|
|
240
|
+
>
|
|
241
|
+
<div
|
|
242
|
+
data-native-section={CHECKOUT_PAYMENT_OPTIONS_SECTION_ID}
|
|
243
|
+
data-placeholder={CHECKOUT_PLACEHOLDER_ID}
|
|
244
|
+
style={{
|
|
245
|
+
outline: isSectionSelected ? '2px solid #2359C4' : 'none',
|
|
246
|
+
outlineOffset: '2px'
|
|
247
|
+
}}
|
|
248
|
+
>
|
|
249
|
+
{children}
|
|
250
|
+
</div>
|
|
251
|
+
</CheckoutPaymentOptionsContext.Provider>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checkout Summary Section Registrar
|
|
5
|
+
*
|
|
6
|
+
* This component registers the "Summary" section for the checkout placeholder.
|
|
7
|
+
* It provides the current styles to child components via context.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
createContext,
|
|
12
|
+
useContext,
|
|
13
|
+
useEffect,
|
|
14
|
+
useRef,
|
|
15
|
+
useState,
|
|
16
|
+
ReactNode
|
|
17
|
+
} from 'react';
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
CHECKOUT_PLACEHOLDER_ID,
|
|
21
|
+
CHECKOUT_SUMMARY_SECTION_ID
|
|
22
|
+
} from './constants';
|
|
23
|
+
|
|
24
|
+
// Global flag to track if registration has been done (survives component remount)
|
|
25
|
+
declare global {
|
|
26
|
+
interface Window {
|
|
27
|
+
__checkoutSummaryRegistered?: boolean;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check if running inside designer iframe
|
|
33
|
+
*/
|
|
34
|
+
function isInDesignerMode(): boolean {
|
|
35
|
+
if (typeof window === 'undefined') return false;
|
|
36
|
+
return window.self !== window.top;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface CheckoutSummaryStyles {
|
|
40
|
+
[key: string]: string | number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Context for sharing styles with other components
|
|
44
|
+
interface CheckoutSummaryContextValue {
|
|
45
|
+
isDesigner: boolean;
|
|
46
|
+
sectionStyles: CheckoutSummaryStyles;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const CheckoutSummaryContext = createContext<CheckoutSummaryContextValue>({
|
|
50
|
+
isDesigner: false,
|
|
51
|
+
sectionStyles: {}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export const useCheckoutSummary = () => useContext(CheckoutSummaryContext);
|
|
55
|
+
|
|
56
|
+
interface CheckoutSummaryRegistrarProps {
|
|
57
|
+
children?: ReactNode;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function CheckoutSummaryRegistrar({
|
|
61
|
+
children
|
|
62
|
+
}: CheckoutSummaryRegistrarProps) {
|
|
63
|
+
const isDesignerRef = useRef(false);
|
|
64
|
+
const [sectionStyles, setSectionStyles] = useState<CheckoutSummaryStyles>({});
|
|
65
|
+
const [isSectionSelected, setIsSectionSelected] = useState(false);
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
isDesignerRef.current = isInDesignerMode();
|
|
69
|
+
}, []);
|
|
70
|
+
|
|
71
|
+
const isDesigner = isDesignerRef.current;
|
|
72
|
+
|
|
73
|
+
// Register native widget with Theme Editor
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const isInIframe =
|
|
76
|
+
typeof window !== 'undefined' && window.self !== window.top;
|
|
77
|
+
if (!isInIframe || !window.parent) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// If already registered, skip
|
|
82
|
+
if (typeof window !== 'undefined' && window.__checkoutSummaryRegistered) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const nativeWidgetConfig = {
|
|
87
|
+
placeholderId: CHECKOUT_PLACEHOLDER_ID,
|
|
88
|
+
section: {
|
|
89
|
+
id: CHECKOUT_SUMMARY_SECTION_ID,
|
|
90
|
+
type: 'native',
|
|
91
|
+
label: 'Summary',
|
|
92
|
+
blocks: []
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
window.parent.postMessage(
|
|
97
|
+
{
|
|
98
|
+
type: 'REGISTER_NATIVE_WIDGETS',
|
|
99
|
+
data: { widgets: [nativeWidgetConfig] }
|
|
100
|
+
},
|
|
101
|
+
'*'
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
window.__checkoutSummaryRegistered = true;
|
|
105
|
+
}, []);
|
|
106
|
+
|
|
107
|
+
// Listen for theme updates and selection changes from Theme Editor
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (typeof window === 'undefined') return;
|
|
110
|
+
|
|
111
|
+
const handleMessage = (event: MessageEvent) => {
|
|
112
|
+
const { type, data } = event.data || {};
|
|
113
|
+
|
|
114
|
+
// Handle theme updates
|
|
115
|
+
if (
|
|
116
|
+
(type === 'UPDATE_THEME' || type === 'LOAD_THEME') &&
|
|
117
|
+
data?.theme?.placeholders
|
|
118
|
+
) {
|
|
119
|
+
const placeholder = data.theme.placeholders?.find(
|
|
120
|
+
(p: { slug: string }) => p.slug === CHECKOUT_PLACEHOLDER_ID
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const section = placeholder?.sections?.find(
|
|
124
|
+
(s: { id: string }) => s.id === CHECKOUT_SUMMARY_SECTION_ID
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
if (section && section.styles) {
|
|
128
|
+
// Flatten responsive styles to current breakpoint (desktop by default)
|
|
129
|
+
const flatStyles: CheckoutSummaryStyles = {};
|
|
130
|
+
Object.entries(section.styles).forEach(([key, value]) => {
|
|
131
|
+
if (typeof value === 'object' && value !== null) {
|
|
132
|
+
const responsiveValue = value as Record<string, string | number>;
|
|
133
|
+
flatStyles[key] =
|
|
134
|
+
responsiveValue.desktop ||
|
|
135
|
+
responsiveValue.mobile ||
|
|
136
|
+
responsiveValue.tablet ||
|
|
137
|
+
Object.values(responsiveValue)[0] ||
|
|
138
|
+
'';
|
|
139
|
+
} else if (typeof value === 'string' || typeof value === 'number') {
|
|
140
|
+
flatStyles[key] = value;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
setSectionStyles(flatStyles);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Handle section selection
|
|
148
|
+
if (type === 'SECTION_SELECTED') {
|
|
149
|
+
const isSelected =
|
|
150
|
+
data?.placeholderId === CHECKOUT_PLACEHOLDER_ID &&
|
|
151
|
+
data?.sectionId === CHECKOUT_SUMMARY_SECTION_ID;
|
|
152
|
+
setIsSectionSelected(isSelected);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (type === 'SECTION_DESELECTED') {
|
|
156
|
+
setIsSectionSelected(false);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
window.addEventListener('message', handleMessage);
|
|
161
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
162
|
+
}, []);
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<CheckoutSummaryContext.Provider
|
|
166
|
+
value={{
|
|
167
|
+
isDesigner,
|
|
168
|
+
sectionStyles
|
|
169
|
+
}}
|
|
170
|
+
>
|
|
171
|
+
<div
|
|
172
|
+
data-native-section={CHECKOUT_SUMMARY_SECTION_ID}
|
|
173
|
+
data-placeholder={CHECKOUT_PLACEHOLDER_ID}
|
|
174
|
+
style={{
|
|
175
|
+
outline: isSectionSelected ? '2px solid #2359C4' : 'none',
|
|
176
|
+
outlineOffset: '2px'
|
|
177
|
+
}}
|
|
178
|
+
>
|
|
179
|
+
{children}
|
|
180
|
+
</div>
|
|
181
|
+
</CheckoutSummaryContext.Provider>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export const CHECKOUT_PLACEHOLDER_ID = 'checkout-page';
|
|
2
|
+
export const CHECKOUT_ADDRESS_SECTION_ID = 'checkout-address';
|
|
3
|
+
export const CHECKOUT_BUTTONS_SECTION_ID = 'checkout-buttons';
|
|
4
|
+
export const CHECKOUT_PAYMENT_OPTIONS_SECTION_ID = 'checkout-payment-options';
|
|
5
|
+
export const CHECKOUT_SUMMARY_SECTION_ID = 'checkout-summary';
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export * from './step-button';
|
|
2
2
|
export * from './step-list';
|
|
3
3
|
export * from './summary';
|
|
4
|
+
export * from './checkout-address-registrar';
|
|
5
|
+
export * from './checkout-delivery-method-registrar';
|
|
6
|
+
export * from './checkout-payment-options-registrar';
|
|
7
|
+
export * from './checkout-summary-registrar';
|
|
8
|
+
export * from './checkout-buttons-registrar';
|