@doswiftly/cli 0.1.18 → 0.1.20

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 (277) hide show
  1. package/README.md +23 -323
  2. package/dist/commands/check.js +1 -1
  3. package/dist/commands/check.js.map +1 -1
  4. package/dist/commands/deploy.d.ts +20 -0
  5. package/dist/commands/deploy.d.ts.map +1 -1
  6. package/dist/commands/deploy.js +249 -17
  7. package/dist/commands/deploy.js.map +1 -1
  8. package/dist/commands/doctor.js +3 -3
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/init.js +4 -4
  11. package/dist/commands/sdk.js +5 -5
  12. package/dist/commands/sdk.js.map +1 -1
  13. package/dist/commands/template.js +4 -4
  14. package/dist/commands/template.js.map +1 -1
  15. package/dist/commands/types.js +5 -5
  16. package/dist/commands/types.js.map +1 -1
  17. package/dist/commands/verify.js +2 -2
  18. package/dist/commands/verify.js.map +1 -1
  19. package/dist/lib/package-manager.d.ts +1 -1
  20. package/dist/lib/package-manager.js +1 -1
  21. package/package.json +4 -4
  22. package/templates/storefront-minimal/.github/workflows/build-template.yml +10 -0
  23. package/templates/storefront-minimal/wrangler.toml +11 -0
  24. package/templates/storefront-nextjs/.github/workflows/build-template.yml +10 -0
  25. package/templates/storefront-nextjs/README.md +16 -12
  26. package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
  27. package/templates/storefront-nextjs/app/account/page.tsx +2 -2
  28. package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
  29. package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
  30. package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
  31. package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
  32. package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
  33. package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
  34. package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
  35. package/templates/storefront-nextjs/app/page.tsx +1 -1
  36. package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
  37. package/templates/storefront-nextjs/app/products/page.tsx +2 -2
  38. package/templates/storefront-nextjs/app/search/page.tsx +1 -1
  39. package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
  40. package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
  41. package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
  42. package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
  43. package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
  44. package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
  45. package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
  46. package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
  47. package/templates/storefront-nextjs/components/providers.tsx +1 -1
  48. package/templates/storefront-nextjs/lib/currency.tsx +3 -3
  49. package/templates/storefront-nextjs/lib/format.ts +1 -1
  50. package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
  51. package/templates/storefront-nextjs/package.dev.json +1 -1
  52. package/templates/storefront-nextjs/package.json +1 -1
  53. package/templates/storefront-nextjs/package.json.template +1 -1
  54. package/templates/storefront-nextjs/wrangler.toml +11 -0
  55. package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +10 -0
  56. package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
  57. package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
  58. package/templates/storefront-nextjs-shadcn/CLAUDE.md +172 -35
  59. package/templates/storefront-nextjs-shadcn/README.md +29 -162
  60. package/templates/storefront-nextjs-shadcn/app/{about → [locale]/about}/page.tsx +17 -14
  61. package/templates/storefront-nextjs-shadcn/app/[locale]/account/addresses/page.tsx +226 -0
  62. package/templates/storefront-nextjs-shadcn/app/[locale]/account/error.tsx +46 -0
  63. package/templates/storefront-nextjs-shadcn/app/[locale]/account/loading.tsx +19 -0
  64. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loyalty/page.tsx +89 -193
  65. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/loading.tsx +60 -0
  66. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/page.tsx +119 -0
  67. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/tracking/page.tsx +27 -25
  68. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/page.tsx +101 -0
  69. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/page.tsx +9 -7
  70. package/templates/storefront-nextjs-shadcn/app/[locale]/account/settings/page.tsx +208 -0
  71. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/forgot-password/page.tsx +24 -17
  72. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/login/page.tsx +5 -2
  73. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/register/page.tsx +5 -2
  74. package/templates/storefront-nextjs-shadcn/app/[locale]/blog/[slug]/loading.tsx +17 -0
  75. package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/page.tsx +44 -3
  76. package/templates/storefront-nextjs-shadcn/app/[locale]/blog/loading.tsx +19 -0
  77. package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/page.tsx +2 -1
  78. package/templates/storefront-nextjs-shadcn/app/[locale]/cart/loading.tsx +26 -0
  79. package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/page.tsx +20 -13
  80. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/category-products-client.tsx +58 -0
  81. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/loading.tsx +32 -0
  82. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/page.tsx +95 -0
  83. package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/page.tsx +21 -12
  84. package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/error.tsx +43 -0
  85. package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/loading.tsx +31 -0
  86. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/page.tsx +334 -253
  87. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/success/[orderId]/page.tsx +36 -34
  88. package/templates/storefront-nextjs-shadcn/app/[locale]/collections/[handle]/loading.tsx +19 -0
  89. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/page.tsx +6 -4
  90. package/templates/storefront-nextjs-shadcn/app/[locale]/collections/loading.tsx +18 -0
  91. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/page.tsx +20 -12
  92. package/templates/storefront-nextjs-shadcn/app/{contact → [locale]/contact}/page.tsx +24 -21
  93. package/templates/storefront-nextjs-shadcn/app/{error.tsx → [locale]/error.tsx} +13 -8
  94. package/templates/storefront-nextjs-shadcn/app/[locale]/layout.tsx +92 -0
  95. package/templates/storefront-nextjs-shadcn/app/{not-found.tsx → [locale]/not-found.tsx} +13 -18
  96. package/templates/storefront-nextjs-shadcn/app/{page.tsx → [locale]/page.tsx} +8 -4
  97. package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/error.tsx +43 -0
  98. package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/loading.tsx +29 -0
  99. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/page.tsx +17 -14
  100. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/product-client.tsx +18 -62
  101. package/templates/storefront-nextjs-shadcn/app/[locale]/products/loading.tsx +32 -0
  102. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/page.tsx +6 -3
  103. package/templates/storefront-nextjs-shadcn/app/[locale]/products/products-client.tsx +450 -0
  104. package/templates/storefront-nextjs-shadcn/app/[locale]/search/loading.tsx +18 -0
  105. package/templates/storefront-nextjs-shadcn/app/{wishlist → [locale]/wishlist}/page.tsx +27 -28
  106. package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
  107. package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
  108. package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
  109. package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
  110. package/templates/storefront-nextjs-shadcn/app/layout.tsx +8 -35
  111. package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
  112. package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +25 -20
  113. package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +11 -10
  114. package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
  115. package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +17 -13
  116. package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +42 -30
  117. package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
  118. package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +18 -16
  119. package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +37 -58
  120. package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +85 -66
  121. package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +1 -1
  122. package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +1 -1
  123. package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +1 -1
  124. package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +10 -6
  125. package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +9 -6
  126. package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +8 -6
  127. package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
  128. package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +10 -8
  129. package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +8 -5
  130. package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +38 -20
  131. package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +15 -25
  132. package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +10 -8
  133. package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +9 -6
  134. package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +7 -5
  135. package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +8 -5
  136. package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +6 -4
  137. package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +10 -9
  138. package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +1 -1
  139. package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +1 -1
  140. package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
  141. package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +9 -6
  142. package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +22 -12
  143. package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +18 -15
  144. package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +53 -28
  145. package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +7 -5
  146. package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
  147. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +19 -15
  148. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +13 -10
  149. package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +10 -6
  150. package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
  151. package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +3 -13
  152. package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +12 -8
  153. package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +13 -8
  154. package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
  155. package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +10 -8
  156. package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
  157. package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +41 -16
  158. package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
  159. package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +7 -4
  160. package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +24 -23
  161. package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +52 -34
  162. package/templates/storefront-nextjs-shadcn/components/layout/language-switcher.tsx +54 -0
  163. package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +33 -30
  164. package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +27 -24
  165. package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
  166. package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
  167. package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +32 -42
  168. package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
  169. package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
  170. package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
  171. package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +6 -14
  172. package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +4 -2
  173. package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +72 -0
  174. package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +87 -0
  175. package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +140 -0
  176. package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
  177. package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
  178. package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +11 -37
  179. package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
  180. package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +179 -124
  181. package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
  182. package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +3 -7
  183. package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
  184. package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
  185. package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +44 -19
  186. package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
  187. package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
  188. package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
  189. package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +26 -34
  190. package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
  191. package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
  192. package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
  193. package/templates/storefront-nextjs-shadcn/components/providers/language-sync-provider.tsx +27 -0
  194. package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +63 -0
  195. package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
  196. package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
  197. package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +59 -72
  198. package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +7 -4
  199. package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
  200. package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +12 -9
  201. package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +23 -12
  202. package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
  203. package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
  204. package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
  205. package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
  206. package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
  207. package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
  208. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +7 -4
  209. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +4 -2
  210. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +2 -10
  211. package/templates/storefront-nextjs-shadcn/generated/graphql.ts +13387 -0
  212. package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
  213. package/templates/storefront-nextjs-shadcn/hooks/index.ts +3 -0
  214. package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
  215. package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
  216. package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +34 -229
  217. package/templates/storefront-nextjs-shadcn/hooks/use-cart-di.ts +67 -0
  218. package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +16 -12
  219. package/templates/storefront-nextjs-shadcn/i18n/navigation.ts +12 -0
  220. package/templates/storefront-nextjs-shadcn/i18n/request.ts +17 -0
  221. package/templates/storefront-nextjs-shadcn/i18n/routing.ts +17 -0
  222. package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
  223. package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
  224. package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +33 -0
  225. package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
  226. package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +720 -632
  227. package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +88 -0
  228. package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +132 -182
  229. package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
  230. package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
  231. package/templates/storefront-nextjs-shadcn/messages/en.json +869 -0
  232. package/templates/storefront-nextjs-shadcn/messages/pl.json +869 -0
  233. package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
  234. package/templates/storefront-nextjs-shadcn/next.config.ts +6 -5
  235. package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
  236. package/templates/storefront-nextjs-shadcn/package.json +14 -14
  237. package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
  238. package/templates/storefront-nextjs-shadcn/proxy.ts +115 -47
  239. package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +24 -56
  240. package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
  241. package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
  242. package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
  243. package/templates/storefront-nextjs-shadcn/wrangler.toml +11 -0
  244. package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
  245. package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
  246. package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
  247. package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
  248. package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
  249. package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
  250. package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
  251. package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
  252. package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +0 -215
  253. package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +0 -128
  254. package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +0 -80
  255. package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +0 -171
  256. package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +0 -78
  257. package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +0 -192
  258. package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
  259. package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
  260. package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
  261. package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
  262. package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
  263. package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
  264. package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
  265. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
  266. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
  267. package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
  268. package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
  269. package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
  270. package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
  271. package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
  272. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/page.tsx +0 -0
  273. /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/[slug]/page.tsx +0 -0
  274. /package/templates/storefront-nextjs-shadcn/app/{returns → [locale]/returns}/page.tsx +0 -0
  275. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/page.tsx +0 -0
  276. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/search-client.tsx +0 -0
  277. /package/templates/storefront-nextjs-shadcn/app/{shipping → [locale]/shipping}/page.tsx +0 -0
@@ -4,6 +4,7 @@ import { MapPin, Edit, Trash2, Plus } from "lucide-react";
4
4
  import { Button } from "@/components/ui/button";
5
5
  import { Badge } from "@/components/ui/badge";
6
6
  import { Card } from "@/components/ui/card";
7
+ import { useTranslations } from "next-intl";
7
8
 
8
9
  export interface Address {
9
10
  id: string;
@@ -40,11 +41,11 @@ export function AddressList({
40
41
  onAdd,
41
42
  className,
42
43
  }: AddressListProps) {
44
+ const t = useTranslations("account");
45
+
43
46
  const handleDelete = (id: string, address: Address) => {
44
47
  if (
45
- confirm(
46
- `Are you sure you want to delete the address at ${address.address1}?`
47
- )
48
+ confirm(t("deleteAddressConfirm", { address: address.address1 }))
48
49
  ) {
49
50
  onDelete?.(id);
50
51
  }
@@ -55,15 +56,15 @@ export function AddressList({
55
56
  <div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
56
57
  <MapPin className="mx-auto h-12 w-12 text-muted-foreground mb-4" />
57
58
  <h2 className="text-xl font-semibold text-foreground mb-2">
58
- No addresses saved
59
+ {t("noAddressesSaved")}
59
60
  </h2>
60
61
  <p className="text-muted-foreground mb-6">
61
- Add an address to make checkout faster
62
+ {t("addAddressDescription")}
62
63
  </p>
63
64
  {onAdd && (
64
65
  <Button onClick={onAdd}>
65
66
  <Plus className="mr-2 h-4 w-4" />
66
- Add Your First Address
67
+ {t("addFirstAddress")}
67
68
  </Button>
68
69
  )}
69
70
  </div>
@@ -78,7 +79,7 @@ export function AddressList({
78
79
  <div className="mb-4 flex items-start justify-between">
79
80
  <div className="flex items-center gap-2">
80
81
  <MapPin className="h-5 w-5 text-muted-foreground" />
81
- {address.isDefault && <Badge variant="default">Default</Badge>}
82
+ {address.isDefault && <Badge variant="default">{t("defaultBadge")}</Badge>}
82
83
  </div>
83
84
  <div className="flex gap-2">
84
85
  {onEdit && (
@@ -87,7 +88,7 @@ export function AddressList({
87
88
  size="sm"
88
89
  className="h-8 w-8 p-0"
89
90
  onClick={() => onEdit(address)}
90
- aria-label="Edit address"
91
+ aria-label={t("editAddress")}
91
92
  >
92
93
  <Edit className="h-4 w-4" />
93
94
  </Button>
@@ -98,7 +99,7 @@ export function AddressList({
98
99
  size="sm"
99
100
  className="h-8 w-8 p-0 text-destructive hover:text-destructive"
100
101
  onClick={() => handleDelete(address.id, address)}
101
- aria-label="Delete address"
102
+ aria-label={t("deleteAddress")}
102
103
  >
103
104
  <Trash2 className="h-4 w-4" />
104
105
  </Button>
@@ -133,7 +134,7 @@ export function AddressList({
133
134
  className="mt-4 w-full"
134
135
  onClick={() => onSetDefault(address.id)}
135
136
  >
136
- Set as Default
137
+ {t("setAsDefault")}
137
138
  </Button>
138
139
  )}
139
140
  </Card>
@@ -0,0 +1,36 @@
1
+ # Fragment for CustomerInfo / AccountDashboard components.
2
+ #
3
+ # Customer profile data for account pages.
4
+ # Does NOT include orders or addresses (fetch separately).
5
+ #
6
+ # Usage in components:
7
+ # import type { CustomerInfoFieldsFragment } from '@/generated/graphql';
8
+ # interface Props { customer: CustomerInfoFieldsFragment }
9
+
10
+ fragment CustomerInfoFields on Customer {
11
+ id
12
+ email
13
+ firstName
14
+ lastName
15
+ displayName
16
+ phone
17
+ emailVerified
18
+ ordersCount
19
+ totalSpent {
20
+ amount
21
+ currencyCode
22
+ }
23
+ defaultAddress {
24
+ id
25
+ firstName
26
+ lastName
27
+ address1
28
+ address2
29
+ city
30
+ province
31
+ zip
32
+ country
33
+ phone
34
+ }
35
+ createdAt
36
+ }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { Package, Truck, CheckCircle, XCircle } from "lucide-react";
4
+ import { useTranslations } from "next-intl";
4
5
  import { Badge } from "@/components/ui/badge";
5
6
  import { Card } from "@/components/ui/card";
6
7
  import { Separator } from "@/components/ui/separator";
@@ -39,7 +40,7 @@ export interface OrderDetailsData {
39
40
  tax: string;
40
41
  total: string;
41
42
  currency: string;
42
- shippingAddress: OrderAddress;
43
+ shippingAddress?: OrderAddress;
43
44
  billingAddress?: OrderAddress;
44
45
  trackingNumber?: string;
45
46
  estimatedDelivery?: string;
@@ -54,6 +55,7 @@ export interface OrderDetailsProps {
54
55
  * OrderDetails - Display detailed information about a single order
55
56
  */
56
57
  export function OrderDetails({ order, className }: OrderDetailsProps) {
58
+ const t = useTranslations("account");
57
59
  const getStatusIcon = (status: OrderDetailsData["status"]) => {
58
60
  switch (status) {
59
61
  case "delivered":
@@ -131,10 +133,10 @@ export function OrderDetails({ order, className }: OrderDetailsProps) {
131
133
  <div className="flex items-start justify-between mb-4">
132
134
  <div>
133
135
  <h2 className="text-2xl font-bold text-foreground mb-2">
134
- Order {order.orderNumber}
136
+ {t("orderNumber", { number: order.orderNumber })}
135
137
  </h2>
136
138
  <p className="text-sm text-muted-foreground">
137
- Placed on {formatDate(order.date)}
139
+ {t("placedOn")} {formatDate(order.date)}
138
140
  </p>
139
141
  </div>
140
142
  <div className="flex items-center gap-2">
@@ -146,7 +148,7 @@ export function OrderDetails({ order, className }: OrderDetailsProps) {
146
148
  {order.trackingNumber && (
147
149
  <div className="mt-4 p-4 bg-muted/50 rounded-lg">
148
150
  <p className="text-sm font-medium text-foreground mb-1">
149
- Tracking Number
151
+ {t("trackingNumber")}
150
152
  </p>
151
153
  <p className="text-sm text-muted-foreground font-mono">
152
154
  {order.trackingNumber}
@@ -157,7 +159,7 @@ export function OrderDetails({ order, className }: OrderDetailsProps) {
157
159
  {order.estimatedDelivery && (
158
160
  <div className="mt-4 p-4 bg-muted/50 rounded-lg">
159
161
  <p className="text-sm font-medium text-foreground mb-1">
160
- Estimated Delivery
162
+ {t("estimatedDelivery")}
161
163
  </p>
162
164
  <p className="text-sm text-muted-foreground">
163
165
  {formatDate(order.estimatedDelivery)}
@@ -169,7 +171,7 @@ export function OrderDetails({ order, className }: OrderDetailsProps) {
169
171
  {/* Order Items */}
170
172
  <Card className="p-6 mb-6">
171
173
  <h3 className="text-lg font-semibold text-foreground mb-4">
172
- Order Items
174
+ {t("orderItems")}
173
175
  </h3>
174
176
  <div className="space-y-4">
175
177
  {order.items.map((item) => (
@@ -191,7 +193,7 @@ export function OrderDetails({ order, className }: OrderDetailsProps) {
191
193
  </p>
192
194
  )}
193
195
  <p className="text-sm text-muted-foreground">
194
- Quantity: {item.quantity}
196
+ {t("itemCount", { count: item.quantity })}
195
197
  </p>
196
198
  </div>
197
199
  <div className="text-right">
@@ -208,26 +210,26 @@ export function OrderDetails({ order, className }: OrderDetailsProps) {
208
210
  {/* Order Summary */}
209
211
  <div className="space-y-2">
210
212
  <div className="flex justify-between text-sm">
211
- <span className="text-muted-foreground">Subtotal</span>
213
+ <span className="text-muted-foreground">{t("subtotal")}</span>
212
214
  <span className="text-foreground">
213
215
  {formatPrice(order.subtotal, order.currency)}
214
216
  </span>
215
217
  </div>
216
218
  <div className="flex justify-between text-sm">
217
- <span className="text-muted-foreground">Shipping</span>
219
+ <span className="text-muted-foreground">{t("shippingLabel")}</span>
218
220
  <span className="text-foreground">
219
221
  {formatPrice(order.shipping, order.currency)}
220
222
  </span>
221
223
  </div>
222
224
  <div className="flex justify-between text-sm">
223
- <span className="text-muted-foreground">Tax</span>
225
+ <span className="text-muted-foreground">{t("taxLabel")}</span>
224
226
  <span className="text-foreground">
225
227
  {formatPrice(order.tax, order.currency)}
226
228
  </span>
227
229
  </div>
228
230
  <Separator className="my-2" />
229
231
  <div className="flex justify-between text-base font-semibold">
230
- <span className="text-foreground">Total</span>
232
+ <span className="text-foreground">{t("orderTotal")}</span>
231
233
  <span className="text-foreground">
232
234
  {formatPrice(order.total, order.currency)}
233
235
  </span>
@@ -237,17 +239,19 @@ export function OrderDetails({ order, className }: OrderDetailsProps) {
237
239
 
238
240
  {/* Addresses */}
239
241
  <div className="grid gap-6 md:grid-cols-2">
242
+ {order.shippingAddress && (
240
243
  <Card className="p-6">
241
244
  <h3 className="text-lg font-semibold text-foreground mb-4">
242
- Shipping Address
245
+ {t("shippingAddress")}
243
246
  </h3>
244
247
  {formatAddress(order.shippingAddress)}
245
248
  </Card>
249
+ )}
246
250
 
247
251
  {order.billingAddress && (
248
252
  <Card className="p-6">
249
253
  <h3 className="text-lg font-semibold text-foreground mb-4">
250
- Billing Address
254
+ {t("billingAddress")}
251
255
  </h3>
252
256
  {formatAddress(order.billingAddress)}
253
257
  </Card>
@@ -1,23 +1,25 @@
1
1
  "use client";
2
2
 
3
- import Link from "next/link";
3
+ import { Link } from "@/i18n/navigation";
4
+ import { useTranslations } from "next-intl";
5
+ import { useLocale } from "next-intl";
4
6
  import { Package, ChevronRight } from "lucide-react";
5
7
  import { Badge } from "@/components/ui/badge";
6
8
  import { Button } from "@/components/ui/button";
7
- import { formatAmount } from "@/lib/format";
9
+ import { formatAmount } from "@doswiftly/storefront-sdk";
10
+ import type { OrderSummaryFields } from "@/lib/graphql/fragments";
8
11
 
9
- export interface Order {
10
- id: string;
11
- orderNumber: string;
12
- date: string;
13
- status: "delivered" | "shipped" | "processing" | "cancelled";
14
- total: string;
15
- currency: string;
16
- itemCount: number;
17
- }
12
+ const STATUS_KEY_MAP: Record<string, string> = {
13
+ DELIVERED: "delivered",
14
+ FULFILLED: "fulfilled",
15
+ IN_TRANSIT: "shipped",
16
+ PARTIALLY_FULFILLED: "partiallyFulfilled",
17
+ UNFULFILLED: "processing",
18
+ RETURNED: "returned",
19
+ };
18
20
 
19
21
  export interface OrderHistoryProps {
20
- orders: Order[];
22
+ orders: OrderSummaryFields[];
21
23
  className?: string;
22
24
  }
23
25
 
@@ -25,23 +27,33 @@ export interface OrderHistoryProps {
25
27
  * OrderHistory - Display list of customer orders
26
28
  */
27
29
  export function OrderHistory({ orders, className }: OrderHistoryProps) {
28
- const getStatusBadge = (status: Order["status"]) => {
29
- const variants: Record<Order["status"], "default" | "secondary" | "success" | "warning"> = {
30
- delivered: "success",
31
- shipped: "default",
32
- processing: "warning",
33
- cancelled: "secondary",
30
+ const t = useTranslations("account");
31
+ const locale = useLocale();
32
+
33
+ const getStatusBadge = (status: string) => {
34
+ const variants: Record<string, "default" | "secondary" | "success" | "warning"> = {
35
+ DELIVERED: "success",
36
+ FULFILLED: "success",
37
+ IN_TRANSIT: "default",
38
+ PARTIALLY_FULFILLED: "warning",
39
+ UNFULFILLED: "warning",
40
+ RETURNED: "secondary",
34
41
  };
35
42
 
43
+ const statusKey = STATUS_KEY_MAP[status];
44
+ const label = statusKey
45
+ ? t(`orderStatuses.${statusKey}`)
46
+ : status;
47
+
36
48
  return (
37
- <Badge variant={variants[status]}>
38
- {status.charAt(0).toUpperCase() + status.slice(1)}
49
+ <Badge variant={variants[status] ?? "secondary"}>
50
+ {label}
39
51
  </Badge>
40
52
  );
41
53
  };
42
54
 
43
55
  const formatDate = (dateString: string) => {
44
- return new Date(dateString).toLocaleDateString("pl-PL", {
56
+ return new Date(dateString).toLocaleDateString(locale, {
45
57
  year: "numeric",
46
58
  month: "long",
47
59
  day: "numeric",
@@ -53,13 +65,13 @@ export function OrderHistory({ orders, className }: OrderHistoryProps) {
53
65
  <div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
54
66
  <Package className="mx-auto h-12 w-12 text-muted-foreground mb-4" />
55
67
  <h2 className="text-xl font-semibold text-foreground mb-2">
56
- No orders yet
68
+ {t("noOrders")}
57
69
  </h2>
58
70
  <p className="text-muted-foreground mb-6">
59
- Start shopping to see your orders here
71
+ {t("startShoppingDescription")}
60
72
  </p>
61
73
  <Button asChild>
62
- <Link href="/products">Browse Products</Link>
74
+ <Link href="/products">{t("browseProducts")}</Link>
63
75
  </Button>
64
76
  </div>
65
77
  );
@@ -78,22 +90,22 @@ export function OrderHistory({ orders, className }: OrderHistoryProps) {
78
90
  <div className="flex-1">
79
91
  <div className="flex items-center gap-3 mb-2">
80
92
  <h3 className="text-lg font-semibold text-foreground">
81
- Order {order.orderNumber}
93
+ {t("orderNumber", { number: order.orderNumber })}
82
94
  </h3>
83
- {getStatusBadge(order.status)}
95
+ {getStatusBadge(order.fulfillmentStatus)}
84
96
  </div>
85
97
  <div className="space-y-1 text-sm text-muted-foreground">
86
- <p>Placed on {formatDate(order.date)}</p>
98
+ <p>{t("placedOn")} {formatDate(order.processedAt)}</p>
87
99
  <p>
88
- {order.itemCount} {order.itemCount === 1 ? "item" : "items"}
100
+ {t("itemCount", { count: order.lineItemsCount })}
89
101
  </p>
90
102
  </div>
91
103
  </div>
92
104
  <div className="flex items-center gap-4">
93
105
  <div className="text-right">
94
- <p className="text-sm text-muted-foreground">Total</p>
106
+ <p className="text-sm text-muted-foreground">{t("orderTotal")}</p>
95
107
  <p className="text-lg font-semibold text-foreground">
96
- {formatAmount(order.total, order.currency)}
108
+ {formatAmount(order.totalPrice.amount, order.totalPrice.currencyCode)}
97
109
  </p>
98
110
  </div>
99
111
  <ChevronRight className="h-5 w-5 text-muted-foreground" />
@@ -0,0 +1,36 @@
1
+ # Fragment for OrderCard component in account pages.
2
+ #
3
+ # Minimal order data for listing view. Full order details
4
+ # require the Order fragment from storefront-operations.
5
+ #
6
+ # Usage in components:
7
+ # import type { OrderSummaryFieldsFragment } from '@/generated/graphql';
8
+ # interface Props { order: OrderSummaryFieldsFragment }
9
+
10
+ fragment OrderSummaryFields on Order {
11
+ id
12
+ orderNumber
13
+ status
14
+ financialStatus
15
+ fulfillmentStatus
16
+ processedAt
17
+ lineItemsCount
18
+ totalPrice {
19
+ amount
20
+ currencyCode
21
+ }
22
+ subtotalPrice {
23
+ amount
24
+ currencyCode
25
+ }
26
+ totalShipping {
27
+ amount
28
+ currencyCode
29
+ }
30
+ shippingAddress {
31
+ firstName
32
+ lastName
33
+ city
34
+ country
35
+ }
36
+ }
@@ -1,30 +1,31 @@
1
1
  "use client";
2
2
 
3
3
  import { useState, useRef, useEffect } from "react";
4
- import Link from "next/link";
5
- import { useRouter } from "next/navigation";
4
+ import { Link, useRouter } from "@/i18n/navigation";
5
+ import { useTranslations } from "next-intl";
6
6
  import { User, LogOut, Package, MapPin, Settings } from "lucide-react";
7
7
  import { Button } from "@/components/ui/button";
8
8
  import { cn } from "@/lib/utils";
9
+ import { useAuth } from "@/hooks/use-auth";
9
10
 
10
11
  export interface AccountMenuProps {
11
12
  customerName?: string;
12
13
  className?: string;
13
14
  }
14
15
 
15
- /**
16
- * AccountMenu - User account dropdown menu
17
- *
18
- * Shows user profile and quick links to account pages
19
- */
20
16
  export function AccountMenu({ customerName, className }: AccountMenuProps) {
17
+ const t = useTranslations("account");
18
+ const tAuth = useTranslations("auth");
21
19
  const router = useRouter();
22
20
  const [isOpen, setIsOpen] = useState(false);
23
21
  const menuRef = useRef<HTMLDivElement>(null);
22
+ const { logout, isLoggingOut } = useAuth();
24
23
 
25
24
  const handleLogout = async () => {
26
- await fetch("/api/auth/clear-token", { method: "POST" });
27
- router.push("/");
25
+ const result = await logout();
26
+ if (result.success) {
27
+ router.push("/");
28
+ }
28
29
  setIsOpen(false);
29
30
  };
30
31
 
@@ -47,22 +48,22 @@ export function AccountMenu({ customerName, className }: AccountMenuProps) {
47
48
 
48
49
  const menuItems = [
49
50
  {
50
- label: "My Account",
51
+ label: t("title"),
51
52
  href: "/account",
52
53
  icon: User,
53
54
  },
54
55
  {
55
- label: "Orders",
56
+ label: t("orders"),
56
57
  href: "/account/orders",
57
58
  icon: Package,
58
59
  },
59
60
  {
60
- label: "Addresses",
61
+ label: t("addresses"),
61
62
  href: "/account/addresses",
62
63
  icon: MapPin,
63
64
  },
64
65
  {
65
- label: "Settings",
66
+ label: t("settings"),
66
67
  href: "/account/settings",
67
68
  icon: Settings,
68
69
  },
@@ -76,7 +77,7 @@ export function AccountMenu({ customerName, className }: AccountMenuProps) {
76
77
  size="sm"
77
78
  onClick={() => setIsOpen(!isOpen)}
78
79
  className="flex items-center gap-2"
79
- aria-label="Account menu"
80
+ aria-label={t("title")}
80
81
  aria-expanded={isOpen}
81
82
  >
82
83
  <User className="h-5 w-5" />
@@ -119,10 +120,11 @@ export function AccountMenu({ customerName, className }: AccountMenuProps) {
119
120
  <div className="border-t border-border py-2">
120
121
  <button
121
122
  onClick={handleLogout}
122
- className="flex w-full items-center gap-3 px-4 py-2 text-sm text-destructive hover:bg-muted transition-colors"
123
+ disabled={isLoggingOut}
124
+ className="flex w-full items-center gap-3 px-4 py-2 text-sm text-destructive hover:bg-muted transition-colors disabled:opacity-50"
123
125
  >
124
126
  <LogOut className="h-4 w-4" />
125
- Sign Out
127
+ {isLoggingOut ? tAuth("signingOut") : tAuth("signOut")}
126
128
  </button>
127
129
  </div>
128
130
  </div>
@@ -1,59 +1,56 @@
1
1
  "use client";
2
2
 
3
3
  import { useState } from "react";
4
- import { useRouter, useSearchParams } from "next/navigation";
5
- import Link from "next/link";
4
+ import { useSearchParams } from "next/navigation";
5
+ import { useRouter, Link } from "@/i18n/navigation";
6
+ import { useTranslations } from "next-intl";
6
7
  import { z } from "zod";
7
8
  import { Button } from "@/components/ui/button";
8
9
  import { Input } from "@/components/ui/input";
9
- import { useCustomerLogin } from "@/lib/graphql/hooks";
10
-
11
- // Zod validation schema for login form
12
- const loginSchema = z.object({
13
- email: z
14
- .string()
15
- .min(1, "Email is required")
16
- .email("Please enter a valid email address"),
17
- password: z
18
- .string()
19
- .min(1, "Password is required")
20
- .min(8, "Password must be at least 8 characters"),
21
- });
22
-
23
- type LoginFormData = z.infer<typeof loginSchema>;
10
+ import { useAuth } from "@/hooks/use-auth";
11
+
12
+ type LoginFormData = {
13
+ email: string;
14
+ password: string;
15
+ };
24
16
 
25
17
  export interface LoginFormProps {
26
18
  onSuccess?: () => void;
27
19
  redirectTo?: string;
28
20
  }
29
21
 
30
- /**
31
- * LoginForm - Reusable login form component with Zod validation
32
- *
33
- * Validates user input before submission and displays field-level errors
34
- */
35
22
  export function LoginForm({ onSuccess, redirectTo }: LoginFormProps) {
23
+ const t = useTranslations("auth");
36
24
  const router = useRouter();
37
25
  const searchParams = useSearchParams();
38
26
  const defaultRedirect = redirectTo || searchParams?.get("redirect") || "/account";
39
27
 
28
+ const loginSchema = z.object({
29
+ email: z
30
+ .string()
31
+ .min(1, t("validation.emailInvalid"))
32
+ .email(t("validation.emailInvalid")),
33
+ password: z
34
+ .string()
35
+ .min(1, t("validation.passwordMinLength"))
36
+ .min(8, t("validation.passwordMinLength")),
37
+ });
38
+
40
39
  const [email, setEmail] = useState("");
41
40
  const [password, setPassword] = useState("");
42
41
  const [error, setError] = useState("");
43
42
  const [fieldErrors, setFieldErrors] = useState<Partial<Record<keyof LoginFormData, string>>>({});
44
43
 
45
- const loginMutation = useCustomerLogin();
44
+ const { login, isLoggingIn } = useAuth();
46
45
 
47
46
  const handleSubmit = async (e: React.FormEvent) => {
48
47
  e.preventDefault();
49
48
  setError("");
50
49
  setFieldErrors({});
51
50
 
52
- // Validate form data with Zod
53
51
  const result = loginSchema.safeParse({ email, password });
54
52
 
55
53
  if (!result.success) {
56
- // Extract field-level errors from Zod validation
57
54
  const errors: Partial<Record<keyof LoginFormData, string>> = {};
58
55
  result.error.errors.forEach((err) => {
59
56
  if (err.path[0]) {
@@ -65,38 +62,20 @@ export function LoginForm({ onSuccess, redirectTo }: LoginFormProps) {
65
62
  }
66
63
 
67
64
  try {
68
- const { customerAccessTokenCreate } = await loginMutation.mutateAsync({
69
- input: { email, password },
70
- });
65
+ const loginResult = await login(email, password);
71
66
 
72
- // Check for user errors first
73
- const userErrors = customerAccessTokenCreate?.userErrors || [];
74
-
75
- if (userErrors.length > 0) {
76
- setError(userErrors[0].message || "Login failed");
67
+ if (!loginResult.success) {
68
+ setError(loginResult.userErrors[0]?.message || t("loginFailed"));
77
69
  return;
78
70
  }
79
71
 
80
- if (customerAccessTokenCreate?.customerAccessToken) {
81
- // Store token in httpOnly cookie via API route
82
- await fetch("/api/auth/set-token", {
83
- method: "POST",
84
- headers: { "Content-Type": "application/json" },
85
- body: JSON.stringify({
86
- token: customerAccessTokenCreate.customerAccessToken.accessToken,
87
- }),
88
- });
89
-
90
- if (onSuccess) {
91
- onSuccess();
92
- } else {
93
- router.push(defaultRedirect);
94
- }
72
+ if (onSuccess) {
73
+ onSuccess();
95
74
  } else {
96
- setError("Login failed. Please check your credentials.");
75
+ router.push(defaultRedirect);
97
76
  }
98
- } catch (err) {
99
- setError("An error occurred. Please try again.");
77
+ } catch {
78
+ setError(t("unexpectedError"));
100
79
  }
101
80
  };
102
81
 
@@ -113,7 +92,7 @@ export function LoginForm({ onSuccess, redirectTo }: LoginFormProps) {
113
92
  htmlFor="email"
114
93
  className="text-sm font-medium text-foreground"
115
94
  >
116
- Email
95
+ {t("email")}
117
96
  </label>
118
97
  <Input
119
98
  id="email"
@@ -139,13 +118,13 @@ export function LoginForm({ onSuccess, redirectTo }: LoginFormProps) {
139
118
  htmlFor="password"
140
119
  className="text-sm font-medium text-foreground"
141
120
  >
142
- Password
121
+ {t("password")}
143
122
  </label>
144
123
  <Link
145
124
  href="/auth/forgot-password"
146
125
  className="text-xs text-primary hover:underline"
147
126
  >
148
- Forgot password?
127
+ {t("forgotPassword")}
149
128
  </Link>
150
129
  </div>
151
130
  <Input
@@ -169,18 +148,18 @@ export function LoginForm({ onSuccess, redirectTo }: LoginFormProps) {
169
148
  <Button
170
149
  type="submit"
171
150
  className="w-full"
172
- disabled={loginMutation.isPending}
151
+ disabled={isLoggingIn}
173
152
  >
174
- {loginMutation.isPending ? "Signing in..." : "Sign In"}
153
+ {isLoggingIn ? t("signingIn") : t("signIn")}
175
154
  </Button>
176
155
 
177
156
  <div className="text-center text-sm text-muted-foreground">
178
- Don't have an account?{" "}
157
+ {t("noAccount")}{" "}
179
158
  <Link
180
159
  href="/auth/register"
181
160
  className="font-medium text-primary hover:underline"
182
161
  >
183
- Sign up
162
+ {t("signUp")}
184
163
  </Link>
185
164
  </div>
186
165
  </form>