@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.
Files changed (441) hide show
  1. package/.env.example +57 -0
  2. package/APPLE_PAY_QUICK_START.md +165 -0
  3. package/APPLE_PAY_SETUP.md +331 -0
  4. package/README.md +46 -0
  5. package/SEO_AUDIT_CHECKLIST_STATUS.md +244 -0
  6. package/SEO_AUDIT_REPORT.md +66 -0
  7. package/eslint.config.mjs +16 -0
  8. package/next-env.d.ts +5 -0
  9. package/next.config.ts +109 -0
  10. package/package.json +47 -0
  11. package/postcss.config.mjs +5 -0
  12. package/public/.well-known/apple-developer-merchantid-domain-association +1 -0
  13. package/public/Logo.png +0 -0
  14. package/public/brand-video.mp4 +0 -0
  15. package/public/favicon.ico +0 -0
  16. package/public/file.svg +1 -0
  17. package/public/footer/facebook.tsx +34 -0
  18. package/public/footer/instagram.tsx +27 -0
  19. package/public/footer/mail.tsx +5 -0
  20. package/public/footer/x.tsx +35 -0
  21. package/public/globe.svg +1 -0
  22. package/public/icons/Authorize.net.webp +0 -0
  23. package/public/icons/amex.gif +0 -0
  24. package/public/icons/appIcon.png +0 -0
  25. package/public/icons/discover.gif +0 -0
  26. package/public/icons/master.gif +0 -0
  27. package/public/icons/paypal.png +0 -0
  28. package/public/icons/stripe.png +0 -0
  29. package/public/icons/visa.gif +0 -0
  30. package/public/images/BackgroundNoise.png +0 -0
  31. package/public/images/footer-background.png +0 -0
  32. package/public/next.svg +1 -0
  33. package/public/no-image-avail-large.png +0 -0
  34. package/public/random-car-1.jpeg +0 -0
  35. package/public/random-car-2.png +0 -0
  36. package/public/random-car-3.jpg +0 -0
  37. package/public/random-car-4.jpg +0 -0
  38. package/public/random-car-5.jpg +0 -0
  39. package/public/star.svg +3 -0
  40. package/public/vercel.svg +1 -0
  41. package/public/window.svg +1 -0
  42. package/scripts/seo-audit/generate-checklist.mjs +156 -0
  43. package/src/app/(auth)/account/forgot-password/layout.tsx +16 -0
  44. package/src/app/(auth)/account/forgot-password/page.tsx +135 -0
  45. package/src/app/(auth)/account/login/layout.tsx +16 -0
  46. package/src/app/(auth)/account/login/page.tsx +288 -0
  47. package/src/app/(auth)/account/otp/layout.tsx +16 -0
  48. package/src/app/(auth)/account/otp/page.tsx +108 -0
  49. package/src/app/(auth)/account/register/layout.tsx +16 -0
  50. package/src/app/(auth)/account/register/page.tsx +431 -0
  51. package/src/app/(auth)/account/reset-password/layout.tsx +16 -0
  52. package/src/app/(auth)/account/reset-password/page.tsx +222 -0
  53. package/src/app/[slug]/page.tsx +43 -0
  54. package/src/app/about/loading.tsx +17 -0
  55. package/src/app/about/page.tsx +61 -0
  56. package/src/app/account/address/layout.tsx +15 -0
  57. package/src/app/account/address/page.tsx +166 -0
  58. package/src/app/account/head.tsx +4 -0
  59. package/src/app/account/layout.tsx +62 -0
  60. package/src/app/account/orders/[id]/layout.tsx +17 -0
  61. package/src/app/account/orders/[id]/page.tsx +115 -0
  62. package/src/app/account/orders/components/orderDetailsModal.tsx +410 -0
  63. package/src/app/account/orders/layout.tsx +15 -0
  64. package/src/app/account/orders/page.tsx +146 -0
  65. package/src/app/account/page.tsx +39 -0
  66. package/src/app/account/settings/components/editProfileSuccessModal.tsx +28 -0
  67. package/src/app/account/settings/layout.tsx +15 -0
  68. package/src/app/account/settings/page.tsx +260 -0
  69. package/src/app/api/affirm/check-status/route.ts +94 -0
  70. package/src/app/api/affirm/create-checkout/route.ts +109 -0
  71. package/src/app/api/affirm/get-config/route.ts +108 -0
  72. package/src/app/api/affirm/process-payment/route.ts +244 -0
  73. package/src/app/api/affirm/test-connection/route.ts +45 -0
  74. package/src/app/api/auth/clear/route.ts +16 -0
  75. package/src/app/api/auth/clear-cookies/route.ts +42 -0
  76. package/src/app/api/auth/set/route.ts +47 -0
  77. package/src/app/api/configuration/route.ts +18 -0
  78. package/src/app/api/dynamic-page/[slug]/route.ts +24 -0
  79. package/src/app/api/form-submission/route.ts +237 -0
  80. package/src/app/api/paypal/capture-order/route.ts +303 -0
  81. package/src/app/api/paypal/create-order/route.ts +211 -0
  82. package/src/app/api/paypal/get-config/route.ts +240 -0
  83. package/src/app/api/search-proxy/route.ts +52 -0
  84. package/src/app/authorize-net-success/layout.tsx +19 -0
  85. package/src/app/authorize-net-success/page.tsx +12 -0
  86. package/src/app/authorize-net-success/summary.tsx +486 -0
  87. package/src/app/blog/[slug]/blogContentRenderer.tsx +369 -0
  88. package/src/app/blog/[slug]/layout.tsx +17 -0
  89. package/src/app/blog/[slug]/page.tsx +151 -0
  90. package/src/app/blog/constant.tsx +147 -0
  91. package/src/app/blog/layout.tsx +31 -0
  92. package/src/app/blog/page.tsx +81 -0
  93. package/src/app/brand/[id]/BrandPageClient.tsx +188 -0
  94. package/src/app/brand/[id]/layout.tsx +17 -0
  95. package/src/app/brand/[id]/page.tsx +176 -0
  96. package/src/app/brands/components/brandsListingClient.tsx +97 -0
  97. package/src/app/brands/layout.tsx +31 -0
  98. package/src/app/brands/page.tsx +40 -0
  99. package/src/app/cancellation-policy/page.tsx +53 -0
  100. package/src/app/cart/layout.tsx +19 -0
  101. package/src/app/cart/page.tsx +752 -0
  102. package/src/app/category/[slug]/CategoryPageClient.tsx +377 -0
  103. package/src/app/category/[slug]/layout.tsx +17 -0
  104. package/src/app/category/[slug]/page.tsx +224 -0
  105. package/src/app/category/page.tsx +114 -0
  106. package/src/app/checkout/components/addNewAddressModal.tsx +474 -0
  107. package/src/app/checkout/layout.tsx +19 -0
  108. package/src/app/checkout/page.tsx +3312 -0
  109. package/src/app/components/account/AccountTabs.tsx +40 -0
  110. package/src/app/components/ads/GoogleAdSense.tsx +74 -0
  111. package/src/app/components/analytics/AnalyticsScripts.tsx +78 -0
  112. package/src/app/components/analytics/ConditionalGTMNoscript.tsx +24 -0
  113. package/src/app/components/analytics/ConditionalGoogleAnalytics.tsx +16 -0
  114. package/src/app/components/ancillary/AncillaryContent.tsx +7 -0
  115. package/src/app/components/auth/TokenExpirationHandler.tsx +8 -0
  116. package/src/app/components/blog/BlogList.tsx +112 -0
  117. package/src/app/components/checkout/AddressInformationSection.tsx +34 -0
  118. package/src/app/components/checkout/AddressManagement.tsx +571 -0
  119. package/src/app/components/checkout/CheckoutHeader.tsx +51 -0
  120. package/src/app/components/checkout/CheckoutQuestions.tsx +454 -0
  121. package/src/app/components/checkout/CheckoutTermsModal.tsx +81 -0
  122. package/src/app/components/checkout/ContactDetailsSection.tsx +52 -0
  123. package/src/app/components/checkout/DealerShippingSection.tsx +359 -0
  124. package/src/app/components/checkout/DeliveryMethodSection.tsx +249 -0
  125. package/src/app/components/checkout/OrderSummary.tsx +386 -0
  126. package/src/app/components/checkout/TermsContentRenderer.tsx +147 -0
  127. package/src/app/components/checkout/WillCallSection.tsx +133 -0
  128. package/src/app/components/checkout/affirmPayment.tsx +383 -0
  129. package/src/app/components/checkout/checkoutProcessingModal.tsx +96 -0
  130. package/src/app/components/checkout/googlePayButton.tsx +334 -0
  131. package/src/app/components/checkout/paymentStep.tsx +180 -0
  132. package/src/app/components/checkout/paypalPayment.tsx +1083 -0
  133. package/src/app/components/checkout/saleorNativePayment.tsx +1758 -0
  134. package/src/app/components/dynamicPage/DynamicPageRenderer.tsx +13 -0
  135. package/src/app/components/dynamicPage/HtmlWidgetRenderer.tsx +144 -0
  136. package/src/app/components/filtersCollapsible/index.tsx +365 -0
  137. package/src/app/components/globalSearch/index.tsx +423 -0
  138. package/src/app/components/layout/cartDropDown.tsx +628 -0
  139. package/src/app/components/layout/components/FooterNewsletter.tsx +21 -0
  140. package/src/app/components/layout/footer.tsx +283 -0
  141. package/src/app/components/layout/header/accountMenuDropdown.tsx +53 -0
  142. package/src/app/components/layout/header/components/CartBadge.tsx +18 -0
  143. package/src/app/components/layout/header/components/LoadingState.tsx +17 -0
  144. package/src/app/components/layout/header/components/MenuItemDropdown.tsx +124 -0
  145. package/src/app/components/layout/header/components/MobileNavbar.tsx +123 -0
  146. package/src/app/components/layout/header/components/NavbarActions.tsx +125 -0
  147. package/src/app/components/layout/header/components/NavbarBrand.tsx +29 -0
  148. package/src/app/components/layout/header/components/NavigationLinks.tsx +131 -0
  149. package/src/app/components/layout/header/hamMenuSlide.tsx +318 -0
  150. package/src/app/components/layout/header/header.tsx +44 -0
  151. package/src/app/components/layout/header/hooks/useDropdown.ts +45 -0
  152. package/src/app/components/layout/header/hooks/useNavbarData.ts +138 -0
  153. package/src/app/components/layout/header/hooks/useNavbarState.ts +66 -0
  154. package/src/app/components/layout/header/megaMenuDropdown.tsx +116 -0
  155. package/src/app/components/layout/header/navBar.tsx +121 -0
  156. package/src/app/components/layout/header/search.tsx +418 -0
  157. package/src/app/components/layout/header/styles/navbarStyles.ts +27 -0
  158. package/src/app/components/layout/header/topBar.tsx +214 -0
  159. package/src/app/components/layout/joinNewsletterForm/index.tsx +72 -0
  160. package/src/app/components/layout/mobileAccordian/index.tsx +92 -0
  161. package/src/app/components/layout/paymentMethods.tsx +75 -0
  162. package/src/app/components/layout/rootLayout.tsx +23 -0
  163. package/src/app/components/layout/siteInfo.tsx +103 -0
  164. package/src/app/components/layout/socialLinks.tsx +65 -0
  165. package/src/app/components/newsletterSection/emailListSection.tsx +224 -0
  166. package/src/app/components/newsletterSection/emailSectionServer.tsx +8 -0
  167. package/src/app/components/providers/ApolloWrapper.tsx +12 -0
  168. package/src/app/components/providers/AppConfigurationProvider.tsx +108 -0
  169. package/src/app/components/providers/GoogleAnalyticsProvider.tsx +149 -0
  170. package/src/app/components/providers/GoogleTagManagerProvider.tsx +31 -0
  171. package/src/app/components/providers/RecaptchaProvider.tsx +18 -0
  172. package/src/app/components/providers/ServerAppConfigurationProvider.tsx +133 -0
  173. package/src/app/components/providers/YMMStatusProvider.tsx +15 -0
  174. package/src/app/components/reuseableUI/AboutUs.tsx +115 -0
  175. package/src/app/components/reuseableUI/AddToCartClient.tsx +125 -0
  176. package/src/app/components/reuseableUI/EditorJsRenderer.tsx +219 -0
  177. package/src/app/components/reuseableUI/HeroSectionsearchByVehicle.tsx +188 -0
  178. package/src/app/components/reuseableUI/ImageWithFallback.tsx +41 -0
  179. package/src/app/components/reuseableUI/Toast.tsx +101 -0
  180. package/src/app/components/reuseableUI/blogCard.tsx +52 -0
  181. package/src/app/components/reuseableUI/brandCard.tsx +68 -0
  182. package/src/app/components/reuseableUI/breadcrumb.tsx +38 -0
  183. package/src/app/components/reuseableUI/categoryCard.tsx +37 -0
  184. package/src/app/components/reuseableUI/categorySkeleton.tsx +31 -0
  185. package/src/app/components/reuseableUI/commonButton.tsx +48 -0
  186. package/src/app/components/reuseableUI/defaultInputField/index.tsx +84 -0
  187. package/src/app/components/reuseableUI/emptyState.tsx +29 -0
  188. package/src/app/components/reuseableUI/errorTag.tsx +15 -0
  189. package/src/app/components/reuseableUI/heading/index.tsx +20 -0
  190. package/src/app/components/reuseableUI/input.tsx +117 -0
  191. package/src/app/components/reuseableUI/listCard.tsx +137 -0
  192. package/src/app/components/reuseableUI/loadingUI.tsx +12 -0
  193. package/src/app/components/reuseableUI/modalLayout.tsx +76 -0
  194. package/src/app/components/reuseableUI/newsletter/newsletterClient.tsx +622 -0
  195. package/src/app/components/reuseableUI/newsletter/newslettersHomeModal.tsx +68 -0
  196. package/src/app/components/reuseableUI/offerCard.tsx +42 -0
  197. package/src/app/components/reuseableUI/passwordRules/passwordRules.tsx +56 -0
  198. package/src/app/components/reuseableUI/primaryButton/index.tsx +34 -0
  199. package/src/app/components/reuseableUI/productCard.tsx +118 -0
  200. package/src/app/components/reuseableUI/productSkeleton.tsx +34 -0
  201. package/src/app/components/reuseableUI/searchByVehicle.tsx +187 -0
  202. package/src/app/components/reuseableUI/secondaryButton/index.tsx +34 -0
  203. package/src/app/components/reuseableUI/section.tsx +20 -0
  204. package/src/app/components/reuseableUI/select/index.tsx +98 -0
  205. package/src/app/components/reuseableUI/skeletonLoader.tsx +117 -0
  206. package/src/app/components/reuseableUI/statusTag.tsx +24 -0
  207. package/src/app/components/reuseableUI/tags/saleTag.tsx +19 -0
  208. package/src/app/components/reuseableUI/testimonialCard.tsx +93 -0
  209. package/src/app/components/richText/EditorRenderer.tsx +318 -0
  210. package/src/app/components/search/HierarchicalCategoryFilter.tsx +155 -0
  211. package/src/app/components/search/SearchFilters.tsx +155 -0
  212. package/src/app/components/search/YMMSearchSidebar.tsx +187 -0
  213. package/src/app/components/seo/ServerProductCard.tsx +91 -0
  214. package/src/app/components/seo/ServerProductGrid.tsx +45 -0
  215. package/src/app/components/shop/CategoryFilter.tsx +184 -0
  216. package/src/app/components/shop/ItemsPerPageSelect.tsx +69 -0
  217. package/src/app/components/shop/ItemsPerPageSelectClient.tsx +58 -0
  218. package/src/app/components/shop/MobileFilters.tsx +103 -0
  219. package/src/app/components/shop/ProductGridSkeleton.tsx +16 -0
  220. package/src/app/components/shop/ProductsGrid.tsx +230 -0
  221. package/src/app/components/shop/SearchFilter.tsx +218 -0
  222. package/src/app/components/shop/SearchFilterClient.tsx +122 -0
  223. package/src/app/components/shop/SearchLoadingOverlay.tsx +32 -0
  224. package/src/app/components/shop/ShopMobileFilters.tsx +205 -0
  225. package/src/app/components/showroom/VehicleSearchDropdowns.tsx +187 -0
  226. package/src/app/components/showroom/brandsSwiper.tsx +49 -0
  227. package/src/app/components/showroom/brandsSwiperClient copy.tsx +93 -0
  228. package/src/app/components/showroom/brandsSwiperClient.tsx +122 -0
  229. package/src/app/components/showroom/brandsSwiperServer.tsx +42 -0
  230. package/src/app/components/showroom/bundleProducts.tsx +120 -0
  231. package/src/app/components/showroom/categoryGrid.tsx +51 -0
  232. package/src/app/components/showroom/categoryGridServer.tsx +45 -0
  233. package/src/app/components/showroom/categorySwiper.tsx +115 -0
  234. package/src/app/components/showroom/featureStrip.tsx +139 -0
  235. package/src/app/components/showroom/offersSwiper.tsx +181 -0
  236. package/src/app/components/showroom/productGrid.tsx +56 -0
  237. package/src/app/components/showroom/productSwiper.tsx +119 -0
  238. package/src/app/components/showroom/promotion-slider.tsx +138 -0
  239. package/src/app/components/showroom/promotion.tsx +207 -0
  240. package/src/app/components/showroom/promotionsSwiper.tsx +174 -0
  241. package/src/app/components/showroom/showroomHeroCarousel.tsx +141 -0
  242. package/src/app/components/showroom/testimonialsGrid.tsx +106 -0
  243. package/src/app/components/skeletons/ContentSkeleton.tsx +14 -0
  244. package/src/app/components/sortDropdown/index.tsx +116 -0
  245. package/src/app/components/tertiaryButton/index.tsx +25 -0
  246. package/src/app/components/theme/theme-provider.tsx +82 -0
  247. package/src/app/contact/layout.tsx +32 -0
  248. package/src/app/contact/page.tsx +591 -0
  249. package/src/app/content/[slug]/layout.tsx +17 -0
  250. package/src/app/content/[slug]/page.tsx +159 -0
  251. package/src/app/content/layout.tsx +31 -0
  252. package/src/app/content/page.tsx +88 -0
  253. package/src/app/core-policies/page.tsx +55 -0
  254. package/src/app/discounts/page.tsx +54 -0
  255. package/src/app/frequently-asked-questions/page.tsx +57 -0
  256. package/src/app/globals.css +440 -0
  257. package/src/app/hooks/useDealerLocations.ts +259 -0
  258. package/src/app/hooks/useGTMEngagement.ts +71 -0
  259. package/src/app/hooks/useGoogleAnalytics.ts +145 -0
  260. package/src/app/layout.tsx +149 -0
  261. package/src/app/not-found.tsx +31 -0
  262. package/src/app/order-confirmation/layout.tsx +19 -0
  263. package/src/app/order-confirmation/page.tsx +12 -0
  264. package/src/app/order-confirmation/summary.tsx +1775 -0
  265. package/src/app/page.tsx +194 -0
  266. package/src/app/privacy-policy/loading.tsx +17 -0
  267. package/src/app/privacy-policy/page.tsx +56 -0
  268. package/src/app/product/[id]/ProductDetailClient.tsx +2448 -0
  269. package/src/app/product/[id]/components/itemInquiryModal.tsx +461 -0
  270. package/src/app/product/[id]/layout.tsx +116 -0
  271. package/src/app/product/[id]/page.tsx +200 -0
  272. package/src/app/product/layout.tsx +15 -0
  273. package/src/app/products/all/AllProductsClient.tsx +743 -0
  274. package/src/app/products/all/page.tsx +176 -0
  275. package/src/app/products/components/shopEmptyState.tsx +29 -0
  276. package/src/app/request-return/layout.tsx +36 -0
  277. package/src/app/request-return/page.tsx +597 -0
  278. package/src/app/robots.txt/route.ts +27 -0
  279. package/src/app/search/layout.tsx +16 -0
  280. package/src/app/search/page.tsx +736 -0
  281. package/src/app/shipping-returns/page.tsx +60 -0
  282. package/src/app/site-map/layout.tsx +33 -0
  283. package/src/app/site-map/page.tsx +113 -0
  284. package/src/app/sitemap-index.xml/route.ts +20 -0
  285. package/src/app/sitemap.ts +10 -0
  286. package/src/app/terms-and-conditions/loading.tsx +17 -0
  287. package/src/app/terms-and-conditions/page.tsx +56 -0
  288. package/src/app/utils/appConfiguration.ts +327 -0
  289. package/src/app/utils/branding.ts +52 -0
  290. package/src/app/utils/configurationService.ts +202 -0
  291. package/src/app/utils/constant.tsx +242 -0
  292. package/src/app/utils/editorJsUtils.tsx +249 -0
  293. package/src/app/utils/functions.ts +146 -0
  294. package/src/app/utils/googleAnalytics.ts +168 -0
  295. package/src/app/utils/googleTagManager.ts +475 -0
  296. package/src/app/utils/ipDetection.ts +270 -0
  297. package/src/app/utils/serverConfigurationService.ts +209 -0
  298. package/src/app/utils/svgs/GridIcon.tsx +45 -0
  299. package/src/app/utils/svgs/account/myAccount/listDotIcon.tsx +3 -0
  300. package/src/app/utils/svgs/account/myAccount/tickIcon.tsx +10 -0
  301. package/src/app/utils/svgs/account/orderHistory/InfoIcon.tsx +49 -0
  302. package/src/app/utils/svgs/arrowDownIcon.tsx +17 -0
  303. package/src/app/utils/svgs/arrowIcon.tsx +25 -0
  304. package/src/app/utils/svgs/arrowUpIcon.tsx +16 -0
  305. package/src/app/utils/svgs/brandsSearchIcon.tsx +25 -0
  306. package/src/app/utils/svgs/cart/cartIcon.tsx +31 -0
  307. package/src/app/utils/svgs/cart/plusIcon.tsx +13 -0
  308. package/src/app/utils/svgs/cart/subtractIcon.tsx +13 -0
  309. package/src/app/utils/svgs/cart/successTickIcon.tsx +14 -0
  310. package/src/app/utils/svgs/chevronDownIcon.tsx +21 -0
  311. package/src/app/utils/svgs/closeEyeIcon.tsx +47 -0
  312. package/src/app/utils/svgs/crossIcon.tsx +25 -0
  313. package/src/app/utils/svgs/eyeIcon.tsx +29 -0
  314. package/src/app/utils/svgs/featureTag.tsx +20 -0
  315. package/src/app/utils/svgs/filterIcon.tsx +3 -0
  316. package/src/app/utils/svgs/globleIcon.tsx +41 -0
  317. package/src/app/utils/svgs/infoIcon.tsx +34 -0
  318. package/src/app/utils/svgs/listIcon.tsx +50 -0
  319. package/src/app/utils/svgs/logOutIcon.tsx +35 -0
  320. package/src/app/utils/svgs/menuIcon.tsx +8 -0
  321. package/src/app/utils/svgs/minusIcon.tsx +18 -0
  322. package/src/app/utils/svgs/newsletterIcon.tsx +19 -0
  323. package/src/app/utils/svgs/noDataFoundIcon-.tsx +26 -0
  324. package/src/app/utils/svgs/noProductFoundIcon.tsx +43 -0
  325. package/src/app/utils/svgs/passwordIcons/errorIcon.tsx +31 -0
  326. package/src/app/utils/svgs/passwordIcons/successIcon.tsx +24 -0
  327. package/src/app/utils/svgs/paymentProcessingIcons/hourglassIcon.tsx +43 -0
  328. package/src/app/utils/svgs/paymentProcessingIcons/modalCrossIcon.tsx +23 -0
  329. package/src/app/utils/svgs/paymentProcessingIcons/paymentFailedIcon.tsx +47 -0
  330. package/src/app/utils/svgs/pencilIcon.tsx +11 -0
  331. package/src/app/utils/svgs/plusIcon.tsx +25 -0
  332. package/src/app/utils/svgs/productInquiryIcon.tsx +40 -0
  333. package/src/app/utils/svgs/searchIcon.tsx +31 -0
  334. package/src/app/utils/svgs/shoppingCart.tsx +32 -0
  335. package/src/app/utils/svgs/spinnerIcon.tsx +22 -0
  336. package/src/app/utils/svgs/spinnerLoadingIcon.tsx +26 -0
  337. package/src/app/utils/svgs/successTickIcon.tsx +40 -0
  338. package/src/app/utils/svgs/swiperArrowIconLeft.tsx +18 -0
  339. package/src/app/utils/svgs/swiperArrowIconRight.tsx +18 -0
  340. package/src/app/utils/svgs/userProfileIcon.tsx +31 -0
  341. package/src/app/utils/svgs/warningCircleIcon.tsx +15 -0
  342. package/src/app/warranty/constant.tsx +63 -0
  343. package/src/app/warranty/loading.tsx +17 -0
  344. package/src/app/warranty/page.tsx +56 -0
  345. package/src/graphql/client.ts +288 -0
  346. package/src/graphql/mutations/accountAddressCreate.ts +56 -0
  347. package/src/graphql/mutations/accountAddressDelete.ts +23 -0
  348. package/src/graphql/mutations/accountAddressUpdate.ts +55 -0
  349. package/src/graphql/mutations/accountSetDefaultAddress.ts +32 -0
  350. package/src/graphql/mutations/accountUpdate.ts +34 -0
  351. package/src/graphql/mutations/changePassword.ts +25 -0
  352. package/src/graphql/mutations/checkout.ts +117 -0
  353. package/src/graphql/mutations/checkoutAddVoucher.ts +63 -0
  354. package/src/graphql/mutations/checkoutComplete.ts +79 -0
  355. package/src/graphql/mutations/checkoutCreate.ts +131 -0
  356. package/src/graphql/mutations/checkoutCustomerAttach.ts +50 -0
  357. package/src/graphql/mutations/checkoutEmailUpdate.ts +15 -0
  358. package/src/graphql/mutations/checkoutLineMetadataUpdate.ts +52 -0
  359. package/src/graphql/mutations/checkoutPaymentCreate.ts +82 -0
  360. package/src/graphql/mutations/paymentGatewayInitialize.ts +58 -0
  361. package/src/graphql/mutations/registerAccount.ts +65 -0
  362. package/src/graphql/mutations/requestPasswordReset.ts +32 -0
  363. package/src/graphql/mutations/setPassword.ts +49 -0
  364. package/src/graphql/mutations/signIn.ts +50 -0
  365. package/src/graphql/mutations/tokenRefresh.ts +19 -0
  366. package/src/graphql/mutations/updateCheckoutMetadata.ts +49 -0
  367. package/src/graphql/mutations/updateProfile.ts +18 -0
  368. package/src/graphql/mutations/willCallDeliveryMethod.ts +81 -0
  369. package/src/graphql/queries/checkout.ts +168 -0
  370. package/src/graphql/queries/findProductByOldSlug.ts +58 -0
  371. package/src/graphql/queries/getAboutPage.ts +24 -0
  372. package/src/graphql/queries/getAboutPageId.ts +9 -0
  373. package/src/graphql/queries/getAboutUs.ts +38 -0
  374. package/src/graphql/queries/getAddressInformation.ts +38 -0
  375. package/src/graphql/queries/getAllCategories.ts +41 -0
  376. package/src/graphql/queries/getAllCategoriesTree.ts +67 -0
  377. package/src/graphql/queries/getAllCategoriesWithProducts.ts +29 -0
  378. package/src/graphql/queries/getAllCollectionsWithProducts.ts +16 -0
  379. package/src/graphql/queries/getBlogs.ts +222 -0
  380. package/src/graphql/queries/getBrands.ts +17 -0
  381. package/src/graphql/queries/getBundles.ts +43 -0
  382. package/src/graphql/queries/getCategories.ts +20 -0
  383. package/src/graphql/queries/getChannels.ts +77 -0
  384. package/src/graphql/queries/getCheckoutQuestions.ts +115 -0
  385. package/src/graphql/queries/getCheckoutTermsAndConditions.ts +37 -0
  386. package/src/graphql/queries/getContactPage.ts +117 -0
  387. package/src/graphql/queries/getContentPage.ts +191 -0
  388. package/src/graphql/queries/getDiscountOffers.ts +18 -0
  389. package/src/graphql/queries/getDynamicPageBySlug.ts +251 -0
  390. package/src/graphql/queries/getFeaturedProducts.ts +48 -0
  391. package/src/graphql/queries/getHeroMetadata.ts +23 -0
  392. package/src/graphql/queries/getMenuBySlug.ts +84 -0
  393. package/src/graphql/queries/getMyProfile.ts +23 -0
  394. package/src/graphql/queries/getNewsletter.ts +122 -0
  395. package/src/graphql/queries/getNewsletterPage.ts +111 -0
  396. package/src/graphql/queries/getPageBySlug.ts +52 -0
  397. package/src/graphql/queries/getPageTypeId.ts +27 -0
  398. package/src/graphql/queries/getPaymentMethods.ts +61 -0
  399. package/src/graphql/queries/getProducts.ts +78 -0
  400. package/src/graphql/queries/getPromotions.ts +24 -0
  401. package/src/graphql/queries/getRequestReturnPage.ts +121 -0
  402. package/src/graphql/queries/getSiteInfo.ts +54 -0
  403. package/src/graphql/queries/getSocialLinks.ts +52 -0
  404. package/src/graphql/queries/getTestimonials.ts +25 -0
  405. package/src/graphql/queries/getUserWithCheckout.ts +27 -0
  406. package/src/graphql/queries/getVehicleMakes.ts +21 -0
  407. package/src/graphql/queries/getVehicleModels.ts +21 -0
  408. package/src/graphql/queries/getVehicleYears.ts +21 -0
  409. package/src/graphql/queries/meAddresses.ts +56 -0
  410. package/src/graphql/queries/myOrders.ts +37 -0
  411. package/src/graphql/queries/orderDetail.ts +231 -0
  412. package/src/graphql/queries/productDetailsById.ts +197 -0
  413. package/src/graphql/queries/productInquiry.ts +115 -0
  414. package/src/graphql/queries/productsByCategoriesAndCollections.ts +39 -0
  415. package/src/graphql/queries/willCallCollectionPoints.ts +55 -0
  416. package/src/graphql/server-client.ts +54 -0
  417. package/src/graphql/types/categories.ts +9 -0
  418. package/src/graphql/types/checkout.ts +168 -0
  419. package/src/graphql/types/offer.ts +12 -0
  420. package/src/graphql/types/product.ts +44 -0
  421. package/src/hooks/scrollPageTop.ts +9 -0
  422. package/src/hooks/serverNavbarData.ts +79 -0
  423. package/src/hooks/useCartSync.ts +24 -0
  424. package/src/hooks/useRecaptcha.ts +33 -0
  425. package/src/hooks/useTokenExpiration.ts +81 -0
  426. package/src/hooks/useVehicleData.ts +346 -0
  427. package/src/lib/api/kount.ts +165 -0
  428. package/src/lib/api/shop.ts +1445 -0
  429. package/src/lib/saleor/getSaleorApiUrl.ts +25 -0
  430. package/src/lib/schema.ts +303 -0
  431. package/src/lib/seo/extractTextFromEditorJs.ts +58 -0
  432. package/src/lib/seo/site.ts +10 -0
  433. package/src/lib/urls/normalizeInternalUrl.ts +53 -0
  434. package/src/middleware.ts +134 -0
  435. package/src/sitemaps/README.md +105 -0
  436. package/src/sitemaps/dynamic-pages-sitemap.ts +247 -0
  437. package/src/sitemaps/sitemap-index.ts +21 -0
  438. package/src/sitemaps/static-pages-sitemap.ts +36 -0
  439. package/src/store/useGlobalStore.tsx +1656 -0
  440. package/src/types/global.d.ts +148 -0
  441. package/tsconfig.json +27 -0
@@ -0,0 +1,115 @@
1
+ 'use client';
2
+
3
+ import Image from 'next/image';
4
+ import Link from 'next/link';
5
+ import { useQuery } from '@apollo/client';
6
+ import { ORDER_DETAIL, type OrderDetailData } from '@/graphql/queries/orderDetail';
7
+ import { useParams } from 'next/navigation';
8
+
9
+ export default function OrderDetailsPage() {
10
+ const params = useParams<{ id: string }>();
11
+ const id = params?.id as string;
12
+ const { data, loading, error } = useQuery<OrderDetailData>(ORDER_DETAIL, {
13
+ variables: { token: id },
14
+ skip: !id,
15
+ });
16
+ const order = data?.orderByToken || null;
17
+
18
+ return (
19
+ <div className="max-w-7xl mx-auto px-4 py-8">
20
+ <div className="mb-6">
21
+ <Link href="/account/orders" className="text-amber-600 hover:text-amber-700 font-medium">
22
+ ← Back to Orders
23
+ </Link>
24
+ <h1 className="text-2xl font-bold mt-2">Order Details</h1>
25
+ </div>
26
+ {loading ? (
27
+ <div className="p-8 text-center text-gray-500">Loading order...</div>
28
+ ) : error ? (
29
+ <div className="p-8 text-center text-red-600">Failed to load order.</div>
30
+ ) : !order ? (
31
+ <div className="p-8 text-center text-gray-500">Order not found.</div>
32
+ ) : (
33
+
34
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
35
+ <div className="lg:col-span-2">
36
+ <div className="bg-white rounded-md shadow-sm p-6 mb-8">
37
+ <div className="flex flex-wrap justify-between items-center mb-6">
38
+ <div>
39
+ <h2 className="text-lg font-semibold">#{order.number ?? order.id}</h2>
40
+ <p className="text-gray-600">Placed on {new Date(order.created).toLocaleDateString()}</p>
41
+ </div>
42
+ <span className="px-3 py-1 bg-green-100 text-green-800 rounded-full text-sm font-medium">
43
+ {order.statusDisplay || order.status}
44
+ </span>
45
+ </div>
46
+
47
+ <div className="space-y-4">
48
+ {order.lines.map((item) => (
49
+ <div key={item.id} className="flex items-center border-b border-gray-100 pb-4 last:border-b-0 last:pb-0">
50
+ <div className="relative w-16 h-16 flex-shrink-0 bg-gray-100 rounded-md overflow-hidden">
51
+ {item.thumbnail?.url ? (
52
+ <Image
53
+ src={item.thumbnail.url}
54
+ alt={item.thumbnail.alt || item.productName}
55
+ className="object-contain w-full h-full"
56
+ width={150}
57
+ height={150}
58
+ />
59
+ ) : null}
60
+ </div>
61
+ <div className="ml-4 flex-1">
62
+ <h3 className="font-medium">{item.productName}{item.variantName ? ` - ${item.variantName}` : ''}</h3>
63
+ <p className="text-gray-600 text-sm">Qty: {item.quantity}</p>
64
+ </div>
65
+ <div className="font-semibold">
66
+ {new Intl.NumberFormat(undefined, { style: 'currency', currency: item.totalPrice.gross.currency }).format(item.totalPrice.gross.amount)}
67
+ </div>
68
+ </div>
69
+ ))}
70
+ </div>
71
+ </div>
72
+ </div>
73
+
74
+ <div className="lg:col-span-1">
75
+ <div className="bg-white rounded-md shadow-sm p-6 mb-8">
76
+ <h2 className="text-lg font-semibold mb-4">Order Summary</h2>
77
+
78
+ <div className="space-y-2 mb-4">
79
+ <div className="flex justify-between">
80
+ <span>Subtotal</span>
81
+ <span>{new Intl.NumberFormat(undefined, { style: 'currency', currency: order.subtotal.gross.currency }).format(order.subtotal.gross.amount)}</span>
82
+ </div>
83
+ <div className="flex justify-between">
84
+ <span>Shipping</span>
85
+ <span>{new Intl.NumberFormat(undefined, { style: 'currency', currency: order.shippingPrice.gross.currency }).format(order.shippingPrice.gross.amount)}</span>
86
+ </div>
87
+ <div className="border-t border-gray-200 pt-2 flex justify-between font-semibold">
88
+ <span>Total</span>
89
+ <span>{new Intl.NumberFormat(undefined, { style: 'currency', currency: order.total.gross.currency }).format(order.total.gross.amount)}</span>
90
+ </div>
91
+ </div>
92
+ </div>
93
+
94
+ <div className="bg-white rounded-md shadow-sm p-6">
95
+ <h2 className="text-lg font-semibold mb-4">Shipping Address</h2>
96
+ <p className="text-gray-600 mb-4">
97
+ {order.shippingAddress?.firstName} {order.shippingAddress?.lastName}<br />
98
+ {order.shippingAddress?.streetAddress1}{order.shippingAddress?.streetAddress2 ? `, ${order.shippingAddress?.streetAddress2}` : ''}<br />
99
+ {order.shippingAddress?.city}, {order.shippingAddress?.countryArea} {order.shippingAddress?.postalCode}<br />
100
+ {order.shippingAddress?.phone}
101
+ </p>
102
+
103
+ <h2 className="text-lg font-semibold mb-4">Billing Address</h2>
104
+ <p className="text-gray-600">
105
+ {order.billingAddress?.firstName} {order.billingAddress?.lastName}<br />
106
+ {order.billingAddress?.streetAddress1}{order.billingAddress?.streetAddress2 ? `, ${order.billingAddress?.streetAddress2}` : ''}<br />
107
+ {order.billingAddress?.city}, {order.billingAddress?.countryArea} {order.billingAddress?.postalCode}
108
+ </p>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ )}
113
+ </div>
114
+ );
115
+ }
@@ -0,0 +1,410 @@
1
+ import EmptyState from "@/app/components/reuseableUI/emptyState";
2
+ import LoadingUI from "@/app/components/reuseableUI/loadingUI";
3
+ import ModalLayout from "@/app/components/reuseableUI/modalLayout";
4
+ import StatusTag from "@/app/components/reuseableUI/statusTag";
5
+ import {
6
+ ORDER_DETAIL,
7
+ type OrderDetailData,
8
+ type OrderLine,
9
+ type MetadataItem,
10
+ } from "@/graphql/queries/orderDetail";
11
+ import { useQuery } from "@apollo/client";
12
+ import Image from "next/image";
13
+ import { useMemo } from "react";
14
+
15
+ // Types for option set handling
16
+ type OptionSetMetadata = {
17
+ name: string;
18
+ label: string;
19
+ type?: string;
20
+ hidden?: boolean;
21
+ deselect?: string;
22
+ required?: boolean;
23
+ base_product_required?: boolean;
24
+ };
25
+
26
+ type OptionItem = {
27
+ lineId: string;
28
+ variantId: string;
29
+ variantName: string;
30
+ optionSetLabel: string;
31
+ price: number;
32
+ currency: string;
33
+ };
34
+
35
+ type CustomInput = {
36
+ key: string;
37
+ value: string;
38
+ };
39
+
40
+ type GroupedOrderItem = {
41
+ id: string;
42
+ name: string;
43
+ variantName: string | null;
44
+ category: string;
45
+ thumbnail: { url: string; alt: string | null } | null;
46
+ quantity: number;
47
+ basePrice: number;
48
+ totalPrice: { gross: { amount: number; currency: string } };
49
+ currency: string;
50
+ options: OptionItem[];
51
+ customInputs: CustomInput[];
52
+ };
53
+
54
+ // Helper to parse option_set metadata from a variant
55
+ function parseOptionSetMetadata(
56
+ metadata: MetadataItem[] | null | undefined
57
+ ): OptionSetMetadata | null {
58
+ if (!metadata) return null;
59
+ const optionMeta = metadata.find((m) => m.key === "option_set");
60
+ if (!optionMeta?.value) return null;
61
+ try {
62
+ return JSON.parse(optionMeta.value) as OptionSetMetadata;
63
+ } catch {
64
+ return null;
65
+ }
66
+ }
67
+
68
+ // Helper to extract custom inputs from line metadata (non-SKU option sets)
69
+ function extractCustomInputs(
70
+ lineMetadata: MetadataItem[] | null | undefined
71
+ ): CustomInput[] {
72
+ if (!lineMetadata || lineMetadata.length === 0) return [];
73
+
74
+ // Filter out system metadata keys that aren't custom inputs
75
+ const systemKeys = new Set([
76
+ "__typename",
77
+ "option_set",
78
+ "wsm_availability",
79
+ "wsm_brand",
80
+ "wsm_condition",
81
+ "wsm_cost",
82
+ "wsm_dealer_id",
83
+ "wsm_height",
84
+ "wsm_id",
85
+ "wsm_inventory",
86
+ "wsm_length",
87
+ "wsm_price",
88
+ "wsm_sale_price",
89
+ "wsm_upscode",
90
+ "wsm_width",
91
+ ]);
92
+
93
+ return lineMetadata
94
+ .filter((m) => !systemKeys.has(m.key))
95
+ .map((m) => ({ key: m.key, value: m.value }));
96
+ }
97
+
98
+ // Group order lines by product, separating base products from options
99
+ function groupOrderLines(lines: OrderLine[]): GroupedOrderItem[] {
100
+ // Build a map of product ID -> lines for that product
101
+ const productMap = new Map<
102
+ string,
103
+ {
104
+ baseLine: OrderLine | null;
105
+ optionLines: Array<{
106
+ line: OrderLine;
107
+ optionMeta: OptionSetMetadata;
108
+ }>;
109
+ }
110
+ >();
111
+
112
+ for (const line of lines) {
113
+ const variant = line.variant;
114
+ if (!variant) {
115
+ // Line has no variant info - treat as standalone item
116
+ const standaloneId = `standalone-${line.id}`;
117
+ productMap.set(standaloneId, { baseLine: line, optionLines: [] });
118
+ continue;
119
+ }
120
+
121
+ const productId = variant.product.id;
122
+ const optionMeta = parseOptionSetMetadata(variant.metadata);
123
+
124
+ if (!productMap.has(productId)) {
125
+ productMap.set(productId, { baseLine: null, optionLines: [] });
126
+ }
127
+
128
+ const entry = productMap.get(productId)!;
129
+
130
+ if (optionMeta) {
131
+ // This is an option variant (SKU-based option set)
132
+ entry.optionLines.push({ line, optionMeta });
133
+ } else {
134
+ // This is a base product variant
135
+ entry.baseLine = line;
136
+ }
137
+ }
138
+
139
+ // Convert the map into grouped items
140
+ const groupedItems: GroupedOrderItem[] = [];
141
+
142
+ for (const [, entry] of productMap) {
143
+ const { baseLine, optionLines } = entry;
144
+
145
+ // Determine the display line (prefer base, fall back to first option)
146
+ const displayLine = baseLine ?? optionLines[0]?.line;
147
+ if (!displayLine) continue;
148
+
149
+ const variant = displayLine.variant;
150
+ const productName = displayLine.productName ?? variant?.product.name ?? "Unknown Product";
151
+ const variantName = displayLine.variantName;
152
+ const category = variant?.product.category?.name ?? "Uncategorized";
153
+ const thumbnail = displayLine.thumbnail;
154
+
155
+ // Calculate base price (0 if no base line)
156
+ let basePrice = 0;
157
+ if (baseLine) {
158
+ basePrice = baseLine.totalPrice.gross.amount;
159
+ }
160
+
161
+ // Build SKU-based options array
162
+ const options: OptionItem[] = optionLines.map(({ line, optionMeta }) => ({
163
+ lineId: line.id,
164
+ variantId: line.variant?.id ?? "",
165
+ variantName: line.variant?.name ?? line.variantName ?? "",
166
+ optionSetLabel: optionMeta.label || optionMeta.name,
167
+ price: line.totalPrice.gross.amount,
168
+ currency: line.totalPrice.gross.currency,
169
+ }));
170
+
171
+ // Extract non-SKU custom inputs from line metadata
172
+ const customInputs = extractCustomInputs(displayLine.metadata);
173
+
174
+ // Calculate combined total price
175
+ const combinedAmount = basePrice + options.reduce((sum, opt) => sum + opt.price, 0);
176
+ const currency = displayLine.totalPrice.gross.currency || options[0]?.currency || "USD";
177
+
178
+ groupedItems.push({
179
+ id: displayLine.id,
180
+ name: productName,
181
+ variantName,
182
+ category,
183
+ thumbnail,
184
+ quantity: displayLine.quantity,
185
+ basePrice,
186
+ totalPrice: {
187
+ gross: { amount: combinedAmount, currency },
188
+ },
189
+ currency,
190
+ options,
191
+ customInputs,
192
+ });
193
+ }
194
+
195
+ return groupedItems;
196
+ }
197
+
198
+ const OrderDetailsModal = ({
199
+ orderId,
200
+ isModalOpen,
201
+ onClose,
202
+ }: {
203
+ orderId: string;
204
+ isModalOpen: boolean;
205
+ onClose: () => void;
206
+ }) => {
207
+ const { data, loading, error } = useQuery<OrderDetailData>(ORDER_DETAIL, {
208
+ variables: { token: orderId },
209
+ skip: !orderId,
210
+ });
211
+ const order = data?.orderByToken || null;
212
+
213
+ // Group order lines by product with options
214
+ const groupedLines = useMemo(() => {
215
+ if (!order?.lines) return [];
216
+ return groupOrderLines(order.lines);
217
+ }, [order?.lines]);
218
+
219
+ return (
220
+ <ModalLayout isModalOpen={isModalOpen} onClose={onClose} className="lg:h-[calc(100dvh-33vh)] lg:overflow-y-auto">
221
+ <div>
222
+ {loading ? (
223
+ <LoadingUI className="h-[30vh]" />
224
+ ) : error ? (
225
+ <EmptyState text="Unable to load order details." className="h-[30vh]" />
226
+ ) : !order ? (
227
+ <EmptyState text="Order not found." className="h-[30vh]" />
228
+ ) : (
229
+ <div className="grid grid-cols-1 gap-4">
230
+ <div className="flex flex-col gap-5 pb-4">
231
+ <div className="flex items-center gap-2">
232
+ <p className="font-semibold font-secondary text-[var(--color-secondary-800)] ">
233
+ ORDER DETAILS
234
+ </p>
235
+ <StatusTag label={order.statusDisplay || order.status} />
236
+ </div>
237
+ <div className="flex items-center gap-10 uppercase text-[var(--color-secondary-600)] font-normal text-sm font-secondary">
238
+ <div className="flex items-center gap-1">
239
+ <p>Order Number</p>
240
+ <p className="text-[var(--color-secondary-800)] font-semibold">
241
+ {order.number ?? order.id}
242
+ </p>
243
+ </div>
244
+ <div className="flex items-center gap-1">
245
+ <p>Placed on</p>
246
+ <p className="text-[var(--color-secondary-800)] font-semibold">
247
+ {new Date(order.created).toLocaleDateString()}
248
+ </p>
249
+ </div>
250
+ </div>
251
+ </div>
252
+
253
+ <div className="space-y-4 border-y border-[var(--color-secondary-200)] py-4">
254
+ {groupedLines.map((item) => (
255
+ <div
256
+ key={item.id}
257
+ className="flex items-start border-b border-gray-100 pb-4 last:border-b-0 last:pb-0"
258
+ >
259
+ <div className="relative w-16 h-16 flex-shrink-0 bg-gray-100 rounded-md overflow-hidden">
260
+ {item.thumbnail?.url ? (
261
+ <Image
262
+ src={item.thumbnail.url}
263
+ alt={item.thumbnail.alt || item.name}
264
+ className="object-contain w-full h-full"
265
+ width={150}
266
+ height={150}
267
+ />
268
+ ) : null}
269
+ </div>
270
+ <div className="ml-4 flex-1">
271
+ <h3 className="font-medium text-xs md:text-base text-[var(--color-secondary-800)]">
272
+ {item.name}
273
+ </h3>
274
+ {/* Display SKU-based options */}
275
+ {item.options.length > 0 && (
276
+ <div className="mt-1 space-y-0.5">
277
+ {item.options.map((option) => (
278
+ <div
279
+ key={option.lineId}
280
+ className="text-xs text-[var(--color-secondary-600)] flex items-center gap-1"
281
+ >
282
+ <span className="text-[var(--color-primary-600)]">+</span>
283
+ <span className="font-medium">{option.optionSetLabel}:</span>
284
+ <span>{option.variantName}</span>
285
+ {option.price > 0 && (
286
+ <span className="text-[var(--color-primary-600)]">
287
+ (+{new Intl.NumberFormat(undefined, {
288
+ style: "currency",
289
+ currency: option.currency,
290
+ }).format(option.price)})
291
+ </span>
292
+ )}
293
+ </div>
294
+ ))}
295
+ </div>
296
+ )}
297
+ {/* Display non-SKU custom inputs */}
298
+ {item.customInputs.length > 0 && (
299
+ <div className="mt-1 space-y-0.5">
300
+ {item.customInputs.map((input, idx) => (
301
+ <div
302
+ key={`${input.key}-${idx}`}
303
+ className="text-xs text-[var(--color-secondary-600)] flex items-center gap-1"
304
+ >
305
+ <span className="font-medium">{input.key}:</span>
306
+ <span>{input.value}</span>
307
+ </div>
308
+ ))}
309
+ </div>
310
+ )}
311
+ <p className="text-gray-600 text-xs md:text-sm mt-1">
312
+ Qty: {item.quantity}
313
+ </p>
314
+ </div>
315
+ <div className="font-semibold pl-4 lg:pl-0 whitespace-nowrap">
316
+ {new Intl.NumberFormat(undefined, {
317
+ style: "currency",
318
+ currency: item.totalPrice.gross.currency,
319
+ }).format(item.totalPrice.gross.amount)}
320
+ </div>
321
+ </div>
322
+ ))}
323
+ </div>
324
+ {order.shippingAddress && (
325
+ <div className="border-b pb-4 border-[var(--color-secondary-200)]">
326
+ <h2 className="text-xl font-secondary text-[var(--color-secondary-800)] uppercase font-semibold mb-4">Shipping Address</h2>
327
+ <div className='flex items-center gap-2 text-medium text-xl font-secondary text-[var(--color-secondary-800)]'>
328
+ {order.shippingAddress?.streetAddress1}
329
+ {order.shippingAddress?.streetAddress2
330
+ ? `, ${order.shippingAddress?.streetAddress2}`
331
+ : ""}
332
+ {order.shippingAddress?.city},{" "}
333
+ {order.shippingAddress?.countryArea}{" "}
334
+
335
+ </div>
336
+ <p className='text-medium text-lg font-secondary text-[var(--color-secondary-500)]'>{order.shippingAddress?.phone}</p>
337
+
338
+ </div>
339
+ )}
340
+ {
341
+ order.billingAddress && (
342
+ <div className="border-b pb-4 border-[var(--color-secondary-200)]">
343
+ <h2 className="text-xl font-secondary text-[var(--color-secondary-800)] uppercase font-semibold mb-4">Billing Address</h2>
344
+ <p className="text-gray-600">
345
+ {order.billingAddress?.firstName} {order.billingAddress?.lastName}
346
+ <br />
347
+ {order.billingAddress?.streetAddress1}
348
+ {order.billingAddress?.streetAddress2
349
+ ? `, ${order.billingAddress?.streetAddress2}`
350
+ : ""}
351
+ <br />
352
+ {order.billingAddress?.city}, {order.billingAddress?.countryArea}{" "}
353
+ {order.billingAddress?.postalCode}
354
+ </p>
355
+ </div>
356
+ )}
357
+ {
358
+ order.shippingMethodName && (
359
+ <div className="border-b pb-4 border-[var(--color-secondary-200)]">
360
+ <h2 className="text-xl font-secondary text-[var(--color-secondary-800)] uppercase font-semibold mb-4">DELIVERY METHOD</h2>
361
+ <p className="text-gray-600">
362
+ {order.shippingMethodName}
363
+ </p>
364
+ </div>
365
+ )}
366
+ <div>
367
+ <h2 className="text-xl uppercase font-secondary font-semibold mb-4">
368
+ Summary
369
+ </h2>
370
+
371
+ <div className="space-y-4">
372
+ <div className="flex justify-between">
373
+ <span>Subtotal</span>
374
+ <span>
375
+ {new Intl.NumberFormat(undefined, {
376
+ style: "currency",
377
+ currency: order.subtotal.gross.currency,
378
+ }).format(order.subtotal.gross.amount)}
379
+ </span>
380
+ </div>
381
+ <div className="flex justify-between">
382
+ <span>Shipping</span>
383
+ <span>
384
+ {new Intl.NumberFormat(undefined, {
385
+ style: "currency",
386
+ currency: order.shippingPrice.gross.currency,
387
+ }).format(order.shippingPrice.gross.amount)}
388
+ </span>
389
+ </div>
390
+ <div className="border-t border-gray-200 pt-4 flex justify-between font-medium text-xl text-[var(--color-secondary-600)]">
391
+ <span>Total</span>
392
+ <span className="text-[var(--color-primary-600)] font-semibold">
393
+ {new Intl.NumberFormat(undefined, {
394
+ style: "currency",
395
+ currency: order.total.gross.currency,
396
+ }).format(order.total.gross.amount)}
397
+ </span>
398
+ </div>
399
+ </div>
400
+ </div>
401
+
402
+
403
+ </div>
404
+ )}
405
+ </div>
406
+ </ModalLayout>
407
+ );
408
+ };
409
+
410
+ export default OrderDetailsModal;
@@ -0,0 +1,15 @@
1
+ import type { Metadata } from "next"
2
+ import { getStoreName } from "@/app/utils/branding"
3
+
4
+ export const metadata: Metadata = {
5
+ title: `Order History - ${getStoreName()}`,
6
+ description: "View your complete order history, track shipments, and manage returns. Access invoices and order details easily.",
7
+ }
8
+
9
+ export default function OrdersLayout({
10
+ children,
11
+ }: {
12
+ children: React.ReactNode
13
+ }) {
14
+ return children
15
+ }
@@ -0,0 +1,146 @@
1
+ "use client";
2
+
3
+ import CommonButton from "@/app/components/reuseableUI/commonButton";
4
+ import EmptyState from "@/app/components/reuseableUI/emptyState";
5
+ import LoadingUI from "@/app/components/reuseableUI/loadingUI";
6
+ import StatusTag from "@/app/components/reuseableUI/statusTag";
7
+ import { InfoIcon } from "@/app/utils/svgs/account/orderHistory/InfoIcon";
8
+ import { MY_ORDERS, type MyOrdersData } from "@/graphql/queries/myOrders";
9
+ import { useQuery } from "@apollo/client";
10
+ import { useRouter, useSearchParams } from "next/navigation";
11
+ import { useState, useEffect, Suspense } from "react";
12
+ import OrderDetailsModal from "./components/orderDetailsModal";
13
+ const NoOrdersSection = () => {
14
+ const router = useRouter();
15
+ return (
16
+ <div className="font-secondary space-y-10 h-[50vh] flex flex-col justify-center">
17
+ <div className="text-center">
18
+ <div className="text-black p-3 md:p-5 rounded-full [&>svg]:size-6 md:[&>svg]:size-10 border border-[var(--color-secondary-300)] bg-[var(--color-secondary-200)] w-fit mx-auto mb-5">
19
+ {InfoIcon}
20
+ </div>
21
+ <p className="font-semibold text-base md:text-xl text-[var(--color-secondary-800)] uppercase pb-2">
22
+ You Haven&apos;t Placed Any Orders Yet
23
+ </p>
24
+ <p className="text-xs md:text-sm font-normal text-[var(--color-secondary-600)]">
25
+ Once you make a purchase, your order history will appear here. Start
26
+ shopping now to track your orders and manage your purchases.
27
+ </p>
28
+ </div>
29
+ <CommonButton
30
+ className="mx-auto text-sm md:text-base py-2.5 md:py-3"
31
+ variant="secondary"
32
+ onClick={() => router.push("/")}
33
+ >
34
+ GO TO HOME
35
+ </CommonButton>
36
+ </div>
37
+ );
38
+ };
39
+ function OrderHistoryPageContent() {
40
+ const searchParams = useSearchParams();
41
+ const { data, loading, error, refetch } = useQuery<MyOrdersData>(MY_ORDERS, {
42
+ fetchPolicy: "cache-and-network", // Always fetch fresh data from server
43
+ notifyOnNetworkStatusChange: true, // Show loading states during refetch
44
+ });
45
+ const [isModalOpen, setIsModalOpen] = useState(false);
46
+ const [selectedOrderId, setSelectedOrderId] = useState<string | null>(null);
47
+
48
+ // Force refetch when coming from success page (has timestamp parameter)
49
+ useEffect(() => {
50
+ const timestamp = searchParams.get("t");
51
+ if (timestamp) {
52
+ // Small delay to ensure component is fully mounted
53
+ setTimeout(() => {
54
+ refetch();
55
+ }, 100);
56
+ }
57
+ }, [searchParams, refetch]);
58
+ const edges = data?.me?.orders?.edges ?? [];
59
+ if (error) {
60
+ console.error("MyOrders query error:", error);
61
+ }
62
+ return (
63
+ <>
64
+ <div>
65
+ <h2 className="text-lg lg:text-xl text-[var(--color-secondary-800)] font-secondary font-semibold">
66
+ ORDER HISTORY
67
+ </h2>
68
+ {loading ? (
69
+ <LoadingUI />
70
+ ) : error ? (
71
+ <EmptyState className="h-[50vh]" text="Failed to load orders." />
72
+ ) : edges.length === 0 ? (
73
+ <NoOrdersSection />
74
+ ) : (
75
+ <div className="overflow-x-auto">
76
+ <table className="min-w-full divide-y divide-gray-200 table-fixed">
77
+ <thead>
78
+ <tr className="[&>th]:py-4 [&>th]:text-left [&>th]:text-sm [&>th]:font-normal [&>th]:text-[var(--color-secondary-400)] [&>th]:uppercase [&>th]:whitespace-nowrap [&>th]:min-w-[152px]">
79
+ <th>ORDER DETAILS</th>
80
+ <th>ORDER NUMBER</th>
81
+ <th>PLACED ON</th>
82
+ <th>STATUS</th>
83
+ <th>Action</th>
84
+ </tr>
85
+ </thead>
86
+ <tbody className="divide-y divide-gray-200">
87
+ {edges.map(({ node }) => (
88
+ <tr
89
+ key={node.id}
90
+ className="[&>td]:py-4 [&>td]:text-left [&>td]:text-sm [&>td]:font-normal [&>td]:text-[var(--color-secondary-800)] [&>td]:pr-1"
91
+ >
92
+ <td>
93
+ <CommonButton
94
+ className="p-0 text-sm"
95
+ variant="tertiary"
96
+ onClick={() => {
97
+ setSelectedOrderId(node.token);
98
+ setIsModalOpen(true);
99
+ }}
100
+ >
101
+ View Details
102
+ </CommonButton>
103
+ </td>
104
+ <td className="whitespace-nowrap text-sm font-medium text-gray-900">
105
+ #{node.number ?? node.id}
106
+ </td>
107
+ <td className="whitespace-nowrap text-sm text-gray-500">
108
+ {new Date(node.created).toLocaleDateString()}
109
+ </td>
110
+ <td className="whitespace-nowrap">
111
+ <StatusTag
112
+ label={node.status}
113
+ className="lg:min-w-36 text-center"
114
+ />
115
+ </td>
116
+ <td>
117
+ <CommonButton
118
+ className="p-0 cursor-not-allowed opacity-50 hover:text-normal text-sm lg:text-base"
119
+ variant="tertiarySecondary"
120
+ >
121
+ Request Return
122
+ </CommonButton>
123
+ </td>
124
+ </tr>
125
+ ))}
126
+ </tbody>
127
+ </table>
128
+ </div>
129
+ )}
130
+ </div>
131
+ <OrderDetailsModal
132
+ orderId={selectedOrderId || ""}
133
+ isModalOpen={isModalOpen}
134
+ onClose={() => setIsModalOpen(false)}
135
+ />
136
+ </>
137
+ );
138
+ }
139
+
140
+ export default function OrderHistoryPage() {
141
+ return (
142
+ <Suspense fallback={<LoadingUI />}>
143
+ <OrderHistoryPageContent />
144
+ </Suspense>
145
+ );
146
+ }