@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,87 +1,3 @@
1
- /**
2
- * API Route: Clear Authentication Token
3
- *
4
- * Clears the customer access token cookie by setting it to expire immediately.
5
- * This is used during logout to ensure the user is fully signed out.
6
- *
7
- * Security Features:
8
- * 1. Origin validation - Only accepts requests from same origin (CSRF protection)
9
- * 2. Immediate expiration - Sets maxAge to 0 to delete cookie
10
- * 3. Same cookie attributes - Ensures proper deletion across all contexts
11
- *
12
- * @see lib/auth/cookies.ts - Cookie configuration
13
- * @see hooks/use-auth.ts - Client-side usage
14
- *
15
- * @example
16
- * ```tsx
17
- * // Client-side usage (via clearAuthToken helper)
18
- * await clearAuthToken();
19
- * ```
20
- */
1
+ import { createClearTokenHandler } from '@doswiftly/storefront-sdk';
21
2
 
22
- import { NextRequest, NextResponse } from "next/server";
23
- import { AUTH_COOKIE_CONFIG } from "@/lib/auth/cookies";
24
-
25
- /**
26
- * POST /api/auth/clear-token
27
- *
28
- * Clears the authentication token cookie.
29
- *
30
- * @param request - Next.js request object
31
- * @returns Response confirming token was cleared
32
- */
33
- export async function POST(request: NextRequest) {
34
- try {
35
- // 1. CSRF Protection: Validate origin
36
- const origin = request.headers.get("origin");
37
- const host = request.headers.get("host");
38
-
39
- // Only allow requests from same origin
40
- if (origin && !origin.includes(host || "")) {
41
- return NextResponse.json(
42
- { error: "Invalid origin" },
43
- { status: 403 }
44
- );
45
- }
46
-
47
- // 2. Create response
48
- const response = NextResponse.json(
49
- { success: true, message: "Token cleared successfully" },
50
- { status: 200 }
51
- );
52
-
53
- // 3. Clear cookie by setting maxAge to 0
54
- response.cookies.set({
55
- name: AUTH_COOKIE_CONFIG.name,
56
- value: "",
57
- maxAge: 0, // Expire immediately
58
- path: AUTH_COOKIE_CONFIG.path,
59
- sameSite: AUTH_COOKIE_CONFIG.sameSite,
60
- secure: AUTH_COOKIE_CONFIG.secure,
61
- httpOnly: AUTH_COOKIE_CONFIG.httpOnly,
62
- });
63
-
64
- return response;
65
- } catch (error) {
66
- console.error("Error clearing auth token:", error);
67
- return NextResponse.json(
68
- { error: "Internal server error" },
69
- { status: 500 }
70
- );
71
- }
72
- }
73
-
74
- /**
75
- * OPTIONS /api/auth/clear-token
76
- *
77
- * Handle preflight requests for CORS.
78
- */
79
- export async function OPTIONS() {
80
- return new NextResponse(null, {
81
- status: 204,
82
- headers: {
83
- "Access-Control-Allow-Methods": "POST, OPTIONS",
84
- "Access-Control-Allow-Headers": "Content-Type",
85
- },
86
- });
87
- }
3
+ export const POST = createClearTokenHandler();
@@ -1,125 +1,3 @@
1
- /**
2
- * API Route: Set Authentication Token
3
- *
4
- * Sets the customer access token in an httpOnly cookie.
5
- * This provides security by preventing client-side JavaScript from accessing the token.
6
- *
7
- * Security Features:
8
- * 1. httpOnly cookie - Cannot be accessed via JavaScript (XSS protection)
9
- * 2. Secure flag - Only sent over HTTPS in production
10
- * 3. SameSite=Lax - CSRF protection
11
- * 4. Origin validation - Only accepts requests from same origin
12
- * 5. Content-Type validation - Only accepts JSON
13
- *
14
- * @see lib/auth/cookies.ts - Cookie configuration
15
- * @see hooks/use-auth.ts - Client-side usage
16
- *
17
- * @example
18
- * ```tsx
19
- * // Client-side usage (via setAuthToken helper)
20
- * await setAuthToken(customerAccessToken.accessToken);
21
- * ```
22
- */
1
+ import { createSetTokenHandler } from '@doswiftly/storefront-sdk';
23
2
 
24
- import { NextRequest, NextResponse } from "next/server";
25
- import { AUTH_COOKIE_CONFIG } from "@/lib/auth/cookies";
26
-
27
- /**
28
- * Request body schema
29
- */
30
- interface SetTokenRequest {
31
- token: string;
32
- }
33
-
34
- /**
35
- * POST /api/auth/set-token
36
- *
37
- * Sets the authentication token in an httpOnly cookie.
38
- *
39
- * @param request - Next.js request object
40
- * @returns Response with Set-Cookie header
41
- */
42
- export async function POST(request: NextRequest) {
43
- try {
44
- // 1. CSRF Protection: Validate origin
45
- const origin = request.headers.get("origin");
46
- const host = request.headers.get("host");
47
-
48
- // Only allow requests from same origin
49
- if (origin && !origin.includes(host || "")) {
50
- return NextResponse.json(
51
- { error: "Invalid origin" },
52
- { status: 403 }
53
- );
54
- }
55
-
56
- // 2. Validate Content-Type
57
- const contentType = request.headers.get("content-type");
58
- if (!contentType?.includes("application/json")) {
59
- return NextResponse.json(
60
- { error: "Content-Type must be application/json" },
61
- { status: 400 }
62
- );
63
- }
64
-
65
- // 3. Parse and validate request body
66
- let body: SetTokenRequest;
67
- try {
68
- body = await request.json();
69
- } catch {
70
- return NextResponse.json(
71
- { error: "Invalid JSON body" },
72
- { status: 400 }
73
- );
74
- }
75
-
76
- const { token } = body;
77
-
78
- if (!token || typeof token !== "string" || token.trim() === "") {
79
- return NextResponse.json(
80
- { error: "Token is required and must be a non-empty string" },
81
- { status: 400 }
82
- );
83
- }
84
-
85
- // 4. Create response with Set-Cookie header
86
- const response = NextResponse.json(
87
- { success: true, message: "Token set successfully" },
88
- { status: 200 }
89
- );
90
-
91
- // 5. Set httpOnly cookie
92
- response.cookies.set({
93
- name: AUTH_COOKIE_CONFIG.name,
94
- value: token,
95
- maxAge: AUTH_COOKIE_CONFIG.maxAge,
96
- path: AUTH_COOKIE_CONFIG.path,
97
- sameSite: AUTH_COOKIE_CONFIG.sameSite,
98
- secure: AUTH_COOKIE_CONFIG.secure,
99
- httpOnly: AUTH_COOKIE_CONFIG.httpOnly,
100
- });
101
-
102
- return response;
103
- } catch (error) {
104
- console.error("Error setting auth token:", error);
105
- return NextResponse.json(
106
- { error: "Internal server error" },
107
- { status: 500 }
108
- );
109
- }
110
- }
111
-
112
- /**
113
- * OPTIONS /api/auth/set-token
114
- *
115
- * Handle preflight requests for CORS.
116
- */
117
- export async function OPTIONS() {
118
- return new NextResponse(null, {
119
- status: 204,
120
- headers: {
121
- "Access-Control-Allow-Methods": "POST, OPTIONS",
122
- "Access-Control-Allow-Headers": "Content-Type",
123
- },
124
- });
125
- }
3
+ export const POST = createSetTokenHandler();
@@ -0,0 +1,117 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * GlobalError — catches errors from root layout (where error.tsx cannot reach).
5
+ *
6
+ * This replaces the entire <html> document, so it must include its own
7
+ * <html> and <body> tags. No providers, no Header/Footer — just a
8
+ * self-contained error page.
9
+ *
10
+ * Next.js docs: https://nextjs.org/docs/app/api-reference/file-conventions/error#global-errorjs
11
+ */
12
+
13
+ import { useEffect } from 'react';
14
+
15
+ interface GlobalErrorProps {
16
+ error: Error & { digest?: string };
17
+ reset: () => void;
18
+ }
19
+
20
+ export default function GlobalError({ error, reset }: GlobalErrorProps) {
21
+ useEffect(() => {
22
+ console.error('[GlobalError]', error);
23
+ }, [error]);
24
+
25
+ return (
26
+ <html lang="pl">
27
+ <body
28
+ style={{
29
+ margin: 0,
30
+ fontFamily:
31
+ '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
32
+ backgroundColor: '#fafafa',
33
+ color: '#1e293b',
34
+ display: 'flex',
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ minHeight: '100vh',
38
+ }}
39
+ >
40
+ <div
41
+ style={{
42
+ maxWidth: '28rem',
43
+ width: '100%',
44
+ padding: '2rem',
45
+ textAlign: 'center',
46
+ }}
47
+ >
48
+ <div
49
+ style={{
50
+ width: '4rem',
51
+ height: '4rem',
52
+ margin: '0 auto 1.5rem',
53
+ borderRadius: '50%',
54
+ backgroundColor: '#fef2f2',
55
+ display: 'flex',
56
+ alignItems: 'center',
57
+ justifyContent: 'center',
58
+ fontSize: '1.5rem',
59
+ }}
60
+ >
61
+ !
62
+ </div>
63
+
64
+ <h1 style={{ fontSize: '1.5rem', fontWeight: 600, margin: '0 0 0.5rem' }}>
65
+ Serwer tymczasowo niedostępny
66
+ </h1>
67
+
68
+ <p style={{ color: '#64748b', margin: '0 0 2rem', lineHeight: 1.6 }}>
69
+ Nie udało się załadować strony. Serwer może być tymczasowo niedostępny.
70
+ Spróbuj odświeżyć stronę za chwilę.
71
+ </p>
72
+
73
+ {process.env.NODE_ENV === 'development' && (
74
+ <div
75
+ style={{
76
+ backgroundColor: '#f1f5f9',
77
+ borderRadius: '0.5rem',
78
+ padding: '0.75rem 1rem',
79
+ marginBottom: '1.5rem',
80
+ textAlign: 'left',
81
+ fontSize: '0.75rem',
82
+ wordBreak: 'break-word',
83
+ }}
84
+ >
85
+ <strong style={{ color: '#ef4444' }}>{error.message}</strong>
86
+ {error.digest && (
87
+ <p style={{ color: '#64748b', margin: '0.25rem 0 0' }}>
88
+ Digest: {error.digest}
89
+ </p>
90
+ )}
91
+ </div>
92
+ )}
93
+
94
+ <button
95
+ onClick={reset}
96
+ style={{
97
+ display: 'inline-flex',
98
+ alignItems: 'center',
99
+ justifyContent: 'center',
100
+ width: '100%',
101
+ padding: '0.625rem 1.25rem',
102
+ fontSize: '0.875rem',
103
+ fontWeight: 500,
104
+ color: '#fff',
105
+ backgroundColor: '#3b82f6',
106
+ border: 'none',
107
+ borderRadius: '0.5rem',
108
+ cursor: 'pointer',
109
+ }}
110
+ >
111
+ Spróbuj ponownie
112
+ </button>
113
+ </div>
114
+ </body>
115
+ </html>
116
+ );
117
+ }
@@ -122,4 +122,12 @@
122
122
  .text-balance {
123
123
  text-wrap: balance;
124
124
  }
125
+
126
+ .scrollbar-hide {
127
+ -ms-overflow-style: none;
128
+ scrollbar-width: none;
129
+ }
130
+ .scrollbar-hide::-webkit-scrollbar {
131
+ display: none;
132
+ }
125
133
  }
@@ -1,57 +1,30 @@
1
1
  import type { Metadata } from "next";
2
2
  import { Inter } from "next/font/google";
3
3
  import "./globals.css";
4
- import { Header } from "@/components/layout/header";
5
- import { Footer } from "@/components/layout/footer";
6
- import { QueryProvider } from "@/components/providers/query-provider";
7
- import { CurrencyProvider } from "@/components/providers/currency-provider";
8
- import { ThemeProvider } from "@/components/providers/theme-provider";
9
- import { Toaster } from "sonner";
10
- import { fetchShop } from "@/lib/graphql/server";
11
- import { themeConfig } from "@/lib/theme/theme-config";
4
+ import { defaultLocale } from "@/i18n/routing";
12
5
 
13
6
  const inter = Inter({ subsets: ["latin"] });
14
7
 
15
8
  const siteName = process.env.NEXT_PUBLIC_SITE_NAME || "My Store";
9
+ const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3001";
16
10
 
17
11
  export const metadata: Metadata = {
12
+ metadataBase: new URL(siteUrl),
18
13
  title: `${siteName} - E-commerce Store`,
19
14
  description: "Welcome to our online store powered by DoSwiftly Commerce",
20
15
  };
21
16
 
22
- // Enable ISR with 60 second revalidation for shop data (currencies)
23
- export const revalidate = 60;
24
-
25
17
  export default async function RootLayout({
26
18
  children,
19
+ params,
27
20
  }: {
28
21
  children: React.ReactNode;
22
+ params: Promise<{ locale?: string }>;
29
23
  }) {
30
- // Fetch shop data (includes currencies) for CurrencyProvider
31
- const shopData = await fetchShop();
32
-
24
+ const { locale } = await params;
33
25
  return (
34
- <html lang="en" suppressHydrationWarning>
35
- <body className={inter.className}>
36
- <ThemeProvider
37
- attribute={themeConfig.attribute}
38
- defaultTheme={themeConfig.defaultTheme}
39
- enableSystem={themeConfig.enableSystem}
40
- disableTransitionOnChange={themeConfig.disableTransitionOnChange}
41
- storageKey={themeConfig.storageKey}
42
- >
43
- <QueryProvider>
44
- <CurrencyProvider shopData={shopData.shop}>
45
- <div className="flex min-h-screen flex-col">
46
- <Header />
47
- <main className="flex-1">{children}</main>
48
- <Footer />
49
- </div>
50
- <Toaster position="bottom-right" richColors />
51
- </CurrencyProvider>
52
- </QueryProvider>
53
- </ThemeProvider>
54
- </body>
26
+ <html lang={locale || defaultLocale} suppressHydrationWarning>
27
+ <body className={inter.className}>{children}</body>
55
28
  </html>
56
29
  );
57
30
  }
@@ -1,45 +1,62 @@
1
- import { CodegenConfig } from '@graphql-codegen/cli';
2
- import { loadEnvConfig } from '@next/env';
3
-
4
- // Load environment variables from .env.local
5
- loadEnvConfig(process.cwd());
6
-
7
- const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';
8
- const shopSlug = process.env.NEXT_PUBLIC_SHOP_SLUG || 'test-shop';
1
+ import type { CodegenConfig } from '@graphql-codegen/cli';
9
2
 
3
+ /**
4
+ * GraphQL Code Generator Configuration
5
+ *
6
+ * Uses `client-preset` with `documentMode: 'string'` (TypedDocumentString).
7
+ * This generates lightweight string-based documents instead of parsed AST objects,
8
+ * eliminating the need for the `graphql` package at runtime.
9
+ *
10
+ * Schema and operations come from @doswiftly/storefront-operations (SSOT).
11
+ * No running backend needed — schema is synced as a file.
12
+ *
13
+ * Architecture decision: https://github.com/dotansimha/graphql-typed-document-node
14
+ * Inspired by: Saleor Storefront (client-preset + TypedDocumentString)
15
+ *
16
+ * To update schema after backend changes:
17
+ * cd packages/@doswiftly/storefront-operations && pnpm run sync
18
+ */
10
19
  const config: CodegenConfig = {
11
- // Schema from live API (introspection)
12
- schema: [
13
- {
14
- [`${apiUrl}/storefront/graphql`]: {
15
- headers: {
16
- 'X-Shop-Slug': shopSlug,
17
- },
18
- },
19
- },
20
- ],
20
+ // Schema from storefront-operations package (no introspection needed!)
21
+ schema: 'node_modules/@doswiftly/storefront-operations/schema.graphql',
21
22
 
22
- // Operations: Backend SSOT + Developer Custom Queries
23
+ // Operations: Backend SSOT + Developer Custom Queries + Colocated Component Fragments
23
24
  documents: [
24
- 'node_modules/@doswiftly/storefront-operations/**/*.graphql', // Backend operations
25
- 'graphql/**/*.{ts,tsx}', // Custom queries in code
25
+ 'node_modules/@doswiftly/storefront-operations/**/*.graphql',
26
+ 'graphql/**/*.graphql',
27
+ 'components/**/*.fragment.graphql',
26
28
  ],
27
29
 
28
- // Output configuration
29
30
  generates: {
30
- 'generated/graphql.ts': {
31
- plugins: [
32
- 'typescript', // Generate TS types
33
- 'typescript-operations', // Generate operation types
34
- 'typed-document-node', // Generate TypedDocumentNode
35
- ],
31
+ 'generated/': {
32
+ preset: 'client',
36
33
  config: {
37
- skipTypename: false,
38
- enumsAsTypes: true,
34
+ // TypedDocumentString: lightweight string wrapper instead of parsed AST
35
+ // Eliminates `graphql` package from runtime bundle (~40kb savings)
36
+ documentMode: 'string',
37
+
38
+ // Scalar mappings
39
39
  scalars: {
40
40
  DateTime: 'string',
41
- JSON: 'Record<string, any>',
41
+ Decimal: 'string',
42
+ JSON: 'Record<string, unknown>',
42
43
  },
44
+
45
+ // Keep __typename for connection normalization and cache keys
46
+ skipTypename: false,
47
+
48
+ // Readable enum types (union of string literals)
49
+ enumsAsTypes: true,
50
+
51
+ // Deduplicate fragments shared across queries
52
+ dedupeFragments: true,
53
+
54
+ // Use `import type` for cleaner output
55
+ useTypeImports: true,
56
+ },
57
+ presetConfig: {
58
+ // Disable fragment masking — simpler DX, developer sees all fields
59
+ fragmentMasking: false,
43
60
  },
44
61
  },
45
62
  },
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useState } from "react";
4
+ import { useTranslations } from "next-intl";
4
5
  import { Button } from "@/components/ui/button";
5
6
  import { Input } from "@/components/ui/input";
6
7
  import { Card } from "@/components/ui/card";
@@ -38,6 +39,10 @@ export function AddressForm({
38
39
  isLoading = false,
39
40
  className,
40
41
  }: AddressFormProps) {
42
+ const t = useTranslations("checkout");
43
+ const tc = useTranslations("common");
44
+ const tAccount = useTranslations("account");
45
+
41
46
  const [formData, setFormData] = useState<AddressFormData>(
42
47
  address || {
43
48
  firstName: "",
@@ -68,25 +73,25 @@ export function AddressForm({
68
73
  const newErrors: Partial<Record<keyof AddressFormData, string>> = {};
69
74
 
70
75
  if (!formData.firstName.trim()) {
71
- newErrors.firstName = "First name is required";
76
+ newErrors.firstName = t("validation.firstNameRequired");
72
77
  }
73
78
  if (!formData.lastName.trim()) {
74
- newErrors.lastName = "Last name is required";
79
+ newErrors.lastName = t("validation.lastNameRequired");
75
80
  }
76
81
  if (!formData.address1.trim()) {
77
- newErrors.address1 = "Address is required";
82
+ newErrors.address1 = t("validation.addressRequired");
78
83
  }
79
84
  if (!formData.city.trim()) {
80
- newErrors.city = "City is required";
85
+ newErrors.city = t("validation.cityRequired");
81
86
  }
82
87
  if (!formData.province.trim()) {
83
- newErrors.province = "Province/State is required";
88
+ newErrors.province = t("validation.provinceRequired");
84
89
  }
85
90
  if (!formData.zip.trim()) {
86
- newErrors.zip = "Postal code is required";
91
+ newErrors.zip = t("validation.zipRequired");
87
92
  }
88
93
  if (!formData.country.trim()) {
89
- newErrors.country = "Country is required";
94
+ newErrors.country = t("validation.countryRequired");
90
95
  }
91
96
 
92
97
  setErrors(newErrors);
@@ -113,7 +118,7 @@ export function AddressForm({
113
118
  htmlFor="firstName"
114
119
  className="block text-sm font-medium text-foreground mb-1"
115
120
  >
116
- First Name *
121
+ {t("address.firstName")} *
117
122
  </label>
118
123
  <Input
119
124
  id="firstName"
@@ -134,7 +139,7 @@ export function AddressForm({
134
139
  htmlFor="lastName"
135
140
  className="block text-sm font-medium text-foreground mb-1"
136
141
  >
137
- Last Name *
142
+ {t("address.lastName")} *
138
143
  </label>
139
144
  <Input
140
145
  id="lastName"
@@ -156,7 +161,7 @@ export function AddressForm({
156
161
  htmlFor="company"
157
162
  className="block text-sm font-medium text-foreground mb-1"
158
163
  >
159
- Company (optional)
164
+ {`${t("address.company")} (${tc("optional")})`}
160
165
  </label>
161
166
  <Input
162
167
  id="company"
@@ -173,7 +178,7 @@ export function AddressForm({
173
178
  htmlFor="address1"
174
179
  className="block text-sm font-medium text-foreground mb-1"
175
180
  >
176
- Address *
181
+ {t("address.address1")} *
177
182
  </label>
178
183
  <Input
179
184
  id="address1"
@@ -194,7 +199,7 @@ export function AddressForm({
194
199
  htmlFor="address2"
195
200
  className="block text-sm font-medium text-foreground mb-1"
196
201
  >
197
- Apartment, suite, etc. (optional)
202
+ {`${t("address.address2")} (${tc("optional")})`}
198
203
  </label>
199
204
  <Input
200
205
  id="address2"
@@ -212,7 +217,7 @@ export function AddressForm({
212
217
  htmlFor="city"
213
218
  className="block text-sm font-medium text-foreground mb-1"
214
219
  >
215
- City *
220
+ {t("address.city")} *
216
221
  </label>
217
222
  <Input
218
223
  id="city"
@@ -233,7 +238,7 @@ export function AddressForm({
233
238
  htmlFor="province"
234
239
  className="block text-sm font-medium text-foreground mb-1"
235
240
  >
236
- Province/State *
241
+ {t("address.province")} *
237
242
  </label>
238
243
  <Input
239
244
  id="province"
@@ -254,7 +259,7 @@ export function AddressForm({
254
259
  htmlFor="zip"
255
260
  className="block text-sm font-medium text-foreground mb-1"
256
261
  >
257
- Postal Code *
262
+ {t("address.zip")} *
258
263
  </label>
259
264
  <Input
260
265
  id="zip"
@@ -276,7 +281,7 @@ export function AddressForm({
276
281
  htmlFor="country"
277
282
  className="block text-sm font-medium text-foreground mb-1"
278
283
  >
279
- Country *
284
+ {t("address.country")} *
280
285
  </label>
281
286
  <Input
282
287
  id="country"
@@ -297,7 +302,7 @@ export function AddressForm({
297
302
  htmlFor="phone"
298
303
  className="block text-sm font-medium text-foreground mb-1"
299
304
  >
300
- Phone (optional)
305
+ {`${t("address.phone")} (${tc("optional")})`}
301
306
  </label>
302
307
  <Input
303
308
  id="phone"
@@ -322,14 +327,14 @@ export function AddressForm({
322
327
  htmlFor="isDefault"
323
328
  className="text-sm font-medium text-foreground"
324
329
  >
325
- Set as default address
330
+ {tAccount("setAsDefault")}
326
331
  </label>
327
332
  </div>
328
333
 
329
334
  {/* Form Actions */}
330
335
  <div className="flex gap-3 pt-4">
331
336
  <Button type="submit" disabled={isLoading} className="flex-1">
332
- {isLoading ? "Saving..." : address ? "Update Address" : "Add Address"}
337
+ {isLoading ? tc("saving") : address ? tAccount("editAddress") : tAccount("addAddress")}
333
338
  </Button>
334
339
  {onCancel && (
335
340
  <Button
@@ -338,7 +343,7 @@ export function AddressForm({
338
343
  onClick={onCancel}
339
344
  disabled={isLoading}
340
345
  >
341
- Cancel
346
+ {tc("cancel")}
342
347
  </Button>
343
348
  )}
344
349
  </div>