@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,7 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import { useParams } from "next/navigation";
4
- import Link from "next/link";
4
+ import { useTranslations } from "next-intl";
5
+ import { Link } from "@/i18n/navigation";
5
6
  import { ChevronLeft } from "lucide-react";
6
7
  import { Button } from "@/components/ui/button";
7
8
  import { Breadcrumbs } from "@/components/layout/breadcrumbs";
@@ -19,6 +20,7 @@ import {
19
20
  export default function OrderTrackingPage() {
20
21
  const params = useParams();
21
22
  const orderId = params.id as string;
23
+ const t = useTranslations("tracking");
22
24
 
23
25
  // TODO: Fetch tracking data from backend using GraphQL
24
26
  const trackingData = {
@@ -40,26 +42,26 @@ export default function OrderTrackingPage() {
40
42
 
41
43
  const milestones = [
42
44
  {
43
- label: "Order Placed",
45
+ label: t("orderPlaced"),
44
46
  status: "completed" as const,
45
47
  date: "2024-01-15",
46
48
  },
47
49
  {
48
- label: "Processing",
50
+ label: t("processing"),
49
51
  status: "completed" as const,
50
52
  date: "2024-01-16",
51
53
  },
52
54
  {
53
- label: "Shipped",
55
+ label: t("shipped"),
54
56
  status: "completed" as const,
55
57
  date: "2024-01-17",
56
58
  },
57
59
  {
58
- label: "In Transit",
60
+ label: t("inTransit"),
59
61
  status: "current" as const,
60
62
  },
61
63
  {
62
- label: "Delivered",
64
+ label: t("delivered"),
63
65
  status: "pending" as const,
64
66
  },
65
67
  ];
@@ -67,40 +69,40 @@ export default function OrderTrackingPage() {
67
69
  const events: TrackingEvent[] = [
68
70
  {
69
71
  id: "1",
70
- status: "In Transit",
71
- description: "Package is on the way to the destination",
72
+ status: t("inTransit"),
73
+ description: t("onTheWay"),
72
74
  location: "Warsaw Distribution Center",
73
75
  timestamp: "2024-01-18T14:30:00Z",
74
76
  isCompleted: true,
75
77
  },
76
78
  {
77
79
  id: "2",
78
- status: "In Transit",
79
- description: "Package arrived at sorting facility",
80
+ status: t("inTransit"),
81
+ description: t("arrivedAtFacility"),
80
82
  location: "Krakow Sorting Facility",
81
83
  timestamp: "2024-01-18T08:15:00Z",
82
84
  isCompleted: true,
83
85
  },
84
86
  {
85
87
  id: "3",
86
- status: "Shipped",
87
- description: "Package has been picked up by carrier",
88
+ status: t("shipped"),
89
+ description: t("pickedUpByCarrier"),
88
90
  location: "Origin Facility",
89
91
  timestamp: "2024-01-17T16:45:00Z",
90
92
  isCompleted: true,
91
93
  },
92
94
  {
93
95
  id: "4",
94
- status: "Processing",
95
- description: "Package is being prepared for shipment",
96
- location: "Warehouse",
96
+ status: t("processing"),
97
+ description: t("preparingShipment"),
98
+ location: t("warehouse"),
97
99
  timestamp: "2024-01-16T10:00:00Z",
98
100
  isCompleted: true,
99
101
  },
100
102
  {
101
103
  id: "5",
102
- status: "Order Placed",
103
- description: "Order has been confirmed",
104
+ status: t("orderPlaced"),
105
+ description: t("orderConfirmed"),
104
106
  timestamp: "2024-01-15T12:30:00Z",
105
107
  isCompleted: true,
106
108
  },
@@ -114,17 +116,17 @@ export default function OrderTrackingPage() {
114
116
  <Button variant="ghost" asChild>
115
117
  <Link href={`/account/orders/${orderId}`}>
116
118
  <ChevronLeft className="mr-2 h-4 w-4" />
117
- Back to Order Details
119
+ {t("backToOrderDetails")}
118
120
  </Link>
119
121
  </Button>
120
122
  </div>
121
123
 
122
124
  <div className="mb-8">
123
125
  <h1 className="text-3xl font-bold text-foreground">
124
- Track Order {trackingData.orderNumber}
126
+ {t("trackOrder", { orderNumber: trackingData.orderNumber })}
125
127
  </h1>
126
128
  <p className="mt-2 text-muted-foreground">
127
- Follow your package's journey
129
+ {t("followJourney")}
128
130
  </p>
129
131
  </div>
130
132
 
@@ -154,7 +156,7 @@ export default function OrderTrackingPage() {
154
156
  {/* Tracking Timeline */}
155
157
  <div>
156
158
  <h2 className="text-xl font-semibold text-foreground mb-4">
157
- Tracking History
159
+ {t("trackingHistory")}
158
160
  </h2>
159
161
  <TrackingTimeline events={events} />
160
162
  </div>
@@ -173,16 +175,16 @@ export default function OrderTrackingPage() {
173
175
  {/* Carrier Information */}
174
176
  <div className="rounded-lg border border-border bg-background p-6">
175
177
  <h3 className="text-lg font-semibold text-foreground mb-4">
176
- Carrier Information
178
+ {t("carrierInfo")}
177
179
  </h3>
178
180
  <div className="space-y-3 text-sm">
179
181
  <div>
180
- <span className="font-medium text-foreground">Carrier:</span>
182
+ <span className="font-medium text-foreground">{t("carrier")}</span>
181
183
  <p className="text-muted-foreground">{trackingData.carrier}</p>
182
184
  </div>
183
185
  <div>
184
186
  <span className="font-medium text-foreground">
185
- Tracking Number:
187
+ {t("trackingNumberLabel")}
186
188
  </span>
187
189
  <p className="font-mono text-muted-foreground">
188
190
  {trackingData.trackingNumber}
@@ -194,7 +196,7 @@ export default function OrderTrackingPage() {
194
196
  target="_blank"
195
197
  rel="noopener noreferrer"
196
198
  >
197
- Track on Carrier Website
199
+ {t("trackOnCarrierWebsite")}
198
200
  </a>
199
201
  </Button>
200
202
  </div>
@@ -0,0 +1,101 @@
1
+ "use client";
2
+
3
+ import { Link } from "@/i18n/navigation";
4
+ import { useTranslations } from "next-intl";
5
+ import { useAuthStore, useAuthHydrated } from "@doswiftly/storefront-sdk/react";
6
+ import { useCustomer } from "@/lib/graphql/hooks";
7
+ import { useHydrated } from "@doswiftly/storefront-sdk/react";
8
+ import { Breadcrumbs } from "@/components/layout/breadcrumbs";
9
+ import { OrderHistory } from "@/components/account/order-history";
10
+ import { Skeleton } from "@/components/ui/skeleton";
11
+
12
+ export default function OrdersPage() {
13
+ const t = useTranslations("account");
14
+ const hydrated = useHydrated();
15
+ const authHydrated = useAuthHydrated();
16
+ const accessToken = useAuthStore((s) => s.accessToken);
17
+
18
+ const { data, isPending, error } = useCustomer();
19
+
20
+ // Wait for DOM + auth persist hydration before checking accessToken
21
+ if (!hydrated || !authHydrated) {
22
+ return (
23
+ <div className="container mx-auto px-4 py-8">
24
+ <Breadcrumbs className="mb-6" />
25
+ <div className="mb-8">
26
+ <Skeleton className="h-10 w-64 mb-2" />
27
+ <Skeleton className="h-6 w-96" />
28
+ </div>
29
+ <div className="space-y-4">
30
+ {[...Array(3)].map((_, i) => (
31
+ <Skeleton key={i} className="h-32 w-full" />
32
+ ))}
33
+ </div>
34
+ </div>
35
+ );
36
+ }
37
+
38
+ // Data loading (customer query fetching after accessToken is available)
39
+ if (isPending) {
40
+ return (
41
+ <div className="container mx-auto px-4 py-8">
42
+ <Breadcrumbs className="mb-6" />
43
+ <div className="mb-8">
44
+ <Skeleton className="h-10 w-64 mb-2" />
45
+ <Skeleton className="h-6 w-96" />
46
+ </div>
47
+ <div className="space-y-4">
48
+ {[...Array(3)].map((_, i) => (
49
+ <Skeleton key={i} className="h-32 w-full" />
50
+ ))}
51
+ </div>
52
+ </div>
53
+ );
54
+ }
55
+
56
+ if (!accessToken) {
57
+ return (
58
+ <div className="container mx-auto px-4 py-8">
59
+ <Breadcrumbs className="mb-6" />
60
+ <div className="rounded-lg border border-destructive bg-destructive/10 p-8 text-center text-sm text-destructive">
61
+ {t.rich("signInToView", {
62
+ link: (chunks) => (
63
+ <Link href="/auth/login?redirect=/account/orders" className="font-medium underline">
64
+ {chunks}
65
+ </Link>
66
+ ),
67
+ })}
68
+ </div>
69
+ </div>
70
+ );
71
+ }
72
+
73
+ if (error) {
74
+ return (
75
+ <div className="container mx-auto px-4 py-8">
76
+ <Breadcrumbs className="mb-6" />
77
+ <div className="rounded-lg border border-red-200 bg-red-50 p-8 text-center">
78
+ <p className="text-red-800">{t("failedLoadOrders")}</p>
79
+ </div>
80
+ </div>
81
+ );
82
+ }
83
+
84
+ const customer = data?.customer;
85
+ const orders = customer?.orders?.edges.map((edge) => edge.node) ?? [];
86
+
87
+ return (
88
+ <div className="container mx-auto px-4 py-8">
89
+ <Breadcrumbs className="mb-6" />
90
+
91
+ <div className="mb-8">
92
+ <h1 className="text-3xl font-bold text-foreground">{t("orders")}</h1>
93
+ <p className="mt-2 text-muted-foreground">
94
+ {t("viewTrackOrders")}
95
+ </p>
96
+ </div>
97
+
98
+ <OrderHistory orders={orders} />
99
+ </div>
100
+ );
101
+ }
@@ -1,18 +1,20 @@
1
1
  "use client";
2
2
 
3
- import Link from "next/link";
4
- import { useRouter } from "next/navigation";
3
+ import { Link, useRouter } from "@/i18n/navigation";
5
4
  import { User, Package, MapPin, Settings } from "lucide-react";
6
5
  import { Button } from "@/components/ui/button";
7
6
  import { Card } from "@/components/ui/card";
7
+ import { useAuth } from "@/hooks/use-auth";
8
8
 
9
9
  export default function AccountPage() {
10
10
  const router = useRouter();
11
+ const { logout, isLoggingOut } = useAuth();
11
12
 
12
13
  const handleLogout = async () => {
13
- // Clear token via API route
14
- await fetch("/api/auth/clear-token", { method: "POST" });
15
- router.push("/");
14
+ const result = await logout();
15
+ if (result.success) {
16
+ router.push("/");
17
+ }
16
18
  };
17
19
 
18
20
  return (
@@ -97,8 +99,8 @@ export default function AccountPage() {
97
99
 
98
100
  {/* Logout Button */}
99
101
  <div className="mt-8">
100
- <Button variant="destructive" onClick={handleLogout}>
101
- Sign Out
102
+ <Button variant="destructive" onClick={handleLogout} disabled={isLoggingOut}>
103
+ {isLoggingOut ? "Signing out..." : "Sign Out"}
102
104
  </Button>
103
105
  </div>
104
106
  </div>
@@ -0,0 +1,208 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect } from "react";
4
+ import { Link } from "@/i18n/navigation";
5
+ import { useAuthStore, useAuthHydrated } from "@doswiftly/storefront-sdk/react";
6
+ import { useCustomerProfile, useCustomerUpdate } from "@/lib/graphql/hooks";
7
+ import { useHydrated } from "@doswiftly/storefront-sdk/react";
8
+ import type { CustomerInfoFields } from "@/lib/graphql/fragments";
9
+ import { Breadcrumbs } from "@/components/layout/breadcrumbs";
10
+ import { Button } from "@/components/ui/button";
11
+ import { Input } from "@/components/ui/input";
12
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
13
+ import { Skeleton } from "@/components/ui/skeleton";
14
+
15
+ export default function SettingsPage() {
16
+ const hydrated = useHydrated();
17
+ const authHydrated = useAuthHydrated();
18
+ const accessToken = useAuthStore((s) => s.accessToken);
19
+ const updateAuthStore = useAuthStore((s) => s.updateCustomer);
20
+
21
+ const [firstName, setFirstName] = useState("");
22
+ const [lastName, setLastName] = useState("");
23
+ const [phone, setPhone] = useState("");
24
+
25
+ const { data: customerData, isPending } = useCustomerProfile();
26
+ const customer: CustomerInfoFields | undefined = customerData?.customer ?? undefined;
27
+
28
+ // Populate form when customer data loads
29
+ useEffect(() => {
30
+ if (customer) {
31
+ setFirstName(customer.firstName || "");
32
+ setLastName(customer.lastName || "");
33
+ setPhone(customer.phone || "");
34
+ }
35
+ }, [customer]);
36
+
37
+ const updateMutation = useCustomerUpdate({
38
+ onSuccess: (data) => {
39
+ const errors = data?.customerUpdate?.userErrors;
40
+ if (errors && errors.length > 0) {
41
+ alert(errors.map((e) => e.message).join(", "));
42
+ return;
43
+ }
44
+ const updated = data?.customerUpdate?.customer;
45
+ if (updated) {
46
+ updateAuthStore({
47
+ firstName: updated.firstName || undefined,
48
+ lastName: updated.lastName || undefined,
49
+ phone: updated.phone || undefined,
50
+ });
51
+ }
52
+ alert("Settings saved successfully!");
53
+ },
54
+ onError: (error: Error) => {
55
+ alert(`Failed to save settings: ${error.message}`);
56
+ },
57
+ });
58
+
59
+ const handleSave = (e: React.FormEvent) => {
60
+ e.preventDefault();
61
+ if (!accessToken) return;
62
+ updateMutation.mutate({
63
+ firstName: firstName || undefined,
64
+ lastName: lastName || undefined,
65
+ phone: phone || undefined,
66
+ });
67
+ };
68
+
69
+ // Wait for DOM hydration AND auth persist rehydration before checking accessToken
70
+ if (!hydrated || !authHydrated) {
71
+ return (
72
+ <div className="container mx-auto px-4 py-8">
73
+ <Breadcrumbs className="mb-6" />
74
+ <div className="mx-auto max-w-2xl">
75
+ <Skeleton className="mb-8 h-10 w-64" />
76
+ <Skeleton className="h-96 w-full" />
77
+ </div>
78
+ </div>
79
+ );
80
+ }
81
+
82
+ // Data loading (customer query enabled only when accessToken is available)
83
+ if (isPending) {
84
+ return (
85
+ <div className="container mx-auto px-4 py-8">
86
+ <Breadcrumbs className="mb-6" />
87
+ <div className="mx-auto max-w-2xl">
88
+ <Skeleton className="mb-8 h-10 w-64" />
89
+ <Skeleton className="h-96 w-full" />
90
+ </div>
91
+ </div>
92
+ );
93
+ }
94
+
95
+ if (!accessToken) {
96
+ return (
97
+ <div className="container mx-auto px-4 py-8">
98
+ <Breadcrumbs className="mb-6" />
99
+ <div className="mx-auto max-w-2xl">
100
+ <div className="rounded-lg border border-destructive bg-destructive/10 p-8 text-center text-sm text-destructive">
101
+ You need to{" "}
102
+ <Link href="/auth/login?redirect=/account/settings" className="font-medium underline">
103
+ sign in
104
+ </Link>{" "}
105
+ to manage your account settings.
106
+ </div>
107
+ </div>
108
+ </div>
109
+ );
110
+ }
111
+
112
+ const email = customer?.email || "";
113
+
114
+ return (
115
+ <div className="container mx-auto px-4 py-8">
116
+ <Breadcrumbs className="mb-6" />
117
+
118
+ <div className="mx-auto max-w-2xl">
119
+ <h1 className="mb-8 text-3xl font-bold text-foreground">Account Settings</h1>
120
+
121
+ <div className="space-y-6">
122
+ <Card>
123
+ <CardHeader>
124
+ <CardTitle>Personal Information</CardTitle>
125
+ </CardHeader>
126
+ <CardContent>
127
+ <form onSubmit={handleSave} className="space-y-4">
128
+ <div className="grid gap-4 sm:grid-cols-2">
129
+ <div className="space-y-2">
130
+ <label htmlFor="firstName" className="text-sm font-medium">
131
+ First Name
132
+ </label>
133
+ <Input
134
+ id="firstName"
135
+ value={firstName}
136
+ onChange={(e) => setFirstName(e.target.value)}
137
+ />
138
+ </div>
139
+ <div className="space-y-2">
140
+ <label htmlFor="lastName" className="text-sm font-medium">
141
+ Last Name
142
+ </label>
143
+ <Input
144
+ id="lastName"
145
+ value={lastName}
146
+ onChange={(e) => setLastName(e.target.value)}
147
+ />
148
+ </div>
149
+ </div>
150
+ <div className="space-y-2">
151
+ <label htmlFor="email" className="text-sm font-medium">
152
+ Email
153
+ </label>
154
+ <Input
155
+ id="email"
156
+ type="email"
157
+ value={email}
158
+ disabled
159
+ className="bg-muted"
160
+ />
161
+ <p className="text-xs text-muted-foreground">
162
+ Email cannot be changed. Contact support if you need to update it.
163
+ </p>
164
+ </div>
165
+ <div className="space-y-2">
166
+ <label htmlFor="phone" className="text-sm font-medium">
167
+ Phone
168
+ </label>
169
+ <Input
170
+ id="phone"
171
+ type="tel"
172
+ value={phone}
173
+ onChange={(e) => setPhone(e.target.value)}
174
+ />
175
+ </div>
176
+ <Button type="submit" disabled={updateMutation.isPending}>
177
+ {updateMutation.isPending ? "Saving..." : "Save Changes"}
178
+ </Button>
179
+ </form>
180
+ </CardContent>
181
+ </Card>
182
+
183
+ <Card>
184
+ <CardHeader>
185
+ <CardTitle>Change Password</CardTitle>
186
+ </CardHeader>
187
+ <CardContent>
188
+ <p className="mb-4 text-sm text-muted-foreground">
189
+ To change your password, we&apos;ll send a password reset link to your email.
190
+ </p>
191
+ <Button
192
+ variant="outline"
193
+ onClick={() => {
194
+ if (email) {
195
+ alert(`Password reset email sent to ${email}. Check your inbox.`);
196
+ }
197
+ }}
198
+ disabled={!email}
199
+ >
200
+ Send Password Reset Email
201
+ </Button>
202
+ </CardContent>
203
+ </Card>
204
+ </div>
205
+ </div>
206
+ </div>
207
+ );
208
+ }
@@ -1,30 +1,37 @@
1
1
  "use client";
2
2
 
3
3
  import { useState } from "react";
4
- import Link from "next/link";
4
+ import { useTranslations } from "next-intl";
5
+ import { Link } from "@/i18n/navigation";
5
6
  import { useMutation } from "@tanstack/react-query";
6
- import { getGraphQLClient } from "@/lib/graphql/client";
7
- import { CustomerPasswordRecoverDocument } from "@/generated/graphql";
7
+ import { useExecute } from "@/lib/graphql/client";
8
+ import {
9
+ CustomerPasswordRecoverDocument,
10
+ type CustomerPasswordRecoverMutation,
11
+ } from "@/generated/graphql";
8
12
  import { Button } from "@/components/ui/button";
9
13
  import { Input } from "@/components/ui/input";
10
14
  import { ArrowLeft } from "lucide-react";
11
15
 
12
16
  export default function ForgotPasswordPage() {
17
+ const t = useTranslations("auth");
18
+ const execute = useExecute();
13
19
  const [email, setEmail] = useState("");
14
20
  const [isSubmitted, setIsSubmitted] = useState(false);
15
21
  const [error, setError] = useState("");
16
22
 
17
- const client = getGraphQLClient();
18
-
19
23
  const recoverMutation = useMutation({
20
24
  mutationFn: async (email: string) => {
21
- return client.request(CustomerPasswordRecoverDocument, { email });
25
+ return execute<CustomerPasswordRecoverMutation>(
26
+ CustomerPasswordRecoverDocument.toString(),
27
+ { email },
28
+ );
22
29
  },
23
30
  onSuccess: () => {
24
31
  setIsSubmitted(true);
25
32
  },
26
33
  onError: () => {
27
- setError("An error occurred. Please try again.");
34
+ setError(t("unexpectedError"));
28
35
  },
29
36
  });
30
37
 
@@ -54,25 +61,25 @@ export default function ForgotPasswordPage() {
54
61
  />
55
62
  </svg>
56
63
  </div>
57
- <h1 className="text-3xl font-bold text-foreground">Check Your Email</h1>
64
+ <h1 className="text-3xl font-bold text-foreground">{t("checkYourEmail")}</h1>
58
65
  <p className="mt-2 text-muted-foreground">
59
- We've sent password reset instructions to {email}
66
+ {t("resetEmailSent", { email })}
60
67
  </p>
61
68
  </div>
62
69
 
63
70
  <div className="space-y-4">
64
71
  <p className="text-sm text-muted-foreground">
65
- Didn't receive the email? Check your spam folder or try again.
72
+ {t("didntReceiveEmail")}
66
73
  </p>
67
74
  <Button variant="outline" onClick={() => setIsSubmitted(false)}>
68
- Try Another Email
75
+ {t("tryAnotherEmail")}
69
76
  </Button>
70
77
  <div>
71
78
  <Link
72
79
  href="/auth/login"
73
80
  className="text-sm text-primary hover:underline"
74
81
  >
75
- Back to Sign In
82
+ {t("backToSignIn")}
76
83
  </Link>
77
84
  </div>
78
85
  </div>
@@ -89,13 +96,13 @@ export default function ForgotPasswordPage() {
89
96
  className="mb-8 inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground"
90
97
  >
91
98
  <ArrowLeft className="h-4 w-4" />
92
- Back to Sign In
99
+ {t("backToSignIn")}
93
100
  </Link>
94
101
 
95
102
  <div className="mb-8">
96
- <h1 className="text-3xl font-bold text-foreground">Reset Password</h1>
103
+ <h1 className="text-3xl font-bold text-foreground">{t("resetPasswordTitle")}</h1>
97
104
  <p className="mt-2 text-muted-foreground">
98
- Enter your email address and we'll send you instructions to reset your password.
105
+ {t("resetPasswordDescription")}
99
106
  </p>
100
107
  </div>
101
108
 
@@ -108,7 +115,7 @@ export default function ForgotPasswordPage() {
108
115
 
109
116
  <div className="space-y-2">
110
117
  <label htmlFor="email" className="text-sm font-medium text-foreground">
111
- Email
118
+ {t("email")}
112
119
  </label>
113
120
  <Input
114
121
  id="email"
@@ -122,7 +129,7 @@ export default function ForgotPasswordPage() {
122
129
  </div>
123
130
 
124
131
  <Button type="submit" className="w-full" disabled={recoverMutation.isPending}>
125
- {recoverMutation.isPending ? "Sending..." : "Send Reset Instructions"}
132
+ {recoverMutation.isPending ? t("sending") : t("sendResetInstructions")}
126
133
  </Button>
127
134
  </form>
128
135
  </div>
@@ -1,17 +1,20 @@
1
1
  "use client";
2
2
 
3
3
  import { Suspense } from "react";
4
+ import { useTranslations } from "next-intl";
4
5
  import { LoginForm } from "@/components/auth/login-form";
5
6
  import { Spinner } from "@/components/ui/spinner";
6
7
 
7
8
  export default function LoginPage() {
9
+ const t = useTranslations("auth");
10
+
8
11
  return (
9
12
  <div className="container mx-auto px-4 py-16">
10
13
  <div className="mx-auto max-w-md">
11
14
  <div className="mb-8 text-center">
12
- <h1 className="text-3xl font-bold text-foreground">Sign In</h1>
15
+ <h1 className="text-3xl font-bold text-foreground">{t("signInTitle")}</h1>
13
16
  <p className="mt-2 text-muted-foreground">
14
- Sign in to your account to continue
17
+ {t("signInDescription")}
15
18
  </p>
16
19
  </div>
17
20
 
@@ -1,15 +1,18 @@
1
1
  "use client";
2
2
 
3
+ import { useTranslations } from "next-intl";
3
4
  import { RegisterForm } from "@/components/auth/register-form";
4
5
 
5
6
  export default function RegisterPage() {
7
+ const t = useTranslations("auth");
8
+
6
9
  return (
7
10
  <div className="container mx-auto px-4 py-16">
8
11
  <div className="mx-auto max-w-md">
9
12
  <div className="mb-8 text-center">
10
- <h1 className="text-3xl font-bold text-foreground">Create Account</h1>
13
+ <h1 className="text-3xl font-bold text-foreground">{t("signUpTitle")}</h1>
11
14
  <p className="mt-2 text-muted-foreground">
12
- Sign up to start shopping
15
+ {t("signUpDescription")}
13
16
  </p>
14
17
  </div>
15
18
 
@@ -0,0 +1,17 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function BlogPostLoading() {
4
+ return (
5
+ <div className="container mx-auto max-w-3xl px-4 py-8">
6
+ <Skeleton className="mb-4 h-5 w-64" />
7
+ <Skeleton className="mb-2 h-10 w-full" />
8
+ <Skeleton className="mb-8 h-5 w-48" />
9
+ <Skeleton className="mb-8 aspect-video w-full rounded-lg" />
10
+ <div className="space-y-4">
11
+ {[...Array(8)].map((_, i) => (
12
+ <Skeleton key={i} className="h-4 w-full" />
13
+ ))}
14
+ </div>
15
+ </div>
16
+ );
17
+ }