@akinon/projectzero 2.0.0-beta.9 → 2.0.1

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 (290) hide show
  1. package/CHANGELOG.md +191 -17
  2. package/app-template/.env.example +3 -0
  3. package/app-template/.github/instructions/account.instructions.md +749 -0
  4. package/app-template/.github/instructions/checkout.instructions.md +678 -0
  5. package/app-template/.github/instructions/default.instructions.md +279 -0
  6. package/app-template/.github/instructions/edge-cases.instructions.md +73 -0
  7. package/app-template/.github/instructions/routing.instructions.md +603 -0
  8. package/app-template/.github/instructions/settings.instructions.md +338 -0
  9. package/app-template/.gitignore +3 -0
  10. package/app-template/AGENTS.md +7 -0
  11. package/app-template/CHANGELOG.md +2065 -232
  12. package/app-template/Procfile +1 -1
  13. package/app-template/akinon.json +1 -4
  14. package/app-template/build.sh +10 -0
  15. package/app-template/docs/advanced-usage.md +111 -0
  16. package/app-template/docs/plugins.md +60 -25
  17. package/app-template/docs/sentry-usage.md +35 -0
  18. package/app-template/jest.config.ts +2 -2
  19. package/app-template/next-env.d.ts +1 -0
  20. package/app-template/{next.config.ts → next.config.mjs} +6 -7
  21. package/app-template/package.json +58 -50
  22. package/app-template/postcss.config.mjs +1 -4
  23. package/app-template/public/amex.svg +12 -0
  24. package/app-template/public/apple-pay.svg +16 -0
  25. package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
  26. package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
  27. package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
  28. package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
  29. package/app-template/public/google-pay.svg +16 -0
  30. package/app-template/public/locales/en/account.json +9 -4
  31. package/app-template/public/locales/en/auth.json +6 -7
  32. package/app-template/public/locales/en/basket.json +6 -6
  33. package/app-template/public/locales/en/blog.json +7 -0
  34. package/app-template/public/locales/en/category.json +3 -1
  35. package/app-template/public/locales/en/checkout.json +17 -4
  36. package/app-template/public/locales/en/common.json +61 -3
  37. package/app-template/public/locales/en/forgot_password.json +6 -7
  38. package/app-template/public/locales/en/product.json +84 -4
  39. package/app-template/public/locales/tr/account.json +9 -4
  40. package/app-template/public/locales/tr/auth.json +16 -17
  41. package/app-template/public/locales/tr/basket.json +4 -4
  42. package/app-template/public/locales/tr/blog.json +7 -0
  43. package/app-template/public/locales/tr/category.json +3 -1
  44. package/app-template/public/locales/tr/checkout.json +48 -36
  45. package/app-template/public/locales/tr/common.json +60 -2
  46. package/app-template/public/locales/tr/forgot_password.json +12 -13
  47. package/app-template/public/locales/tr/product.json +82 -0
  48. package/app-template/public/logo.svg +3 -27
  49. package/app-template/public/mastercard.svg +14 -0
  50. package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
  51. package/app-template/public/promotion-banner.jpg +0 -0
  52. package/app-template/public/shop-pay.svg +12 -0
  53. package/app-template/public/visa.svg +12 -0
  54. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +11 -11
  55. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +4 -3
  56. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +13 -10
  57. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +73 -51
  58. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +1 -1
  59. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
  60. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +2 -2
  61. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +1 -1
  62. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +2 -2
  63. package/app-template/src/app/[pz]/blog/[slug]/page.tsx +120 -0
  64. package/app-template/src/app/[pz]/category/[pk]/page.tsx +37 -0
  65. package/app-template/src/app/[pz]/flat-page/[pk]/page.tsx +23 -0
  66. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/forms/[pk]/generate/page.tsx +2 -3
  67. package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +93 -0
  68. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/page.tsx +2 -4
  69. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/layout.tsx +6 -11
  70. package/app-template/src/app/[pz]/list/page.tsx +26 -0
  71. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/not-found.tsx +5 -7
  72. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
  73. package/app-template/src/app/[pz]/page.tsx +28 -0
  74. package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
  75. package/app-template/src/app/[pz]/product/[pk]/page.tsx +102 -0
  76. package/app-template/src/app/[pz]/special-page/[pk]/page.tsx +35 -0
  77. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/email-set-primary/[[...id]]/page.tsx +3 -4
  78. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/registration/account-confirm-email/[[...id]]/page.tsx +3 -3
  79. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/reset/[[...id]]/page.tsx +41 -5
  80. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/[node]/route.ts +8 -6
  81. package/app-template/src/app/api/auth/[...nextauth]/route.ts +3 -0
  82. package/app-template/src/app/api/barcode-search/route.ts +1 -0
  83. package/app-template/src/app/api/cache/route.ts +1 -1
  84. package/app-template/src/app/api/form/[...id]/route.ts +1 -7
  85. package/app-template/src/app/api/image-proxy/route.ts +1 -0
  86. package/app-template/src/app/api/logout/route.ts +1 -1
  87. package/app-template/src/app/api/product-categories/route.ts +1 -0
  88. package/app-template/src/app/api/similar-product-list/route.ts +1 -0
  89. package/app-template/src/app/api/similar-products/route.ts +1 -0
  90. package/app-template/src/app/api/theme-settings/route.ts +12 -0
  91. package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
  92. package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
  93. package/app-template/src/app/api/web-vitals/route.ts +1 -1
  94. package/app-template/src/assets/fonts/pz-icon.css +211 -49
  95. package/app-template/src/assets/fonts/pz-icon.eot +0 -0
  96. package/app-template/src/assets/fonts/pz-icon.html +486 -0
  97. package/app-template/src/assets/fonts/pz-icon.scss +373 -49
  98. package/app-template/src/assets/fonts/pz-icon.svg +215 -53
  99. package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
  100. package/app-template/src/assets/fonts/pz-icon.woff +0 -0
  101. package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
  102. package/app-template/src/assets/globals.scss +8 -133
  103. package/app-template/src/assets/icons/arrow-right.svg +3 -0
  104. package/app-template/src/assets/icons/cart.svg +4 -12
  105. package/app-template/src/assets/icons/check.svg +2 -18
  106. package/app-template/src/assets/icons/chevron-down.svg +2 -7
  107. package/app-template/src/assets/icons/delete.svg +3 -0
  108. package/app-template/src/assets/icons/facebook.svg +2 -8
  109. package/app-template/src/assets/icons/fav-off.svg +5 -0
  110. package/app-template/src/assets/icons/fav-on.svg +5 -0
  111. package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
  112. package/app-template/src/assets/icons/heart.svg +3 -0
  113. package/app-template/src/assets/icons/instagram.svg +2 -13
  114. package/app-template/src/assets/icons/materials.svg +3 -0
  115. package/app-template/src/assets/icons/person.svg +4 -0
  116. package/app-template/src/assets/icons/pinterest.svg +5 -11
  117. package/app-template/src/assets/icons/ruler.svg +3 -0
  118. package/app-template/src/assets/icons/search.svg +8 -11
  119. package/app-template/src/assets/icons/share.svg +2 -9
  120. package/app-template/src/assets/icons/snapchat.svg +3 -0
  121. package/app-template/src/assets/icons/tiktok.svg +3 -0
  122. package/app-template/src/assets/icons/tumblr.svg +6 -0
  123. package/app-template/src/assets/icons/twitter.svg +2 -10
  124. package/app-template/src/assets/icons/vimeo.svg +3 -0
  125. package/app-template/src/assets/icons/youtube.svg +3 -0
  126. package/app-template/src/assets/icons/zoom.svg +8 -0
  127. package/app-template/src/auth.ts +3 -0
  128. package/app-template/src/components/__tests__/badge.test.tsx +2 -2
  129. package/app-template/src/components/__tests__/link.test.tsx +2 -0
  130. package/app-template/src/components/accordion.tsx +48 -23
  131. package/app-template/src/components/action-tooltip.tsx +160 -0
  132. package/app-template/src/components/button.tsx +1 -1
  133. package/app-template/src/components/carousel-core.tsx +4 -11
  134. package/app-template/src/components/checkbox.tsx +2 -1
  135. package/app-template/src/components/currency-select.tsx +150 -4
  136. package/app-template/src/components/file-input.tsx +27 -7
  137. package/app-template/src/components/generate-form-fields.tsx +49 -10
  138. package/app-template/src/components/icon.tsx +5 -6
  139. package/app-template/src/components/index.ts +4 -1
  140. package/app-template/src/components/input.tsx +11 -5
  141. package/app-template/src/components/language-select.tsx +88 -2
  142. package/app-template/src/components/modal.tsx +34 -16
  143. package/app-template/src/components/pagination.tsx +133 -20
  144. package/app-template/src/components/price.tsx +1 -1
  145. package/app-template/src/components/pwa-tags.tsx +1 -0
  146. package/app-template/src/components/quantity-input.tsx +63 -0
  147. package/app-template/src/components/quantity-selector.tsx +215 -0
  148. package/app-template/src/components/route-handler.tsx +50 -0
  149. package/app-template/src/components/select.tsx +86 -54
  150. package/app-template/src/components/shimmer.tsx +1 -1
  151. package/app-template/src/components/types/index.ts +51 -1
  152. package/app-template/src/components/widget-content.tsx +323 -0
  153. package/app-template/src/data/server/theme.ts +70 -0
  154. package/app-template/src/hooks/use-fav-button.tsx +9 -10
  155. package/app-template/src/hooks/use-product-cart.ts +80 -0
  156. package/app-template/src/hooks/use-stock-alert.ts +74 -0
  157. package/app-template/src/hooks/use-theme-settings.ts +42 -0
  158. package/app-template/src/lib/fonts.ts +149 -0
  159. package/app-template/src/plugins.js +12 -2
  160. package/app-template/src/{middleware.ts → proxy.ts} +3 -3
  161. package/app-template/src/redux/middlewares/category.ts +5 -4
  162. package/app-template/src/redux/store.ts +21 -1
  163. package/app-template/src/routes/index.ts +8 -7
  164. package/app-template/src/settings.js +6 -3
  165. package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
  166. package/app-template/src/types/index.ts +74 -3
  167. package/app-template/src/types/next-auth.d.ts +2 -2
  168. package/app-template/src/types/widget.ts +169 -0
  169. package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
  170. package/app-template/src/utils/formatDate.ts +48 -0
  171. package/app-template/src/utils/styles.ts +71 -0
  172. package/app-template/src/utils/theme-page-context.ts +309 -0
  173. package/app-template/src/utils/variant-validation.ts +41 -0
  174. package/app-template/src/views/account/address-form.tsx +8 -4
  175. package/app-template/src/views/account/contact-form.tsx +148 -131
  176. package/app-template/src/views/account/content-header.tsx +4 -3
  177. package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
  178. package/app-template/src/views/account/favorite-item.tsx +1 -1
  179. package/app-template/src/views/account/order.tsx +11 -9
  180. package/app-template/src/views/account/orders/order-cancellation-item.tsx +1 -1
  181. package/app-template/src/views/account/orders/order-detail-header.tsx +1 -1
  182. package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +45 -38
  183. package/app-template/src/views/basket/basket-item.tsx +6 -1
  184. package/app-template/src/views/basket/summary.tsx +16 -0
  185. package/app-template/src/views/breadcrumb.tsx +2 -2
  186. package/app-template/src/views/category/category-banner.tsx +4 -23
  187. package/app-template/src/views/category/category-info.tsx +2 -1
  188. package/app-template/src/views/category/filters/filter-item.tsx +138 -42
  189. package/app-template/src/views/category/filters/index.tsx +1 -1
  190. package/app-template/src/views/category/layout.tsx +1 -0
  191. package/app-template/src/views/checkout/auth.tsx +64 -40
  192. package/app-template/src/views/checkout/layout/header.tsx +10 -6
  193. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +22 -6
  194. package/app-template/src/views/checkout/steps/payment/options/funds-transfer.tsx +25 -5
  195. package/app-template/src/views/checkout/steps/payment/options/loyalty.tsx +21 -2
  196. package/app-template/src/views/checkout/steps/payment/options/redirection.tsx +27 -5
  197. package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +464 -0
  198. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +4 -4
  199. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +33 -20
  200. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +2 -2
  201. package/app-template/src/views/checkout/summary.tsx +12 -2
  202. package/app-template/src/views/find-in-store/index.tsx +2 -2
  203. package/app-template/src/views/guest-login/index.tsx +62 -58
  204. package/app-template/src/views/header/action-menu.tsx +1 -1
  205. package/app-template/src/views/header/band.tsx +2 -2
  206. package/app-template/src/views/header/index.tsx +1 -1
  207. package/app-template/src/views/header/mini-basket.tsx +3 -3
  208. package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
  209. package/app-template/src/views/header/mobile-menu.tsx +18 -6
  210. package/app-template/src/views/header/navbar.tsx +1 -1
  211. package/app-template/src/views/header/pwa-back-button.tsx +1 -1
  212. package/app-template/src/views/header/search/index.tsx +13 -3
  213. package/app-template/src/views/header/search/results.tsx +1 -1
  214. package/app-template/src/views/header/user-menu.tsx +1 -3
  215. package/app-template/src/views/login/index.tsx +66 -57
  216. package/app-template/src/views/otp-login/index.tsx +11 -6
  217. package/app-template/src/views/product/index.ts +1 -0
  218. package/app-template/src/views/product/layout.tsx +26 -6
  219. package/app-template/src/views/product/price-wrapper.tsx +3 -24
  220. package/app-template/src/views/product/product-actions.tsx +165 -0
  221. package/app-template/src/views/product/product-info.tsx +76 -238
  222. package/app-template/src/views/product/product-share.tsx +58 -0
  223. package/app-template/src/views/product/product-variants.tsx +26 -0
  224. package/app-template/src/views/product/slider.tsx +22 -1
  225. package/app-template/src/views/product/variant.tsx +69 -41
  226. package/app-template/src/views/product-pointer-banner-item.tsx +1 -1
  227. package/app-template/src/views/register/index.tsx +31 -46
  228. package/app-template/src/views/sales-contract-modal/index.tsx +17 -17
  229. package/app-template/src/views/share/index.tsx +9 -6
  230. package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
  231. package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
  232. package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
  233. package/app-template/src/widgets/footer-info.tsx +1 -1
  234. package/app-template/src/widgets/footer-menu.tsx +7 -3
  235. package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
  236. package/app-template/src/widgets/footer-subscription/index.tsx +1 -1
  237. package/app-template/src/widgets/home-stories-eng.tsx +43 -35
  238. package/app-template/src/widgets/index.ts +7 -0
  239. package/app-template/src/widgets/schemas/about-us.json +46 -0
  240. package/app-template/src/widgets/schemas/blog-list.json +37 -0
  241. package/app-template/src/widgets/schemas/blog.json +29 -0
  242. package/app-template/tailwind.config.js +155 -7
  243. package/app-template/tsconfig.json +29 -11
  244. package/codemods/migrate-auth-v5/index.js +339 -0
  245. package/codemods/migrate-auth-v5/transform.js +86 -0
  246. package/codemods/migrate-segments/index.js +591 -0
  247. package/codemods/update-tailwind-config/index.js +30 -0
  248. package/codemods/update-tailwind-config/transform.js +102 -0
  249. package/codemods/upgrade-to-2/index.js +549 -0
  250. package/commands/codemod.ts +0 -1
  251. package/commands/plugins.ts +111 -46
  252. package/dist/commands/codemod.js +0 -1
  253. package/dist/commands/plugins.js +104 -36
  254. package/package.json +3 -2
  255. package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
  256. package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
  257. package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
  258. package/app-template/src/app/[commerce]/[locale]/[currency]/list/page.tsx +0 -18
  259. package/app-template/src/app/[commerce]/[locale]/[currency]/page.tsx +0 -50
  260. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
  261. package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
  262. package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
  263. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
  264. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
  265. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
  266. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
  267. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
  268. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
  269. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
  270. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
  271. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
  272. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
  273. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
  274. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
  275. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
  276. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
  277. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
  278. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
  279. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
  280. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/error.tsx +0 -0
  281. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
  282. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
  283. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
  284. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
  285. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +0 -0
  286. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
  287. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
  288. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
  289. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
  290. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
@@ -22,14 +22,15 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
22
22
  const groupedOrder = [];
23
23
 
24
24
  if (order) {
25
- const groupedData = order.orderitem_set.reduce((groups, item) => {
26
- const { tracking_number } = item;
27
- if (!groups[tracking_number]) {
28
- groups[tracking_number] = [];
29
- }
30
- groups[tracking_number].push(item);
31
- return groups;
32
- }, {});
25
+ const groupedData =
26
+ order?.orderitem_set?.reduce((groups, item) => {
27
+ const { tracking_number } = item;
28
+ if (!groups[tracking_number]) {
29
+ groups[tracking_number] = [];
30
+ }
31
+ groups[tracking_number].push(item);
32
+ return groups;
33
+ }, {}) || {};
33
34
 
34
35
  const result = Object.values(groupedData);
35
36
 
@@ -67,8 +68,8 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
67
68
 
68
69
  <div>
69
70
  <span className="text-base font-bold">
70
- {order.orderitem_set.length}{' '}
71
- {t('account.my_orders.detail.products')} {groupedOrder.length}{' '}
71
+ {order?.orderitem_set?.length}{' '}
72
+ {t('account.my_orders.detail.products')} {groupedOrder?.length}{' '}
72
73
  {t('account.my_orders.detail.packages')}
73
74
  </span>
74
75
  </div>
@@ -78,17 +79,17 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
78
79
  className="break-words"
79
80
  >
80
81
  <span>{t('account.my_orders.detail.delivery_address')}</span>:{' '}
81
- {order?.shipping_address.line}{' '}
82
- {order?.shipping_address.district.name}{' '}
83
- {order?.shipping_address.township.name}{' '}
84
- {order?.shipping_address.city.name}
82
+ {order?.shipping_address?.line}{' '}
83
+ {order?.shipping_address?.district?.name}{' '}
84
+ {order?.shipping_address?.township?.name}{' '}
85
+ {order?.shipping_address?.city?.name}
85
86
  </div>
86
87
  </OrderDetailHeader>
87
88
 
88
89
  <div>
89
90
  {groupedOrder.map((group, i) => {
90
91
  const orderStatus = getOrderStatus(
91
- group[0].status.value.toString(),
92
+ group[0]?.status?.value?.toString(),
92
93
  t
93
94
  );
94
95
 
@@ -112,8 +113,8 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
112
113
  <div className="flex justify-between items-center lg:gap-x-12">
113
114
  <div className="text-base">{orderStatus.label}</div>
114
115
 
115
- {group[0].tracking_number && group[0].tracking_url && (
116
- <Link href={group[0].tracking_url}>
116
+ {group[0]?.tracking_number && group[0]?.tracking_url && (
117
+ <Link href={group[0]?.tracking_url}>
117
118
  <Button className="px-7" appearance="filled">
118
119
  {t('account.my_orders.detail.track_shipment')}
119
120
  </Button>
@@ -125,7 +126,7 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
125
126
  <div className="px-4 lg:px-7">
126
127
  {group.map((item, index) => {
127
128
  const itemStatus = getOrderStatus(
128
- item.status.value.toString(),
129
+ item?.status?.value?.toString(),
129
130
  t
130
131
  );
131
132
 
@@ -135,18 +136,18 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
135
136
  key={index}
136
137
  >
137
138
  <div className="flex gap-3 mb-5 lg:mb-0">
138
- <div className="shrink-0">
139
+ <div className="flex-shrink-0">
139
140
  <Link
140
141
  className="block"
141
- href={item.product.absolute_url}
142
+ href={item?.product?.absolute_url}
142
143
  >
143
144
  <Image
144
145
  src={
145
- item.product.image
146
+ item?.product?.image
146
147
  ? item.product.image
147
148
  : '/noimage.jpg'
148
149
  }
149
- alt={item.product.name}
150
+ alt={item?.product?.name}
150
151
  width={112}
151
152
  height={150}
152
153
  />
@@ -155,27 +156,32 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
155
156
 
156
157
  <div className="flex flex-col justify-between lg:max-w-48">
157
158
  <div className="text-sm">
158
- <Link href={item.product.absolute_url}>
159
- {item.product.name}
159
+ <Link href={item?.product?.absolute_url}>
160
+ {item?.product?.name}
160
161
  </Link>
161
162
  </div>
162
163
 
163
164
  <div className="text-gray-900 text-xs">
164
- {item.product.attributes.filterable_color && (
165
+ {item?.product?.attributes
166
+ ?.filterable_color && (
165
167
  <div>
166
168
  <span>
167
169
  {t('account.my_orders.detail.color')}
168
170
  </span>
169
- : {item.product.attributes.filterable_color}
171
+ :{' '}
172
+ {
173
+ item?.product?.attributes
174
+ ?.filterable_color
175
+ }
170
176
  </div>
171
177
  )}
172
178
 
173
- {item.product.attributes.size && (
179
+ {item?.product?.attributes?.size && (
174
180
  <div>
175
181
  <span>
176
182
  {t('account.my_orders.detail.size')}
177
183
  </span>
178
- :{item.product.attributes.size}
184
+ :{item?.product?.attributes?.size}
179
185
  </div>
180
186
  )}
181
187
 
@@ -183,7 +189,7 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
183
189
  <span>
184
190
  {t('account.my_orders.detail.code')}
185
191
  </span>
186
- : {item.product.base_code}
192
+ : {item?.product?.base_code}
187
193
  </div>
188
194
  </div>
189
195
  </div>
@@ -202,7 +208,7 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
202
208
 
203
209
  {(item.is_cancellable || item.is_refundable) &&
204
210
  order.is_cancellable &&
205
- item.status.value == '400' && (
211
+ item?.status?.value == '400' && (
206
212
  <div className="lg:ml-24">
207
213
  <Link
208
214
  href={`${ROUTES.ACCOUNT_ORDERS}/${order.id}/cancellation`}
@@ -256,29 +262,29 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
256
262
  <div className="flex justify-between text-sm text-black-700 mb-2">
257
263
  <p>
258
264
  <span>{t('account.my_orders.detail.subtotal')}</span> (
259
- {order?.orderitem_set.length}{' '}
265
+ {order?.orderitem_set?.length}{' '}
260
266
  <span>{t('account.my_orders.detail.items')}</span>)
261
267
  </p>
262
268
 
263
269
  <Price
264
270
  className="font-normal min-w-max"
265
271
  value={
266
- parseFloat(order.amount_without_discount) -
267
- parseFloat(order.shipping_amount)
272
+ parseFloat(order?.amount_without_discount || '0') -
273
+ parseFloat(order?.shipping_amount || '0')
268
274
  }
269
275
  />
270
276
  </div>
271
277
 
272
- {order.discountitem_set &&
273
- order.discountitem_set.map((item, index) => (
278
+ {order?.discountitem_set &&
279
+ order?.discountitem_set?.map((item, index) => (
274
280
  <div
275
281
  className="flex justify-between text-sm text-black-700 mb-2"
276
282
  key={index}
277
283
  >
278
- <p>{item.name}</p>
284
+ <p>{item?.name}</p>
279
285
  <Price
280
286
  className="font-normal min-w-max"
281
- value={item.amount}
287
+ value={item?.amount}
282
288
  useNegative
283
289
  />
284
290
  </div>
@@ -291,7 +297,8 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
291
297
  className="font-normal min-w-max"
292
298
  data-testid="account-orders-detail-total"
293
299
  value={
294
- parseFloat(order.amount) - parseFloat(order.shipping_amount)
300
+ parseFloat(order?.amount || '0') -
301
+ parseFloat(order?.shipping_amount || '0')
295
302
  }
296
303
  />
297
304
  </div>
@@ -39,7 +39,12 @@ export const BasketItem = (props: Props) => {
39
39
  quantity: number,
40
40
  attributes: object = {}
41
41
  ) => {
42
- const requestParams: any = {
42
+ const requestParams: {
43
+ product: number;
44
+ quantity: number;
45
+ attributes: object;
46
+ namespace?: string;
47
+ } = {
43
48
  product: productPk,
44
49
  quantity,
45
50
  attributes
@@ -223,6 +223,22 @@ export const Summary = (props: Props) => {
223
223
  component={Component.OneClickCheckoutButtons}
224
224
  props={checkoutProviderProps}
225
225
  />
226
+
227
+ <div className="mt-4">
228
+ <PluginModule
229
+ component={Component.BasketVirtualTryOn}
230
+ props={{
231
+ basketItems: basket.basketitem_set.map((item) => ({
232
+ pk: item.product.pk,
233
+ sku: item.product.sku,
234
+ name: item.product.name,
235
+ productimage_set: item.product.productimage_set,
236
+ attributes: item.product.attributes,
237
+ category: (item.product as any).category
238
+ }))
239
+ }}
240
+ />
241
+ </div>
226
242
  </div>
227
243
  </div>
228
244
  );
@@ -12,7 +12,7 @@ export interface BreadcrumbProps {
12
12
  }
13
13
 
14
14
  export default function Breadcrumb(props: BreadcrumbProps) {
15
- const { t } = useLocalization();
15
+ const { t, locale } = useLocalization();
16
16
  const { breadcrumbList = [] } = props;
17
17
 
18
18
  const list = [
@@ -28,7 +28,7 @@ export default function Breadcrumb(props: BreadcrumbProps) {
28
28
  {list.map((item, index) => (
29
29
  <Fragment key={index}>
30
30
  <Link href={item.url}>
31
- {capitalize(item.text.toLocaleLowerCase())}
31
+ {capitalize(item.text.toLocaleLowerCase(locale))}
32
32
  </Link>
33
33
  {index !== list.length - 1 && <Icon name="chevron-end" size={8} />}
34
34
  </Fragment>
@@ -1,34 +1,15 @@
1
1
  'use client';
2
2
 
3
3
  import { Category } from '@akinon/next/types';
4
- import { Image } from '@akinon/next/components/image';
5
4
 
6
- export const CategoryBanner = (
7
- props: Category['attributes']['category_banner']
8
- ) => {
5
+ export const CategoryBanner = (props: Category['attributes']['banner']) => {
9
6
  if (Object.keys(props).length === 0) {
10
7
  return null;
11
8
  }
12
9
 
13
10
  return (
14
- <>
15
- <Image
16
- src={props.kwargs.value.image_mobile.url}
17
- alt="Category Banner"
18
- aspectRatio={768 / 375}
19
- sizes="768px"
20
- fill
21
- className="block md:hidden"
22
- />
23
-
24
- <Image
25
- src={props.kwargs.value.image_desktop.url}
26
- alt="Category Banner"
27
- aspectRatio={1370 / 400}
28
- sizes="1370px"
29
- fill
30
- className="hidden md:block"
31
- />
32
- </>
11
+ <h1 className="text-3xl lg:text-[40px] mb-5 lg:mb-10">
12
+ {props.value.title}
13
+ </h1>
33
14
  );
34
15
  };
@@ -57,6 +57,7 @@ export default function ListPage(props: ListPageProps) {
57
57
  newUrl.searchParams.delete('page');
58
58
  router.push(newUrl.pathname + newUrl.search, undefined);
59
59
  }
60
+ // eslint-disable-next-line react-hooks/exhaustive-deps
60
61
  }, [searchParams, data.products, page]);
61
62
 
62
63
  const { t } = useLocalization();
@@ -79,7 +80,7 @@ export default function ListPage(props: ListPageProps) {
79
80
  className={clsx(
80
81
  'transition-opacity duration-300 ease-linear lg:hidden',
81
82
  isMenuOpen
82
- ? 'fixed bg-black/60 inset-0 z-10 opacity-100'
83
+ ? 'fixed bg-black bg-opacity-60 inset-0 z-10 opacity-100'
83
84
  : 'opacity-0'
84
85
  )}
85
86
  ></div>
@@ -1,7 +1,14 @@
1
1
  import clsx from 'clsx';
2
2
  import { useAppDispatch } from '@akinon/next/redux/hooks';
3
3
  import { Facet, FacetChoice } from '@akinon/next/types';
4
- import { Accordion, Radio, Checkbox, LoaderSpinner } from '../../../components';
4
+ import {
5
+ Accordion,
6
+ Radio,
7
+ Checkbox,
8
+ LoaderSpinner,
9
+ Button,
10
+ Icon
11
+ } from '../../../components';
5
12
  import { WIDGET_TYPE } from '../../../types';
6
13
  import { SizeFilter } from './size-filter';
7
14
  import { toggleFacet } from '@theme/redux/reducers/category';
@@ -25,6 +32,16 @@ interface Props {
25
32
  startTransition: (callback: () => void) => void;
26
33
  }
27
34
 
35
+ interface FilterItemProps {
36
+ facet: any;
37
+ isPending: boolean;
38
+ startTransition: (callback: () => void) => void;
39
+ isDropdown?: boolean;
40
+ itemPaddingY?: number;
41
+ itemPaddingX?: number;
42
+ itemMarginBottom?: number;
43
+ }
44
+
28
45
  const sortByPredefinedOrder = (
29
46
  aLabel: string,
30
47
  bLabel: string,
@@ -82,12 +99,21 @@ const getComponentByWidgetType = (widgetType: string, facetKey: string) => {
82
99
  return COMPONENT_TYPES[widgetType] || COMPONENT_TYPES[WIDGET_TYPE.category];
83
100
  };
84
101
 
85
- export const FilterItem = ({ facet, isPending, startTransition }: Props) => {
102
+ export const FilterItem = ({
103
+ facet,
104
+ isPending,
105
+ startTransition,
106
+ isDropdown = false,
107
+ itemPaddingY = 6,
108
+ itemPaddingX = 0,
109
+ itemMarginBottom = 0
110
+ }: FilterItemProps) => {
86
111
  const dispatch = useAppDispatch();
87
112
  const router = useRouter();
88
113
  const pathname = usePathname();
89
114
 
90
115
  const [pendingChoice, setPendingChoice] = useState<string | null>(null);
116
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
91
117
 
92
118
  const handleSelectFilter = ({
93
119
  facet,
@@ -96,6 +122,7 @@ export const FilterItem = ({ facet, isPending, startTransition }: Props) => {
96
122
  facet: Facet;
97
123
  choice: FacetChoice;
98
124
  }) => {
125
+ setIsDrawerOpen(false);
99
126
  setPendingChoice(choice.label);
100
127
  startTransition(() => {
101
128
  if (facet.key === 'category_ids') {
@@ -114,50 +141,119 @@ export const FilterItem = ({ facet, isPending, startTransition }: Props) => {
114
141
  const Component = getComponentByWidgetType(facet.widget_type, facet.key);
115
142
  const choices = sortChoices(facet?.key, [...(facet?.data?.choices || [])]);
116
143
 
117
- return (
118
- <Accordion
119
- key={facet.key}
120
- title={facet.name}
121
- isCollapse={choices.some((choice) => choice.is_selected)}
122
- dataTestId={`filter-${facet.name}`}
123
- >
124
- <div
125
- className={clsx('flex gap-4', {
126
- 'flex-wrap flex-row': facet.key === sizeKey,
127
- 'flex-col': facet.key !== sizeKey
128
- })}
144
+ const choiceItemStyles = {
145
+ paddingTop: `${itemPaddingY}px`,
146
+ paddingBottom: `${itemPaddingY}px`,
147
+ paddingLeft: `${itemPaddingX}px`,
148
+ paddingRight: `${itemPaddingX}px`,
149
+ marginBottom: `${itemMarginBottom}px`
150
+ };
151
+
152
+ const renderChoice = (choice: FacetChoice, index: number) => (
153
+ <div key={choice.label} className="relative" style={choiceItemStyles}>
154
+ <Component
155
+ data={choice}
156
+ name={facet.key}
157
+ onChange={() => handleSelectFilter({ facet, choice })}
158
+ onClick={() =>
159
+ facet.key === sizeKey && handleSelectFilter({ facet, choice })
160
+ }
161
+ checked={choice.is_selected}
162
+ data-testid={`${choice.label.trim()}`}
163
+ disabled={isPending}
129
164
  >
130
- {choices.map((choice, index) => (
131
- <div key={choice.label} className="relative">
132
- <Component
133
- key={choice.label}
134
- data={choice}
135
- name={facet.key}
136
- onChange={() => handleSelectFilter({ facet, choice })}
137
- onClick={() =>
138
- facet.key === sizeKey && handleSelectFilter({ facet, choice })
139
- }
140
- checked={choice.is_selected}
141
- data-testid={`${choice.label.trim()}`}
142
- disabled={isPending}
165
+ {choice.label} (
166
+ <span data-testid={`filter-count-${facet.name.toLowerCase()}-${index}`}>
167
+ {choice.quantity}
168
+ </span>
169
+ )
170
+ </Component>
171
+
172
+ {isPending && pendingChoice === choice.label && (
173
+ <div className="absolute inset-0 flex items-center justify-center z-50">
174
+ <LoaderSpinner />
175
+ </div>
176
+ )}
177
+ </div>
178
+ );
179
+
180
+ const renderChoices = (className: string) => (
181
+ <div className={className}>
182
+ {choices.map((choice, index) => renderChoice(choice, index))}
183
+ </div>
184
+ );
185
+
186
+ const containerStyles = {
187
+ paddingTop: `${itemPaddingY}px`,
188
+ paddingBottom: `${itemPaddingY}px`,
189
+ paddingLeft: `${itemPaddingX}px`,
190
+ paddingRight: `${itemPaddingX}px`,
191
+ marginBottom: `${itemMarginBottom}px`
192
+ };
193
+
194
+ return (
195
+ <div style={containerStyles}>
196
+ {isDropdown ? (
197
+ renderChoices(
198
+ clsx({
199
+ 'flex flex-wrap gap-4': facet.key === sizeKey,
200
+ 'space-y-2': facet.key !== sizeKey
201
+ })
202
+ )
203
+ ) : (
204
+ <>
205
+ <div className="block lg:hidden">
206
+ <Button
207
+ className="w-full flex justify-between items-center text-base hover:bg-transparent hover:text-black-750 p-0"
208
+ appearance="ghost"
209
+ onClick={() => setIsDrawerOpen(true)}
143
210
  >
144
- {choice.label} (
145
- <span
146
- data-testid={`filter-count-${facet.name.toLowerCase()}-${index}`}
147
- >
148
- {choice.quantity}
149
- </span>
150
- )
151
- </Component>
152
-
153
- {isPending && pendingChoice === choice.label && (
154
- <div className="absolute inset-0 flex items-center justify-center z-50">
155
- <LoaderSpinner />
211
+ <span>{facet.name}</span>
212
+ <Icon name="arrow-right" size={20} />
213
+ </Button>
214
+
215
+ {isDrawerOpen && (
216
+ <div className="absolute w-full top-16 inset-x-0 bottom-0 z-50 bg-white">
217
+ <div className="flex items-center text-black-750 text-sm">
218
+ <Button
219
+ type="button"
220
+ className="text-sm hover:bg-transparent hover:text-black-750"
221
+ appearance="ghost"
222
+ onClick={() => setIsDrawerOpen(false)}
223
+ >
224
+ <Icon name="arrow-left" size={16} />
225
+ </Button>
226
+ <span className="text-sm">{facet.name}</span>
227
+ </div>
228
+ <div className="p-4 overflow-y-auto h-full">
229
+ {renderChoices(
230
+ clsx('flex gap-4', {
231
+ 'flex-wrap flex-row': facet.key === sizeKey,
232
+ 'flex-col': facet.key !== sizeKey
233
+ })
234
+ )}
235
+ </div>
156
236
  </div>
157
237
  )}
158
238
  </div>
159
- ))}
160
- </div>
161
- </Accordion>
239
+
240
+ <div className="hidden lg:block">
241
+ <Accordion
242
+ key={facet.key}
243
+ title={facet.name}
244
+ isCollapse={choices.some((choice) => choice.is_selected)}
245
+ dataTestId={`filter-${facet.name}`}
246
+ >
247
+ {renderChoices(
248
+ clsx('flex gap-4', {
249
+ 'flex-wrap flex-row': facet.key === sizeKey,
250
+ 'flex-col': facet.key !== sizeKey
251
+ })
252
+ )}
253
+ </Accordion>
254
+ </div>
255
+ </>
256
+ )}
257
+ </div>
162
258
  );
163
259
  };
@@ -6,7 +6,7 @@ import { useLocalization } from '@akinon/next/hooks';
6
6
  import { useAppDispatch, useAppSelector } from '@akinon/next/redux/hooks';
7
7
  import { resetSelectedFacets } from '@theme/redux/reducers/category';
8
8
  import CategoryActiveFilters from '@theme/views/category/category-active-filters';
9
- import { useMemo, useState, useTransition } from 'react';
9
+ import { useMemo, useTransition } from 'react';
10
10
  import { FilterItem } from './filter-item';
11
11
 
12
12
  interface Props {
@@ -12,6 +12,7 @@ export default async function Layout({
12
12
  data: GetCategoryResponse;
13
13
  children?: React.ReactNode;
14
14
  breadcrumbData?: BreadcrumbResultType[];
15
+ pageContext?: Record<string, unknown>;
15
16
  }) {
16
17
  return (
17
18
  <>