@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,369 @@
1
+ import React from "react";
2
+ import Link from "next/link";
3
+
4
+ export type EditorJsBlock = {
5
+ id: string;
6
+ type: string;
7
+ data: {
8
+ text?: string;
9
+ level?: number;
10
+ style?: "ordered" | "unordered";
11
+ items?: string[];
12
+ caption?: string;
13
+ alignment?: "left" | "center" | "right";
14
+ };
15
+ };
16
+
17
+ // Helper function to decode HTML entities
18
+ function decodeHtmlEntities(text: string): string {
19
+ const textarea =
20
+ typeof document !== "undefined" ? document.createElement("textarea") : null;
21
+
22
+ if (textarea) {
23
+ textarea.innerHTML = text;
24
+ return textarea.value;
25
+ }
26
+
27
+ // Fallback for server-side rendering
28
+ return text
29
+ .replace(/&lt;/g, "<")
30
+ .replace(/&gt;/g, ">")
31
+ .replace(/&amp;/g, "&")
32
+ .replace(/&quot;/g, '"')
33
+ .replace(/&#39;/g, "'")
34
+ .replace(/&nbsp;/g, " ");
35
+ }
36
+
37
+ // Helper function to make all anchor tags open in new tab
38
+ function processAnchorsForNewTab(html: string): string {
39
+ // Match <a tags and add target="_blank" rel="noopener noreferrer"
40
+ return html.replace(
41
+ /<a\s+([^>]*?)>/gi,
42
+ (match, attributes) => {
43
+ // Check if target already exists
44
+ if (/target\s*=/i.test(attributes)) {
45
+ return match;
46
+ }
47
+ return `<a ${attributes} target="_blank" rel="noopener noreferrer">`;
48
+ }
49
+ );
50
+ }
51
+
52
+ // Helper function to check if text contains HTML table elements
53
+ function isTableFragment(text: string): boolean {
54
+ const tablePatterns = [
55
+ /<table/i,
56
+ /<\/table>/i,
57
+ /<thead/i,
58
+ /<\/thead>/i,
59
+ /<tbody/i,
60
+ /<\/tbody>/i,
61
+ /<tr/i,
62
+ /<\/tr>/i,
63
+ /<td/i,
64
+ /<\/td>/i,
65
+ /<th/i,
66
+ /<\/th>/i,
67
+ /<colgroup/i,
68
+ /<\/colgroup>/i,
69
+ /<col/i,
70
+ ];
71
+ return tablePatterns.some((pattern) => pattern.test(text));
72
+ }
73
+
74
+ // Helper function to merge table fragments
75
+ function mergeTableBlocks(blocks: EditorJsBlock[]): EditorJsBlock[] {
76
+ const merged: EditorJsBlock[] = [];
77
+ let tableBuffer: string[] = [];
78
+ let tableStartId: string | null = null;
79
+ let isInTable = false;
80
+
81
+ for (let i = 0; i < blocks.length; i++) {
82
+ const block = blocks[i];
83
+ const text = block.data?.text || "";
84
+ const decodedText = decodeHtmlEntities(text);
85
+
86
+ // Check if this starts a table
87
+ if (/<table/i.test(decodedText)) {
88
+ isInTable = true;
89
+ tableStartId = block.id;
90
+ }
91
+
92
+ if (
93
+ block.type === "paragraph" &&
94
+ (isInTable || isTableFragment(decodedText))
95
+ ) {
96
+ // Start or continue accumulating table content
97
+ if (!tableStartId) {
98
+ tableStartId = block.id;
99
+ isInTable = true;
100
+ }
101
+
102
+ // Clean up individual fragments: remove <br> tags and preserve whitespace
103
+ const cleanedText = decodedText
104
+ .replace(/<br\s*\/?>/gi, "")
105
+ .replace(/^\s+|\s+$/g, ""); // Trim leading/trailing whitespace only
106
+
107
+ if (cleanedText) {
108
+ tableBuffer.push(cleanedText);
109
+ }
110
+
111
+ // Check if this closes the table
112
+ if (/<\/table>/i.test(decodedText)) {
113
+ isInTable = false;
114
+ // Create merged table block
115
+ const mergedHTML = tableBuffer.join("");
116
+ merged.push({
117
+ id: tableStartId || block.id,
118
+ type: "table",
119
+ data: {
120
+ text: mergedHTML,
121
+ },
122
+ });
123
+ tableBuffer = [];
124
+ tableStartId = null;
125
+ }
126
+ } else {
127
+ // If we have accumulated table content, create a merged block
128
+ if (tableBuffer.length > 0 && tableStartId) {
129
+ // Join without extra newlines to preserve HTML structure
130
+ const mergedHTML = tableBuffer.join("");
131
+ merged.push({
132
+ id: tableStartId,
133
+ type: "table",
134
+ data: {
135
+ text: mergedHTML,
136
+ },
137
+ });
138
+ tableBuffer = [];
139
+ tableStartId = null;
140
+ isInTable = false;
141
+ }
142
+ // Add the non-table block
143
+ merged.push(block);
144
+ }
145
+ }
146
+
147
+ // Handle any remaining table content
148
+ if (tableBuffer.length > 0 && tableStartId) {
149
+ const mergedHTML = tableBuffer.join("");
150
+ merged.push({
151
+ id: tableStartId,
152
+ type: "table",
153
+ data: {
154
+ text: mergedHTML,
155
+ },
156
+ });
157
+ }
158
+
159
+ return merged;
160
+ }
161
+
162
+ export default function BlogEditorRenderer({
163
+ content,
164
+ }: {
165
+ content: string | null | undefined;
166
+ }) {
167
+ let blocks: EditorJsBlock[] = [];
168
+ if (content) {
169
+ try {
170
+ const parsed = JSON.parse(content);
171
+ if (Array.isArray(parsed?.blocks)) {
172
+ blocks = parsed.blocks as EditorJsBlock[];
173
+ }
174
+ } catch (_) {}
175
+ }
176
+
177
+ if (!blocks.length) {
178
+ return (
179
+ <div className="w-full p-6">
180
+ <h2 className="text-xl font-semibold">Call for Availability</h2>
181
+ </div>
182
+ );
183
+ }
184
+
185
+ // Merge table fragments before rendering
186
+ const mergedBlocks = mergeTableBlocks(blocks);
187
+
188
+ const renderBlock = (block: EditorJsBlock) => {
189
+ const { type, data } = block;
190
+ const html = processAnchorsForNewTab(decodeHtmlEntities(data?.text || ""));
191
+
192
+ switch (type) {
193
+ case "table":
194
+ return (
195
+ <div
196
+ key={block.id}
197
+ className="table-wrapper my-6"
198
+ dangerouslySetInnerHTML={{ __html: data?.text || "" }}
199
+ />
200
+ );
201
+ case "header": {
202
+ const level = Math.min(Math.max(Number(data?.level) || 3, 1), 6);
203
+ return React.createElement(`h${level}`, {
204
+ key: block.id,
205
+ className: "text-2xl font-semibold leading-8 tracking-[-0.06px] my-6",
206
+ dangerouslySetInnerHTML: { __html: html },
207
+ });
208
+ }
209
+ case "list": {
210
+ const style = data?.style || "unordered";
211
+ const items = Array.isArray(data?.items) ? data.items : [];
212
+ const ListTag = style === "ordered" ? "ol" : "ul";
213
+ const listClassName =
214
+ style === "ordered"
215
+ ? "list-decimal list-inside my-4 space-y-2 text-lg leading-7 tracking-[-0.045px]"
216
+ : "list-disc list-inside my-4 space-y-2 text-lg leading-7 tracking-[-0.045px]";
217
+
218
+ return (
219
+ <ListTag key={block.id} className={listClassName}>
220
+ {items.map((item, idx) => (
221
+ <li
222
+ key={`${block.id}-${idx}`}
223
+ dangerouslySetInnerHTML={{ __html: processAnchorsForNewTab(decodeHtmlEntities(item)) }}
224
+ />
225
+ ))}
226
+ </ListTag>
227
+ );
228
+ }
229
+ case "quote": {
230
+ const alignment = data?.alignment || "left";
231
+ const alignmentClass = alignment === "center" ? "text-center" : alignment === "right" ? "text-right" : "text-left";
232
+ return (
233
+ <blockquote
234
+ key={block.id}
235
+ className={`my-6 pl-4 border-l-4 border-[var(--color-primary-600)] italic text-lg leading-7 text-[var(--color-secondary-700)] ${alignmentClass}`}
236
+ >
237
+ <p dangerouslySetInnerHTML={{ __html: html }} />
238
+ {data?.caption && data.caption !== data.text && (
239
+ <cite
240
+ className="block mt-2 text-sm not-italic text-[var(--color-secondary-500)]"
241
+ dangerouslySetInnerHTML={{ __html: processAnchorsForNewTab(decodeHtmlEntities(data.caption)) }}
242
+ />
243
+ )}
244
+ </blockquote>
245
+ );
246
+ }
247
+ case "paragraph":
248
+ default:
249
+ // Check if this paragraph contains table HTML that wasn't merged
250
+ if (isTableFragment(html)) {
251
+ return (
252
+ <div
253
+ key={block.id}
254
+ className="table-wrapper my-6"
255
+ dangerouslySetInnerHTML={{ __html: html }}
256
+ />
257
+ );
258
+ }
259
+ return (
260
+ <p
261
+ key={block.id}
262
+ className="text-lg leading-7 tracking-[-0.045px] my-4"
263
+ dangerouslySetInnerHTML={{ __html: html }}
264
+ />
265
+ );
266
+ }
267
+ };
268
+
269
+ return (
270
+ <>
271
+ <style
272
+ dangerouslySetInnerHTML={{
273
+ __html: `
274
+ .editor-content a {
275
+ color: var(--color-primary-600);
276
+ text-decoration: underline;
277
+ transition: opacity 0.2s;
278
+ }
279
+
280
+ .editor-content strong,
281
+ .editor-content b {
282
+ font-weight: 600;
283
+ }
284
+ .editor-content em,
285
+ .editor-content i {
286
+ font-style: italic;
287
+ }
288
+ .editor-content blockquote {
289
+ background-color: var(--color-secondary-50);
290
+ padding: 1rem 1.5rem;
291
+ border-radius: 0 0.5rem 0.5rem 0;
292
+ }
293
+ .editor-content img {
294
+ max-width: 100%;
295
+ width: 100%;
296
+ height: auto;
297
+ display: block;
298
+ margin: 1.5rem 0;
299
+ border-radius: 0.5rem;
300
+ }
301
+ .editor-content table {
302
+ width: 100% !important;
303
+ max-width: 100% !important;
304
+ border-collapse: collapse;
305
+ margin: 2rem 0;
306
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
307
+ display: table;
308
+ table-layout: auto !important;
309
+ }
310
+ .editor-content .table-wrapper {
311
+ width: 100%;
312
+ overflow-x: auto;
313
+ }
314
+ .editor-content table col {
315
+ width: auto !important;
316
+ }
317
+ .editor-content table colgroup {
318
+ display: table-column-group;
319
+ }
320
+ .editor-content table thead {
321
+ background-color: var(--color-primary-600);
322
+ color: white;
323
+ }
324
+ .editor-content table th,
325
+ .editor-content table td {
326
+ padding: 1rem 1.5rem;
327
+ text-align: left;
328
+ border: 1px solid var(--color-secondary-300);
329
+ line-height: 1.6;
330
+ }
331
+ .editor-content table th {
332
+ font-weight: 600;
333
+ font-size: 1rem;
334
+ }
335
+ .editor-content table tbody tr:nth-child(even) {
336
+ background-color: var(--color-secondary-50);
337
+ }
338
+ .editor-content .table-header {
339
+ font-weight: 600;
340
+ font-size: 1.1rem;
341
+ padding: 1.25rem 1.5rem;
342
+ }
343
+ .editor-content .table-data {
344
+ font-size: 0.95rem;
345
+ padding: 0.875rem 1.25rem;
346
+ }
347
+ .ezo-table {
348
+ width: 100%;
349
+ border-collapse: collapse;
350
+ margin: 2rem 0;
351
+ }
352
+ @media (max-width: 768px) {
353
+ .editor-content table {
354
+ font-size: 0.875rem;
355
+ }
356
+ .editor-content table th,
357
+ .editor-content table td {
358
+ padding: 0.75rem 1rem;
359
+ }
360
+ }
361
+ `,
362
+ }}
363
+ />
364
+ <div className="editor-content overflow-x-auto">
365
+ {mergedBlocks.map(renderBlock)}
366
+ </div>
367
+ </>
368
+ );
369
+ }
@@ -0,0 +1,17 @@
1
+ import type { Metadata } from "next"
2
+ import { getStoreName } from "@/app/utils/branding"
3
+
4
+ export async function generateMetadata(): Promise<Metadata> {
5
+ return {
6
+ title: `Blog Post - ${getStoreName()}`,
7
+ description: `Read this article with expert insights, tips, and advice from ${getStoreName()}'s team.`,
8
+ }
9
+ }
10
+
11
+ export default function BlogPostLayout({
12
+ children,
13
+ }: {
14
+ children: React.ReactNode
15
+ }) {
16
+ return children
17
+ }
@@ -0,0 +1,151 @@
1
+ import React from "react"
2
+ import type { Metadata } from "next"
3
+ import Link from "next/link"
4
+ import Breadcrumb from "@/app/components/reuseableUI/breadcrumb"
5
+ import Heading from "@/app/components/reuseableUI/heading"
6
+ import EditorRenderer from "@/app/components/richText/EditorRenderer"
7
+ import { fetchBlogBySlug } from "@/graphql/queries/getBlogs"
8
+ import { getStoreName } from "@/app/utils/branding"
9
+ import {
10
+ generateBlogPostingSchema,
11
+ generateBreadcrumbSchema,
12
+ } from "@/lib/schema"
13
+ import { notFound } from "next/navigation"
14
+ import { extractTextFromEditorJs } from "@/lib/seo/extractTextFromEditorJs"
15
+
16
+ function truncate(input: string, maxLen: number): string {
17
+ const v = input.trim()
18
+ if (v.length <= maxLen) return v
19
+ return v.slice(0, Math.max(0, maxLen - 1)).trimEnd() + "…"
20
+ }
21
+
22
+ export async function generateMetadata({
23
+ params,
24
+ }: {
25
+ params: Promise<{ slug: string }>
26
+ }): Promise<Metadata> {
27
+ const { slug } = await params
28
+ const post = await fetchBlogBySlug(slug)
29
+
30
+ if (!post || !post.title) {
31
+ return {
32
+ title: `Blog Post Not Found - ${getStoreName()}`,
33
+ }
34
+ }
35
+
36
+ const desc =
37
+ truncate(extractTextFromEditorJs(post.content), 160) ||
38
+ `${post.title} - ${getStoreName()}`
39
+
40
+ return {
41
+ title: `${post.title} - ${getStoreName()}`,
42
+ description: desc,
43
+ alternates: {
44
+ canonical: `/blog/${slug}`,
45
+ },
46
+ openGraph: {
47
+ title: `${post.title} - ${getStoreName()}`,
48
+ description: desc,
49
+ type: "article",
50
+ url: `/blog/${slug}`,
51
+ images: [{ url: "/Logo.png" }],
52
+ },
53
+ twitter: {
54
+ card: "summary_large_image",
55
+ title: `${post.title} - ${getStoreName()}`,
56
+ description: desc,
57
+ images: ["/Logo.png"],
58
+ },
59
+ }
60
+ }
61
+
62
+ export default async function BlogPostPage({
63
+ params,
64
+ }: {
65
+ params: Promise<{ slug: string }>
66
+ }) {
67
+ const { slug } = await params
68
+ const post = await fetchBlogBySlug(slug)
69
+
70
+ if (!post || !post.title) {
71
+ notFound()
72
+ }
73
+
74
+ // Format date if available
75
+ const formattedDate = post.created
76
+ ? new Date(post.created).toLocaleDateString("en-US", {
77
+ year: "numeric",
78
+ month: "long",
79
+ day: "numeric",
80
+ })
81
+ : ""
82
+
83
+ // Generate schema.org structured data
84
+ const desc =
85
+ truncate(extractTextFromEditorJs(post.content), 200) ||
86
+ `${post.title} - ${getStoreName()}`
87
+
88
+ const blogSchema = generateBlogPostingSchema(
89
+ post.title,
90
+ desc,
91
+ `/blog/${slug}`,
92
+ post.created || new Date().toISOString(),
93
+ post.created || new Date().toISOString()
94
+ );
95
+
96
+ const breadcrumbSchema = generateBreadcrumbSchema([
97
+ { name: "Home", url: "/" },
98
+ { name: "Blog", url: "/blog" },
99
+ { name: post.title, url: `/blog/${slug}` },
100
+ ]);
101
+
102
+ return (
103
+ <main className="h-full w-full">
104
+ {/* Schema.org structured data */}
105
+ <script
106
+ type="application/ld+json"
107
+ dangerouslySetInnerHTML={{ __html: JSON.stringify(blogSchema) }}
108
+ />
109
+ <script
110
+ type="application/ld+json"
111
+ dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbSchema) }}
112
+ />
113
+ <div className="container mx-auto max-w-[1276px]">
114
+ <div className="flex flex-col items-start w-full gap-8 px-4 md:px-6 py-12 md:py-16 lg:py-24">
115
+ <div className="flex flex-col items-start gap-5 w-full">
116
+ <Breadcrumb
117
+ items={[
118
+ { text: "Home", link: "/" },
119
+ { text: "BLOGS", link: "/blog" },
120
+ { text: post.title, link: `/blog/${post.slug}` },
121
+ ]}
122
+ />
123
+ <Heading as="h1" content={post.title} />
124
+ {formattedDate && (
125
+ <p className="text-sm text-[var(--color-secondary-500)]">
126
+ Published on {formattedDate}
127
+ </p>
128
+ )}
129
+ </div>
130
+
131
+ <div className="w-full flex flex-col items-start gap-6">
132
+ {/* Blog Content */}
133
+ <div className="w-full">
134
+ <EditorRenderer content={post.content} />
135
+ </div>
136
+
137
+ {/* Back to Blog Link */}
138
+ <div className="w-full pt-8 border-t border-[var(--color-secondary-200)]">
139
+ <Link
140
+ href="/blog"
141
+ className="text-[var(--color-primary-600)] hover:underline inline-flex items-center gap-2"
142
+ >
143
+ ← Back to all blogs
144
+ </Link>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ </main>
150
+ )
151
+ }
@@ -0,0 +1,147 @@
1
+ export const blogPosts = [
2
+ {
3
+ id: 1,
4
+ title: "The Future of Performance Exhaust Systems",
5
+ excerpt:
6
+ "Exploring the latest innovations in exhaust technology and what it means for car enthusiasts.",
7
+ date: "August 15, 2025",
8
+ readTime: "5 min read",
9
+ image: "/no-image-avail-large.png",
10
+ slug: "future-of-performance-exhaust-systems",
11
+ },
12
+ {
13
+ id: 2,
14
+ title: "Top 5 Exhaust Upgrades for Your Vehicle",
15
+ excerpt:
16
+ "Discover the best exhaust upgrades to enhance your vehicle's performance and sound.",
17
+ date: "July 28, 2025",
18
+ readTime: "4 min read",
19
+ image: "/no-image-avail-large.png",
20
+ slug: "top-5-exhaust-upgrades",
21
+ },
22
+ {
23
+ id: 3,
24
+ title: "Maintaining Your Exhaust System: A Complete Guide",
25
+ excerpt:
26
+ "Learn essential maintenance tips to keep your exhaust system in top condition.",
27
+ date: "July 10, 2025",
28
+ readTime: "6 min read",
29
+ image: "/no-image-avail-large.png",
30
+ slug: "exhaust-system-maintenance-guide",
31
+ },
32
+ {
33
+ id: 4,
34
+ title: "The Future of Performance Exhaust Systems",
35
+ excerpt:
36
+ "Exploring the latest innovations in exhaust technology and what it means for car enthusiasts.",
37
+ date: "August 15, 2025",
38
+ readTime: "5 min read",
39
+ image: "/no-image-avail-large.png",
40
+ slug: "future-of-performance-exhaust-systems",
41
+ },
42
+ {
43
+ id: 5,
44
+ title: "Top 5 Exhaust Upgrades for Your Vehicle",
45
+ excerpt:
46
+ "Discover the best exhaust upgrades to enhance your vehicle's performance and sound.",
47
+ date: "July 28, 2025",
48
+ readTime: "4 min read",
49
+ image: "/no-image-avail-large.png",
50
+ slug: "top-5-exhaust-upgrades",
51
+ },
52
+ {
53
+ id: 6,
54
+ title: "Maintaining Your Exhaust System: A Complete Guide",
55
+ excerpt:
56
+ "Learn essential maintenance tips to keep your exhaust system in top condition.",
57
+ date: "July 10, 2025",
58
+ readTime: "6 min read",
59
+ image: "/no-image-avail-large.png",
60
+ slug: "exhaust-system-maintenance-guide",
61
+ },
62
+ {
63
+ id: 7,
64
+ title: "The Future of Performance Exhaust Systems",
65
+ excerpt:
66
+ "Exploring the latest innovations in exhaust technology and what it means for car enthusiasts.",
67
+ date: "August 15, 2025",
68
+ readTime: "5 min read",
69
+ image: "/no-image-avail-large.png",
70
+ slug: "future-of-performance-exhaust-systems",
71
+ },
72
+ {
73
+ id: 8,
74
+ title: "Top 5 Exhaust Upgrades for Your Vehicle",
75
+ excerpt:
76
+ "Discover the best exhaust upgrades to enhance your vehicle's performance and sound.",
77
+ date: "July 28, 2025",
78
+ readTime: "4 min read",
79
+ image: "/no-image-avail-large.png",
80
+ slug: "top-5-exhaust-upgrades",
81
+ },
82
+ {
83
+ id: 9,
84
+ title: "Maintaining Your Exhaust System: A Complete Guide",
85
+ excerpt:
86
+ "Learn essential maintenance tips to keep your exhaust system in top condition.",
87
+ date: "July 10, 2025",
88
+ readTime: "6 min read",
89
+ image: "/no-image-avail-large.png",
90
+ slug: "exhaust-system-maintenance-guide",
91
+ },
92
+ ];
93
+
94
+ export const BlogPostContent = {
95
+ title: "COMPONENTS OF THE BULKHEAD FITTING KIT",
96
+ description:
97
+ "This kit includes various parts that ensure a secure, leak-proof connection between the air supply line and the ARB differential. Here's a comprehensive overview of each component, along with their part numbers and roles in the assembly.",
98
+ subtitle:"6mm Banjo Bolt",
99
+ desc: "This kit comprises multiple components designed to ensure a secure and leak-free connection between the air supply line and the ARB differential. Below is a thorough overview of each part, their part numbers, and their functions in the assembly.",
100
+ components: [
101
+ {
102
+ id: 1,
103
+ title: "6MM BANJO BOLT",
104
+ description:
105
+ "The banjo bolt (Item #01) fastens the banjo elbow and washer to the differential body. This bolt is crucial for maintaining pressure and airflow to the differential.",
106
+ },
107
+ {
108
+ id: 2,
109
+ title: "6MM BANJO BOLT",
110
+ description:
111
+ "The banjo bolt (Item #01) secures the banjo elbow and washer to the differential body. This bolt is vital for ensuring proper pressure and airflow to the differential.",
112
+ },
113
+ {
114
+ id: 3,
115
+ title: "6MM BANJO BOLT",
116
+ description:
117
+ "The banjo bolt (Item #01) secures the banjo elbow and washer to the differential body. This bolt is essential for maintaining pressure and airflow to the differential.",
118
+ },
119
+ {
120
+ id: 4,
121
+ title: "6MM BANJO BOLT",
122
+ description:
123
+ "The banjo bolt (Item #01) fastens the banjo elbow and washer to the differential body. This bolt is key to ensuring proper pressure and airflow to the differential.",
124
+ },
125
+ {
126
+ id: 5,
127
+ title: "6MM BANJO BOLT",
128
+ description:
129
+ "The banjo bolt (Item #01) secures the banjo elbow and washer to the differential body. This bolt plays a vital role in maintaining pressure and airflow to the differential.",
130
+ },
131
+ {
132
+ id: 6,
133
+ title: "6MM BANJO BOLT",
134
+ description:
135
+ "The banjo bolt (Item #01) fastens the banjo elbow and washer to the differential body. This bolt is essential for ensuring pressure and airflow to the differential.",
136
+ },
137
+ {
138
+ id: 7,
139
+ title: "6MM BANJO BOLT",
140
+ specs: [
141
+ "External Tube Diameter: 6mm",
142
+ "Internal Tube Diameter: 3mm",
143
+ "Bulkhead Thread: 1/4\" NPT",
144
+ ],
145
+ },
146
+ ],
147
+ };