@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
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import { useState, useEffect } from "react";
4
- import { useRouter } from "next/navigation";
5
- import Link from "next/link";
4
+ import { useRouter, Link } from "@/i18n/navigation";
5
+ import { StorefrontError } from "@doswiftly/storefront-sdk";
6
6
  import { useCartStore } from "@/stores/cart-store";
7
7
  import { useCartSync } from "@/hooks/use-cart-sync";
8
8
  import {
@@ -15,10 +15,13 @@ import {
15
15
  useCheckoutDiscountCodeRemove,
16
16
  useCheckoutGiftCardApply,
17
17
  useCheckoutGiftCardRemove,
18
+ useCheckoutGiftCardRecipientUpdate,
18
19
  useCheckoutComplete,
19
20
  useCheckout,
20
21
  } from "@/lib/graphql/hooks";
21
- import { formatAmount } from "@/lib/format";
22
+ import { useQueryClient } from "@tanstack/react-query";
23
+ import { queryKeys } from "@/lib/graphql/query-keys";
24
+ import { formatAmount } from "@doswiftly/storefront-sdk";
22
25
  import { Button } from "@/components/ui/button";
23
26
  import { Input } from "@/components/ui/input";
24
27
  import { Label } from "@/components/ui/label";
@@ -37,6 +40,7 @@ import { PaymentStep } from "@/components/checkout/payment-step";
37
40
  import type { PaymentMethod } from "@/components/checkout/payment-method-card";
38
41
  import { toast } from "sonner";
39
42
  import { z } from "zod";
43
+ import { useTranslations } from "next-intl";
40
44
  import {
41
45
  Loader2,
42
46
  ChevronLeft,
@@ -57,45 +61,7 @@ import {
57
61
  // CONSTANTS
58
62
  // ============================================================================
59
63
 
60
- const COUNTRIES = [
61
- { code: "PL", name: "Polska" },
62
- { code: "DE", name: "Niemcy" },
63
- { code: "CZ", name: "Czechy" },
64
- { code: "SK", name: "Słowacja" },
65
- { code: "AT", name: "Austria" },
66
- { code: "FR", name: "Francja" },
67
- { code: "NL", name: "Holandia" },
68
- { code: "BE", name: "Belgia" },
69
- { code: "IT", name: "Włochy" },
70
- { code: "ES", name: "Hiszpania" },
71
- { code: "GB", name: "Wielka Brytania" },
72
- { code: "US", name: "Stany Zjednoczone" },
73
- ];
74
-
75
- // ============================================================================
76
- // VALIDATION SCHEMAS
77
- // ============================================================================
78
-
79
- const contactSchema = z.object({
80
- email: z.string().email("Podaj prawidłowy adres email"),
81
- phone: z
82
- .string()
83
- .min(9, "Numer telefonu jest wymagany")
84
- .regex(/^\+?[0-9\s\-]{9,15}$/, "Nieprawidłowy format numeru telefonu"),
85
- });
86
-
87
- const addressSchema = z.object({
88
- firstName: z.string().min(1, "Imię jest wymagane"),
89
- lastName: z.string().min(1, "Nazwisko jest wymagane"),
90
- address1: z.string().min(1, "Adres jest wymagany"),
91
- address2: z.string().optional(),
92
- city: z.string().min(1, "Miasto jest wymagane"),
93
- province: z.string().optional(),
94
- zip: z.string().min(1, "Kod pocztowy jest wymagany"),
95
- country: z.string().min(2, "Kraj jest wymagany"),
96
- phone: z.string().optional(),
97
- company: z.string().optional(),
98
- });
64
+ const COUNTRY_CODES = ["PL", "DE", "CZ", "SK", "AT", "FR", "NL", "BE", "IT", "ES", "GB", "US"] as const;
99
65
 
100
66
  // ============================================================================
101
67
  // TYPES
@@ -165,11 +131,20 @@ interface AddressFormFieldsProps {
165
131
  }
166
132
 
167
133
  function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFieldsProps) {
134
+ const t = useTranslations("checkout");
135
+ const tc = useTranslations("common");
136
+ const tCountries = useTranslations("countries");
137
+
138
+ const countries = COUNTRY_CODES.map((code) => ({
139
+ code,
140
+ name: tCountries(code),
141
+ }));
142
+
168
143
  return (
169
144
  <div className="space-y-4">
170
145
  <div className="grid gap-4 sm:grid-cols-2">
171
146
  <div>
172
- <Label htmlFor={`${prefix}_firstName`}>Imię *</Label>
147
+ <Label htmlFor={`${prefix}_firstName`}>{t("address.firstName")} *</Label>
173
148
  <Input
174
149
  id={`${prefix}_firstName`}
175
150
  value={values.firstName}
@@ -181,7 +156,7 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
181
156
  )}
182
157
  </div>
183
158
  <div>
184
- <Label htmlFor={`${prefix}_lastName`}>Nazwisko *</Label>
159
+ <Label htmlFor={`${prefix}_lastName`}>{t("address.lastName")} *</Label>
185
160
  <Input
186
161
  id={`${prefix}_lastName`}
187
162
  value={values.lastName}
@@ -195,7 +170,7 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
195
170
  </div>
196
171
 
197
172
  <div>
198
- <Label htmlFor={`${prefix}_company`}>Firma (opcjonalnie)</Label>
173
+ <Label htmlFor={`${prefix}_company`}>{t("address.company")} ({tc("optional")})</Label>
199
174
  <Input
200
175
  id={`${prefix}_company`}
201
176
  value={values.company}
@@ -204,10 +179,10 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
204
179
  </div>
205
180
 
206
181
  <div>
207
- <Label htmlFor={`${prefix}_address1`}>Adres *</Label>
182
+ <Label htmlFor={`${prefix}_address1`}>{t("address.address1")} *</Label>
208
183
  <Input
209
184
  id={`${prefix}_address1`}
210
- placeholder="Ulica i numer"
185
+ placeholder={t("address.address1Placeholder")}
211
186
  value={values.address1}
212
187
  onChange={(e) => onChange("address1", e.target.value)}
213
188
  className={errors[`${prefix}_address1`] ? "border-destructive" : ""}
@@ -218,7 +193,7 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
218
193
  </div>
219
194
 
220
195
  <div>
221
- <Label htmlFor={`${prefix}_address2`}>Mieszkanie, piętro (opcjonalnie)</Label>
196
+ <Label htmlFor={`${prefix}_address2`}>{t("address.address2")} ({tc("optional")})</Label>
222
197
  <Input
223
198
  id={`${prefix}_address2`}
224
199
  value={values.address2}
@@ -228,10 +203,10 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
228
203
 
229
204
  <div className="grid gap-4 sm:grid-cols-2">
230
205
  <div>
231
- <Label htmlFor={`${prefix}_zip`}>Kod pocztowy *</Label>
206
+ <Label htmlFor={`${prefix}_zip`}>{t("address.zip")} *</Label>
232
207
  <Input
233
208
  id={`${prefix}_zip`}
234
- placeholder="00-000"
209
+ placeholder={t("address.zipPlaceholder")}
235
210
  value={values.zip}
236
211
  onChange={(e) => onChange("zip", e.target.value)}
237
212
  className={errors[`${prefix}_zip`] ? "border-destructive" : ""}
@@ -241,7 +216,7 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
241
216
  )}
242
217
  </div>
243
218
  <div>
244
- <Label htmlFor={`${prefix}_city`}>Miasto *</Label>
219
+ <Label htmlFor={`${prefix}_city`}>{t("address.city")} *</Label>
245
220
  <Input
246
221
  id={`${prefix}_city`}
247
222
  value={values.city}
@@ -256,13 +231,13 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
256
231
 
257
232
  <div className="grid gap-4 sm:grid-cols-2">
258
233
  <div>
259
- <Label htmlFor={`${prefix}_country`}>Kraj *</Label>
234
+ <Label htmlFor={`${prefix}_country`}>{t("address.country")} *</Label>
260
235
  <Select value={values.country} onValueChange={(value) => onChange("country", value)}>
261
236
  <SelectTrigger className={errors[`${prefix}_country`] ? "border-destructive" : ""}>
262
- <SelectValue placeholder="Wybierz kraj" />
237
+ <SelectValue placeholder={t("address.countryPlaceholder")} />
263
238
  </SelectTrigger>
264
239
  <SelectContent>
265
- {COUNTRIES.map((country) => (
240
+ {countries.map((country) => (
266
241
  <SelectItem key={country.code} value={country.code}>
267
242
  {country.name}
268
243
  </SelectItem>
@@ -274,7 +249,7 @@ function AddressFormFields({ prefix, values, onChange, errors }: AddressFormFiel
274
249
  )}
275
250
  </div>
276
251
  <div>
277
- <Label htmlFor={`${prefix}_province`}>Województwo (opcjonalnie)</Label>
252
+ <Label htmlFor={`${prefix}_province`}>{t("address.province")} ({tc("optional")})</Label>
278
253
  <Input
279
254
  id={`${prefix}_province`}
280
255
  value={values.province}
@@ -295,6 +270,42 @@ export default function CheckoutPage() {
295
270
  const { cartId, clearCart } = useCartStore();
296
271
  const { items, isLoading: isCartLoading } = useCartSync();
297
272
 
273
+ const t = useTranslations("checkout");
274
+ const tc = useTranslations("common");
275
+ const tCountries = useTranslations("countries");
276
+ const tCart = useTranslations("cart");
277
+
278
+ // ============================================================================
279
+ // VALIDATION SCHEMAS (inside component to use translations)
280
+ // ============================================================================
281
+
282
+ const contactSchema = z.object({
283
+ email: z.string().email(t("validation.emailRequired")),
284
+ phone: z
285
+ .string()
286
+ .min(9, t("validation.phoneRequired"))
287
+ .regex(/^\+?[0-9\s\-]{9,15}$/, t("validation.phoneInvalid")),
288
+ });
289
+
290
+ const addressSchema = z.object({
291
+ firstName: z.string().min(1, t("validation.firstNameRequired")),
292
+ lastName: z.string().min(1, t("validation.lastNameRequired")),
293
+ address1: z.string().min(1, t("validation.addressRequired")),
294
+ address2: z.string().optional(),
295
+ city: z.string().min(1, t("validation.cityRequired")),
296
+ province: z.string().optional(),
297
+ zip: z.string().min(1, t("validation.zipRequired")),
298
+ country: z.string().min(2, t("validation.countryRequired")),
299
+ phone: z.string().optional(),
300
+ company: z.string().optional(),
301
+ });
302
+
303
+ // Countries for review section
304
+ const countries = COUNTRY_CODES.map((code) => ({
305
+ code,
306
+ name: tCountries(code),
307
+ }));
308
+
298
309
  // Step management
299
310
  const [currentStep, setCurrentStep] = useState<CheckoutStep>("contact");
300
311
  const [checkoutId, setCheckoutId] = useState<string | null>(null);
@@ -337,7 +348,9 @@ export default function CheckoutPage() {
337
348
  const removeDiscount = useCheckoutDiscountCodeRemove();
338
349
  const applyGiftCard = useCheckoutGiftCardApply();
339
350
  const removeGiftCard = useCheckoutGiftCardRemove();
351
+ const updateGiftCardRecipient = useCheckoutGiftCardRecipientUpdate();
340
352
  const completeCheckout = useCheckoutComplete();
353
+ const queryClient = useQueryClient();
341
354
 
342
355
  // Query checkout for shipping rates
343
356
  const { data: checkoutData, refetch: refetchCheckout } = useCheckout(checkoutId);
@@ -345,8 +358,8 @@ export default function CheckoutPage() {
345
358
 
346
359
  // Sync discount codes from checkout (transferred from cart) to form state
347
360
  useEffect(() => {
348
- if (checkout?.discountCodes?.length > 0 && !formState.appliedDiscountCode) {
349
- const applicableCode = checkout.discountCodes.find((dc: any) => dc.applicable);
361
+ if ((checkout?.discountCodes?.length ?? 0) > 0 && !formState.appliedDiscountCode) {
362
+ const applicableCode = checkout?.discountCodes?.find((dc) => dc.applicable);
350
363
  if (applicableCode) {
351
364
  setFormState((prev) => ({
352
365
  ...prev,
@@ -367,6 +380,7 @@ export default function CheckoutPage() {
367
380
  removeDiscount.isPending ||
368
381
  applyGiftCard.isPending ||
369
382
  removeGiftCard.isPending ||
383
+ updateGiftCardRecipient.isPending ||
370
384
  completeCheckout.isPending;
371
385
 
372
386
  // Calculate totals from checkout or cart
@@ -398,6 +412,8 @@ export default function CheckoutPage() {
398
412
  setErrors({});
399
413
 
400
414
  try {
415
+ let newCheckoutId = checkoutId;
416
+
401
417
  // Create checkout if not exists
402
418
  if (!checkoutId) {
403
419
  const createResult = await createCheckout.mutateAsync({
@@ -413,7 +429,8 @@ export default function CheckoutPage() {
413
429
  }
414
430
 
415
431
  if (createResult.checkoutCreate.checkout) {
416
- setCheckoutId(createResult.checkoutCreate.checkout.id);
432
+ newCheckoutId = createResult.checkoutCreate.checkout.id;
433
+ setCheckoutId(newCheckoutId);
417
434
  }
418
435
  } else {
419
436
  // Update email on existing checkout
@@ -428,9 +445,38 @@ export default function CheckoutPage() {
428
445
  }
429
446
  }
430
447
 
448
+ // Send gift card recipient data (if any)
449
+ if (hasGiftCards && newCheckoutId) {
450
+ const giftCardItems = items.filter((item) => item.productType === "GIFT_CARD");
451
+ const recipientMutations = giftCardItems
452
+ .filter((gc) => giftCardRecipients[gc.lineId]?.recipientEmail)
453
+ .map((gc) =>
454
+ updateGiftCardRecipient.mutateAsync({
455
+ input: {
456
+ checkoutId: newCheckoutId!,
457
+ lineItemId: gc.lineId,
458
+ ...giftCardRecipients[gc.lineId],
459
+ },
460
+ })
461
+ );
462
+
463
+ if (recipientMutations.length > 0) {
464
+ const results = await Promise.allSettled(recipientMutations);
465
+ const failed = results.filter((r) => r.status === "rejected");
466
+ if (failed.length > 0) {
467
+ toast.warning(
468
+ t("giftCard.recipientSaveError", { count: failed.length })
469
+ );
470
+ }
471
+ // Refetch checkout after recipient updates — prevents stale UI
472
+ await queryClient.refetchQueries({ queryKey: queryKeys.checkout.detail(newCheckoutId, currencyCode) });
473
+ }
474
+ }
475
+
431
476
  setCurrentStep(allGiftCards ? "payment" : "shipping");
432
- } catch (error: any) {
433
- toast.error(error.message || "Nie udało się przetworzyć danych kontaktowych");
477
+ } catch (error: unknown) {
478
+ const message = error instanceof Error ? error.message : t("errors.contactProcessing");
479
+ toast.error(message);
434
480
  }
435
481
  };
436
482
 
@@ -470,7 +516,7 @@ export default function CheckoutPage() {
470
516
  setErrors({});
471
517
 
472
518
  if (!checkoutId) {
473
- toast.error("Checkout nie znaleziony. Wróć i spróbuj ponownie.");
519
+ toast.error(t("errors.checkoutNotFound"));
474
520
  return;
475
521
  }
476
522
 
@@ -510,8 +556,9 @@ export default function CheckoutPage() {
510
556
  // Refetch checkout to get shipping rates
511
557
  await refetchCheckout();
512
558
  setCurrentStep("delivery");
513
- } catch (error: any) {
514
- toast.error(error.message || "Nie udało się zaktualizować adresu");
559
+ } catch (error: unknown) {
560
+ const message = error instanceof Error ? error.message : t("errors.addressUpdate");
561
+ toast.error(message);
515
562
  }
516
563
  };
517
564
 
@@ -521,13 +568,13 @@ export default function CheckoutPage() {
521
568
 
522
569
  const handleDeliverySubmit = async () => {
523
570
  if (!formState.selectedShippingRate) {
524
- setErrors({ shipping: "Wybierz metodę dostawy" });
571
+ setErrors({ shipping: t("delivery.selectMethod") });
525
572
  return;
526
573
  }
527
574
  setErrors({});
528
575
 
529
576
  if (!checkoutId) {
530
- toast.error("Checkout nie znaleziony. Wróć i spróbuj ponownie.");
577
+ toast.error(t("errors.checkoutNotFound"));
531
578
  return;
532
579
  }
533
580
 
@@ -544,8 +591,9 @@ export default function CheckoutPage() {
544
591
 
545
592
  await refetchCheckout();
546
593
  setCurrentStep("payment");
547
- } catch (error: any) {
548
- toast.error(error.message || "Nie udało się wybrać metody dostawy");
594
+ } catch (error: unknown) {
595
+ const message = error instanceof Error ? error.message : t("errors.deliverySelect");
596
+ toast.error(message);
549
597
  }
550
598
  };
551
599
 
@@ -556,14 +604,14 @@ export default function CheckoutPage() {
556
604
  const handlePaymentMethodSelect = (paymentMethodId: string) => {
557
605
  // Validate payment method supports current currency
558
606
  const selectedMethod = checkout?.availablePaymentMethods?.find(
559
- (pm: any) => pm.id === paymentMethodId
607
+ (pm) => pm.id === paymentMethodId
560
608
  );
561
609
 
562
- if (selectedMethod?.supportedCurrencies?.length > 0) {
610
+ if (selectedMethod?.supportedCurrencies && selectedMethod.supportedCurrencies.length > 0) {
563
611
  const supportsCurrency = selectedMethod.supportedCurrencies.includes(currencyCode);
564
612
  if (!supportsCurrency) {
565
613
  setErrors({
566
- payment: `Ta metoda płatności nie obsługuje waluty ${currencyCode}. Wybierz inną metodę.`,
614
+ payment: t("payment.unsupportedCurrency", { currency: currencyCode }),
567
615
  });
568
616
  return;
569
617
  }
@@ -575,27 +623,27 @@ export default function CheckoutPage() {
575
623
 
576
624
  const handlePaymentSubmit = async () => {
577
625
  if (!formState.selectedPaymentMethodId) {
578
- setErrors({ payment: "Wybierz metodę płatności" });
626
+ setErrors({ payment: t("payment.selectMethod") });
579
627
  return;
580
628
  }
581
629
 
582
630
  // Validate selected payment method still exists and is valid
583
631
  const selectedMethod = checkout?.availablePaymentMethods?.find(
584
- (pm: any) => pm.id === formState.selectedPaymentMethodId
632
+ (pm) => pm.id === formState.selectedPaymentMethodId
585
633
  );
586
634
 
587
635
  if (!selectedMethod) {
588
- setErrors({ payment: "Wybrana metoda płatności jest niedostępna. Wybierz inną metodę." });
636
+ setErrors({ payment: t("payment.unavailable") });
589
637
  setFormState((prev) => ({ ...prev, selectedPaymentMethodId: null }));
590
638
  return;
591
639
  }
592
640
 
593
641
  // Validate currency support
594
- if (selectedMethod.supportedCurrencies?.length > 0) {
642
+ if (selectedMethod.supportedCurrencies && selectedMethod.supportedCurrencies.length > 0) {
595
643
  const supportsCurrency = selectedMethod.supportedCurrencies.includes(currencyCode);
596
644
  if (!supportsCurrency) {
597
645
  setErrors({
598
- payment: `Metoda "${selectedMethod.name}" nie obsługuje waluty ${currencyCode}. Wybierz inną metodę.`,
646
+ payment: t("payment.unsupportedCurrency", { currency: currencyCode }),
599
647
  });
600
648
  return;
601
649
  }
@@ -615,7 +663,7 @@ export default function CheckoutPage() {
615
663
  }
616
664
 
617
665
  if (!checkoutId) {
618
- toast.error("Checkout nie znaleziony");
666
+ toast.error(t("errors.checkoutNotFound"));
619
667
  return;
620
668
  }
621
669
 
@@ -633,7 +681,7 @@ export default function CheckoutPage() {
633
681
  }
634
682
 
635
683
  if (!payload?.checkout) {
636
- toast.error("Nie udało się zastosować kodu rabatowego");
684
+ toast.error(t("errors.discountApply"));
637
685
  return;
638
686
  }
639
687
 
@@ -643,9 +691,10 @@ export default function CheckoutPage() {
643
691
  discountCode: "",
644
692
  }));
645
693
  await refetchCheckout();
646
- toast.success("Kod rabatowy został zastosowany");
647
- } catch (error: any) {
648
- toast.error(error.message || "Nie udało się zastosować kodu rabatowego");
694
+ toast.success(t("discount.applied"));
695
+ } catch (error: unknown) {
696
+ const message = error instanceof Error ? error.message : t("errors.discountApply");
697
+ toast.error(message);
649
698
  }
650
699
  };
651
700
 
@@ -670,9 +719,10 @@ export default function CheckoutPage() {
670
719
  appliedDiscountCode: null,
671
720
  }));
672
721
  await refetchCheckout();
673
- toast.success("Kod rabatowy został usunięty");
674
- } catch (error: any) {
675
- toast.error(error.message || "Nie udało się usunąć kodu rabatowego");
722
+ toast.success(t("discount.removed"));
723
+ } catch (error: unknown) {
724
+ const message = error instanceof Error ? error.message : t("errors.discountRemove");
725
+ toast.error(message);
676
726
  }
677
727
  };
678
728
 
@@ -686,7 +736,7 @@ export default function CheckoutPage() {
686
736
  }
687
737
 
688
738
  if (!checkoutId) {
689
- toast.error("Checkout nie znaleziony");
739
+ toast.error(t("errors.checkoutNotFound"));
690
740
  return;
691
741
  }
692
742
 
@@ -700,13 +750,13 @@ export default function CheckoutPage() {
700
750
  const error = result.checkoutGiftCardApply.userErrors[0];
701
751
  // Translate common error codes to user-friendly messages
702
752
  const errorMessages: Record<string, string> = {
703
- GIFT_CARD_NOT_FOUND: "Nie znaleziono karty podarunkowej o podanym kodzie",
704
- GIFT_CARD_EXPIRED: "Ta karta podarunkowa wygasła",
705
- GIFT_CARD_DISABLED: "Ta karta podarunkowa jest wyłączona",
706
- GIFT_CARD_NO_BALANCE: "Ta karta podarunkowa nie ma dostępnego salda",
707
- GIFT_CARD_ALREADY_APPLIED: "Ta karta jest już zastosowana",
753
+ GIFT_CARD_NOT_FOUND: t("errors.giftCardNotFound"),
754
+ GIFT_CARD_EXPIRED: t("errors.giftCardExpired"),
755
+ GIFT_CARD_DISABLED: t("errors.giftCardDisabled"),
756
+ GIFT_CARD_DEPLETED: t("errors.giftCardDepleted"),
757
+ GIFT_CARD_UNUSABLE: t("errors.giftCardUnusable"),
708
758
  };
709
- toast.error(errorMessages[error.code] || error.message);
759
+ toast.error((error.code && errorMessages[error.code]) || error.message);
710
760
  return;
711
761
  }
712
762
 
@@ -715,9 +765,10 @@ export default function CheckoutPage() {
715
765
  giftCardCode: "",
716
766
  }));
717
767
  await refetchCheckout();
718
- toast.success("Karta podarunkowa została zastosowana");
719
- } catch (error: any) {
720
- toast.error(error.message || "Nie udało się zastosować karty podarunkowej");
768
+ toast.success(tCart("giftCardApplied"));
769
+ } catch (error: unknown) {
770
+ const message = error instanceof Error ? error.message : t("errors.giftCardApply");
771
+ toast.error(message);
721
772
  }
722
773
  };
723
774
 
@@ -738,9 +789,10 @@ export default function CheckoutPage() {
738
789
  }
739
790
 
740
791
  await refetchCheckout();
741
- toast.success("Karta podarunkowa została usunięta");
742
- } catch (error: any) {
743
- toast.error(error.message || "Nie udało się usunąć karty podarunkowej");
792
+ toast.success(tCart("giftCardRemoved"));
793
+ } catch (error: unknown) {
794
+ const message = error instanceof Error ? error.message : t("errors.giftCardRemove");
795
+ toast.error(message);
744
796
  }
745
797
  };
746
798
 
@@ -750,12 +802,12 @@ export default function CheckoutPage() {
750
802
 
751
803
  const handleCompleteCheckout = async () => {
752
804
  if (!formState.acceptTerms) {
753
- setErrors({ terms: "Musisz zaakceptować regulamin" });
805
+ setErrors({ terms: t("review.mustAcceptTerms") });
754
806
  return;
755
807
  }
756
808
 
757
809
  if (!formState.selectedPaymentMethodId) {
758
- setErrors({ payment: "Wybierz metodę płatności" });
810
+ setErrors({ payment: t("payment.selectMethod") });
759
811
  setCurrentStep("payment");
760
812
  return;
761
813
  }
@@ -763,7 +815,7 @@ export default function CheckoutPage() {
763
815
  setErrors({});
764
816
 
765
817
  if (!checkoutId) {
766
- toast.error("Checkout nie znaleziony. Wróć i spróbuj ponownie.");
818
+ toast.error(t("errors.checkoutNotFound"));
767
819
  return;
768
820
  }
769
821
 
@@ -781,31 +833,24 @@ export default function CheckoutPage() {
781
833
  const errorMessage = error.message;
782
834
 
783
835
  // Handle specific payment-related error codes
784
- switch (errorCode) {
836
+ // Cast to string since backend may return codes not in the generated enum
837
+ const codeStr = errorCode as string | null | undefined;
838
+ switch (codeStr) {
785
839
  case "INVALID_PAYMENT_METHOD":
786
- case "PAYMENT_METHOD_NOT_FOUND":
787
- setErrors({ payment: "Wybrana metoda płatności jest niedostępna. Wybierz inną metodę." });
840
+ case "NO_PAYMENT_METHODS":
841
+ setErrors({ payment: t("payment.unavailable") });
788
842
  setFormState((prev) => ({ ...prev, selectedPaymentMethodId: null }));
789
843
  setCurrentStep("payment");
790
- toast.error("Metoda płatności jest niedostępna");
844
+ toast.error(t("errors.paymentUnavailable"));
791
845
  break;
792
- case "PAYMENT_METHOD_CURRENCY_NOT_SUPPORTED":
793
- setErrors({ payment: `Metoda płatności nie obsługuje wybranej waluty (${currencyCode}).` });
794
- setCurrentStep("payment");
795
- toast.error("Waluta nie jest obsługiwana przez tę metodę płatności");
846
+ case "ALREADY_COMPLETED":
847
+ toast.error(t("errors.sessionExpired"));
796
848
  break;
797
- case "PAYMENT_DECLINED":
798
- toast.error("Płatność została odrzucona. Spróbuj ponownie lub wybierz inną metodę.");
799
- setCurrentStep("payment");
800
- break;
801
- case "CHECKOUT_EXPIRED":
802
- toast.error("Sesja checkout wygasła. Proszę odświeżyć stronę i spróbować ponownie.");
803
- break;
804
- case "INVENTORY_NOT_AVAILABLE":
805
- toast.error("Niektóre produkty są niedostępne. Sprawdź swój koszyk.");
849
+ case "NOT_ENOUGH_IN_STOCK":
850
+ toast.error(t("errors.outOfStock"));
806
851
  break;
807
852
  default:
808
- toast.error(errorMessage || "Nie udało się sfinalizować zamówienia");
853
+ toast.error(errorMessage || t("errors.checkoutComplete"));
809
854
  }
810
855
  return;
811
856
  }
@@ -821,7 +866,7 @@ export default function CheckoutPage() {
821
866
  const orderId = completeResult.checkoutComplete.order.id;
822
867
  const paymentType = formState.selectedPaymentMethodId
823
868
  ? checkout?.availablePaymentMethods?.find(
824
- (pm: any) => pm.id === formState.selectedPaymentMethodId
869
+ (pm) => pm.id === formState.selectedPaymentMethodId
825
870
  )?.type
826
871
  : null;
827
872
 
@@ -830,10 +875,11 @@ export default function CheckoutPage() {
830
875
  router.push(`/checkout/success/${orderId}${searchParams}`);
831
876
  } else {
832
877
  // Fallback: no payment URL and no order - show error
833
- toast.error("Wystąpił nieoczekiwany błąd. Skontaktuj się z obsługą.");
878
+ toast.error(t("errors.unexpected"));
834
879
  }
835
- } catch (error: any) {
836
- toast.error(error.message || "Nie udało się sfinalizować zamówienia");
880
+ } catch (error: unknown) {
881
+ const message = error instanceof Error ? error.message : t("errors.checkoutComplete");
882
+ toast.error(message);
837
883
  }
838
884
  };
839
885
 
@@ -863,7 +909,7 @@ export default function CheckoutPage() {
863
909
  return (
864
910
  <div className="container mx-auto px-4 py-16 text-center">
865
911
  <Loader2 className="mx-auto h-8 w-8 animate-spin text-muted-foreground" />
866
- <p className="mt-4 text-muted-foreground">Ładowanie...</p>
912
+ <p className="mt-4 text-muted-foreground">{tc("loading")}</p>
867
913
  </div>
868
914
  );
869
915
  }
@@ -873,12 +919,12 @@ export default function CheckoutPage() {
873
919
  return (
874
920
  <div className="container mx-auto px-4 py-16 text-center">
875
921
  <ShoppingBag className="mx-auto h-16 w-16 text-muted-foreground" />
876
- <h1 className="mt-4 text-2xl font-bold">Twój koszyk jest pusty</h1>
922
+ <h1 className="mt-4 text-2xl font-bold">{tCart("empty")}</h1>
877
923
  <p className="mt-2 text-muted-foreground">
878
- Dodaj produkty do koszyka, aby kontynuować zakupy.
924
+ {tCart("emptyDescription")}
879
925
  </p>
880
926
  <Button className="mt-6" asChild>
881
- <Link href="/products">Przeglądaj produkty</Link>
927
+ <Link href="/products">{tCart("browseProducts")}</Link>
882
928
  </Button>
883
929
  </div>
884
930
  );
@@ -889,11 +935,11 @@ export default function CheckoutPage() {
889
935
  // ============================================================================
890
936
 
891
937
  const allSteps: { id: CheckoutStep; label: string; icon: React.ReactNode }[] = [
892
- { id: "contact", label: "Kontakt", icon: <User className="h-4 w-4" /> },
893
- { id: "shipping", label: "Adres", icon: <Package className="h-4 w-4" /> },
894
- { id: "delivery", label: "Dostawa", icon: <Truck className="h-4 w-4" /> },
895
- { id: "payment", label: "Płatność", icon: <CreditCard className="h-4 w-4" /> },
896
- { id: "review", label: "Podsumowanie", icon: <ClipboardCheck className="h-4 w-4" /> },
938
+ { id: "contact", label: t("steps.contact"), icon: <User className="h-4 w-4" /> },
939
+ { id: "shipping", label: t("steps.shipping"), icon: <Package className="h-4 w-4" /> },
940
+ { id: "delivery", label: t("steps.delivery"), icon: <Truck className="h-4 w-4" /> },
941
+ { id: "payment", label: t("steps.payment"), icon: <CreditCard className="h-4 w-4" /> },
942
+ { id: "review", label: t("steps.review"), icon: <ClipboardCheck className="h-4 w-4" /> },
897
943
  ];
898
944
  // Skip shipping and delivery steps when all items are gift cards
899
945
  const steps = allGiftCards
@@ -911,9 +957,9 @@ export default function CheckoutPage() {
911
957
  <Breadcrumbs className="mb-6" />
912
958
 
913
959
  <div className="mb-8 flex items-center justify-between">
914
- <h1 className="text-3xl font-bold">Checkout</h1>
960
+ <h1 className="text-3xl font-bold">{t("title")}</h1>
915
961
  <Link href="/auth/login" className="text-sm text-primary hover:underline">
916
- Masz konto? Zaloguj się
962
+ {t("haveAccount")}
917
963
  </Link>
918
964
  </div>
919
965
 
@@ -961,19 +1007,19 @@ export default function CheckoutPage() {
961
1007
  <CardHeader>
962
1008
  <CardTitle className="flex items-center gap-2">
963
1009
  <User className="h-5 w-5" />
964
- Dane kontaktowe
1010
+ {t("contact.title")}
965
1011
  </CardTitle>
966
1012
  <CardDescription>
967
- Podaj swój email i telefon - wyślemy na nie potwierdzenie zamówienia
1013
+ {t("contact.description")}
968
1014
  </CardDescription>
969
1015
  </CardHeader>
970
1016
  <CardContent className="space-y-4">
971
1017
  <div>
972
- <Label htmlFor="email">Email *</Label>
1018
+ <Label htmlFor="email">{t("contact.email")} *</Label>
973
1019
  <Input
974
1020
  id="email"
975
1021
  type="email"
976
- placeholder="twoj@email.pl"
1022
+ placeholder={t("contact.emailPlaceholder")}
977
1023
  value={formState.email}
978
1024
  onChange={(e) =>
979
1025
  setFormState((prev) => ({ ...prev, email: e.target.value }))
@@ -986,11 +1032,11 @@ export default function CheckoutPage() {
986
1032
  </div>
987
1033
 
988
1034
  <div>
989
- <Label htmlFor="phone">Telefon *</Label>
1035
+ <Label htmlFor="phone">{t("contact.phone")} *</Label>
990
1036
  <Input
991
1037
  id="phone"
992
1038
  type="tel"
993
- placeholder="+48 123 456 789"
1039
+ placeholder={t("contact.phonePlaceholder")}
994
1040
  value={formState.phone}
995
1041
  onChange={(e) =>
996
1042
  setFormState((prev) => ({ ...prev, phone: e.target.value }))
@@ -1001,7 +1047,7 @@ export default function CheckoutPage() {
1001
1047
  <p className="mt-1 text-sm text-destructive">{errors.phone}</p>
1002
1048
  )}
1003
1049
  <p className="mt-1 text-xs text-muted-foreground">
1004
- Kurier może potrzebować kontaktu w sprawie dostawy
1050
+ {t("contact.phoneHint")}
1005
1051
  </p>
1006
1052
  </div>
1007
1053
 
@@ -1014,7 +1060,7 @@ export default function CheckoutPage() {
1014
1060
  }
1015
1061
  />
1016
1062
  <Label htmlFor="marketing" className="text-sm font-normal cursor-pointer">
1017
- Chcę otrzymywać informacje o promocjach i nowościach
1063
+ {t("contact.marketing")}
1018
1064
  </Label>
1019
1065
  </div>
1020
1066
 
@@ -1023,28 +1069,28 @@ export default function CheckoutPage() {
1023
1069
  <div className="space-y-4 border-t pt-4">
1024
1070
  <div className="flex items-center gap-2 text-sm font-medium">
1025
1071
  <Gift className="h-4 w-4" />
1026
- Dane odbiorcy karty podarunkowej
1072
+ {t("giftCard.recipientTitle")}
1027
1073
  </div>
1028
1074
  <p className="text-xs text-muted-foreground">
1029
- Opcjonalnie: podaj dane osoby, która otrzyma kartę podarunkową
1075
+ {t("giftCard.recipientDescription")}
1030
1076
  </p>
1031
1077
  {items
1032
1078
  .filter((item) => item.productType === "GIFT_CARD")
1033
1079
  .map((item) => (
1034
- <div key={item.variantId} className="space-y-3 rounded-lg border p-4">
1080
+ <div key={item.lineId} className="space-y-3 rounded-lg border p-4">
1035
1081
  <p className="text-sm font-medium">{item.productTitle} — {item.variantTitle}</p>
1036
1082
  <div>
1037
- <Label htmlFor={`recipient-email-${item.variantId}`}>E-mail odbiorcy</Label>
1083
+ <Label htmlFor={`recipient-email-${item.lineId}`}>{t("giftCard.recipientEmail")}</Label>
1038
1084
  <Input
1039
- id={`recipient-email-${item.variantId}`}
1085
+ id={`recipient-email-${item.lineId}`}
1040
1086
  type="email"
1041
- placeholder="odbiorca@email.pl"
1042
- value={giftCardRecipients[item.variantId]?.recipientEmail || ""}
1087
+ placeholder={t("giftCard.recipientEmailPlaceholder")}
1088
+ value={giftCardRecipients[item.lineId]?.recipientEmail || ""}
1043
1089
  onChange={(e) =>
1044
1090
  setGiftCardRecipients((prev) => ({
1045
1091
  ...prev,
1046
- [item.variantId]: {
1047
- ...prev[item.variantId],
1092
+ [item.lineId]: {
1093
+ ...prev[item.lineId],
1048
1094
  recipientEmail: e.target.value,
1049
1095
  },
1050
1096
  }))
@@ -1052,17 +1098,17 @@ export default function CheckoutPage() {
1052
1098
  />
1053
1099
  </div>
1054
1100
  <div>
1055
- <Label htmlFor={`recipient-name-${item.variantId}`}>Imię odbiorcy</Label>
1101
+ <Label htmlFor={`recipient-name-${item.lineId}`}>{t("giftCard.recipientName")}</Label>
1056
1102
  <Input
1057
- id={`recipient-name-${item.variantId}`}
1103
+ id={`recipient-name-${item.lineId}`}
1058
1104
  type="text"
1059
- placeholder="Jan"
1060
- value={giftCardRecipients[item.variantId]?.recipientName || ""}
1105
+ placeholder={t("giftCard.recipientNamePlaceholder")}
1106
+ value={giftCardRecipients[item.lineId]?.recipientName || ""}
1061
1107
  onChange={(e) =>
1062
1108
  setGiftCardRecipients((prev) => ({
1063
1109
  ...prev,
1064
- [item.variantId]: {
1065
- ...prev[item.variantId],
1110
+ [item.lineId]: {
1111
+ ...prev[item.lineId],
1066
1112
  recipientName: e.target.value,
1067
1113
  },
1068
1114
  }))
@@ -1070,17 +1116,17 @@ export default function CheckoutPage() {
1070
1116
  />
1071
1117
  </div>
1072
1118
  <div>
1073
- <Label htmlFor={`recipient-message-${item.variantId}`}>Wiadomość</Label>
1119
+ <Label htmlFor={`recipient-message-${item.lineId}`}>{t("giftCard.message")}</Label>
1074
1120
  <Input
1075
- id={`recipient-message-${item.variantId}`}
1121
+ id={`recipient-message-${item.lineId}`}
1076
1122
  type="text"
1077
- placeholder="Wszystkiego najlepszego!"
1078
- value={giftCardRecipients[item.variantId]?.message || ""}
1123
+ placeholder={t("giftCard.messagePlaceholder")}
1124
+ value={giftCardRecipients[item.lineId]?.message || ""}
1079
1125
  onChange={(e) =>
1080
1126
  setGiftCardRecipients((prev) => ({
1081
1127
  ...prev,
1082
- [item.variantId]: {
1083
- ...prev[item.variantId],
1128
+ [item.lineId]: {
1129
+ ...prev[item.lineId],
1084
1130
  message: e.target.value,
1085
1131
  },
1086
1132
  }))
@@ -1098,7 +1144,7 @@ export default function CheckoutPage() {
1098
1144
  ) : (
1099
1145
  <ChevronRight className="mr-2 h-4 w-4" />
1100
1146
  )}
1101
- {allGiftCards ? "Dalej: Płatność" : "Dalej: Adres dostawy"}
1147
+ {allGiftCards ? t("contact.nextPayment") : t("contact.nextShipping")}
1102
1148
  </Button>
1103
1149
  </CardContent>
1104
1150
  </Card>
@@ -1111,9 +1157,9 @@ export default function CheckoutPage() {
1111
1157
  <CardHeader>
1112
1158
  <CardTitle className="flex items-center gap-2">
1113
1159
  <Package className="h-5 w-5" />
1114
- Adres dostawy
1160
+ {t("shipping.title")}
1115
1161
  </CardTitle>
1116
- <CardDescription>Podaj adres, na który mamy wysłać zamówienie</CardDescription>
1162
+ <CardDescription>{t("shipping.description")}</CardDescription>
1117
1163
  </CardHeader>
1118
1164
  <CardContent>
1119
1165
  <AddressFormFields
@@ -1134,7 +1180,7 @@ export default function CheckoutPage() {
1134
1180
  <CardHeader>
1135
1181
  <CardTitle className="flex items-center gap-2">
1136
1182
  <CreditCard className="h-5 w-5" />
1137
- Adres rozliczeniowy
1183
+ {t("shipping.billingTitle")}
1138
1184
  </CardTitle>
1139
1185
  </CardHeader>
1140
1186
  <CardContent className="space-y-4">
@@ -1147,7 +1193,7 @@ export default function CheckoutPage() {
1147
1193
  }
1148
1194
  />
1149
1195
  <Label htmlFor="sameAsBilling" className="cursor-pointer">
1150
- Taki sam jak adres dostawy
1196
+ {t("shipping.sameAsShipping")}
1151
1197
  </Label>
1152
1198
  </div>
1153
1199
 
@@ -1170,7 +1216,7 @@ export default function CheckoutPage() {
1170
1216
  <div className="flex gap-4">
1171
1217
  <Button variant="outline" onClick={goBack} size="lg">
1172
1218
  <ChevronLeft className="mr-2 h-4 w-4" />
1173
- Wstecz
1219
+ {tc("back")}
1174
1220
  </Button>
1175
1221
  <Button onClick={handleShippingSubmit} disabled={isLoading} className="flex-1" size="lg">
1176
1222
  {isLoading ? (
@@ -1178,7 +1224,7 @@ export default function CheckoutPage() {
1178
1224
  ) : (
1179
1225
  <ChevronRight className="mr-2 h-4 w-4" />
1180
1226
  )}
1181
- Dalej: Metoda dostawy
1227
+ {t("shipping.nextDelivery")}
1182
1228
  </Button>
1183
1229
  </div>
1184
1230
  </>
@@ -1190,23 +1236,23 @@ export default function CheckoutPage() {
1190
1236
  <CardHeader>
1191
1237
  <CardTitle className="flex items-center gap-2">
1192
1238
  <Truck className="h-5 w-5" />
1193
- Metoda dostawy
1239
+ {t("delivery.title")}
1194
1240
  </CardTitle>
1195
- <CardDescription>Wybierz sposób dostarczenia zamówienia</CardDescription>
1241
+ <CardDescription>{t("delivery.description")}</CardDescription>
1196
1242
  </CardHeader>
1197
1243
  <CardContent className="space-y-4">
1198
1244
  {!shippingRatesReady ? (
1199
1245
  <div className="flex items-center justify-center py-8">
1200
1246
  <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
1201
- <span className="ml-2 text-muted-foreground">Ładowanie metod dostawy...</span>
1247
+ <span className="ml-2 text-muted-foreground">{t("delivery.loading")}</span>
1202
1248
  </div>
1203
1249
  ) : availableShippingRates.length === 0 ? (
1204
1250
  <div className="rounded-lg border border-destructive/50 bg-destructive/10 p-4 text-center">
1205
1251
  <p className="text-destructive">
1206
- Brak dostępnych metod dostawy dla podanego adresu.
1252
+ {t("delivery.noMethods")}
1207
1253
  </p>
1208
1254
  <Button variant="outline" onClick={goBack} className="mt-4">
1209
- Zmień adres dostawy
1255
+ {t("delivery.changeAddress")}
1210
1256
  </Button>
1211
1257
  </div>
1212
1258
  ) : (
@@ -1249,7 +1295,7 @@ export default function CheckoutPage() {
1249
1295
  <div className="flex gap-4 pt-4">
1250
1296
  <Button variant="outline" onClick={goBack} size="lg">
1251
1297
  <ChevronLeft className="mr-2 h-4 w-4" />
1252
- Wstecz
1298
+ {tc("back")}
1253
1299
  </Button>
1254
1300
  <Button
1255
1301
  onClick={handleDeliverySubmit}
@@ -1262,7 +1308,7 @@ export default function CheckoutPage() {
1262
1308
  ) : (
1263
1309
  <ChevronRight className="mr-2 h-4 w-4" />
1264
1310
  )}
1265
- Dalej: Płatność
1311
+ {t("delivery.nextPayment")}
1266
1312
  </Button>
1267
1313
  </div>
1268
1314
  </CardContent>
@@ -1275,15 +1321,15 @@ export default function CheckoutPage() {
1275
1321
  <CardHeader>
1276
1322
  <CardTitle className="flex items-center gap-2">
1277
1323
  <CreditCard className="h-5 w-5" />
1278
- Metoda płatności
1324
+ {t("payment.title")}
1279
1325
  </CardTitle>
1280
- <CardDescription>Wybierz sposób zapłaty za zamówienie</CardDescription>
1326
+ <CardDescription>{t("payment.description")}</CardDescription>
1281
1327
  </CardHeader>
1282
1328
  <CardContent className="space-y-4">
1283
1329
  {/* PaymentStep component handles payment method selection */}
1284
1330
  <PaymentStep
1285
1331
  availablePaymentMethods={(checkout.availablePaymentMethods || []).map(
1286
- (pm: any): PaymentMethod => ({
1332
+ (pm): PaymentMethod => ({
1287
1333
  id: pm.id,
1288
1334
  name: pm.name,
1289
1335
  provider: pm.provider,
@@ -1307,7 +1353,7 @@ export default function CheckoutPage() {
1307
1353
  <div className="flex gap-4 pt-4">
1308
1354
  <Button variant="outline" onClick={goBack} size="lg">
1309
1355
  <ChevronLeft className="mr-2 h-4 w-4" />
1310
- Wstecz
1356
+ {tc("back")}
1311
1357
  </Button>
1312
1358
  <Button
1313
1359
  onClick={handlePaymentSubmit}
@@ -1320,7 +1366,7 @@ export default function CheckoutPage() {
1320
1366
  ) : (
1321
1367
  <ChevronRight className="mr-2 h-4 w-4" />
1322
1368
  )}
1323
- Dalej: Podsumowanie
1369
+ {t("payment.nextReview")}
1324
1370
  </Button>
1325
1371
  </div>
1326
1372
  </CardContent>
@@ -1333,15 +1379,15 @@ export default function CheckoutPage() {
1333
1379
  <CardHeader>
1334
1380
  <CardTitle className="flex items-center gap-2">
1335
1381
  <ClipboardCheck className="h-5 w-5" />
1336
- Podsumowanie zamówienia
1382
+ {t("review.title")}
1337
1383
  </CardTitle>
1338
- <CardDescription>Sprawdź wszystkie dane przed finalizacją</CardDescription>
1384
+ <CardDescription>{t("review.description")}</CardDescription>
1339
1385
  </CardHeader>
1340
1386
  <CardContent className="space-y-6">
1341
1387
  {/* Contact */}
1342
1388
  <div className="flex items-start justify-between rounded-lg border p-4">
1343
1389
  <div>
1344
- <h3 className="mb-1 font-medium">Kontakt</h3>
1390
+ <h3 className="mb-1 font-medium">{t("review.contact")}</h3>
1345
1391
  <p className="text-sm text-muted-foreground">{checkout.email}</p>
1346
1392
  <p className="text-sm text-muted-foreground">{formState.phone}</p>
1347
1393
  </div>
@@ -1350,7 +1396,7 @@ export default function CheckoutPage() {
1350
1396
  size="sm"
1351
1397
  onClick={() => setCurrentStep("contact")}
1352
1398
  >
1353
- Zmień
1399
+ {t("review.change")}
1354
1400
  </Button>
1355
1401
  </div>
1356
1402
 
@@ -1358,7 +1404,7 @@ export default function CheckoutPage() {
1358
1404
  {!allGiftCards && (
1359
1405
  <div className="flex items-start justify-between rounded-lg border p-4">
1360
1406
  <div>
1361
- <h3 className="mb-1 font-medium">Adres dostawy</h3>
1407
+ <h3 className="mb-1 font-medium">{t("review.shippingAddress")}</h3>
1362
1408
  {checkout.shippingAddress && (
1363
1409
  <p className="text-sm text-muted-foreground">
1364
1410
  {checkout.shippingAddress.firstName} {checkout.shippingAddress.lastName}
@@ -1373,7 +1419,7 @@ export default function CheckoutPage() {
1373
1419
  <br />
1374
1420
  {checkout.shippingAddress.zip} {checkout.shippingAddress.city}
1375
1421
  <br />
1376
- {COUNTRIES.find((c) => c.code === checkout.shippingAddress?.country)?.name ||
1422
+ {countries.find((c) => c.code === checkout.shippingAddress?.country)?.name ||
1377
1423
  checkout.shippingAddress.country}
1378
1424
  </p>
1379
1425
  )}
@@ -1383,7 +1429,7 @@ export default function CheckoutPage() {
1383
1429
  size="sm"
1384
1430
  onClick={() => setCurrentStep("shipping")}
1385
1431
  >
1386
- Zmień
1432
+ {t("review.change")}
1387
1433
  </Button>
1388
1434
  </div>
1389
1435
  )}
@@ -1392,7 +1438,7 @@ export default function CheckoutPage() {
1392
1438
  {!allGiftCards && (
1393
1439
  <div className="flex items-start justify-between rounded-lg border p-4">
1394
1440
  <div>
1395
- <h3 className="mb-1 font-medium">Metoda dostawy</h3>
1441
+ <h3 className="mb-1 font-medium">{t("review.shippingMethod")}</h3>
1396
1442
  {checkout.shippingLine && (
1397
1443
  <p className="text-sm text-muted-foreground">
1398
1444
  {checkout.shippingLine.title} -{" "}
@@ -1405,7 +1451,7 @@ export default function CheckoutPage() {
1405
1451
  size="sm"
1406
1452
  onClick={() => setCurrentStep("delivery")}
1407
1453
  >
1408
- Zmień
1454
+ {t("review.change")}
1409
1455
  </Button>
1410
1456
  </div>
1411
1457
  )}
@@ -1413,12 +1459,12 @@ export default function CheckoutPage() {
1413
1459
  {/* Payment Method */}
1414
1460
  <div className="flex items-start justify-between rounded-lg border p-4">
1415
1461
  <div>
1416
- <h3 className="mb-1 font-medium">Metoda płatności</h3>
1462
+ <h3 className="mb-1 font-medium">{t("review.paymentMethod")}</h3>
1417
1463
  {formState.selectedPaymentMethodId && (
1418
1464
  <p className="text-sm text-muted-foreground">
1419
1465
  {checkout.availablePaymentMethods?.find(
1420
- (pm: any) => pm.id === formState.selectedPaymentMethodId
1421
- )?.name || "Wybrana metoda płatności"}
1466
+ (pm) => pm.id === formState.selectedPaymentMethodId
1467
+ )?.name || t("review.paymentMethod")}
1422
1468
  </p>
1423
1469
  )}
1424
1470
  </div>
@@ -1427,7 +1473,7 @@ export default function CheckoutPage() {
1427
1473
  size="sm"
1428
1474
  onClick={() => setCurrentStep("payment")}
1429
1475
  >
1430
- Zmień
1476
+ {t("review.change")}
1431
1477
  </Button>
1432
1478
  </div>
1433
1479
 
@@ -1444,13 +1490,13 @@ export default function CheckoutPage() {
1444
1490
  />
1445
1491
  <div className="grid gap-1.5 leading-none">
1446
1492
  <Label htmlFor="terms" className="cursor-pointer">
1447
- Akceptuję{" "}
1493
+ {t("review.acceptTerms")}{" "}
1448
1494
  <Link href="/terms" className="text-primary hover:underline">
1449
- regulamin sklepu
1495
+ {t("review.termsLink")}
1450
1496
  </Link>{" "}
1451
- oraz{" "}
1497
+ {t("review.and")}{" "}
1452
1498
  <Link href="/privacy" className="text-primary hover:underline">
1453
- politykę prywatności
1499
+ {t("review.privacyLink")}
1454
1500
  </Link>{" "}
1455
1501
  *
1456
1502
  </Label>
@@ -1464,7 +1510,7 @@ export default function CheckoutPage() {
1464
1510
  <div className="flex gap-4">
1465
1511
  <Button variant="outline" onClick={goBack} size="lg">
1466
1512
  <ChevronLeft className="mr-2 h-4 w-4" />
1467
- Wstecz
1513
+ {tc("back")}
1468
1514
  </Button>
1469
1515
  <Button
1470
1516
  onClick={handleCompleteCheckout}
@@ -1477,7 +1523,7 @@ export default function CheckoutPage() {
1477
1523
  ) : (
1478
1524
  <CreditCard className="mr-2 h-4 w-4" />
1479
1525
  )}
1480
- Zapłać i zamów
1526
+ {t("review.placeOrder")}
1481
1527
  </Button>
1482
1528
  </div>
1483
1529
  </CardContent>
@@ -1491,49 +1537,84 @@ export default function CheckoutPage() {
1491
1537
  <CardHeader>
1492
1538
  <CardTitle className="flex items-center gap-2">
1493
1539
  <ShoppingBag className="h-5 w-5" />
1494
- Twoje zamówienie
1540
+ {tCart("yourOrder")}
1495
1541
  </CardTitle>
1496
1542
  </CardHeader>
1497
1543
  <CardContent className="space-y-4">
1498
1544
  {/* Line Items */}
1499
1545
  <div className="space-y-3">
1500
- {(checkout?.lineItems || items).map((item: any) => (
1501
- <div
1502
- key={item.id || item.lineId || item.variantId}
1503
- className="flex gap-3 text-sm"
1504
- >
1505
- <div className="relative h-16 w-16 flex-shrink-0 overflow-hidden rounded-md border bg-muted">
1506
- {item.image?.url ? (
1507
- <img
1508
- src={item.image.url}
1509
- alt={item.title || item.productTitle}
1510
- className="h-full w-full object-cover"
1511
- />
1512
- ) : (
1513
- <div className="flex h-full w-full items-center justify-center">
1514
- <Package className="h-6 w-6 text-muted-foreground" />
1546
+ {(checkout?.lineItems ?? []).length > 0
1547
+ ? checkout!.lineItems.map((item) => (
1548
+ <div
1549
+ key={item.id}
1550
+ className="flex gap-3 text-sm"
1551
+ >
1552
+ <div className="relative h-16 w-16 flex-shrink-0 overflow-hidden rounded-md border bg-muted">
1553
+ {item.image?.url ? (
1554
+ <img
1555
+ src={item.image.url}
1556
+ alt={item.title}
1557
+ className="h-full w-full object-cover"
1558
+ />
1559
+ ) : (
1560
+ <div className="flex h-full w-full items-center justify-center">
1561
+ <Package className="h-6 w-6 text-muted-foreground" />
1562
+ </div>
1563
+ )}
1564
+ <span className="absolute -right-2 -top-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground">
1565
+ {item.quantity}
1566
+ </span>
1515
1567
  </div>
1516
- )}
1517
- <span className="absolute -right-2 -top-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground">
1518
- {item.quantity}
1519
- </span>
1520
- </div>
1521
- <div className="flex-1">
1522
- <p className="font-medium line-clamp-2">
1523
- {item.title || item.productTitle}
1524
- </p>
1525
- {item.variantTitle && item.variantTitle !== "Default" && (
1526
- <p className="text-xs text-muted-foreground">{item.variantTitle}</p>
1527
- )}
1528
- </div>
1529
- <p className="font-medium">
1530
- {formatPrice(
1531
- item.totalPrice?.amount ||
1532
- parseFloat(item.price.amount) * item.quantity
1533
- )}
1534
- </p>
1535
- </div>
1536
- ))}
1568
+ <div className="flex-1">
1569
+ <p className="font-medium line-clamp-2">
1570
+ {item.title}
1571
+ </p>
1572
+ {item.variantTitle && item.variantTitle !== "Default" && (
1573
+ <p className="text-xs text-muted-foreground">{item.variantTitle}</p>
1574
+ )}
1575
+ </div>
1576
+ <p className="font-medium">
1577
+ {formatPrice(item.totalPrice.amount)}
1578
+ </p>
1579
+ </div>
1580
+ ))
1581
+ : items.map((item) => (
1582
+ <div
1583
+ key={item.lineId}
1584
+ className="flex gap-3 text-sm"
1585
+ >
1586
+ <div className="relative h-16 w-16 flex-shrink-0 overflow-hidden rounded-md border bg-muted">
1587
+ {item.image?.url ? (
1588
+ <img
1589
+ src={item.image.url}
1590
+ alt={item.productTitle}
1591
+ className="h-full w-full object-cover"
1592
+ />
1593
+ ) : (
1594
+ <div className="flex h-full w-full items-center justify-center">
1595
+ <Package className="h-6 w-6 text-muted-foreground" />
1596
+ </div>
1597
+ )}
1598
+ <span className="absolute -right-2 -top-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground">
1599
+ {item.quantity}
1600
+ </span>
1601
+ </div>
1602
+ <div className="flex-1">
1603
+ <p className="font-medium line-clamp-2">
1604
+ {item.productTitle}
1605
+ </p>
1606
+ {item.variantTitle && item.variantTitle !== "Default" && (
1607
+ <p className="text-xs text-muted-foreground">{item.variantTitle}</p>
1608
+ )}
1609
+ </div>
1610
+ <p className="font-medium">
1611
+ {formatPrice(
1612
+ parseFloat(item.price.amount) * item.quantity
1613
+ )}
1614
+ </p>
1615
+ </div>
1616
+ ))
1617
+ }
1537
1618
  </div>
1538
1619
 
1539
1620
  {/* Discount Code */}
@@ -1560,7 +1641,7 @@ export default function CheckoutPage() {
1560
1641
  ) : (
1561
1642
  <div className="flex gap-2">
1562
1643
  <Input
1563
- placeholder="Kod rabatowy"
1644
+ placeholder={t("discount.codePlaceholder")}
1564
1645
  value={formState.discountCode}
1565
1646
  onChange={(e) =>
1566
1647
  setFormState((prev) => ({ ...prev, discountCode: e.target.value }))
@@ -1575,7 +1656,7 @@ export default function CheckoutPage() {
1575
1656
  {applyDiscount.isPending ? (
1576
1657
  <Loader2 className="h-4 w-4 animate-spin" />
1577
1658
  ) : (
1578
- "Zastosuj"
1659
+ tc("apply")
1579
1660
  )}
1580
1661
  </Button>
1581
1662
  </div>
@@ -1586,12 +1667,12 @@ export default function CheckoutPage() {
1586
1667
  {/* Gift Card */}
1587
1668
  {checkoutId && (
1588
1669
  <div className="border-t pt-4 space-y-3">
1589
- <p className="text-sm font-medium">Karta podarunkowa</p>
1670
+ <p className="text-sm font-medium">{tCart("giftCardLabel")}</p>
1590
1671
 
1591
1672
  {/* Applied Gift Cards */}
1592
1673
  {checkout?.appliedGiftCards && checkout.appliedGiftCards.length > 0 && (
1593
1674
  <div className="space-y-2">
1594
- {checkout.appliedGiftCards.map((giftCard: any) => (
1675
+ {checkout.appliedGiftCards.map((giftCard) => (
1595
1676
  <div
1596
1677
  key={giftCard.lastCharacters}
1597
1678
  className="flex items-center justify-between rounded-lg bg-purple-50 p-3 dark:bg-purple-950"
@@ -1624,7 +1705,7 @@ export default function CheckoutPage() {
1624
1705
  {/* Gift Card Input */}
1625
1706
  <div className="flex gap-2">
1626
1707
  <Input
1627
- placeholder="Kod karty podarunkowej"
1708
+ placeholder={tCart("giftCardPlaceholder")}
1628
1709
  value={formState.giftCardCode}
1629
1710
  onChange={(e) =>
1630
1711
  setFormState((prev) => ({ ...prev, giftCardCode: e.target.value.toUpperCase() }))
@@ -1645,7 +1726,7 @@ export default function CheckoutPage() {
1645
1726
  {applyGiftCard.isPending ? (
1646
1727
  <Loader2 className="h-4 w-4 animate-spin" />
1647
1728
  ) : (
1648
- "Zastosuj"
1729
+ tc("apply")
1649
1730
  )}
1650
1731
  </Button>
1651
1732
  </div>
@@ -1656,7 +1737,7 @@ export default function CheckoutPage() {
1656
1737
  <div className="border-t pt-4 space-y-2">
1657
1738
  {/* Subtotal */}
1658
1739
  <div className="flex justify-between text-sm">
1659
- <span className="text-muted-foreground">Produkty</span>
1740
+ <span className="text-muted-foreground">{tCart("products")}</span>
1660
1741
  <span>
1661
1742
  {formatPrice(
1662
1743
  checkout?.subtotalPrice?.amount ||
@@ -1671,20 +1752,20 @@ export default function CheckoutPage() {
1671
1752
  {/* Shipping */}
1672
1753
  {checkout?.shippingLine ? (
1673
1754
  <div className="flex justify-between text-sm">
1674
- <span className="text-muted-foreground">Dostawa</span>
1755
+ <span className="text-muted-foreground">{tCart("shipping")}</span>
1675
1756
  <span>{formatPrice(checkout.totalShippingPrice?.amount || "0")}</span>
1676
1757
  </div>
1677
1758
  ) : (
1678
1759
  <div className="flex justify-between text-sm">
1679
- <span className="text-muted-foreground">Dostawa</span>
1680
- <span className="text-muted-foreground">Obliczona w następnym kroku</span>
1760
+ <span className="text-muted-foreground">{tCart("shipping")}</span>
1761
+ <span className="text-muted-foreground">{tCart("calculatedNextStep")}</span>
1681
1762
  </div>
1682
1763
  )}
1683
1764
 
1684
1765
  {/* Discount */}
1685
1766
  {checkout?.totalDiscounts && parseFloat(checkout.totalDiscounts.amount) > 0 && (
1686
1767
  <div className="flex justify-between text-sm text-green-600">
1687
- <span>Rabat</span>
1768
+ <span>{tCart("discount")}</span>
1688
1769
  <span>-{formatPrice(checkout.totalDiscounts.amount)}</span>
1689
1770
  </div>
1690
1771
  )}
@@ -1692,7 +1773,7 @@ export default function CheckoutPage() {
1692
1773
  {/* Tax */}
1693
1774
  {checkout?.totalTax && parseFloat(checkout.totalTax.amount) > 0 && (
1694
1775
  <div className="flex justify-between text-sm">
1695
- <span className="text-muted-foreground">Podatek VAT</span>
1776
+ <span className="text-muted-foreground">{tCart("tax")}</span>
1696
1777
  <span>{formatPrice(checkout.totalTax.amount)}</span>
1697
1778
  </div>
1698
1779
  )}
@@ -1700,14 +1781,14 @@ export default function CheckoutPage() {
1700
1781
  {/* Gift Card Deduction */}
1701
1782
  {checkout?.totalGiftCardAmount && parseFloat(checkout.totalGiftCardAmount.amount) > 0 && (
1702
1783
  <div className="flex justify-between text-sm text-purple-600">
1703
- <span>Karta podarunkowa</span>
1784
+ <span>{tCart("giftCard")}</span>
1704
1785
  <span>-{formatPrice(checkout.totalGiftCardAmount.amount)}</span>
1705
1786
  </div>
1706
1787
  )}
1707
1788
 
1708
1789
  {/* Total */}
1709
1790
  <div className="flex justify-between border-t pt-2 text-lg font-semibold">
1710
- <span>Razem</span>
1791
+ <span>{tCart("total")}</span>
1711
1792
  <span>
1712
1793
  {formatPrice(
1713
1794
  checkout?.totalPrice?.amount ||
@@ -1724,7 +1805,7 @@ export default function CheckoutPage() {
1724
1805
  checkout?.totalPrice &&
1725
1806
  parseFloat(checkout.paymentDue.amount) !== parseFloat(checkout.totalPrice.amount) && (
1726
1807
  <div className="flex justify-between border-t pt-2 text-lg font-bold text-primary">
1727
- <span>Do zapłaty</span>
1808
+ <span>{tCart("paymentDue")}</span>
1728
1809
  <span>{formatPrice(checkout.paymentDue.amount)}</span>
1729
1810
  </div>
1730
1811
  )}
@@ -1735,11 +1816,11 @@ export default function CheckoutPage() {
1735
1816
  <div className="flex items-center justify-center gap-4 text-xs text-muted-foreground">
1736
1817
  <div className="flex items-center gap-1">
1737
1818
  <Check className="h-3 w-3" />
1738
- Bezpieczna płatność
1819
+ {tc("securePayment")}
1739
1820
  </div>
1740
1821
  <div className="flex items-center gap-1">
1741
1822
  <Check className="h-3 w-3" />
1742
- Szyfrowane dane
1823
+ {tc("encryptedData")}
1743
1824
  </div>
1744
1825
  </div>
1745
1826
  </div>