@alphasquad/saleor-template-advance 0.1.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/.env.example +57 -0
- package/APPLE_PAY_QUICK_START.md +165 -0
- package/APPLE_PAY_SETUP.md +331 -0
- package/README.md +46 -0
- package/SEO_AUDIT_CHECKLIST_STATUS.md +244 -0
- package/SEO_AUDIT_REPORT.md +66 -0
- package/eslint.config.mjs +16 -0
- package/next-env.d.ts +5 -0
- package/next.config.ts +109 -0
- package/package.json +47 -0
- package/postcss.config.mjs +5 -0
- package/public/.well-known/apple-developer-merchantid-domain-association +1 -0
- package/public/Logo.png +0 -0
- package/public/brand-video.mp4 +0 -0
- package/public/favicon.ico +0 -0
- package/public/file.svg +1 -0
- package/public/footer/facebook.tsx +34 -0
- package/public/footer/instagram.tsx +27 -0
- package/public/footer/mail.tsx +5 -0
- package/public/footer/x.tsx +35 -0
- package/public/globe.svg +1 -0
- package/public/icons/Authorize.net.webp +0 -0
- package/public/icons/amex.gif +0 -0
- package/public/icons/appIcon.png +0 -0
- package/public/icons/discover.gif +0 -0
- package/public/icons/master.gif +0 -0
- package/public/icons/paypal.png +0 -0
- package/public/icons/stripe.png +0 -0
- package/public/icons/visa.gif +0 -0
- package/public/images/BackgroundNoise.png +0 -0
- package/public/images/footer-background.png +0 -0
- package/public/next.svg +1 -0
- package/public/no-image-avail-large.png +0 -0
- package/public/random-car-1.jpeg +0 -0
- package/public/random-car-2.png +0 -0
- package/public/random-car-3.jpg +0 -0
- package/public/random-car-4.jpg +0 -0
- package/public/random-car-5.jpg +0 -0
- package/public/star.svg +3 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/scripts/seo-audit/generate-checklist.mjs +156 -0
- package/src/app/(auth)/account/forgot-password/layout.tsx +16 -0
- package/src/app/(auth)/account/forgot-password/page.tsx +135 -0
- package/src/app/(auth)/account/login/layout.tsx +16 -0
- package/src/app/(auth)/account/login/page.tsx +288 -0
- package/src/app/(auth)/account/otp/layout.tsx +16 -0
- package/src/app/(auth)/account/otp/page.tsx +108 -0
- package/src/app/(auth)/account/register/layout.tsx +16 -0
- package/src/app/(auth)/account/register/page.tsx +431 -0
- package/src/app/(auth)/account/reset-password/layout.tsx +16 -0
- package/src/app/(auth)/account/reset-password/page.tsx +222 -0
- package/src/app/[slug]/page.tsx +43 -0
- package/src/app/about/loading.tsx +17 -0
- package/src/app/about/page.tsx +61 -0
- package/src/app/account/address/layout.tsx +15 -0
- package/src/app/account/address/page.tsx +166 -0
- package/src/app/account/head.tsx +4 -0
- package/src/app/account/layout.tsx +62 -0
- package/src/app/account/orders/[id]/layout.tsx +17 -0
- package/src/app/account/orders/[id]/page.tsx +115 -0
- package/src/app/account/orders/components/orderDetailsModal.tsx +410 -0
- package/src/app/account/orders/layout.tsx +15 -0
- package/src/app/account/orders/page.tsx +146 -0
- package/src/app/account/page.tsx +39 -0
- package/src/app/account/settings/components/editProfileSuccessModal.tsx +28 -0
- package/src/app/account/settings/layout.tsx +15 -0
- package/src/app/account/settings/page.tsx +260 -0
- package/src/app/api/affirm/check-status/route.ts +94 -0
- package/src/app/api/affirm/create-checkout/route.ts +109 -0
- package/src/app/api/affirm/get-config/route.ts +108 -0
- package/src/app/api/affirm/process-payment/route.ts +244 -0
- package/src/app/api/affirm/test-connection/route.ts +45 -0
- package/src/app/api/auth/clear/route.ts +16 -0
- package/src/app/api/auth/clear-cookies/route.ts +42 -0
- package/src/app/api/auth/set/route.ts +47 -0
- package/src/app/api/configuration/route.ts +18 -0
- package/src/app/api/dynamic-page/[slug]/route.ts +24 -0
- package/src/app/api/form-submission/route.ts +237 -0
- package/src/app/api/paypal/capture-order/route.ts +303 -0
- package/src/app/api/paypal/create-order/route.ts +211 -0
- package/src/app/api/paypal/get-config/route.ts +240 -0
- package/src/app/api/search-proxy/route.ts +52 -0
- package/src/app/authorize-net-success/layout.tsx +19 -0
- package/src/app/authorize-net-success/page.tsx +12 -0
- package/src/app/authorize-net-success/summary.tsx +486 -0
- package/src/app/blog/[slug]/blogContentRenderer.tsx +369 -0
- package/src/app/blog/[slug]/layout.tsx +17 -0
- package/src/app/blog/[slug]/page.tsx +151 -0
- package/src/app/blog/constant.tsx +147 -0
- package/src/app/blog/layout.tsx +31 -0
- package/src/app/blog/page.tsx +81 -0
- package/src/app/brand/[id]/BrandPageClient.tsx +188 -0
- package/src/app/brand/[id]/layout.tsx +17 -0
- package/src/app/brand/[id]/page.tsx +176 -0
- package/src/app/brands/components/brandsListingClient.tsx +97 -0
- package/src/app/brands/layout.tsx +31 -0
- package/src/app/brands/page.tsx +40 -0
- package/src/app/cancellation-policy/page.tsx +53 -0
- package/src/app/cart/layout.tsx +19 -0
- package/src/app/cart/page.tsx +752 -0
- package/src/app/category/[slug]/CategoryPageClient.tsx +377 -0
- package/src/app/category/[slug]/layout.tsx +17 -0
- package/src/app/category/[slug]/page.tsx +224 -0
- package/src/app/category/page.tsx +114 -0
- package/src/app/checkout/components/addNewAddressModal.tsx +474 -0
- package/src/app/checkout/layout.tsx +19 -0
- package/src/app/checkout/page.tsx +3312 -0
- package/src/app/components/account/AccountTabs.tsx +40 -0
- package/src/app/components/ads/GoogleAdSense.tsx +74 -0
- package/src/app/components/analytics/AnalyticsScripts.tsx +78 -0
- package/src/app/components/analytics/ConditionalGTMNoscript.tsx +24 -0
- package/src/app/components/analytics/ConditionalGoogleAnalytics.tsx +16 -0
- package/src/app/components/ancillary/AncillaryContent.tsx +7 -0
- package/src/app/components/auth/TokenExpirationHandler.tsx +8 -0
- package/src/app/components/blog/BlogList.tsx +112 -0
- package/src/app/components/checkout/AddressInformationSection.tsx +34 -0
- package/src/app/components/checkout/AddressManagement.tsx +571 -0
- package/src/app/components/checkout/CheckoutHeader.tsx +51 -0
- package/src/app/components/checkout/CheckoutQuestions.tsx +454 -0
- package/src/app/components/checkout/CheckoutTermsModal.tsx +81 -0
- package/src/app/components/checkout/ContactDetailsSection.tsx +52 -0
- package/src/app/components/checkout/DealerShippingSection.tsx +359 -0
- package/src/app/components/checkout/DeliveryMethodSection.tsx +249 -0
- package/src/app/components/checkout/OrderSummary.tsx +386 -0
- package/src/app/components/checkout/TermsContentRenderer.tsx +147 -0
- package/src/app/components/checkout/WillCallSection.tsx +133 -0
- package/src/app/components/checkout/affirmPayment.tsx +383 -0
- package/src/app/components/checkout/checkoutProcessingModal.tsx +96 -0
- package/src/app/components/checkout/googlePayButton.tsx +334 -0
- package/src/app/components/checkout/paymentStep.tsx +180 -0
- package/src/app/components/checkout/paypalPayment.tsx +1083 -0
- package/src/app/components/checkout/saleorNativePayment.tsx +1758 -0
- package/src/app/components/dynamicPage/DynamicPageRenderer.tsx +13 -0
- package/src/app/components/dynamicPage/HtmlWidgetRenderer.tsx +144 -0
- package/src/app/components/filtersCollapsible/index.tsx +365 -0
- package/src/app/components/globalSearch/index.tsx +423 -0
- package/src/app/components/layout/cartDropDown.tsx +628 -0
- package/src/app/components/layout/components/FooterNewsletter.tsx +21 -0
- package/src/app/components/layout/footer.tsx +283 -0
- package/src/app/components/layout/header/accountMenuDropdown.tsx +53 -0
- package/src/app/components/layout/header/components/CartBadge.tsx +18 -0
- package/src/app/components/layout/header/components/LoadingState.tsx +17 -0
- package/src/app/components/layout/header/components/MenuItemDropdown.tsx +124 -0
- package/src/app/components/layout/header/components/MobileNavbar.tsx +123 -0
- package/src/app/components/layout/header/components/NavbarActions.tsx +125 -0
- package/src/app/components/layout/header/components/NavbarBrand.tsx +29 -0
- package/src/app/components/layout/header/components/NavigationLinks.tsx +131 -0
- package/src/app/components/layout/header/hamMenuSlide.tsx +318 -0
- package/src/app/components/layout/header/header.tsx +44 -0
- package/src/app/components/layout/header/hooks/useDropdown.ts +45 -0
- package/src/app/components/layout/header/hooks/useNavbarData.ts +138 -0
- package/src/app/components/layout/header/hooks/useNavbarState.ts +66 -0
- package/src/app/components/layout/header/megaMenuDropdown.tsx +116 -0
- package/src/app/components/layout/header/navBar.tsx +121 -0
- package/src/app/components/layout/header/search.tsx +418 -0
- package/src/app/components/layout/header/styles/navbarStyles.ts +27 -0
- package/src/app/components/layout/header/topBar.tsx +214 -0
- package/src/app/components/layout/joinNewsletterForm/index.tsx +72 -0
- package/src/app/components/layout/mobileAccordian/index.tsx +92 -0
- package/src/app/components/layout/paymentMethods.tsx +75 -0
- package/src/app/components/layout/rootLayout.tsx +23 -0
- package/src/app/components/layout/siteInfo.tsx +103 -0
- package/src/app/components/layout/socialLinks.tsx +65 -0
- package/src/app/components/newsletterSection/emailListSection.tsx +224 -0
- package/src/app/components/newsletterSection/emailSectionServer.tsx +8 -0
- package/src/app/components/providers/ApolloWrapper.tsx +12 -0
- package/src/app/components/providers/AppConfigurationProvider.tsx +108 -0
- package/src/app/components/providers/GoogleAnalyticsProvider.tsx +149 -0
- package/src/app/components/providers/GoogleTagManagerProvider.tsx +31 -0
- package/src/app/components/providers/RecaptchaProvider.tsx +18 -0
- package/src/app/components/providers/ServerAppConfigurationProvider.tsx +133 -0
- package/src/app/components/providers/YMMStatusProvider.tsx +15 -0
- package/src/app/components/reuseableUI/AboutUs.tsx +115 -0
- package/src/app/components/reuseableUI/AddToCartClient.tsx +125 -0
- package/src/app/components/reuseableUI/EditorJsRenderer.tsx +219 -0
- package/src/app/components/reuseableUI/HeroSectionsearchByVehicle.tsx +188 -0
- package/src/app/components/reuseableUI/ImageWithFallback.tsx +41 -0
- package/src/app/components/reuseableUI/Toast.tsx +101 -0
- package/src/app/components/reuseableUI/blogCard.tsx +52 -0
- package/src/app/components/reuseableUI/brandCard.tsx +68 -0
- package/src/app/components/reuseableUI/breadcrumb.tsx +38 -0
- package/src/app/components/reuseableUI/categoryCard.tsx +37 -0
- package/src/app/components/reuseableUI/categorySkeleton.tsx +31 -0
- package/src/app/components/reuseableUI/commonButton.tsx +48 -0
- package/src/app/components/reuseableUI/defaultInputField/index.tsx +84 -0
- package/src/app/components/reuseableUI/emptyState.tsx +29 -0
- package/src/app/components/reuseableUI/errorTag.tsx +15 -0
- package/src/app/components/reuseableUI/heading/index.tsx +20 -0
- package/src/app/components/reuseableUI/input.tsx +117 -0
- package/src/app/components/reuseableUI/listCard.tsx +137 -0
- package/src/app/components/reuseableUI/loadingUI.tsx +12 -0
- package/src/app/components/reuseableUI/modalLayout.tsx +76 -0
- package/src/app/components/reuseableUI/newsletter/newsletterClient.tsx +622 -0
- package/src/app/components/reuseableUI/newsletter/newslettersHomeModal.tsx +68 -0
- package/src/app/components/reuseableUI/offerCard.tsx +42 -0
- package/src/app/components/reuseableUI/passwordRules/passwordRules.tsx +56 -0
- package/src/app/components/reuseableUI/primaryButton/index.tsx +34 -0
- package/src/app/components/reuseableUI/productCard.tsx +118 -0
- package/src/app/components/reuseableUI/productSkeleton.tsx +34 -0
- package/src/app/components/reuseableUI/searchByVehicle.tsx +187 -0
- package/src/app/components/reuseableUI/secondaryButton/index.tsx +34 -0
- package/src/app/components/reuseableUI/section.tsx +20 -0
- package/src/app/components/reuseableUI/select/index.tsx +98 -0
- package/src/app/components/reuseableUI/skeletonLoader.tsx +117 -0
- package/src/app/components/reuseableUI/statusTag.tsx +24 -0
- package/src/app/components/reuseableUI/tags/saleTag.tsx +19 -0
- package/src/app/components/reuseableUI/testimonialCard.tsx +93 -0
- package/src/app/components/richText/EditorRenderer.tsx +318 -0
- package/src/app/components/search/HierarchicalCategoryFilter.tsx +155 -0
- package/src/app/components/search/SearchFilters.tsx +155 -0
- package/src/app/components/search/YMMSearchSidebar.tsx +187 -0
- package/src/app/components/seo/ServerProductCard.tsx +91 -0
- package/src/app/components/seo/ServerProductGrid.tsx +45 -0
- package/src/app/components/shop/CategoryFilter.tsx +184 -0
- package/src/app/components/shop/ItemsPerPageSelect.tsx +69 -0
- package/src/app/components/shop/ItemsPerPageSelectClient.tsx +58 -0
- package/src/app/components/shop/MobileFilters.tsx +103 -0
- package/src/app/components/shop/ProductGridSkeleton.tsx +16 -0
- package/src/app/components/shop/ProductsGrid.tsx +230 -0
- package/src/app/components/shop/SearchFilter.tsx +218 -0
- package/src/app/components/shop/SearchFilterClient.tsx +122 -0
- package/src/app/components/shop/SearchLoadingOverlay.tsx +32 -0
- package/src/app/components/shop/ShopMobileFilters.tsx +205 -0
- package/src/app/components/showroom/VehicleSearchDropdowns.tsx +187 -0
- package/src/app/components/showroom/brandsSwiper.tsx +49 -0
- package/src/app/components/showroom/brandsSwiperClient copy.tsx +93 -0
- package/src/app/components/showroom/brandsSwiperClient.tsx +122 -0
- package/src/app/components/showroom/brandsSwiperServer.tsx +42 -0
- package/src/app/components/showroom/bundleProducts.tsx +120 -0
- package/src/app/components/showroom/categoryGrid.tsx +51 -0
- package/src/app/components/showroom/categoryGridServer.tsx +45 -0
- package/src/app/components/showroom/categorySwiper.tsx +115 -0
- package/src/app/components/showroom/featureStrip.tsx +139 -0
- package/src/app/components/showroom/offersSwiper.tsx +181 -0
- package/src/app/components/showroom/productGrid.tsx +56 -0
- package/src/app/components/showroom/productSwiper.tsx +119 -0
- package/src/app/components/showroom/promotion-slider.tsx +138 -0
- package/src/app/components/showroom/promotion.tsx +207 -0
- package/src/app/components/showroom/promotionsSwiper.tsx +174 -0
- package/src/app/components/showroom/showroomHeroCarousel.tsx +141 -0
- package/src/app/components/showroom/testimonialsGrid.tsx +106 -0
- package/src/app/components/skeletons/ContentSkeleton.tsx +14 -0
- package/src/app/components/sortDropdown/index.tsx +116 -0
- package/src/app/components/tertiaryButton/index.tsx +25 -0
- package/src/app/components/theme/theme-provider.tsx +82 -0
- package/src/app/contact/layout.tsx +32 -0
- package/src/app/contact/page.tsx +591 -0
- package/src/app/content/[slug]/layout.tsx +17 -0
- package/src/app/content/[slug]/page.tsx +159 -0
- package/src/app/content/layout.tsx +31 -0
- package/src/app/content/page.tsx +88 -0
- package/src/app/core-policies/page.tsx +55 -0
- package/src/app/discounts/page.tsx +54 -0
- package/src/app/frequently-asked-questions/page.tsx +57 -0
- package/src/app/globals.css +440 -0
- package/src/app/hooks/useDealerLocations.ts +259 -0
- package/src/app/hooks/useGTMEngagement.ts +71 -0
- package/src/app/hooks/useGoogleAnalytics.ts +145 -0
- package/src/app/layout.tsx +149 -0
- package/src/app/not-found.tsx +31 -0
- package/src/app/order-confirmation/layout.tsx +19 -0
- package/src/app/order-confirmation/page.tsx +12 -0
- package/src/app/order-confirmation/summary.tsx +1775 -0
- package/src/app/page.tsx +194 -0
- package/src/app/privacy-policy/loading.tsx +17 -0
- package/src/app/privacy-policy/page.tsx +56 -0
- package/src/app/product/[id]/ProductDetailClient.tsx +2448 -0
- package/src/app/product/[id]/components/itemInquiryModal.tsx +461 -0
- package/src/app/product/[id]/layout.tsx +116 -0
- package/src/app/product/[id]/page.tsx +200 -0
- package/src/app/product/layout.tsx +15 -0
- package/src/app/products/all/AllProductsClient.tsx +743 -0
- package/src/app/products/all/page.tsx +176 -0
- package/src/app/products/components/shopEmptyState.tsx +29 -0
- package/src/app/request-return/layout.tsx +36 -0
- package/src/app/request-return/page.tsx +597 -0
- package/src/app/robots.txt/route.ts +27 -0
- package/src/app/search/layout.tsx +16 -0
- package/src/app/search/page.tsx +736 -0
- package/src/app/shipping-returns/page.tsx +60 -0
- package/src/app/site-map/layout.tsx +33 -0
- package/src/app/site-map/page.tsx +113 -0
- package/src/app/sitemap-index.xml/route.ts +20 -0
- package/src/app/sitemap.ts +10 -0
- package/src/app/terms-and-conditions/loading.tsx +17 -0
- package/src/app/terms-and-conditions/page.tsx +56 -0
- package/src/app/utils/appConfiguration.ts +327 -0
- package/src/app/utils/branding.ts +52 -0
- package/src/app/utils/configurationService.ts +202 -0
- package/src/app/utils/constant.tsx +242 -0
- package/src/app/utils/editorJsUtils.tsx +249 -0
- package/src/app/utils/functions.ts +146 -0
- package/src/app/utils/googleAnalytics.ts +168 -0
- package/src/app/utils/googleTagManager.ts +475 -0
- package/src/app/utils/ipDetection.ts +270 -0
- package/src/app/utils/serverConfigurationService.ts +209 -0
- package/src/app/utils/svgs/GridIcon.tsx +45 -0
- package/src/app/utils/svgs/account/myAccount/listDotIcon.tsx +3 -0
- package/src/app/utils/svgs/account/myAccount/tickIcon.tsx +10 -0
- package/src/app/utils/svgs/account/orderHistory/InfoIcon.tsx +49 -0
- package/src/app/utils/svgs/arrowDownIcon.tsx +17 -0
- package/src/app/utils/svgs/arrowIcon.tsx +25 -0
- package/src/app/utils/svgs/arrowUpIcon.tsx +16 -0
- package/src/app/utils/svgs/brandsSearchIcon.tsx +25 -0
- package/src/app/utils/svgs/cart/cartIcon.tsx +31 -0
- package/src/app/utils/svgs/cart/plusIcon.tsx +13 -0
- package/src/app/utils/svgs/cart/subtractIcon.tsx +13 -0
- package/src/app/utils/svgs/cart/successTickIcon.tsx +14 -0
- package/src/app/utils/svgs/chevronDownIcon.tsx +21 -0
- package/src/app/utils/svgs/closeEyeIcon.tsx +47 -0
- package/src/app/utils/svgs/crossIcon.tsx +25 -0
- package/src/app/utils/svgs/eyeIcon.tsx +29 -0
- package/src/app/utils/svgs/featureTag.tsx +20 -0
- package/src/app/utils/svgs/filterIcon.tsx +3 -0
- package/src/app/utils/svgs/globleIcon.tsx +41 -0
- package/src/app/utils/svgs/infoIcon.tsx +34 -0
- package/src/app/utils/svgs/listIcon.tsx +50 -0
- package/src/app/utils/svgs/logOutIcon.tsx +35 -0
- package/src/app/utils/svgs/menuIcon.tsx +8 -0
- package/src/app/utils/svgs/minusIcon.tsx +18 -0
- package/src/app/utils/svgs/newsletterIcon.tsx +19 -0
- package/src/app/utils/svgs/noDataFoundIcon-.tsx +26 -0
- package/src/app/utils/svgs/noProductFoundIcon.tsx +43 -0
- package/src/app/utils/svgs/passwordIcons/errorIcon.tsx +31 -0
- package/src/app/utils/svgs/passwordIcons/successIcon.tsx +24 -0
- package/src/app/utils/svgs/paymentProcessingIcons/hourglassIcon.tsx +43 -0
- package/src/app/utils/svgs/paymentProcessingIcons/modalCrossIcon.tsx +23 -0
- package/src/app/utils/svgs/paymentProcessingIcons/paymentFailedIcon.tsx +47 -0
- package/src/app/utils/svgs/pencilIcon.tsx +11 -0
- package/src/app/utils/svgs/plusIcon.tsx +25 -0
- package/src/app/utils/svgs/productInquiryIcon.tsx +40 -0
- package/src/app/utils/svgs/searchIcon.tsx +31 -0
- package/src/app/utils/svgs/shoppingCart.tsx +32 -0
- package/src/app/utils/svgs/spinnerIcon.tsx +22 -0
- package/src/app/utils/svgs/spinnerLoadingIcon.tsx +26 -0
- package/src/app/utils/svgs/successTickIcon.tsx +40 -0
- package/src/app/utils/svgs/swiperArrowIconLeft.tsx +18 -0
- package/src/app/utils/svgs/swiperArrowIconRight.tsx +18 -0
- package/src/app/utils/svgs/userProfileIcon.tsx +31 -0
- package/src/app/utils/svgs/warningCircleIcon.tsx +15 -0
- package/src/app/warranty/constant.tsx +63 -0
- package/src/app/warranty/loading.tsx +17 -0
- package/src/app/warranty/page.tsx +56 -0
- package/src/graphql/client.ts +288 -0
- package/src/graphql/mutations/accountAddressCreate.ts +56 -0
- package/src/graphql/mutations/accountAddressDelete.ts +23 -0
- package/src/graphql/mutations/accountAddressUpdate.ts +55 -0
- package/src/graphql/mutations/accountSetDefaultAddress.ts +32 -0
- package/src/graphql/mutations/accountUpdate.ts +34 -0
- package/src/graphql/mutations/changePassword.ts +25 -0
- package/src/graphql/mutations/checkout.ts +117 -0
- package/src/graphql/mutations/checkoutAddVoucher.ts +63 -0
- package/src/graphql/mutations/checkoutComplete.ts +79 -0
- package/src/graphql/mutations/checkoutCreate.ts +131 -0
- package/src/graphql/mutations/checkoutCustomerAttach.ts +50 -0
- package/src/graphql/mutations/checkoutEmailUpdate.ts +15 -0
- package/src/graphql/mutations/checkoutLineMetadataUpdate.ts +52 -0
- package/src/graphql/mutations/checkoutPaymentCreate.ts +82 -0
- package/src/graphql/mutations/paymentGatewayInitialize.ts +58 -0
- package/src/graphql/mutations/registerAccount.ts +65 -0
- package/src/graphql/mutations/requestPasswordReset.ts +32 -0
- package/src/graphql/mutations/setPassword.ts +49 -0
- package/src/graphql/mutations/signIn.ts +50 -0
- package/src/graphql/mutations/tokenRefresh.ts +19 -0
- package/src/graphql/mutations/updateCheckoutMetadata.ts +49 -0
- package/src/graphql/mutations/updateProfile.ts +18 -0
- package/src/graphql/mutations/willCallDeliveryMethod.ts +81 -0
- package/src/graphql/queries/checkout.ts +168 -0
- package/src/graphql/queries/findProductByOldSlug.ts +58 -0
- package/src/graphql/queries/getAboutPage.ts +24 -0
- package/src/graphql/queries/getAboutPageId.ts +9 -0
- package/src/graphql/queries/getAboutUs.ts +38 -0
- package/src/graphql/queries/getAddressInformation.ts +38 -0
- package/src/graphql/queries/getAllCategories.ts +41 -0
- package/src/graphql/queries/getAllCategoriesTree.ts +67 -0
- package/src/graphql/queries/getAllCategoriesWithProducts.ts +29 -0
- package/src/graphql/queries/getAllCollectionsWithProducts.ts +16 -0
- package/src/graphql/queries/getBlogs.ts +222 -0
- package/src/graphql/queries/getBrands.ts +17 -0
- package/src/graphql/queries/getBundles.ts +43 -0
- package/src/graphql/queries/getCategories.ts +20 -0
- package/src/graphql/queries/getChannels.ts +77 -0
- package/src/graphql/queries/getCheckoutQuestions.ts +115 -0
- package/src/graphql/queries/getCheckoutTermsAndConditions.ts +37 -0
- package/src/graphql/queries/getContactPage.ts +117 -0
- package/src/graphql/queries/getContentPage.ts +191 -0
- package/src/graphql/queries/getDiscountOffers.ts +18 -0
- package/src/graphql/queries/getDynamicPageBySlug.ts +251 -0
- package/src/graphql/queries/getFeaturedProducts.ts +48 -0
- package/src/graphql/queries/getHeroMetadata.ts +23 -0
- package/src/graphql/queries/getMenuBySlug.ts +84 -0
- package/src/graphql/queries/getMyProfile.ts +23 -0
- package/src/graphql/queries/getNewsletter.ts +122 -0
- package/src/graphql/queries/getNewsletterPage.ts +111 -0
- package/src/graphql/queries/getPageBySlug.ts +52 -0
- package/src/graphql/queries/getPageTypeId.ts +27 -0
- package/src/graphql/queries/getPaymentMethods.ts +61 -0
- package/src/graphql/queries/getProducts.ts +78 -0
- package/src/graphql/queries/getPromotions.ts +24 -0
- package/src/graphql/queries/getRequestReturnPage.ts +121 -0
- package/src/graphql/queries/getSiteInfo.ts +54 -0
- package/src/graphql/queries/getSocialLinks.ts +52 -0
- package/src/graphql/queries/getTestimonials.ts +25 -0
- package/src/graphql/queries/getUserWithCheckout.ts +27 -0
- package/src/graphql/queries/getVehicleMakes.ts +21 -0
- package/src/graphql/queries/getVehicleModels.ts +21 -0
- package/src/graphql/queries/getVehicleYears.ts +21 -0
- package/src/graphql/queries/meAddresses.ts +56 -0
- package/src/graphql/queries/myOrders.ts +37 -0
- package/src/graphql/queries/orderDetail.ts +231 -0
- package/src/graphql/queries/productDetailsById.ts +197 -0
- package/src/graphql/queries/productInquiry.ts +115 -0
- package/src/graphql/queries/productsByCategoriesAndCollections.ts +39 -0
- package/src/graphql/queries/willCallCollectionPoints.ts +55 -0
- package/src/graphql/server-client.ts +54 -0
- package/src/graphql/types/categories.ts +9 -0
- package/src/graphql/types/checkout.ts +168 -0
- package/src/graphql/types/offer.ts +12 -0
- package/src/graphql/types/product.ts +44 -0
- package/src/hooks/scrollPageTop.ts +9 -0
- package/src/hooks/serverNavbarData.ts +79 -0
- package/src/hooks/useCartSync.ts +24 -0
- package/src/hooks/useRecaptcha.ts +33 -0
- package/src/hooks/useTokenExpiration.ts +81 -0
- package/src/hooks/useVehicleData.ts +346 -0
- package/src/lib/api/kount.ts +165 -0
- package/src/lib/api/shop.ts +1445 -0
- package/src/lib/saleor/getSaleorApiUrl.ts +25 -0
- package/src/lib/schema.ts +303 -0
- package/src/lib/seo/extractTextFromEditorJs.ts +58 -0
- package/src/lib/seo/site.ts +10 -0
- package/src/lib/urls/normalizeInternalUrl.ts +53 -0
- package/src/middleware.ts +134 -0
- package/src/sitemaps/README.md +105 -0
- package/src/sitemaps/dynamic-pages-sitemap.ts +247 -0
- package/src/sitemaps/sitemap-index.ts +21 -0
- package/src/sitemaps/static-pages-sitemap.ts +36 -0
- package/src/store/useGlobalStore.tsx +1656 -0
- package/src/types/global.d.ts +148 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility function to get the user's IP address
|
|
3
|
+
* This will try multiple methods to detect the user's IP
|
|
4
|
+
*/
|
|
5
|
+
export async function getUserIP(): Promise<string> {
|
|
6
|
+
try {
|
|
7
|
+
// Try ipify service first (most reliable)
|
|
8
|
+
const response = await fetch('https://api.ipify.org?format=json');
|
|
9
|
+
if (response.ok) {
|
|
10
|
+
const data = await response.json();
|
|
11
|
+
if (data.ip) return data.ip;
|
|
12
|
+
}
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.warn('Failed to get IP from ipify:', error);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
// Fallback to ipinfo.io
|
|
19
|
+
const response = await fetch('https://ipinfo.io/json');
|
|
20
|
+
if (response.ok) {
|
|
21
|
+
const data = await response.json();
|
|
22
|
+
if (data.ip) return data.ip;
|
|
23
|
+
}
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.warn('Failed to get IP from ipinfo.io:', error);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Final fallback - return a default IP
|
|
29
|
+
return '127.0.0.1';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Generate a random transaction ID for Kount
|
|
34
|
+
*/
|
|
35
|
+
export function generateTransactionId(): string {
|
|
36
|
+
return Array.from(crypto.getRandomValues(new Uint8Array(16)))
|
|
37
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
38
|
+
.join('');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate a valid device session ID for Kount
|
|
43
|
+
* Must be <= 36 characters and contain only alphanumeric, hyphen, and underscore
|
|
44
|
+
*/
|
|
45
|
+
export function generateDeviceSessionId(userId?: string, checkoutId?: string): string {
|
|
46
|
+
// Create a base from user ID or checkout ID if available
|
|
47
|
+
let base = '';
|
|
48
|
+
if (userId) {
|
|
49
|
+
base = userId.replace(/[^a-zA-Z0-9\-_]/g, '').substring(0, 16);
|
|
50
|
+
} else if (checkoutId) {
|
|
51
|
+
base = checkoutId.replace(/[^a-zA-Z0-9\-_]/g, '').substring(0, 16);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Generate random suffix to make it unique
|
|
55
|
+
const randomBytes = crypto.getRandomValues(new Uint8Array(8));
|
|
56
|
+
const randomSuffix = Array.from(randomBytes)
|
|
57
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
58
|
+
.join('');
|
|
59
|
+
|
|
60
|
+
// Combine base with random suffix, ensuring total length <= 36
|
|
61
|
+
const deviceSessionId = base ? `${base}-${randomSuffix}` : `device-${randomSuffix}`;
|
|
62
|
+
|
|
63
|
+
// Ensure it's not longer than 36 characters
|
|
64
|
+
return deviceSessionId.substring(0, 36);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Format date to RFC3339 format for Kount API
|
|
69
|
+
*/
|
|
70
|
+
export function formatRFC3339Date(date: Date): string {
|
|
71
|
+
return date.toISOString();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Payment type constants as defined by Kount API
|
|
76
|
+
*/
|
|
77
|
+
export const PAYMENT_TYPES = {
|
|
78
|
+
AFFIRM: 'AFFIRM',
|
|
79
|
+
AFTERPAY: 'AFTRPAY',
|
|
80
|
+
ALIPAY: 'ALIPAY',
|
|
81
|
+
AMAZON_PAY: 'AMZN',
|
|
82
|
+
APPLE_PAY: 'APAY',
|
|
83
|
+
BILL_ME_LATER: 'BLML',
|
|
84
|
+
BPAY: 'BPAY',
|
|
85
|
+
CARTE_BLEUE: 'CARTE_BLEUE',
|
|
86
|
+
CHECK: 'CHEK',
|
|
87
|
+
CREDIT_CARD: 'CREDIT_CARD',
|
|
88
|
+
CRYPTO: 'CRYPTO',
|
|
89
|
+
DEBIT_CARD: 'DEBIT_CARD',
|
|
90
|
+
ELV: 'ELV',
|
|
91
|
+
FACEBOOK_PAY: 'FBPAY',
|
|
92
|
+
GREEN_DOT_MONEY_PACK: 'GDMP',
|
|
93
|
+
GIFT_CARD: 'GIFT',
|
|
94
|
+
GIROPAY: 'GIROPAY',
|
|
95
|
+
GOOGLE_CHECKOUT: 'GOOG',
|
|
96
|
+
INTERAC: 'INTERAC',
|
|
97
|
+
KLARNA: 'KLARNA',
|
|
98
|
+
PAYPAL: 'PYPL',
|
|
99
|
+
MERCADE_PAGO: 'MERCADE_PAGO',
|
|
100
|
+
NETELLER: 'NETELLER',
|
|
101
|
+
NONE: 'NONE',
|
|
102
|
+
POLI: 'POLI',
|
|
103
|
+
SAMSUNG_PAY: 'SAMPAY',
|
|
104
|
+
SEPA: 'SEPA',
|
|
105
|
+
SKRILL: 'SKRILL',
|
|
106
|
+
SOFORT: 'SOFORT',
|
|
107
|
+
SPLITIT: 'SPLIT',
|
|
108
|
+
TOKEN: 'TOKEN',
|
|
109
|
+
WECHAT_PAY: 'WCPAY'
|
|
110
|
+
} as const;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Detect payment type based on card number patterns
|
|
114
|
+
* @param cardNumber - The card number (with or without spaces/dashes)
|
|
115
|
+
* @param paymentMethod - Optional payment method identifier
|
|
116
|
+
* @returns Payment type constant
|
|
117
|
+
*/
|
|
118
|
+
export function detectPaymentType(cardNumber: string, paymentMethod?: string): string {
|
|
119
|
+
// Handle non-card payment methods first
|
|
120
|
+
if (paymentMethod) {
|
|
121
|
+
const method = paymentMethod.toLowerCase();
|
|
122
|
+
|
|
123
|
+
if (method.includes('paypal')) return PAYMENT_TYPES.PAYPAL;
|
|
124
|
+
if (method.includes('apple') || method.includes('applepay')) return PAYMENT_TYPES.APPLE_PAY;
|
|
125
|
+
if (method.includes('google') || method.includes('googlepay')) return PAYMENT_TYPES.GOOGLE_CHECKOUT;
|
|
126
|
+
if (method.includes('samsung') || method.includes('samsungpay')) return PAYMENT_TYPES.SAMSUNG_PAY;
|
|
127
|
+
if (method.includes('amazon')) return PAYMENT_TYPES.AMAZON_PAY;
|
|
128
|
+
if (method.includes('affirm')) return PAYMENT_TYPES.AFFIRM;
|
|
129
|
+
if (method.includes('afterpay')) return PAYMENT_TYPES.AFTERPAY;
|
|
130
|
+
if (method.includes('klarna')) return PAYMENT_TYPES.KLARNA;
|
|
131
|
+
if (method.includes('alipay')) return PAYMENT_TYPES.ALIPAY;
|
|
132
|
+
if (method.includes('wechat')) return PAYMENT_TYPES.WECHAT_PAY;
|
|
133
|
+
if (method.includes('facebook')) return PAYMENT_TYPES.FACEBOOK_PAY;
|
|
134
|
+
if (method.includes('sofort')) return PAYMENT_TYPES.SOFORT;
|
|
135
|
+
if (method.includes('giropay')) return PAYMENT_TYPES.GIROPAY;
|
|
136
|
+
if (method.includes('sepa')) return PAYMENT_TYPES.SEPA;
|
|
137
|
+
if (method.includes('interac')) return PAYMENT_TYPES.INTERAC;
|
|
138
|
+
if (method.includes('splitit')) return PAYMENT_TYPES.SPLITIT;
|
|
139
|
+
if (method.includes('crypto') || method.includes('bitcoin') || method.includes('ethereum')) return PAYMENT_TYPES.CRYPTO;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Clean the card number - remove spaces, dashes, and any non-digit characters
|
|
143
|
+
const cleanCardNumber = cardNumber.replace(/\D/g, '');
|
|
144
|
+
|
|
145
|
+
// Return early if no valid card number
|
|
146
|
+
if (!cleanCardNumber || cleanCardNumber.length < 4) {
|
|
147
|
+
return PAYMENT_TYPES.CREDIT_CARD; // Default fallback
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Get first few digits for pattern matching
|
|
151
|
+
const firstDigit = cleanCardNumber.charAt(0);
|
|
152
|
+
const firstTwoDigits = cleanCardNumber.substring(0, 2);
|
|
153
|
+
const firstThreeDigits = cleanCardNumber.substring(0, 3);
|
|
154
|
+
const firstFourDigits = cleanCardNumber.substring(0, 4);
|
|
155
|
+
|
|
156
|
+
// Visa: starts with 4
|
|
157
|
+
if (firstDigit === '4') {
|
|
158
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Mastercard: starts with 5 (51-55) or 2 (2221-2720)
|
|
162
|
+
if (firstDigit === '5') {
|
|
163
|
+
const secondDigit = parseInt(cleanCardNumber.charAt(1));
|
|
164
|
+
if (secondDigit >= 1 && secondDigit <= 5) {
|
|
165
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (firstDigit === '2') {
|
|
169
|
+
const first4 = parseInt(firstFourDigits);
|
|
170
|
+
if (first4 >= 2221 && first4 <= 2720) {
|
|
171
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// American Express: starts with 34 or 37
|
|
176
|
+
if (firstTwoDigits === '34' || firstTwoDigits === '37') {
|
|
177
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Discover: starts with 6011, 622126-622925, 644-649, or 65
|
|
181
|
+
if (firstFourDigits === '6011' || firstTwoDigits === '65') {
|
|
182
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
183
|
+
}
|
|
184
|
+
if (firstTwoDigits === '64') {
|
|
185
|
+
const thirdDigit = parseInt(cleanCardNumber.charAt(2));
|
|
186
|
+
if (thirdDigit >= 4 && thirdDigit <= 9) {
|
|
187
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (firstThreeDigits === '622') {
|
|
191
|
+
const next3 = parseInt(cleanCardNumber.substring(3, 6));
|
|
192
|
+
if (next3 >= 126 && next3 <= 925) {
|
|
193
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Diners Club: starts with 300-305, 36, 38, or 54-55
|
|
198
|
+
if (firstThreeDigits >= '300' && firstThreeDigits <= '305') {
|
|
199
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
200
|
+
}
|
|
201
|
+
if (firstTwoDigits === '36' || firstTwoDigits === '38') {
|
|
202
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// JCB: starts with 35 or 2131/1800
|
|
206
|
+
if (firstTwoDigits === '35') {
|
|
207
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
208
|
+
}
|
|
209
|
+
if (firstFourDigits === '2131' || firstFourDigits === '1800') {
|
|
210
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// UnionPay: starts with 62
|
|
214
|
+
if (firstTwoDigits === '62') {
|
|
215
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Maestro: starts with 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763
|
|
219
|
+
const maestroPrefixes = ['5018', '5020', '5038', '5893', '6304', '6759', '6761', '6762', '6763'];
|
|
220
|
+
if (maestroPrefixes.includes(firstFourDigits)) {
|
|
221
|
+
return PAYMENT_TYPES.DEBIT_CARD;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// If we can't determine the specific type, default to credit card
|
|
225
|
+
return PAYMENT_TYPES.CREDIT_CARD;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Get a user-friendly name for the payment type
|
|
230
|
+
* @param paymentType - Payment type constant
|
|
231
|
+
* @returns Human-readable payment type name
|
|
232
|
+
*/
|
|
233
|
+
export function getPaymentTypeName(paymentType: string): string {
|
|
234
|
+
const names: Record<string, string> = {
|
|
235
|
+
[PAYMENT_TYPES.AFFIRM]: 'Affirm',
|
|
236
|
+
[PAYMENT_TYPES.AFTERPAY]: 'Afterpay',
|
|
237
|
+
[PAYMENT_TYPES.ALIPAY]: 'AliPay',
|
|
238
|
+
[PAYMENT_TYPES.AMAZON_PAY]: 'Amazon Pay',
|
|
239
|
+
[PAYMENT_TYPES.APPLE_PAY]: 'Apple Pay',
|
|
240
|
+
[PAYMENT_TYPES.BILL_ME_LATER]: 'Bill Me Later',
|
|
241
|
+
[PAYMENT_TYPES.BPAY]: 'BPAY',
|
|
242
|
+
[PAYMENT_TYPES.CARTE_BLEUE]: 'Carte Bleue',
|
|
243
|
+
[PAYMENT_TYPES.CHECK]: 'Check',
|
|
244
|
+
[PAYMENT_TYPES.CREDIT_CARD]: 'Credit Card',
|
|
245
|
+
[PAYMENT_TYPES.CRYPTO]: 'Crypto Payments',
|
|
246
|
+
[PAYMENT_TYPES.DEBIT_CARD]: 'Debit Card',
|
|
247
|
+
[PAYMENT_TYPES.ELV]: 'ELV',
|
|
248
|
+
[PAYMENT_TYPES.FACEBOOK_PAY]: 'Facebook Pay',
|
|
249
|
+
[PAYMENT_TYPES.GREEN_DOT_MONEY_PACK]: 'Green Dot Money Pack',
|
|
250
|
+
[PAYMENT_TYPES.GIFT_CARD]: 'Gift Card',
|
|
251
|
+
[PAYMENT_TYPES.GIROPAY]: 'GiroPay',
|
|
252
|
+
[PAYMENT_TYPES.GOOGLE_CHECKOUT]: 'Google Checkout',
|
|
253
|
+
[PAYMENT_TYPES.INTERAC]: 'Interac',
|
|
254
|
+
[PAYMENT_TYPES.KLARNA]: 'Klarna',
|
|
255
|
+
[PAYMENT_TYPES.PAYPAL]: 'PayPal',
|
|
256
|
+
[PAYMENT_TYPES.MERCADE_PAGO]: 'Mercade Pago',
|
|
257
|
+
[PAYMENT_TYPES.NETELLER]: 'Neteller',
|
|
258
|
+
[PAYMENT_TYPES.NONE]: 'None',
|
|
259
|
+
[PAYMENT_TYPES.POLI]: 'POLi',
|
|
260
|
+
[PAYMENT_TYPES.SAMSUNG_PAY]: 'Samsung Pay',
|
|
261
|
+
[PAYMENT_TYPES.SEPA]: 'Single Euro Payments Area',
|
|
262
|
+
[PAYMENT_TYPES.SKRILL]: 'Skrill/Moneybookers',
|
|
263
|
+
[PAYMENT_TYPES.SOFORT]: 'Sofort',
|
|
264
|
+
[PAYMENT_TYPES.SPLITIT]: 'Splitit',
|
|
265
|
+
[PAYMENT_TYPES.TOKEN]: 'Token provided from payment processor',
|
|
266
|
+
[PAYMENT_TYPES.WECHAT_PAY]: 'WeChat Pay'
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return names[paymentType] || 'Unknown Payment Type';
|
|
270
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { AppConfigurationResponse } from './appConfiguration';
|
|
2
|
+
import { fetchConfigurationDirect } from './configurationService';
|
|
3
|
+
import { cache } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Cached server-side configuration fetcher
|
|
7
|
+
* This will only run once per server request/render cycle
|
|
8
|
+
*/
|
|
9
|
+
export const getServerConfiguration = cache(async (): Promise<AppConfigurationResponse> => {
|
|
10
|
+
try {
|
|
11
|
+
const configuration = await fetchConfigurationDirect();
|
|
12
|
+
return configuration;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error('Server-side configuration fetch failed:', error);
|
|
15
|
+
|
|
16
|
+
// Return minimal fallback configuration
|
|
17
|
+
return {
|
|
18
|
+
internal: [
|
|
19
|
+
{ app_name: 'tiered_pricing', is_active: false }
|
|
20
|
+
],
|
|
21
|
+
external: [
|
|
22
|
+
{
|
|
23
|
+
app_name: 'dealer_locator',
|
|
24
|
+
configurations: { token: '' },
|
|
25
|
+
is_active: false
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
app_name: 'google_recaptcha',
|
|
29
|
+
configurations: {
|
|
30
|
+
site_key: '',
|
|
31
|
+
locations: {
|
|
32
|
+
login: false,
|
|
33
|
+
signup: false,
|
|
34
|
+
checkout: false
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
is_active: false
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
app_name: 'google_tag_manager',
|
|
41
|
+
configurations: { container_id: '' },
|
|
42
|
+
is_active: false
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
app_name: 'google_maps',
|
|
46
|
+
configurations: { api_key: '' },
|
|
47
|
+
is_active: false
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
app_name: 'google_analytics',
|
|
51
|
+
configurations: { measurement_id: '' },
|
|
52
|
+
is_active: false
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
app_name: 'google_adsense',
|
|
56
|
+
configurations: { publisher_id: '' },
|
|
57
|
+
is_active: false
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Server-side helper functions that extract only necessary client-side data
|
|
66
|
+
* This ensures we only send minimal, non-sensitive data to the client
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
export interface ClientSafeConfiguration {
|
|
70
|
+
features: {
|
|
71
|
+
dealer_locator: boolean;
|
|
72
|
+
tiered_pricing: boolean;
|
|
73
|
+
will_call: boolean;
|
|
74
|
+
};
|
|
75
|
+
dealer_locator: {
|
|
76
|
+
token: string | null;
|
|
77
|
+
};
|
|
78
|
+
google: {
|
|
79
|
+
recaptcha_site_key: string | null;
|
|
80
|
+
recaptcha_locations: {
|
|
81
|
+
login: boolean;
|
|
82
|
+
signup: boolean;
|
|
83
|
+
checkout: boolean;
|
|
84
|
+
};
|
|
85
|
+
tag_manager_container_id: string | null;
|
|
86
|
+
maps_api_key: string | null;
|
|
87
|
+
analytics_measurement_id: string | null;
|
|
88
|
+
adsense_publisher_id: string | null;
|
|
89
|
+
search_console_verification_content: string | null;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Extracts only client-safe configuration data
|
|
95
|
+
* This removes sensitive server-side configuration and only includes what the client needs
|
|
96
|
+
*/
|
|
97
|
+
export async function getClientSafeConfiguration(): Promise<ClientSafeConfiguration> {
|
|
98
|
+
const config = await getServerConfiguration();
|
|
99
|
+
// Helper function to find app configuration
|
|
100
|
+
const findInternalApp = (appName: string) =>
|
|
101
|
+
config.internal?.find(app => app.app_name === appName);
|
|
102
|
+
|
|
103
|
+
const findExternalApp = (appName: string) =>
|
|
104
|
+
config.external?.find(app => app.app_name === appName);
|
|
105
|
+
|
|
106
|
+
// Extract only client-safe configuration
|
|
107
|
+
const clientConfig: ClientSafeConfiguration = {
|
|
108
|
+
features: {
|
|
109
|
+
dealer_locator: findExternalApp('dealer_locator')?.is_active ?? false,
|
|
110
|
+
tiered_pricing: findInternalApp('tiered_pricing')?.is_active ?? false,
|
|
111
|
+
will_call: findExternalApp('will-call')?.is_active ?? false,
|
|
112
|
+
},
|
|
113
|
+
dealer_locator: {
|
|
114
|
+
token: (() => {
|
|
115
|
+
const app = findExternalApp('dealer_locator');
|
|
116
|
+
if (app?.is_active && app.configurations) {
|
|
117
|
+
return (app.configurations as import('./appConfiguration').DealerLocatorConfig).token || null;
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
})(),
|
|
121
|
+
},
|
|
122
|
+
google: {
|
|
123
|
+
recaptcha_site_key: (() => {
|
|
124
|
+
const app = findExternalApp('google_recaptcha');
|
|
125
|
+
if (app?.is_active && app.configurations) {
|
|
126
|
+
return (app.configurations as { site_key: string }).site_key || null;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
})(),
|
|
130
|
+
recaptcha_locations: (() => {
|
|
131
|
+
const app = findExternalApp('google_recaptcha');
|
|
132
|
+
if (app?.is_active && app.configurations) {
|
|
133
|
+
const config = app.configurations as { locations?: { login?: boolean; signup?: boolean; checkout?: boolean } };
|
|
134
|
+
return {
|
|
135
|
+
login: config.locations?.login ?? false,
|
|
136
|
+
signup: config.locations?.signup ?? false,
|
|
137
|
+
checkout: config.locations?.checkout ?? false,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
login: false,
|
|
142
|
+
signup: false,
|
|
143
|
+
checkout: false,
|
|
144
|
+
};
|
|
145
|
+
})(),
|
|
146
|
+
tag_manager_container_id: (() => {
|
|
147
|
+
const app = findExternalApp('google_tag_manager');
|
|
148
|
+
if (app?.is_active && app.configurations) {
|
|
149
|
+
return (app.configurations as { container_id: string }).container_id || null;
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
})(),
|
|
153
|
+
maps_api_key: (() => {
|
|
154
|
+
const app = findExternalApp('google_maps');
|
|
155
|
+
if (app?.is_active && app.configurations) {
|
|
156
|
+
return (app.configurations as { api_key: string }).api_key || null;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
})(),
|
|
160
|
+
analytics_measurement_id: (() => {
|
|
161
|
+
const app = findExternalApp('google_analytics');
|
|
162
|
+
if (app?.is_active && app.configurations) {
|
|
163
|
+
return (app.configurations as { measurement_id: string }).measurement_id || null;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
})(),
|
|
167
|
+
adsense_publisher_id: (() => {
|
|
168
|
+
const app = findExternalApp('google_adsense');
|
|
169
|
+
if (app?.is_active && app.configurations) {
|
|
170
|
+
return (app.configurations as { publisher_id: string }).publisher_id || null;
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
})(),
|
|
174
|
+
search_console_verification_content: (() => {
|
|
175
|
+
const app = findExternalApp('google_search_console');
|
|
176
|
+
if (app?.is_active && app.configurations) {
|
|
177
|
+
const metaTag = (app.configurations as import('./appConfiguration').GoogleSearchConsoleConfig).verification_meta_tag;
|
|
178
|
+
if (metaTag) {
|
|
179
|
+
// Extract content value from meta tag
|
|
180
|
+
const contentMatch = metaTag.match(/content="([^"]+)"/);
|
|
181
|
+
return contentMatch ? contentMatch[1] : null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return null;
|
|
185
|
+
})(),
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
return clientConfig;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Server-side feature check (for server components and middleware)
|
|
194
|
+
*/
|
|
195
|
+
export async function isFeatureEnabledOnServer(featureName: string): Promise<boolean> {
|
|
196
|
+
const config = await getServerConfiguration();
|
|
197
|
+
|
|
198
|
+
const internalApp = config.internal?.find(app => app.app_name === featureName);
|
|
199
|
+
if (internalApp) {
|
|
200
|
+
return internalApp.is_active;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const externalApp = config.external?.find(app => app.app_name === featureName);
|
|
204
|
+
if (externalApp) {
|
|
205
|
+
return externalApp.is_active;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export const GridIcon = (
|
|
2
|
+
<svg
|
|
3
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
4
|
+
width={20}
|
|
5
|
+
height={20}
|
|
6
|
+
viewBox="0 0 20 20"
|
|
7
|
+
fill="none"
|
|
8
|
+
>
|
|
9
|
+
<g clipPath="url(#clip0_960_52845)">
|
|
10
|
+
<path
|
|
11
|
+
d="M8.125 3.75H4.375C4.02982 3.75 3.75 4.02982 3.75 4.375V8.125C3.75 8.47018 4.02982 8.75 4.375 8.75H8.125C8.47018 8.75 8.75 8.47018 8.75 8.125V4.375C8.75 4.02982 8.47018 3.75 8.125 3.75Z"
|
|
12
|
+
stroke="currentColor"
|
|
13
|
+
strokeWidth="1.25"
|
|
14
|
+
strokeLinecap="round"
|
|
15
|
+
strokeLinejoin="round"
|
|
16
|
+
/>
|
|
17
|
+
<path
|
|
18
|
+
d="M15.625 3.75H11.875C11.5298 3.75 11.25 4.02982 11.25 4.375V8.125C11.25 8.47018 11.5298 8.75 11.875 8.75H15.625C15.9702 8.75 16.25 8.47018 16.25 8.125V4.375C16.25 4.02982 15.9702 3.75 15.625 3.75Z"
|
|
19
|
+
stroke="currentColor"
|
|
20
|
+
strokeWidth="1.25"
|
|
21
|
+
strokeLinecap="round"
|
|
22
|
+
strokeLinejoin="round"
|
|
23
|
+
/>
|
|
24
|
+
<path
|
|
25
|
+
d="M8.125 11.25H4.375C4.02982 11.25 3.75 11.5298 3.75 11.875V15.625C3.75 15.9702 4.02982 16.25 4.375 16.25H8.125C8.47018 16.25 8.75 15.9702 8.75 15.625V11.875C8.75 11.5298 8.47018 11.25 8.125 11.25Z"
|
|
26
|
+
stroke="currentColor"
|
|
27
|
+
strokeWidth="1.25"
|
|
28
|
+
strokeLinecap="round"
|
|
29
|
+
strokeLinejoin="round"
|
|
30
|
+
/>
|
|
31
|
+
<path
|
|
32
|
+
d="M15.625 11.25H11.875C11.5298 11.25 11.25 11.5298 11.25 11.875V15.625C11.25 15.9702 11.5298 16.25 11.875 16.25H15.625C15.9702 16.25 16.25 15.9702 16.25 15.625V11.875C16.25 11.5298 15.9702 11.25 15.625 11.25Z"
|
|
33
|
+
stroke="currentColor"
|
|
34
|
+
strokeWidth="1.25"
|
|
35
|
+
strokeLinecap="round"
|
|
36
|
+
strokeLinejoin="round"
|
|
37
|
+
/>
|
|
38
|
+
</g>
|
|
39
|
+
<defs>
|
|
40
|
+
<clipPath id="clip0_960_52845">
|
|
41
|
+
<rect width={20} height={20} fill="white" />
|
|
42
|
+
</clipPath>
|
|
43
|
+
</defs>
|
|
44
|
+
</svg>
|
|
45
|
+
);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const TickIcon = <svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clipPath="url(#clip0_960_55629)">
|
|
3
|
+
<path d="M1.875 6.75L4.5 9.375L10.5 3.375" stroke="#15803D" strokeWidth="0.75" strokeLinecap="round" strokeLinejoin="round" />
|
|
4
|
+
</g>
|
|
5
|
+
<defs>
|
|
6
|
+
<clipPath id="clip0_960_55629">
|
|
7
|
+
<rect width="12" height="12" fill="currentColor" />
|
|
8
|
+
</clipPath>
|
|
9
|
+
</defs>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export const InfoIcon = (
|
|
2
|
+
<svg viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
+
<g clipPath="url(#clip0_1456_102685)">
|
|
4
|
+
<path
|
|
5
|
+
opacity="0.2"
|
|
6
|
+
d="M33.75 10H13.75V30H33.75V10Z"
|
|
7
|
+
fill="currentColor"
|
|
8
|
+
/>
|
|
9
|
+
<path
|
|
10
|
+
d="M13.75 10H33.75"
|
|
11
|
+
stroke="currentColor"
|
|
12
|
+
strokeWidth="2.5"
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
/>
|
|
16
|
+
<path
|
|
17
|
+
d="M13.752 20H33.7504"
|
|
18
|
+
stroke="currentColor"
|
|
19
|
+
strokeWidth="2.5"
|
|
20
|
+
strokeLinecap="round"
|
|
21
|
+
strokeLinejoin="round"
|
|
22
|
+
/>
|
|
23
|
+
<path
|
|
24
|
+
d="M13.752 30H33.7504"
|
|
25
|
+
stroke="currentColor"
|
|
26
|
+
strokeWidth="2.5"
|
|
27
|
+
strokeLinecap="round"
|
|
28
|
+
strokeLinejoin="round"
|
|
29
|
+
/>
|
|
30
|
+
<path
|
|
31
|
+
d="M6.875 11.875C7.91053 11.875 8.75 11.0355 8.75 10C8.75 8.96447 7.91053 8.125 6.875 8.125C5.83947 8.125 5 8.96447 5 10C5 11.0355 5.83947 11.875 6.875 11.875Z"
|
|
32
|
+
fill="currentColor"
|
|
33
|
+
/>
|
|
34
|
+
<path
|
|
35
|
+
d="M6.875 21.875C7.91053 21.875 8.75 21.0355 8.75 20C8.75 18.9645 7.91053 18.125 6.875 18.125C5.83947 18.125 5 18.9645 5 20C5 21.0355 5.83947 21.875 6.875 21.875Z"
|
|
36
|
+
fill="currentColor"
|
|
37
|
+
/>
|
|
38
|
+
<path
|
|
39
|
+
d="M6.875 31.875C7.91053 31.875 8.75 31.0355 8.75 30C8.75 28.9645 7.91053 28.125 6.875 28.125C5.83947 28.125 5 28.9645 5 30C5 31.0355 5.83947 31.875 6.875 31.875Z"
|
|
40
|
+
fill="currentColor"
|
|
41
|
+
/>
|
|
42
|
+
</g>
|
|
43
|
+
<defs>
|
|
44
|
+
<clipPath id="clip0_1456_102685">
|
|
45
|
+
<rect width="40" height="40" fill="white" />
|
|
46
|
+
</clipPath>
|
|
47
|
+
</defs>
|
|
48
|
+
</svg>
|
|
49
|
+
);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const ArrowDownIcon = (
|
|
2
|
+
<svg
|
|
3
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
4
|
+
width="12"
|
|
5
|
+
height="7"
|
|
6
|
+
viewBox="0 0 12 7"
|
|
7
|
+
fill="none"
|
|
8
|
+
>
|
|
9
|
+
<path
|
|
10
|
+
d="M11 1L6 6L1 1"
|
|
11
|
+
stroke="#E5E5E5"
|
|
12
|
+
strokeLinecap="round"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
/>
|
|
15
|
+
</svg>
|
|
16
|
+
);
|
|
17
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const ArrowIcon = (
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none">
|
|
3
|
+
<g clipPath="url(#clip0_673_17)">
|
|
4
|
+
<path
|
|
5
|
+
d="M3.125 10H16.875"
|
|
6
|
+
stroke="currentColor"
|
|
7
|
+
strokeWidth="1.25"
|
|
8
|
+
strokeLinecap="round"
|
|
9
|
+
strokeLinejoin="round"
|
|
10
|
+
/>
|
|
11
|
+
<path
|
|
12
|
+
d="M11.25 4.375L16.875 10L11.25 15.625"
|
|
13
|
+
stroke="currentColor"
|
|
14
|
+
strokeWidth="1.25"
|
|
15
|
+
strokeLinecap="round"
|
|
16
|
+
strokeLinejoin="round"
|
|
17
|
+
/>
|
|
18
|
+
</g>
|
|
19
|
+
<defs>
|
|
20
|
+
<clipPath id="clip0_673_17">
|
|
21
|
+
<rect width={20} height={20} fill="currentColor" />
|
|
22
|
+
</clipPath>
|
|
23
|
+
</defs>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const ArrowUpIcon = (
|
|
2
|
+
<svg
|
|
3
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
4
|
+
width="12"
|
|
5
|
+
height="7"
|
|
6
|
+
viewBox="0 0 12 7"
|
|
7
|
+
fill="none"
|
|
8
|
+
>
|
|
9
|
+
<path
|
|
10
|
+
d="M11 6L6 1L1 6"
|
|
11
|
+
stroke="currentColor"
|
|
12
|
+
strokeLinecap="round"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
/>
|
|
15
|
+
</svg>
|
|
16
|
+
);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const brandSearchIcon = (
|
|
2
|
+
<svg
|
|
3
|
+
width={20}
|
|
4
|
+
height={20}
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
+
>
|
|
9
|
+
<g id="SVGRepo_bgCarrier" strokeWidth={0} />
|
|
10
|
+
<g
|
|
11
|
+
id="SVGRepo_tracerCarrier"
|
|
12
|
+
strokeLinecap="round"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
/>
|
|
15
|
+
<g id="SVGRepo_iconCarrier">
|
|
16
|
+
<path
|
|
17
|
+
d="M15.7955 15.8111L21 21M18 10.5C18 14.6421 14.6421 18 10.5 18C6.35786 18 3 14.6421 3 10.5C3 6.35786 6.35786 3 10.5 3C14.6421 3 18 6.35786 18 10.5Z"
|
|
18
|
+
stroke="#000000"
|
|
19
|
+
strokeWidth={2}
|
|
20
|
+
strokeLinecap="round"
|
|
21
|
+
strokeLinejoin="round"
|
|
22
|
+
/>
|
|
23
|
+
</g>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|