@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
@@ -62,68 +62,72 @@ const GuestLogin = () => {
62
62
  };
63
63
 
64
64
  return (
65
- <form onSubmit={handleSubmit(onSubmit)}>
66
- <div className={clsx(errors.user_email ? 'mb-8' : 'mb-4')}>
67
- <Input
68
- labelStyle="floating"
69
- label={t('checkout.auth.form.login.email.placeholder')}
70
- name="email"
71
- className="h-14"
72
- {...register('user_email')}
73
- error={errors.user_email}
74
- data-testid="guest-email"
75
- required
76
- />
77
- </div>
65
+ <section className="w-full mt-6 lg:mt-8">
66
+ <form onSubmit={handleSubmit(onSubmit)}>
67
+ <div>
68
+ <Input
69
+ labelStyle="floating"
70
+ label={t('checkout.auth.form.login.email.placeholder')}
71
+ name="email"
72
+ className="h-12"
73
+ {...register('user_email')}
74
+ error={errors.user_email}
75
+ data-testid="guest-email"
76
+ required
77
+ />
78
+ </div>
78
79
 
79
- <div className={clsx(errors.phone_number ? 'mb-8' : 'mb-4')}>
80
- <Input
81
- labelStyle="floating"
82
- label={t('checkout.auth.form.login.phone.placeholder')}
83
- className="h-14"
84
- name="phone_number"
85
- type="tel"
86
- format={user_phone_format.replace(/9/g, '#')}
87
- mask="_"
88
- control={control}
89
- {...register('phone_number')}
90
- error={errors.phone_number}
91
- data-testid="guest-phone"
92
- required
93
- />
94
- </div>
80
+ <div className="mt-4">
81
+ <Input
82
+ labelStyle="floating"
83
+ label={t('checkout.auth.form.login.phone.placeholder')}
84
+ className="h-12"
85
+ name="phone_number"
86
+ type="tel"
87
+ format={user_phone_format.replace(/9/g, '#')}
88
+ mask="_"
89
+ control={control}
90
+ {...register('phone_number')}
91
+ error={errors.phone_number}
92
+ data-testid="guest-phone"
93
+ required
94
+ />
95
+ </div>
95
96
 
96
- <Button
97
- type="submit"
98
- className="w-full h-12 uppercase text-xs font-semibold mb-4"
99
- data-testid="guest-submit"
100
- >
101
- {t('checkout.auth.form.login.button')}
102
- </Button>
103
-
104
- <div className="text-sm text-black-400 md:text-xs">
105
- <p className="mb-4">{t('checkout.auth.form.login.agreement.label')}</p>
106
- <Checkbox
107
- name="sms_allowed"
108
- className={clsx('underline', errors.sms_allowed ? 'mb-8' : 'mb-4')}
109
- {...register('sms_allowed')}
110
- error={errors.sms_allowed}
111
- data-testid="guest-sms"
97
+ <Button
98
+ type="submit"
99
+ className="w-full h-12 uppercase text-xs font-semibold mt-[38px]"
100
+ data-testid="guest-submit"
112
101
  >
113
- {t('checkout.auth.form.login.agreement.terms_conditions')}
114
- </Checkbox>
102
+ {t('checkout.auth.form.login.button')}
103
+ </Button>
115
104
 
116
- <Checkbox
117
- name="confirm"
118
- className={clsx('underline', errors.kvkk_confirm ? 'mb-8' : 'mb-4')}
119
- {...register('kvkk_confirm')}
120
- error={errors.kvkk_confirm}
121
- data-testid="guest-kvkk"
122
- >
123
- {t('checkout.auth.form.login.agreement.privacy_policy')}
124
- </Checkbox>
125
- </div>
126
- </form>
105
+ <div className="mt-[38px] text-sm text-black-400 md:text-xs">
106
+ <p className="mb-4">
107
+ {t('checkout.auth.form.login.agreement.label')}
108
+ </p>
109
+ <Checkbox
110
+ name="sms_allowed"
111
+ className="underline"
112
+ {...register('sms_allowed')}
113
+ error={errors.sms_allowed}
114
+ data-testid="guest-sms"
115
+ >
116
+ {t('checkout.auth.form.login.agreement.terms_conditions')}
117
+ </Checkbox>
118
+
119
+ <Checkbox
120
+ name="confirm"
121
+ className="underline mt-4"
122
+ {...register('kvkk_confirm')}
123
+ error={errors.kvkk_confirm}
124
+ data-testid="guest-kvkk"
125
+ >
126
+ {t('checkout.auth.form.login.agreement.privacy_policy')}
127
+ </Checkbox>
128
+ </div>
129
+ </form>
130
+ </section>
127
131
  );
128
132
  };
129
133
 
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { ReactNode, useMemo, useRef, useCallback } from 'react';
4
- import { useGetBasketQuery } from '@akinon/next/data/client/basket';
4
+ import { useGetMiniBasketQuery } from '@akinon/next/data/client/basket';
5
5
  import { useAppDispatch, useAppSelector } from '@akinon/next/redux/hooks';
6
6
  import {
7
7
  closeMiniBasket,
@@ -29,8 +29,11 @@ interface MenuItem {
29
29
  export default function ActionMenu() {
30
30
  const dispatch = useAppDispatch();
31
31
 
32
- const { data } = useGetBasketQuery();
33
- const totalQuantity = useMemo(() => data?.total_quantity ?? 0, [data]);
32
+ const { data: miniBasket } = useGetMiniBasketQuery();
33
+ const totalQuantity = useMemo(
34
+ () => miniBasket?.total_quantity ?? 0,
35
+ [miniBasket]
36
+ );
34
37
 
35
38
  const { open: miniBasketOpen } = useAppSelector(
36
39
  (state) => state.root.miniBasket
@@ -73,7 +76,7 @@ export default function ActionMenu() {
73
76
  : 'bg-secondary-500 text-white'
74
77
  )}
75
78
  >
76
- {totalQuantity}
79
+ <span data-testid="header-basket-count">{totalQuantity}</span>
77
80
  </Badge>
78
81
  ),
79
82
  miniBasket: <MiniBasket />
@@ -13,7 +13,7 @@ import { getMenu } from '@akinon/next/data/server';
13
13
  import { Image } from '@akinon/next/components/image';
14
14
 
15
15
  export default async function Header() {
16
- const response = await getMenu();
16
+ const response = await getMenu({ depth: 3 });
17
17
  const menu = menuGenerator(response);
18
18
 
19
19
  return (
@@ -5,6 +5,7 @@ import clsx from 'clsx';
5
5
  import {
6
6
  basketApi,
7
7
  useGetBasketQuery,
8
+ useGetMiniBasketQuery,
8
9
  useUpdateQuantityMutation
9
10
  } from '@akinon/next/data/client/basket';
10
11
  import { useAppDispatch, useAppSelector } from '@akinon/next/redux/hooks';
@@ -150,14 +151,24 @@ export default function MiniBasket() {
150
151
  (state) => state.root.miniBasket
151
152
  );
152
153
  const dispatch = useAppDispatch();
153
- const { data: basket, isLoading, isSuccess } = useGetBasketQuery();
154
+ const {
155
+ data: basket,
156
+ isLoading,
157
+ isSuccess
158
+ } = useGetBasketQuery(undefined, {
159
+ skip: !miniBasketOpen
160
+ });
161
+ const { data: miniBasket } = useGetMiniBasketQuery();
154
162
  const { t } = useLocalization();
155
163
  const { highlightedItem } = useAppSelector((state) => state.root.miniBasket);
156
164
  const [highlightedItemPk, setHighlightedItemPk] = useState(0);
157
165
  const [sortedBasket, setSortedBasket] = useState([]);
158
166
 
159
- const totalQuantity = useMemo(() => basket?.total_quantity ?? 0, [basket]);
160
- const miniBasketList = useRef(null);
167
+ const totalQuantity = useMemo(
168
+ () => miniBasket?.total_quantity ?? 0,
169
+ [miniBasket]
170
+ );
171
+ const miniBasketList = useRef<HTMLUListElement | null>(null);
161
172
 
162
173
  useEffect(() => {
163
174
  if (highlightedItem > 0) {
@@ -11,24 +11,21 @@ export default function MobileHamburgerButton() {
11
11
  const dispatch = useAppDispatch();
12
12
 
13
13
  return (
14
- <div className="flex row-start-2 sm:hidden ">
14
+ <div className="flex sm:hidden">
15
15
  <PwaBackButton />
16
16
  <Button
17
17
  className={clsx([
18
- 'w-12',
19
- 'h-12',
20
- 'bg-secondary',
21
- 'text-white',
18
+ 'h-auto',
19
+ 'bg-transparent',
22
20
  'flex',
23
21
  'items-center',
24
22
  'justify-center',
25
23
  'px-0',
26
- 'border-none',
27
- 'hover:bg-secondary-hover'
24
+ 'border-none'
28
25
  ])}
29
26
  onClick={() => dispatch(toggleMobileMenu())}
30
27
  >
31
- <Icon name="hamburger" size={18} className="fill-white" />
28
+ <Icon name="hamburger" size={18} className="text-black" />
32
29
  </Button>
33
30
  </div>
34
31
  );
@@ -90,10 +90,22 @@ export default function MobileMenu(props: MobileMenuProps) {
90
90
  onClick={(e) => {
91
91
  if (item.children.length > 0) {
92
92
  e.preventDefault();
93
+ e.stopPropagation();
93
94
  setSelectedSubMenu(item);
95
+
96
+ window?.parent?.postMessage(
97
+ {
98
+ type: 'MENU_TOGGLE',
99
+ isMenuAction: true
100
+ },
101
+ '*'
102
+ );
94
103
  }
95
104
  }}
96
105
  className="flex items-center justify-between"
106
+ data-is-menu-toggle={
107
+ item.children.length > 0 ? 'true' : undefined
108
+ }
97
109
  >
98
110
  <span>{item.label}</span>
99
111
  <Icon name="chevron-end" size={14} />
@@ -9,6 +9,7 @@ import { Icon } from '@theme/components';
9
9
  import Results from './results';
10
10
  import { ROUTES } from '@theme/routes';
11
11
  import { useLocalization, useRouter } from '@akinon/next/hooks';
12
+ import PluginModule, { Component } from '@akinon/next/components/plugin-module';
12
13
 
13
14
  export default function Search() {
14
15
  const { t } = useLocalization();
@@ -22,12 +23,24 @@ export default function Search() {
22
23
  if (isSearchOpen) {
23
24
  inputRef.current?.focus();
24
25
  document.body.style.overflow = 'hidden';
26
+
27
+ const handleEscKey = (e: KeyboardEvent) => {
28
+ if (e.key === 'Escape') {
29
+ dispatch(closeSearch());
30
+ }
31
+ };
32
+
33
+ document.addEventListener('keydown', handleEscKey);
34
+ return () => {
35
+ document.removeEventListener('keydown', handleEscKey);
36
+ document.body.style.overflow = 'auto';
37
+ };
25
38
  }
26
39
 
27
40
  return () => {
28
41
  document.body.style.overflow = 'auto';
29
42
  };
30
- }, [isSearchOpen]);
43
+ }, [isSearchOpen, dispatch]);
31
44
 
32
45
  return (
33
46
  <>
@@ -66,6 +79,15 @@ export default function Search() {
66
79
  placeholder={t('common.search.placeholder')}
67
80
  ref={inputRef}
68
81
  />
82
+
83
+ <PluginModule
84
+ component={Component.HeaderImageSearchFeature}
85
+ props={{
86
+ enableTextSearch: true,
87
+ isEnabled: true
88
+ }}
89
+ />
90
+
69
91
  <Icon
70
92
  name="close"
71
93
  size={14}
@@ -22,7 +22,7 @@ const InstallmentOptions = (props: InstallmentProps) => {
22
22
 
23
23
  useEffect(() => {
24
24
  if (isSuccess && data) {
25
- setActiveCardSlug(data.results[0].slug);
25
+ setActiveCardSlug(data.results?.[0]?.slug);
26
26
  }
27
27
  }, [isSuccess, data]);
28
28
 
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
 
3
- import { signIn, SignInOptions } from 'next-auth/react';
4
- import { useSearchParams } from 'next/navigation';
5
- import { useState } from 'react';
3
+ import { signIn } from 'next-auth/react';
4
+ import { usePathname, useSearchParams } from 'next/navigation';
5
+ import { useEffect, useState } from 'react';
6
6
  import { ROUTES } from '@theme/routes';
7
- import { LoginFormType } from '@theme/types';
7
+ import { LoginFormType, FormType, PzSignInOptions } from '@theme/types';
8
8
  import { Button, Input, Link } from '@theme/components';
9
9
  import { SubmitHandler, useForm } from 'react-hook-form';
10
10
  import * as yup from 'yup';
@@ -15,6 +15,7 @@ import { useCaptcha, useLocalization } from '@akinon/next/hooks';
15
15
  import { AuthError } from '@akinon/next/types';
16
16
  import { Image } from '@akinon/next/components/image';
17
17
  import PluginModule, { Component } from '@akinon/next/components/plugin-module';
18
+ import { twMerge } from 'tailwind-merge';
18
19
 
19
20
  const oauthProviders: Array<{
20
21
  key: string;
@@ -24,18 +25,15 @@ const oauthProviders: Array<{
24
25
  }> = [
25
26
  {
26
27
  key: 'google',
27
- label: 'Google',
28
- image: '/google.svg'
28
+ label: 'Google'
29
29
  },
30
30
  {
31
31
  key: 'facebook',
32
- label: 'Facebook',
33
- image: '/facebook.svg'
32
+ label: 'Facebook'
34
33
  },
35
34
  {
36
35
  key: 'apple',
37
- label: 'Apple',
38
- image: '/apple.svg'
36
+ label: 'Apple'
39
37
  }
40
38
  ];
41
39
 
@@ -48,7 +46,11 @@ const loginFormSchema = (t) =>
48
46
  password: yup.string().required(t('auth.login.form.error.required'))
49
47
  });
50
48
 
51
- export const Login = () => {
49
+ export const Login = ({
50
+ setActiveTab
51
+ }: {
52
+ setActiveTab?: (tab: string) => void;
53
+ }) => {
52
54
  const { t, locale } = useLocalization();
53
55
 
54
56
  const { refetch: refetchBasketData } = useGetBasketQuery();
@@ -62,8 +64,10 @@ export const Login = () => {
62
64
  resolver: yupResolver(loginFormSchema(t))
63
65
  });
64
66
 
67
+ const pathname = usePathname();
65
68
  const searchParams = useSearchParams();
66
69
  const [formError, setFormError] = useState(null);
70
+ const [isCheckout, setIsCheckout] = useState<boolean>(false);
67
71
 
68
72
  const {
69
73
  CaptchaView,
@@ -79,11 +83,12 @@ export const Login = () => {
79
83
  redirect: false,
80
84
  callbackUrl: searchParams.get('callbackUrl') ?? '/',
81
85
  captchaValidated,
82
- ...data
83
- } as SignInOptions);
86
+ ...data,
87
+ formType: FormType.login
88
+ } as PzSignInOptions & { redirect: false });
84
89
 
85
90
  if (loginResponse.error) {
86
- const errors: AuthError[] = JSON.parse(loginResponse.error);
91
+ const errors: AuthError[] = JSON.parse(loginResponse.code);
87
92
 
88
93
  if (errors.find((error) => error.type === 'captcha')) {
89
94
  if (await validateCaptcha()) {
@@ -103,10 +108,34 @@ export const Login = () => {
103
108
  )?.data as string[];
104
109
 
105
110
  fieldErrors?.forEach((item) => {
106
- setError(item.name as keyof LoginFormType, {
107
- type: 'custom',
108
- message: item.value.join(', ')
109
- });
111
+ let parsedValue: Record<string, string[]> | string[] = [];
112
+
113
+ if (typeof item.value === 'string') {
114
+ try {
115
+ parsedValue = JSON.parse(item.value);
116
+ } catch {
117
+ parsedValue = [item.value];
118
+ }
119
+ } else {
120
+ parsedValue = item.value;
121
+ }
122
+
123
+ if (Array.isArray(parsedValue)) {
124
+ setError(item.name as keyof LoginFormType, {
125
+ type: 'custom',
126
+ message: parsedValue.join(', ')
127
+ });
128
+ } else {
129
+ Object.keys(parsedValue).forEach((key) => {
130
+ const fieldName = key as keyof LoginFormType;
131
+ const errorMessages = parsedValue[key] as string[];
132
+
133
+ setError(fieldName, {
134
+ type: 'custom',
135
+ message: errorMessages.join(', ')
136
+ });
137
+ });
138
+ }
110
139
  });
111
140
 
112
141
  if (nonFieldErrors?.length) {
@@ -122,29 +151,27 @@ export const Login = () => {
122
151
  }
123
152
  };
124
153
 
125
- return (
126
- <section
127
- className={clsx([
128
- 'w-full py-10 px-5 md:py-0 md:px-8 md:mx-auto lg:px-16'
129
- ])}
130
- >
131
- <h2 className="mb-3 text-lg text-start text-black-800 font-light md:mb-9 md:text-2xl">
132
- {t('auth.login.title')}
133
- </h2>
154
+ useEffect(() => {
155
+ if (pathname.includes('/orders/checkout')) {
156
+ setIsCheckout(true);
157
+ }
158
+ }, [pathname]);
134
159
 
160
+ return (
161
+ <section className="w-full mt-6 lg:mt-8">
135
162
  <form
136
163
  action="/api/auth/signin/credentials"
137
164
  method="post"
138
165
  onSubmit={handleSubmit(onSubmit)}
139
166
  >
140
- <input type="hidden" value="login" {...register('formType')} />
167
+ <input type="hidden" value={FormType.login} {...register('formType')} />
141
168
  <input type="hidden" value={locale} {...register('locale')} />
142
169
 
143
- <div className={clsx(errors.email ? 'mb-8' : 'mb-4')}>
170
+ <div>
144
171
  <Input
145
172
  labelStyle="floating"
146
173
  label={t('auth.login.form.email.placeholder')}
147
- className="h-14"
174
+ className="h-12"
148
175
  {...register('email')}
149
176
  error={errors.email}
150
177
  data-testid="login-email"
@@ -152,11 +179,11 @@ export const Login = () => {
152
179
  />
153
180
  </div>
154
181
 
155
- <div className={clsx(errors.password ? 'mb-8' : 'mb-4')}>
182
+ <div className="mt-4">
156
183
  <Input
157
184
  labelStyle="floating"
158
185
  label={t('auth.login.form.password.placeholder')}
159
- className="h-14"
186
+ className="h-12"
160
187
  type="password"
161
188
  {...register('password')}
162
189
  error={errors.password}
@@ -167,7 +194,7 @@ export const Login = () => {
167
194
 
168
195
  <Link
169
196
  href={ROUTES.FORGOT_PASSWORD}
170
- className="block text-sm underline mb-8"
197
+ className="block text-black-750/75 text-sm underline mt-4"
171
198
  data-testid="login-forgot-password"
172
199
  >
173
200
  {t('auth.login.form.forgot_password')}
@@ -175,7 +202,7 @@ export const Login = () => {
175
202
 
176
203
  {formError && (
177
204
  <p
178
- className="text-error text-xs my-5"
205
+ className="text-error text-xs my-2"
179
206
  data-testid="login-error-field"
180
207
  >
181
208
  {formError}
@@ -183,11 +210,11 @@ export const Login = () => {
183
210
  )}
184
211
 
185
212
  <div className="flex justify-center">
186
- <CaptchaView className="mb-5" data-testid="login-captcha" />
213
+ <CaptchaView className="mt-8" data-testid="login-captcha" />
187
214
  </div>
188
215
 
189
216
  <Button
190
- className="w-full h-12 uppercase text-xs font-semibold"
217
+ className="w-full h-12 text-sm font-normal mt-6 lg:mt-8"
191
218
  type="submit"
192
219
  disabled={isCaptchaVisible && !captchaValidated}
193
220
  data-testid="login-submit"
@@ -195,22 +222,23 @@ export const Login = () => {
195
222
  {t('auth.login.form.submit')}
196
223
  </Button>
197
224
 
198
- <p className="relative text-gray-600 text-center my-4 before:absolute before:h-[1px] before:w-5/12 before:bg-gray-600 before:bg-opacity-25 before:top-1/2 before:left-0 after:absolute after:h-[1px] after:w-5/12 after:bg-gray-600 after:bg-opacity-25 after:top-1/2 after:right-0">
199
- {t('auth.login.form.or')}
225
+ <p
226
+ className={clsx(
227
+ twMerge(
228
+ 'relative block text-center mt-3 lg:mt-8 text-black-750 text-sm',
229
+ 'before:absolute before:left-0 before:top-1/2 before:w-full before:h-px before:bg-[#d2d2d2] before:-z-10'
230
+ )
231
+ )}
232
+ >
233
+ <span className="bg-white px-4">{t('auth.login.form.or')}</span>
200
234
  </p>
201
-
202
- <div className="social-login">
203
- <p className="mb-3 text-lg text-start font-light md:mb-9 md:text-2xl">
204
- {t('auth.login.form.sign_in_with')}
205
- </p>
206
- </div>
207
235
  </form>
208
236
 
209
- <div className="grid grid-cols-2 gap-4 lg:grid-cols-3">
237
+ <div className="grid gap-4 mt-2">
210
238
  {oauthProviders.map((provider) => (
211
239
  <Button
212
240
  key={provider.key}
213
- className="w-full h-14 uppercase text-xs font-semibold flex items-center justify-center gap-2 hover:bg-transparent hover:border hover:border-primary-800 hover:text-primary"
241
+ className="text-base text-black-750 h-auto py-4 border border-gray-650 leading-[0.94]"
214
242
  type="submit"
215
243
  appearance="outlined"
216
244
  disabled={isCaptchaVisible && !captchaValidated}
@@ -218,19 +246,24 @@ export const Login = () => {
218
246
  location.href = `/${provider.key}/login/`;
219
247
  }}
220
248
  >
221
- {provider.image && (
222
- <Image
223
- src={provider.image}
224
- alt={provider.label}
225
- width={provider.label === 'Facebook' ? 10 : 18}
226
- height={18}
227
- className="flex-shrink-0"
228
- />
249
+ {t('auth.login.form.continue_with_provider').replace(
250
+ '{provider}',
251
+ provider.localeKey ? t(provider.localeKey) : provider.label
229
252
  )}
230
-
231
- {provider.localeKey ? t(provider.localeKey) : provider.label}
232
253
  </Button>
233
254
  ))}
255
+ {isCheckout && (
256
+ <Button
257
+ className="text-base text-black-750 h-auto py-4 border border-gray-650 leading-[0.94]"
258
+ type="submit"
259
+ appearance="outlined"
260
+ onClick={() => {
261
+ setActiveTab?.('guest');
262
+ }}
263
+ >
264
+ {t('checkout.auth.continue_as_guest_checkout')}
265
+ </Button>
266
+ )}
234
267
  <PluginModule
235
268
  component={Component.AkifastQuickLoginButton}
236
269
  props={{