@akinon/projectzero 2.0.0-beta.2 → 2.0.0-beta.21

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 (300) hide show
  1. package/CHANGELOG.md +155 -6
  2. package/app-template/.env.example +8 -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 +5 -0
  10. package/app-template/AGENTS.md +7 -0
  11. package/app-template/CHANGELOG.md +1783 -61
  12. package/app-template/Procfile +1 -1
  13. package/app-template/README.md +6 -0
  14. package/app-template/akinon.json +1 -4
  15. package/app-template/build.sh +10 -0
  16. package/app-template/config/prebuild-tests.json +5 -0
  17. package/app-template/docs/advanced-usage.md +111 -0
  18. package/app-template/docs/plugins.md +60 -25
  19. package/app-template/docs/sentry-usage.md +35 -0
  20. package/app-template/jest.config.ts +2 -2
  21. package/app-template/next-env.d.ts +1 -0
  22. package/app-template/next.config.mjs +8 -6
  23. package/app-template/package.json +61 -50
  24. package/app-template/postcss.config.mjs +5 -0
  25. package/app-template/public/amex.svg +12 -0
  26. package/app-template/public/apple-pay.svg +16 -0
  27. package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
  28. package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
  29. package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
  30. package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
  31. package/app-template/public/google-pay.svg +16 -0
  32. package/app-template/public/locales/en/account.json +13 -4
  33. package/app-template/public/locales/en/auth.json +6 -7
  34. package/app-template/public/locales/en/basket.json +6 -6
  35. package/app-template/public/locales/en/blog.json +7 -0
  36. package/app-template/public/locales/en/category.json +3 -1
  37. package/app-template/public/locales/en/checkout.json +17 -4
  38. package/app-template/public/locales/en/common.json +71 -3
  39. package/app-template/public/locales/en/forgot_password.json +6 -7
  40. package/app-template/public/locales/en/product.json +84 -4
  41. package/app-template/public/locales/tr/account.json +13 -4
  42. package/app-template/public/locales/tr/auth.json +16 -17
  43. package/app-template/public/locales/tr/basket.json +4 -4
  44. package/app-template/public/locales/tr/blog.json +7 -0
  45. package/app-template/public/locales/tr/category.json +3 -1
  46. package/app-template/public/locales/tr/checkout.json +48 -36
  47. package/app-template/public/locales/tr/common.json +70 -2
  48. package/app-template/public/locales/tr/forgot_password.json +12 -13
  49. package/app-template/public/locales/tr/product.json +82 -0
  50. package/app-template/public/logo.svg +3 -27
  51. package/app-template/public/mastercard.svg +14 -0
  52. package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
  53. package/app-template/public/promotion-banner.jpg +0 -0
  54. package/app-template/public/shop-pay.svg +12 -0
  55. package/app-template/public/visa.svg +12 -0
  56. package/app-template/src/__tests__/middleware-matcher.test.ts +135 -0
  57. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +11 -11
  58. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +4 -3
  59. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +105 -13
  60. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +136 -52
  61. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
  62. package/app-template/src/app/[pz]/blog/[slug]/page.tsx +120 -0
  63. package/app-template/src/app/[pz]/category/[pk]/page.tsx +37 -0
  64. package/app-template/src/app/[pz]/error.tsx +17 -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 +1 -2
  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/page.tsx → [pz]/not-found.tsx} +5 -7
  72. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +7 -4
  73. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
  74. package/app-template/src/app/[pz]/page.tsx +28 -0
  75. package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
  76. package/app-template/src/app/[pz]/product/[pk]/page.tsx +102 -0
  77. package/app-template/src/app/[pz]/special-page/[pk]/page.tsx +35 -0
  78. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/email-set-primary/[[...id]]/page.tsx +3 -4
  79. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/registration/account-confirm-email/[[...id]]/page.tsx +3 -3
  80. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/reset/[[...id]]/page.tsx +41 -5
  81. package/app-template/src/app/[pz]/xml-sitemap/[node]/route.ts +73 -0
  82. package/app-template/src/app/api/auth/[...nextauth]/route.ts +3 -0
  83. package/app-template/src/app/api/barcode-search/route.ts +1 -0
  84. package/app-template/src/app/api/cache/route.ts +1 -1
  85. package/app-template/src/app/api/form/[...id]/route.ts +1 -7
  86. package/app-template/src/app/api/image-proxy/route.ts +1 -0
  87. package/app-template/src/app/api/logout/route.ts +1 -1
  88. package/app-template/src/app/api/product-categories/route.ts +1 -0
  89. package/app-template/src/app/api/similar-product-list/route.ts +1 -0
  90. package/app-template/src/app/api/similar-products/route.ts +1 -0
  91. package/app-template/src/app/api/theme-settings/route.ts +12 -0
  92. package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
  93. package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
  94. package/app-template/src/app/api/web-vitals/route.ts +1 -1
  95. package/app-template/src/assets/fonts/pz-icon.css +211 -49
  96. package/app-template/src/assets/fonts/pz-icon.eot +0 -0
  97. package/app-template/src/assets/fonts/pz-icon.html +486 -0
  98. package/app-template/src/assets/fonts/pz-icon.scss +373 -49
  99. package/app-template/src/assets/fonts/pz-icon.svg +215 -53
  100. package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
  101. package/app-template/src/assets/fonts/pz-icon.woff +0 -0
  102. package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
  103. package/app-template/src/assets/globals.scss +37 -34
  104. package/app-template/src/assets/icons/arrow-right.svg +3 -0
  105. package/app-template/src/assets/icons/cart.svg +4 -12
  106. package/app-template/src/assets/icons/check.svg +2 -18
  107. package/app-template/src/assets/icons/chevron-down.svg +2 -7
  108. package/app-template/src/assets/icons/delete.svg +3 -0
  109. package/app-template/src/assets/icons/facebook.svg +2 -8
  110. package/app-template/src/assets/icons/fav-off.svg +5 -0
  111. package/app-template/src/assets/icons/fav-on.svg +5 -0
  112. package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
  113. package/app-template/src/assets/icons/heart.svg +3 -0
  114. package/app-template/src/assets/icons/instagram.svg +2 -13
  115. package/app-template/src/assets/icons/materials.svg +3 -0
  116. package/app-template/src/assets/icons/person.svg +4 -0
  117. package/app-template/src/assets/icons/pinterest.svg +5 -11
  118. package/app-template/src/assets/icons/ruler.svg +3 -0
  119. package/app-template/src/assets/icons/search.svg +8 -11
  120. package/app-template/src/assets/icons/share.svg +2 -9
  121. package/app-template/src/assets/icons/snapchat.svg +3 -0
  122. package/app-template/src/assets/icons/tiktok.svg +3 -0
  123. package/app-template/src/assets/icons/tumblr.svg +6 -0
  124. package/app-template/src/assets/icons/twitter.svg +2 -10
  125. package/app-template/src/assets/icons/vimeo.svg +3 -0
  126. package/app-template/src/assets/icons/youtube.svg +3 -0
  127. package/app-template/src/assets/icons/zoom.svg +8 -0
  128. package/app-template/src/auth.ts +3 -0
  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 +50 -35
  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 +64 -2
  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 +8 -2
  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/tabs.tsx +2 -2
  151. package/app-template/src/components/types/index.ts +55 -2
  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/middleware.ts +1 -0
  160. package/app-template/src/plugins.js +13 -2
  161. package/app-template/src/redux/middlewares/category.ts +6 -5
  162. package/app-template/src/redux/reducers/category.ts +1 -1
  163. package/app-template/src/redux/store.ts +21 -1
  164. package/app-template/src/routes/index.ts +8 -7
  165. package/app-template/src/settings.js +5 -3
  166. package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
  167. package/app-template/src/types/index.ts +74 -3
  168. package/app-template/src/types/next-auth.d.ts +2 -2
  169. package/app-template/src/types/widget.ts +169 -0
  170. package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
  171. package/app-template/src/utils/convert-facet-search-params.ts +1 -1
  172. package/app-template/src/utils/formatDate.ts +48 -0
  173. package/app-template/src/utils/styles.ts +71 -0
  174. package/app-template/src/utils/theme-page-context.ts +309 -0
  175. package/app-template/src/utils/variant-validation.ts +41 -0
  176. package/app-template/src/views/account/address-form.tsx +8 -4
  177. package/app-template/src/views/account/contact-form.tsx +148 -136
  178. package/app-template/src/views/account/content-header.tsx +2 -2
  179. package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
  180. package/app-template/src/views/account/favorite-item.tsx +1 -1
  181. package/app-template/src/views/account/order.tsx +10 -8
  182. package/app-template/src/views/account/orders/order-cancellation-item.tsx +4 -3
  183. package/app-template/src/views/account/orders/order-detail-header.tsx +1 -1
  184. package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +44 -37
  185. package/app-template/src/views/basket/basket-item.tsx +7 -1
  186. package/app-template/src/views/basket/summary.tsx +16 -0
  187. package/app-template/src/views/breadcrumb.tsx +2 -2
  188. package/app-template/src/views/category/category-active-filters.tsx +1 -1
  189. package/app-template/src/views/category/category-banner.tsx +4 -23
  190. package/app-template/src/views/category/category-header.tsx +12 -6
  191. package/app-template/src/views/category/category-info.tsx +4 -3
  192. package/app-template/src/views/category/filters/filter-item.tsx +138 -42
  193. package/app-template/src/views/category/filters/index.tsx +3 -3
  194. package/app-template/src/views/category/layout.tsx +1 -0
  195. package/app-template/src/views/checkout/auth.tsx +64 -40
  196. package/app-template/src/views/checkout/layout/header.tsx +9 -5
  197. package/app-template/src/views/checkout/steps/payment/index.tsx +1 -1
  198. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +21 -5
  199. package/app-template/src/views/checkout/steps/payment/options/funds-transfer.tsx +25 -5
  200. package/app-template/src/views/checkout/steps/payment/options/loyalty.tsx +21 -2
  201. package/app-template/src/views/checkout/steps/payment/options/redirection.tsx +27 -5
  202. package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +464 -0
  203. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +30 -17
  204. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +1 -1
  205. package/app-template/src/views/checkout/summary.tsx +10 -0
  206. package/app-template/src/views/find-in-store/index.tsx +2 -2
  207. package/app-template/src/views/guest-login/index.tsx +62 -58
  208. package/app-template/src/views/header/action-menu.tsx +7 -4
  209. package/app-template/src/views/header/index.tsx +1 -1
  210. package/app-template/src/views/header/mini-basket.tsx +14 -3
  211. package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
  212. package/app-template/src/views/header/mobile-menu.tsx +12 -0
  213. package/app-template/src/views/header/search/index.tsx +23 -1
  214. package/app-template/src/views/installment-options/index.tsx +1 -1
  215. package/app-template/src/views/login/index.tsx +89 -56
  216. package/app-template/src/views/otp-login/index.tsx +23 -20
  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 +75 -237
  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 +21 -0
  225. package/app-template/src/views/product/variant.tsx +69 -41
  226. package/app-template/src/views/register/index.tsx +54 -44
  227. package/app-template/src/views/share/index.tsx +9 -6
  228. package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
  229. package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
  230. package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
  231. package/app-template/src/widgets/footer-menu.tsx +6 -2
  232. package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
  233. package/app-template/src/widgets/home-stories-eng.tsx +42 -34
  234. package/app-template/src/widgets/index.ts +7 -0
  235. package/app-template/src/widgets/schemas/about-us.json +46 -0
  236. package/app-template/src/widgets/schemas/blog-list.json +37 -0
  237. package/app-template/src/widgets/schemas/blog.json +29 -0
  238. package/app-template/tailwind.config.js +19 -7
  239. package/app-template/tsconfig.json +29 -11
  240. package/codemods/migrate-segments/index.js +591 -0
  241. package/codemods/sentry-9/index.js +30 -0
  242. package/codemods/sentry-9/remove-sentry-configs.js +14 -0
  243. package/codemods/sentry-9/remove-sentry-dependency.js +25 -0
  244. package/codemods/sentry-9/replace-error-page.js +32 -0
  245. package/codemods/update-tailwind-config/index.js +30 -0
  246. package/codemods/update-tailwind-config/transform.js +102 -0
  247. package/commands/codemod.ts +17 -0
  248. package/commands/index.ts +3 -1
  249. package/commands/plugins.ts +115 -46
  250. package/dist/codemods/sentry-9/templates/error.js +14 -0
  251. package/dist/commands/codemod.js +15 -0
  252. package/dist/commands/index.js +3 -1
  253. package/dist/commands/plugins.js +108 -36
  254. package/package.json +3 -2
  255. package/app-template/postcss.config.js +0 -6
  256. package/app-template/sentry.client.config.ts +0 -16
  257. package/app-template/sentry.edge.config.ts +0 -3
  258. package/app-template/sentry.properties +0 -4
  259. package/app-template/sentry.server.config.ts +0 -3
  260. package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
  261. package/app-template/src/app/[commerce]/[locale]/[currency]/error.tsx +0 -20
  262. package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
  263. package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
  264. package/app-template/src/app/[commerce]/[locale]/[currency]/list/page.tsx +0 -18
  265. package/app-template/src/app/[commerce]/[locale]/[currency]/page.tsx +0 -50
  266. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/loading.tsx +0 -67
  267. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
  268. package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
  269. package/app-template/src/app/[commerce]/[locale]/[currency]/xml-sitemap/[node]/route.ts +0 -25
  270. package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
  271. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
  272. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
  273. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
  274. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
  275. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
  276. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
  277. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
  278. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
  279. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
  280. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
  281. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
  282. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +0 -0
  283. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +0 -0
  284. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
  285. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
  286. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +0 -0
  287. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +0 -0
  288. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
  289. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
  290. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
  291. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
  292. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
  293. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
  294. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
  295. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
  296. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
  297. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
  298. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
  299. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
  300. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
@@ -0,0 +1,12 @@
1
+ <svg width="38" height="24" viewBox="0 0 38 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#2mu4dnqfla)">
3
+ <path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z" fill="#000"/>
4
+ <path d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32z" fill="#5A31F4"/>
5
+ <path d="M21.382 9.713c0 1.668-1.177 2.858-2.82 2.858h-1.55a.132.132 0 0 0-.13.13v2.191a.13.13 0 0 1-.08.12.13.13 0 0 1-.05.01h-1.084a.13.13 0 0 1-.13-.13V6.985a.127.127 0 0 1 .08-.12.129.129 0 0 1 .05-.01h2.9c1.637 0 2.814 1.19 2.814 2.858zm-1.352 0c0-.958-.658-1.658-1.55-1.658h-1.468a.13.13 0 0 0-.12.08.13.13 0 0 0-.01.05v3.05a.127.127 0 0 0 .038.092.13.13 0 0 0 .092.038h1.468c.892.005 1.55-.695 1.55-1.652zm1.674 3.791a1.528 1.528 0 0 1 .647-1.317c.423-.316 1.084-.48 2.055-.514l1.033-.036v-.303c0-.607-.41-.863-1.068-.863-.658 0-1.075.231-1.17.61a.127.127 0 0 1-.125.09h-1.022a.13.13 0 0 1-.126-.092.125.125 0 0 1-.004-.055c.152-.898.904-1.58 2.494-1.58 1.692 0 2.303.783 2.303 2.276v3.172a.13.13 0 0 1-.132.13h-1.03a.13.13 0 0 1-.13-.13v-.237a.096.096 0 0 0-.118-.096.1.1 0 0 0-.05.027c-.31.334-.808.575-1.607.575-1.175 0-1.95-.607-1.95-1.657zm3.735-.687v-.246l-1.339.07c-.705.036-1.115.326-1.115.816 0 .444.376.69 1.034.69.893 0 1.42-.48 1.42-1.33zm2.316 4.6v-.919a.13.13 0 0 1 .1-.125.13.13 0 0 1 .057-.002c.158.03.318.044.48.044a1.23 1.23 0 0 0 1.244-.876l.067-.21a.133.133 0 0 0 0-.089L27.558 9.77a.13.13 0 0 1 .122-.18h1.04a.132.132 0 0 1 .123.085l1.456 3.86a.131.131 0 0 0 .125.087.133.133 0 0 0 .125-.088l1.265-3.848a.13.13 0 0 1 .126-.09h1.076a.134.134 0 0 1 .132.116.134.134 0 0 1-.008.063l-2.295 6.076c-.528 1.413-1.433 1.773-2.43 1.773a1.963 1.963 0 0 1-.56-.066.132.132 0 0 1-.1-.14zM8.57 6.4a5.363 5.363 0 0 0-3.683 1.427.231.231 0 0 0-.029.31l.618.84a.236.236 0 0 0 .362.027 3.823 3.823 0 0 1 2.738-1.11c2.12 0 3.227 1.584 3.227 3.15 0 1.7-1.163 2.898-2.835 2.921-1.292 0-2.266-.85-2.266-1.974a1.908 1.908 0 0 1 .713-1.48.231.231 0 0 0 .033-.324l-.65-.815a.236.236 0 0 0-.339-.034 3.43 3.43 0 0 0-.942 1.183 3.39 3.39 0 0 0-.337 1.47c0 1.935 1.655 3.452 3.775 3.464h.03c2.517-.032 4.337-1.884 4.337-4.415 0-2.247-1.667-4.64-4.752-4.64z" fill="#fff"/>
6
+ </g>
7
+ <defs>
8
+ <clipPath id="2mu4dnqfla">
9
+ <path fill="#fff" d="M0 0h38v24H0z"/>
10
+ </clipPath>
11
+ </defs>
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg width="38" height="24" viewBox="0 0 38 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#ezvyrlvp0a)">
3
+ <path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z" fill="#000"/>
4
+ <path d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32z" fill="#fff"/>
5
+ <path d="M28.3 10.1H28c-.4 1-.7 1.5-1 3h1.9c-.3-1.5-.3-2.2-.6-3zm2.9 5.9h-1.7c-.1 0-.1 0-.2-.1l-.2-.9-.1-.2h-2.4c-.1 0-.2 0-.2.2l-.3.9c0 .1-.1.1-.1.1h-2.1l.2-.5L27 8.7c0-.5.3-.7.8-.7h1.5c.1 0 .2 0 .2.2l1.4 6.5c.1.4.2.7.2 1.1.1.1.1.1.1.2zm-13.4-.3.4-1.8c.1 0 .2.1.2.1.7.3 1.4.5 2.1.4.2 0 .5-.1.7-.2.5-.2.5-.7.1-1.1-.2-.2-.5-.3-.8-.5-.4-.2-.8-.4-1.1-.7-1.2-1-.8-2.4-.1-3.1.6-.4.9-.8 1.7-.8 1.2 0 2.5 0 3.1.2h.1c-.1.6-.2 1.1-.4 1.7-.5-.2-1-.4-1.5-.4-.3 0-.6 0-.9.1-.2 0-.3.1-.4.2-.2.2-.2.5 0 .7l.5.4c.4.2.8.4 1.1.6.5.3 1 .8 1.1 1.4.2.9-.1 1.7-.9 2.3-.5.4-.7.6-1.4.6-1.4 0-2.5.1-3.4-.2-.1.2-.1.2-.2.1zm-3.5.3c.1-.7.1-.7.2-1 .5-2.2 1-4.5 1.4-6.7.1-.2.1-.3.3-.3H18c-.2 1.2-.4 2.1-.7 3.2-.3 1.5-.6 3-1 4.5 0 .2-.1.2-.3.2l-1.7.1zM5 8.2c0-.1.2-.2.3-.2h3.4c.5 0 .9.3 1 .8l.9 4.4c0 .1 0 .1.1.2 0-.1.1-.1.1-.1l2.1-5.1c-.1-.1 0-.2.1-.2h2.1c0 .1 0 .1-.1.2l-3.1 7.3c-.1.2-.1.3-.2.4-.1.1-.3 0-.5 0H9.7c-.1 0-.2 0-.2-.2L7.9 9.5c-.2-.2-.5-.5-.9-.6-.6-.3-1.7-.5-1.9-.5L5 8.2z" fill="#142688"/>
6
+ </g>
7
+ <defs>
8
+ <clipPath id="ezvyrlvp0a">
9
+ <path fill="#fff" d="M0 0h38v24H0z"/>
10
+ </clipPath>
11
+ </defs>
12
+ </svg>
@@ -0,0 +1,135 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ describe('Middleware matcher regex tests', () => {
5
+ const middlewareFilePath = path.resolve(__dirname, '../middleware.ts');
6
+ const middlewareContent = fs.readFileSync(middlewareFilePath, 'utf8');
7
+
8
+ let actualMatcherStrings: string[] = [];
9
+ let matcherPatterns: RegExp[] = [];
10
+
11
+ const matcherBlockRegex = middlewareContent.match(/matcher:\s*\[([\s\S]*?)\](?=\s*[,}])/);
12
+
13
+ if (matcherBlockRegex && matcherBlockRegex[1]) {
14
+ const matcherContentInsideBrackets = matcherBlockRegex[1];
15
+
16
+ actualMatcherStrings = matcherContentInsideBrackets
17
+ .split(',')
18
+ .map(line => {
19
+ const uncommentedLine = line.replace(/\/\/.*$/, '').trim();
20
+ const quoteMatch = uncommentedLine.match(/^(['"])(.*)\1$/);
21
+ return quoteMatch ? quoteMatch[2] : null;
22
+ })
23
+ .filter((pattern): pattern is string => pattern !== null && pattern !== '');
24
+
25
+ matcherPatterns = matcherContentInsideBrackets
26
+ .split(',')
27
+ .map((pattern) => pattern.trim())
28
+ .filter(Boolean)
29
+ .map((pattern) => {
30
+ let cleanPattern = pattern
31
+ .replace(/^['"]|['"]$/g, '');
32
+
33
+ try {
34
+ if (cleanPattern.includes('(?!') && cleanPattern.includes('api') && cleanPattern.includes('_next')) {
35
+ cleanPattern = '^(?!/(?:api|_next)/)(?!.*\\.\\w+$).*$';
36
+ }
37
+
38
+ return new RegExp(cleanPattern);
39
+ } catch (error) {
40
+ console.error(`Invalid simplified regex: ${cleanPattern}`, error);
41
+ return null;
42
+ }
43
+ })
44
+ .filter(Boolean) as RegExp[];
45
+ }
46
+
47
+ const testPath = (path: string): boolean => {
48
+ return matcherPatterns.some((pattern) => {
49
+ try {
50
+ const result = pattern.test(path);
51
+ return result;
52
+ } catch (error) {
53
+ console.error(
54
+ `Error testing path: ${path} | Pattern: ${pattern.toString()}`,
55
+ error
56
+ );
57
+ return false;
58
+ }
59
+ });
60
+ };
61
+
62
+ it('should NOT match api routes', () => {
63
+ const apiPaths = ['/api/products', '/api/auth/login', '/api/v1/users'];
64
+ apiPaths.forEach((path) => {
65
+ expect(testPath(path)).toBe(false);
66
+ });
67
+ });
68
+
69
+ it('should NOT match _next routes', () => {
70
+ const nextPaths = [
71
+ '/_next/static/chunks/main.js',
72
+ '/_next/image',
73
+ '/_next/data/build-id/products.json'
74
+ ];
75
+ nextPaths.forEach((path) => {
76
+ expect(testPath(path)).toBe(false);
77
+ });
78
+ });
79
+
80
+ it('should NOT match static files with extensions', () => {
81
+ const staticFiles = [
82
+ '/images/logo.png',
83
+ '/styles/main.css',
84
+ '/fonts/roboto.woff2',
85
+ '/favicon.ico',
86
+ '/manifest.json'
87
+ ];
88
+ staticFiles.forEach((path) => {
89
+ expect(testPath(path)).toBe(false);
90
+ });
91
+ });
92
+
93
+ it('should match dynamic routes and specific patterns', () => {
94
+ const validPaths = [
95
+ '/profile/settings',
96
+ '/dashboard/stats',
97
+ '/products/123'
98
+ ];
99
+ validPaths.forEach((path) => {
100
+ expect(testPath(path)).toBe(true);
101
+ });
102
+ });
103
+
104
+ it('should match checkout-with-token routes', () => {
105
+ const expectedRegexString = '\'/(.*orders\\\\/checkout-with-token.*)\'';
106
+ expect(middlewareContent.includes(expectedRegexString)).toBe(true);
107
+
108
+ const checkoutPaths = [
109
+ '/orders/checkout-with-token/123',
110
+ '/orders/checkout-with-token/abc-xyz',
111
+ '/orders/checkout-with-token'
112
+ ];
113
+ checkoutPaths.forEach((path) => {
114
+ expect(testPath(path)).toBe(true);
115
+ });
116
+ });
117
+
118
+ it('should contain the exact specific extensions regex string in the file content', () => {
119
+ const expectedRegexString = '\'/(.+\\\\.)(html|htm|aspx|asp|php)\'';
120
+ expect(middlewareContent.includes(expectedRegexString)).toBe(true);
121
+ });
122
+
123
+ it('should include the sitemap pattern specifically within the matcher array', () => {
124
+ const sitemapPattern = '/(.*sitemap\\\\.xml)';
125
+ expect(actualMatcherStrings).toContain(sitemapPattern);
126
+ });
127
+
128
+ it('should verify that api pattern is excluded in the matcher configuration', () => {
129
+ expect(/api/.test(middlewareContent)).toBe(true);
130
+ });
131
+
132
+ it('should verify that _next pattern is excluded in the matcher configuration', () => {
133
+ expect(/_next/.test(middlewareContent)).toBe(true);
134
+ });
135
+ });
@@ -1,5 +1,5 @@
1
1
  import { URLS } from '@akinon/next/data/urls';
2
- import { Metadata, PageProps } from '@akinon/next/types';
2
+ import { Metadata, AsyncPageProps } from '@akinon/next/types';
3
3
  import logger from '@akinon/next/utils/log';
4
4
  import { notFound } from 'next/navigation';
5
5
 
@@ -56,7 +56,7 @@ const resolvePrettyUrlHandler =
56
56
  return prettyUrlResult;
57
57
  };
58
58
 
59
- export async function generateMetadata(props: PageProps) {
59
+ export async function generateMetadata(props: AsyncPageProps) {
60
60
  const params = await props.params;
61
61
  let result: Metadata = {};
62
62
  const { prettyurl } = params;
@@ -78,41 +78,41 @@ export async function generateMetadata(props: PageProps) {
78
78
  }
79
79
 
80
80
  const commonProps = {
81
- params: {
81
+ params: Promise.resolve({
82
82
  ...params,
83
83
  pk: prettyUrlResult.pk
84
- },
84
+ }),
85
85
  searchParams: Promise.resolve(searchParams)
86
86
  };
87
87
 
88
88
  try {
89
89
  if (prettyUrlResult.path.startsWith('/product/')) {
90
90
  await import('@product/[pk]/page').then(async (module) => {
91
- result = await module['generateMetadata']?.(commonProps);
91
+ result = await module['generateMetadata']?.(commonProps as any);
92
92
  });
93
93
  }
94
94
 
95
95
  if (prettyUrlResult.path.startsWith('/group-product/')) {
96
96
  await import('@group-product/[pk]/page').then(async (module) => {
97
- result = await module['generateMetadata']?.(commonProps);
97
+ result = await module['generateMetadata']?.(commonProps as any);
98
98
  });
99
99
  }
100
100
 
101
101
  if (prettyUrlResult.path.startsWith('/category/')) {
102
102
  await import('@category/[pk]/page').then(async (module) => {
103
- result = await module['generateMetadata']?.(commonProps);
103
+ result = await module['generateMetadata']?.(commonProps as any);
104
104
  });
105
105
  }
106
106
 
107
107
  if (prettyUrlResult.path.startsWith('/special-page/')) {
108
108
  await import('@special-page/[pk]/page').then(async (module) => {
109
- result = await module['generateMetadata']?.(commonProps);
109
+ result = await module['generateMetadata']?.(commonProps as any);
110
110
  });
111
111
  }
112
112
 
113
113
  if (prettyUrlResult.path.startsWith('/flat-page/')) {
114
114
  await import('@flat-page/[pk]/page').then(async (module) => {
115
- result = await module['generateMetadata']?.(commonProps);
115
+ result = await module['generateMetadata']?.(commonProps as any);
116
116
  });
117
117
  }
118
118
  // eslint-disable-next-line no-empty
@@ -161,8 +161,8 @@ export default async function Page(props) {
161
161
  ...params,
162
162
  pk: result.pk
163
163
  },
164
- searchParams: Promise.resolve(urlSearchParams)
165
- };
164
+ searchParams: urlSearchParams
165
+ } as any;
166
166
 
167
167
  if (result.path.startsWith('/category/')) {
168
168
  const CategoryPage = (await import('@category/[pk]/page')).default;
@@ -1,6 +1,7 @@
1
1
  import AccountBackButton from '@theme/views/account/back-button';
2
2
  import AccountMenu from '@theme/views/account/account-menu';
3
- import { getServerSession } from 'next-auth/next';
3
+ import ThemePlaceholder from '@akinon/pz-theme/src/theme-placeholder';
4
+ import { auth } from 'auth';
4
5
  import { ROUTES } from 'routes';
5
6
  import { redirect } from '@akinon/next/utils/redirect';
6
7
 
@@ -9,7 +10,7 @@ export default async function AccountLayout({
9
10
  }: {
10
11
  children: React.ReactNode;
11
12
  }) {
12
- const session = await getServerSession();
13
+ const session = await auth();
13
14
 
14
15
  if (!session?.user) {
15
16
  return redirect(ROUTES.AUTH);
@@ -20,7 +21,7 @@ export default async function AccountLayout({
20
21
  <AccountMenu />
21
22
  <div className="w-full flex-1">
22
23
  <AccountBackButton />
23
-
24
+ <ThemePlaceholder slug="account-page-body" />
24
25
  {children}
25
26
  </div>
26
27
  </div>
@@ -15,9 +15,11 @@ import {
15
15
  Select,
16
16
  Modal,
17
17
  LoaderSpinner,
18
- Link
18
+ Link,
19
+ FileInput
19
20
  } from '@theme/components';
20
- import { useState, use } from 'react';
21
+ import { useState } from 'react';
22
+ import { useParams } from 'next/navigation';
21
23
  import { OrderDetailHeader } from '@theme/views/account/orders/order-detail-header';
22
24
  import { OrderCancellationItem } from '@theme/views/account/orders/order-cancellation-item';
23
25
  import { useLocalization } from '@akinon/next/hooks';
@@ -26,9 +28,8 @@ const accountOrderCancellationSchema = yup.object().shape({
26
28
  return_policy: yup.boolean().oneOf([true], 'This field is required.')
27
29
  });
28
30
 
29
- const AccountOrderCancellation = ({ params }) => {
30
- const pageParams = use(params) as { id: string };
31
-
31
+ const AccountOrderCancellation = () => {
32
+ const params = useParams<{ id: string }>();
32
33
  const { t } = useLocalization();
33
34
  const {
34
35
  register,
@@ -41,6 +42,7 @@ const AccountOrderCancellation = ({ params }) => {
41
42
  } = useForm<AccountOrderCancellation>({
42
43
  resolver: yupResolver(accountOrderCancellationSchema)
43
44
  });
45
+
44
46
  const { data: cancellationReasons, isSuccess: cancellationReasonsSuccess } =
45
47
  useGetCancellationReasonsQuery();
46
48
 
@@ -48,7 +50,7 @@ const AccountOrderCancellation = ({ params }) => {
48
50
  data: order,
49
51
  isLoading,
50
52
  isSuccess: orderSuccess
51
- } = useGetOrderQuery(pageParams.id);
53
+ } = useGetOrderQuery(params.id);
52
54
 
53
55
  const [isModalOpen, setIsModalOpen] = useState(false);
54
56
  const [responseMessage, setResponseMessage] = useState({
@@ -58,6 +60,9 @@ const AccountOrderCancellation = ({ params }) => {
58
60
  const watchAllFields = watch();
59
61
  const cancelItemsLength = watchAllFields?.cancel_order_items?.length;
60
62
  const [cancelOrder] = useCancelOrderMutation();
63
+ const [files, setFiles] = useState<
64
+ { itemId: string; image: string; description: string }[]
65
+ >([]);
61
66
 
62
67
  const modalHandleClick = () => {
63
68
  setIsModalOpen(false);
@@ -114,8 +119,68 @@ const AccountOrderCancellation = ({ params }) => {
114
119
  ]);
115
120
  };
116
121
 
122
+ const handleFileChange = async (
123
+ e: React.ChangeEvent<HTMLInputElement>,
124
+ itemId: string,
125
+ description: string
126
+ ) => {
127
+ const selectedFiles = Array.from(e.target.files || []);
128
+
129
+ const base64Files = await Promise.all(
130
+ selectedFiles.map((file) => {
131
+ return new Promise<string>((resolve, reject) => {
132
+ const reader = new FileReader();
133
+ reader.onload = () => resolve(reader.result as string);
134
+ reader.onerror = reject;
135
+ reader.readAsDataURL(file);
136
+ });
137
+ })
138
+ );
139
+
140
+ const validFiles = base64Files.filter((file) =>
141
+ /^data:image\/(jpeg|png|jpg);base64,.+/.test(file)
142
+ );
143
+
144
+ const formattedFiles = validFiles.map((file) => ({
145
+ itemId,
146
+ image: file,
147
+ description
148
+ }));
149
+
150
+ setFiles((prevFiles) => [
151
+ ...prevFiles.filter((f) => f.itemId !== itemId),
152
+ ...formattedFiles
153
+ ]);
154
+ };
155
+
156
+ const fileInputCondition = (item, description: string) => {
157
+ if (item.is_refundable && !item.active_cancellation_request) {
158
+ return (
159
+ <FileInput
160
+ name="files"
161
+ title="files"
162
+ multiple
163
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
164
+ handleFileChange(e, item.id, description)
165
+ }
166
+ />
167
+ );
168
+ }
169
+ };
170
+
117
171
  const onSubmit: SubmitHandler<AccountOrderCancellation> = (orderItems) => {
118
- cancelOrder({ id: order.number, ...orderItems })
172
+ const mergedData = {
173
+ ...orderItems,
174
+ cancel_order_items: orderItems.cancel_order_items.map((orderItem) => ({
175
+ ...orderItem,
176
+ ...(files.length > 0 && {
177
+ cancellation_request_image_set: files.filter(
178
+ (file) => file.itemId === orderItem.order_item
179
+ )
180
+ })
181
+ }))
182
+ };
183
+ cancelOrder({ id: order.number, ...mergedData })
119
184
  .unwrap()
120
185
  .then(() => {
121
186
  setResponseMessage({
@@ -124,10 +189,33 @@ const AccountOrderCancellation = ({ params }) => {
124
189
  });
125
190
  setIsModalOpen(true);
126
191
  })
127
- .catch(() => {
192
+ .catch((err) => {
193
+ console.error('Err', err);
194
+
195
+ const errorMessages = new Set();
196
+
197
+ if (err?.data?.cancel_order_items) {
198
+ err.data.cancel_order_items.forEach((item) => {
199
+ if (item.cancellation_request_image_set) {
200
+ item.cancellation_request_image_set.forEach((error) => {
201
+ if (typeof error === 'string') {
202
+ errorMessages.add(error);
203
+ } else if (typeof error === 'object' && error?.image) {
204
+ error.image.forEach((msg) => errorMessages.add(msg));
205
+ }
206
+ });
207
+ }
208
+ });
209
+ }
210
+
211
+ const errorContent =
212
+ errorMessages.size > 0
213
+ ? Array.from(errorMessages).join('\n')
214
+ : t('account.my_orders.return.error.description').toString();
215
+
128
216
  setResponseMessage({
129
217
  title: t('account.my_orders.return.error.title').toString(),
130
- content: t('account.my_orders.return.error.description').toString()
218
+ content: errorContent
131
219
  });
132
220
  setIsModalOpen(true);
133
221
  });
@@ -149,13 +237,13 @@ const AccountOrderCancellation = ({ params }) => {
149
237
  <div>
150
238
  <div className="pb-2 mb-3 text-lg border-gray border-b">
151
239
  <span data-testid="account-orders-return-order-count">
152
- {order.orderitem_set.length}
240
+ {order?.orderitem_set?.length}
153
241
  </span>{' '}
154
242
  <span>{t('account.my_orders.detail.products')}</span>
155
243
  </div>
156
244
 
157
245
  <form onSubmit={handleSubmit(onSubmit)}>
158
- {order.orderitem_set.map((item, index: number) => (
246
+ {order?.orderitem_set?.map((item, index: number) => (
159
247
  <Controller
160
248
  defaultValue={[]}
161
249
  control={control}
@@ -166,7 +254,7 @@ const AccountOrderCancellation = ({ params }) => {
166
254
  return cancelItem.order_item === item.id;
167
255
  });
168
256
 
169
- const cancellationType = item.is_refundable
257
+ const cancellationType = item?.is_refundable
170
258
  ? 'refund'
171
259
  : 'cancel';
172
260
 
@@ -182,6 +270,10 @@ const AccountOrderCancellation = ({ params }) => {
182
270
  onChange={onChange}
183
271
  value={value}
184
272
  selectOption={selectOption}
273
+ fileInput={fileInputCondition(
274
+ item,
275
+ item?.product?.name
276
+ )}
185
277
  />
186
278
  );
187
279
  }}
@@ -208,7 +300,7 @@ const AccountOrderCancellation = ({ params }) => {
208
300
  </label>
209
301
  {errors.return_policy && (
210
302
  <div className="text-sm text-error">
211
- {errors.return_policy.message}
303
+ {String(errors.return_policy.message)}
212
304
  </div>
213
305
  )}
214
306
  </div>