@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,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useState, useRef, useEffect } from "react";
4
+ import { useTranslations } from "next-intl";
4
5
  import { ShoppingCart, Check } from "lucide-react";
5
6
  import { Button } from "@/components/ui/button";
6
7
  import { Spinner } from "@/components/ui/spinner";
@@ -74,6 +75,7 @@ export function AddToCartButton({
74
75
  size = "md",
75
76
  fullWidth = false,
76
77
  }: AddToCartButtonProps) {
78
+ const t = useTranslations("product");
77
79
  const [isAdded, setIsAdded] = useState(false);
78
80
  const { addToCart, isLoading } = useCartActions();
79
81
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
@@ -95,17 +97,7 @@ export function AddToCartButton({
95
97
  if (onAddToCart) {
96
98
  await onAddToCart(variantId, quantity);
97
99
  } else {
98
- await addToCart({
99
- variantId,
100
- productId,
101
- productHandle,
102
- productTitle,
103
- variantTitle,
104
- price,
105
- image,
106
- available,
107
- quantity,
108
- });
100
+ await addToCart(variantId, quantity);
109
101
  }
110
102
 
111
103
  setIsAdded(true);
@@ -143,17 +135,17 @@ export function AddToCartButton({
143
135
  {isLoading ? (
144
136
  <>
145
137
  <Spinner size="sm" className="mr-2" />
146
- Adding...
138
+ {t("adding")}
147
139
  </>
148
140
  ) : isAdded ? (
149
141
  <>
150
142
  <Check className="mr-2 h-5 w-5" />
151
- Added to Cart
143
+ {t("addedToCart")}
152
144
  </>
153
145
  ) : (
154
146
  <>
155
147
  <ShoppingCart className="mr-2 h-5 w-5" />
156
- {!available ? "Out of Stock" : "Add to Cart"}
148
+ {!available ? t("outOfStock") : t("addToCart")}
157
149
  </>
158
150
  )}
159
151
  </Button>
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
 
3
3
  import { cn } from "@/lib/utils";
4
+ import { CURRENCY_LOCALES } from "@doswiftly/storefront-sdk";
4
5
  import { Tag, LogIn, TrendingDown } from "lucide-react";
5
- import Link from "next/link";
6
+ import { Link } from "@/i18n/navigation";
6
7
 
7
8
  /**
8
9
  * Types matching GraphQL schema
@@ -67,7 +68,8 @@ export function B2BPriceDisplayComponent({
67
68
 
68
69
  const formatPrice = (money: Money) => {
69
70
  const amount = parseFloat(money.amount);
70
- return new Intl.NumberFormat("pl-PL", {
71
+ const locale = CURRENCY_LOCALES[money.currencyCode] || "en-US";
72
+ return new Intl.NumberFormat(locale, {
71
73
  style: "currency",
72
74
  currency: money.currencyCode,
73
75
  }).format(amount);
@@ -0,0 +1,72 @@
1
+ "use client";
2
+
3
+ import { useTranslations } from "next-intl";
4
+ import { X } from "lucide-react";
5
+ import { Badge } from "@/components/ui/badge";
6
+ import { Button } from "@/components/ui/button";
7
+
8
+ export interface ActivePill {
9
+ filterId: string;
10
+ label: string;
11
+ value: string;
12
+ displayValue: string;
13
+ }
14
+
15
+ interface FilterActivePillsProps {
16
+ pills: ActivePill[];
17
+ onRemove: (filterId: string, value: string) => void;
18
+ onClearAll: () => void;
19
+ }
20
+
21
+ /**
22
+ * FilterActivePills - Shows active filters as removable badges
23
+ *
24
+ * Pattern from Saleor Storefront:
25
+ * - Each pill shows "Label: Value" with X button
26
+ * - "Clear all" link at the end
27
+ * - Horizontally scrollable on mobile
28
+ */
29
+ export function FilterActivePills({
30
+ pills,
31
+ onRemove,
32
+ onClearAll,
33
+ }: FilterActivePillsProps) {
34
+ const t = useTranslations("product");
35
+
36
+ if (pills.length === 0) return null;
37
+
38
+ return (
39
+ <div
40
+ className="scrollbar-hide flex items-center gap-2 overflow-x-auto py-1"
41
+ role="region"
42
+ aria-label="Active filters"
43
+ >
44
+ {pills.map((pill) => (
45
+ <Badge
46
+ key={`${pill.filterId}-${pill.value}`}
47
+ variant="secondary"
48
+ className="shrink-0 gap-1.5 pr-1.5"
49
+ >
50
+ <span className="text-xs text-muted-foreground">{pill.label}:</span>
51
+ {pill.displayValue}
52
+ <button
53
+ type="button"
54
+ onClick={() => onRemove(pill.filterId, pill.value)}
55
+ className="ml-0.5 rounded-full p-0.5 transition-colors hover:bg-background/50"
56
+ aria-label={`Remove ${pill.displayValue} filter`}
57
+ >
58
+ <X className="h-3 w-3" />
59
+ </button>
60
+ </Badge>
61
+ ))}
62
+ <Button
63
+ variant="ghost"
64
+ size="sm"
65
+ className="h-6 shrink-0 px-2 text-xs text-muted-foreground"
66
+ onClick={onClearAll}
67
+ >
68
+ {t("clearAllFilters")}
69
+ </Button>
70
+ </div>
71
+ );
72
+ }
@@ -0,0 +1,87 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { useTranslations } from "next-intl";
5
+ import { SlidersHorizontal } from "lucide-react";
6
+ import { Button } from "@/components/ui/button";
7
+ import { Badge } from "@/components/ui/badge";
8
+ import {
9
+ Sheet,
10
+ SheetTrigger,
11
+ SheetContent,
12
+ SheetHeader,
13
+ SheetTitle,
14
+ SheetDescription,
15
+ } from "@/components/ui/sheet";
16
+ import { ProductFilters, type ProductFiltersProps } from "./product-filters";
17
+
18
+ interface FilterMobileSheetProps extends ProductFiltersProps {
19
+ activeFilterCount: number;
20
+ totalProducts?: number;
21
+ }
22
+
23
+ /**
24
+ * FilterMobileSheet - Mobile filter panel (slides from left)
25
+ *
26
+ * Pattern from Saleor Storefront:
27
+ * - Trigger button visible only on mobile (lg:hidden)
28
+ * - Sheet slides from left with full filter panel
29
+ * - Footer shows "Clear all" when filters active
30
+ * - Auto-closes after clearing
31
+ */
32
+ export function FilterMobileSheet({
33
+ activeFilterCount,
34
+ totalProducts,
35
+ ...filterProps
36
+ }: FilterMobileSheetProps) {
37
+ const [open, setOpen] = useState(false);
38
+ const t = useTranslations("product");
39
+ const tFilters = useTranslations("filters");
40
+
41
+ return (
42
+ <Sheet open={open} onOpenChange={setOpen}>
43
+ <SheetTrigger asChild>
44
+ <Button
45
+ variant="outline"
46
+ size="sm"
47
+ className="shrink-0 lg:hidden"
48
+ >
49
+ <SlidersHorizontal className="mr-2 h-4 w-4" />
50
+ {t("filters")}
51
+ {activeFilterCount > 0 && (
52
+ <Badge variant="secondary" className="ml-2 h-5 px-1.5 py-0 text-xs">
53
+ {activeFilterCount}
54
+ </Badge>
55
+ )}
56
+ </Button>
57
+ </SheetTrigger>
58
+ <SheetContent side="left" className="flex w-[300px] flex-col overflow-hidden">
59
+ <SheetHeader>
60
+ <SheetTitle>{t("filters")}</SheetTitle>
61
+ <SheetDescription>
62
+ {totalProducts !== undefined && (
63
+ <span>{tFilters("productCount", { count: totalProducts })}</span>
64
+ )}
65
+ </SheetDescription>
66
+ </SheetHeader>
67
+ <div className="flex-1 overflow-y-auto px-4 pb-4">
68
+ <ProductFilters {...filterProps} />
69
+ </div>
70
+ {activeFilterCount > 0 && filterProps.onClearAll && (
71
+ <div className="border-t border-border p-4">
72
+ <Button
73
+ variant="outline"
74
+ className="w-full"
75
+ onClick={() => {
76
+ filterProps.onClearAll?.();
77
+ setOpen(false);
78
+ }}
79
+ >
80
+ {t("clearAllFilters")} ({activeFilterCount})
81
+ </Button>
82
+ </div>
83
+ )}
84
+ </SheetContent>
85
+ </Sheet>
86
+ );
87
+ }
@@ -0,0 +1,140 @@
1
+ "use client";
2
+
3
+ import { useState, useCallback, useEffect, useRef } from "react";
4
+ import { useTranslations } from "next-intl";
5
+ import { Slider } from "@/components/ui/slider";
6
+ import { Input } from "@/components/ui/input";
7
+
8
+ interface FilterPriceRangeProps {
9
+ min: number;
10
+ max: number;
11
+ currentMin?: number;
12
+ currentMax?: number;
13
+ currency?: string;
14
+ onChange: (min: number | undefined, max: number | undefined) => void;
15
+ }
16
+
17
+ /**
18
+ * FilterPriceRange - Dual-thumb range slider with number inputs
19
+ *
20
+ * - Slider commits on thumb release (onValueCommit) — natural debounce
21
+ * - Input fields commit on blur — no Apply button needed
22
+ * - Shows formatted currency values
23
+ */
24
+ export function FilterPriceRange({
25
+ min,
26
+ max,
27
+ currentMin,
28
+ currentMax,
29
+ currency = "PLN",
30
+ onChange,
31
+ }: FilterPriceRangeProps) {
32
+ const t = useTranslations("product");
33
+ const [localMin, setLocalMin] = useState<number>(currentMin ?? min);
34
+ const [localMax, setLocalMax] = useState<number>(currentMax ?? max);
35
+ const debounceRef = useRef<ReturnType<typeof setTimeout>>(undefined);
36
+
37
+ // Sync local state when props change (e.g., URL navigation)
38
+ useEffect(() => {
39
+ setLocalMin(currentMin ?? min);
40
+ setLocalMax(currentMax ?? max);
41
+ }, [currentMin, currentMax, min, max]);
42
+
43
+ const commitChange = useCallback(
44
+ (newMin: number, newMax: number) => {
45
+ const effectiveMin = newMin <= min ? undefined : newMin;
46
+ const effectiveMax = newMax >= max ? undefined : newMax;
47
+ onChange(effectiveMin, effectiveMax);
48
+ },
49
+ [min, max, onChange]
50
+ );
51
+
52
+ const handleSliderChange = useCallback(
53
+ (values: number[]) => {
54
+ setLocalMin(values[0]);
55
+ setLocalMax(values[1]);
56
+ },
57
+ []
58
+ );
59
+
60
+ const handleSliderCommit = useCallback(
61
+ (values: number[]) => {
62
+ commitChange(values[0], values[1]);
63
+ },
64
+ [commitChange]
65
+ );
66
+
67
+ const handleInputBlur = useCallback(() => {
68
+ // Clamp values
69
+ const clampedMin = Math.max(min, Math.min(localMin, localMax));
70
+ const clampedMax = Math.min(max, Math.max(localMin, localMax));
71
+ setLocalMin(clampedMin);
72
+ setLocalMax(clampedMax);
73
+
74
+ if (debounceRef.current) clearTimeout(debounceRef.current);
75
+ debounceRef.current = setTimeout(() => {
76
+ commitChange(clampedMin, clampedMax);
77
+ }, 150);
78
+ }, [localMin, localMax, min, max, commitChange]);
79
+
80
+ // Cleanup timeout
81
+ useEffect(() => {
82
+ return () => {
83
+ if (debounceRef.current) clearTimeout(debounceRef.current);
84
+ };
85
+ }, []);
86
+
87
+ const step = max - min > 1000 ? 10 : max - min > 100 ? 1 : 0.01;
88
+
89
+ return (
90
+ <div className="space-y-4 px-1">
91
+ {/* Slider */}
92
+ <Slider
93
+ value={[localMin, localMax]}
94
+ min={min}
95
+ max={max}
96
+ step={step}
97
+ onValueChange={handleSliderChange}
98
+ onValueCommit={handleSliderCommit}
99
+ aria-label={t("priceRange")}
100
+ />
101
+
102
+ {/* Input fields */}
103
+ <div className="flex items-center gap-2">
104
+ <div className="relative flex-1">
105
+ <Input
106
+ type="number"
107
+ value={localMin}
108
+ onChange={(e) => setLocalMin(parseFloat(e.target.value) || min)}
109
+ onBlur={handleInputBlur}
110
+ min={min}
111
+ max={max}
112
+ step={step}
113
+ className="pr-12 text-sm"
114
+ aria-label={t("minPrice")}
115
+ />
116
+ <span className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-xs text-muted-foreground">
117
+ {currency}
118
+ </span>
119
+ </div>
120
+ <span className="text-muted-foreground">—</span>
121
+ <div className="relative flex-1">
122
+ <Input
123
+ type="number"
124
+ value={localMax}
125
+ onChange={(e) => setLocalMax(parseFloat(e.target.value) || max)}
126
+ onBlur={handleInputBlur}
127
+ min={min}
128
+ max={max}
129
+ step={step}
130
+ className="pr-12 text-sm"
131
+ aria-label={t("maxPrice")}
132
+ />
133
+ <span className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-xs text-muted-foreground">
134
+ {currency}
135
+ </span>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ );
140
+ }
@@ -1,5 +1,5 @@
1
1
  export { ProductCard } from './product-card';
2
- export type { ProductCardProps, ProductCardProduct } from './product-card';
2
+ export type { ProductCardProps } from './product-card';
3
3
 
4
4
  export { ProductGrid } from './product-grid';
5
5
  export type { ProductGridProps } from './product-grid';
@@ -16,8 +16,15 @@ export type { ProductFiltersProps, FilterGroup, FilterOption } from './product-f
16
16
  export { ProductSort } from './product-sort';
17
17
  export type { ProductSortProps, SortOption } from './product-sort';
18
18
 
19
+ export { FilterActivePills } from './filter-active-pills';
20
+ export type { ActivePill } from './filter-active-pills';
21
+
22
+ export { FilterPriceRange } from './filter-price-range';
23
+
24
+ export { FilterMobileSheet } from './filter-mobile-sheet';
25
+
19
26
  export { ProductVariantSelector } from './product-variant-selector';
20
- export type { ProductVariantSelectorProps, ProductVariant, VariantOption } from './product-variant-selector';
27
+ export type { ProductVariantSelectorProps } from './product-variant-selector';
21
28
 
22
29
  export { ProductGallery } from './product-gallery';
23
30
  export type { ProductGalleryProps } from './product-gallery';
@@ -0,0 +1,49 @@
1
+ # Fragment for ProductCard component.
2
+ #
3
+ # Defines the minimal product data needed for listing views:
4
+ # grids, search results, collection products, recommendations.
5
+ #
6
+ # Usage in components:
7
+ # import type { ProductCardFieldsFragment } from '@/generated/graphql';
8
+ # interface Props { product: ProductCardFieldsFragment }
9
+ #
10
+ # Usage in custom queries:
11
+ # query FeaturedProducts {
12
+ # products(first: 8) {
13
+ # edges { node { ...ProductCardFields } }
14
+ # }
15
+ # }
16
+
17
+ fragment ProductCardFields on Product {
18
+ id
19
+ handle
20
+ title
21
+ vendor
22
+ productType
23
+ availableForSale
24
+ averageRating
25
+ reviewCount
26
+ tags
27
+ featuredImage {
28
+ url
29
+ altText
30
+ width
31
+ height
32
+ }
33
+ priceRange {
34
+ minVariantPrice {
35
+ amount
36
+ currencyCode
37
+ }
38
+ maxVariantPrice {
39
+ amount
40
+ currencyCode
41
+ }
42
+ }
43
+ compareAtPriceRange {
44
+ minVariantPrice {
45
+ amount
46
+ currencyCode
47
+ }
48
+ }
49
+ }
@@ -1,43 +1,16 @@
1
1
  "use client";
2
2
 
3
- import Link from "next/link";
3
+ import { Link } from "@/i18n/navigation";
4
+ import { useTranslations } from "next-intl";
4
5
  import { Gift } from "lucide-react";
5
6
  import { ProductImage } from "./product-image";
6
7
  import { ProductPrice } from "./product-price";
7
8
  import { Badge } from "@/components/ui/badge";
8
9
  import { cn } from "@/lib/utils";
9
-
10
- export interface ProductCardProduct {
11
- id: string;
12
- handle: string;
13
- title: string;
14
- featuredImage?: {
15
- url: string;
16
- altText?: string | null;
17
- } | null;
18
- priceRange: {
19
- minVariantPrice: {
20
- amount: string;
21
- currencyCode: string;
22
- };
23
- maxVariantPrice: {
24
- amount: string;
25
- currencyCode: string;
26
- };
27
- };
28
- compareAtPriceRange?: {
29
- minVariantPrice: {
30
- amount: string;
31
- currencyCode: string;
32
- };
33
- } | null;
34
- availableForSale: boolean;
35
- tags?: string[];
36
- type?: string;
37
- }
10
+ import type { ProductCardFields } from "@/lib/graphql/fragments";
38
11
 
39
12
  export interface ProductCardProps {
40
- product: ProductCardProduct;
13
+ product: ProductCardFields;
41
14
  className?: string;
42
15
  priority?: boolean;
43
16
  showBadges?: boolean;
@@ -63,6 +36,7 @@ export function ProductCard({
63
36
  priority = false,
64
37
  showBadges = true,
65
38
  }: ProductCardProps) {
39
+ const t = useTranslations("product");
66
40
  const isOnSale = product.compareAtPriceRange &&
67
41
  parseFloat(product.compareAtPriceRange.minVariantPrice.amount) >
68
42
  parseFloat(product.priceRange.minVariantPrice.amount);
@@ -72,7 +46,7 @@ export function ProductCard({
72
46
  );
73
47
 
74
48
  const isOutOfStock = !product.availableForSale;
75
- const isGiftCard = product.type === "GIFT_CARD";
49
+ const isGiftCard = product.productType === "GIFT_CARD";
76
50
 
77
51
  return (
78
52
  <Link
@@ -98,22 +72,22 @@ export function ProductCard({
98
72
  {isGiftCard && (
99
73
  <Badge variant="default" className="shadow-sm">
100
74
  <Gift className="mr-1 h-3 w-3" />
101
- Karta podarunkowa
75
+ {t("giftCardLabel")}
102
76
  </Badge>
103
77
  )}
104
78
  {isNew && !isGiftCard && (
105
79
  <Badge variant="default" className="shadow-sm">
106
- NEW
80
+ {t("badgeNew")}
107
81
  </Badge>
108
82
  )}
109
83
  {isOnSale && (
110
84
  <Badge variant="destructive" className="shadow-sm">
111
- SALE
85
+ {t("badgeSale")}
112
86
  </Badge>
113
87
  )}
114
88
  {isOutOfStock && (
115
89
  <Badge variant="secondary" className="shadow-sm">
116
- Out of Stock
90
+ {t("outOfStock")}
117
91
  </Badge>
118
92
  )}
119
93
  </div>
@@ -138,7 +112,7 @@ export function ProductCard({
138
112
 
139
113
  {isOutOfStock && (
140
114
  <p className="mt-2 text-xs text-muted-foreground">
141
- Currently unavailable
115
+ {t("currentlyUnavailable")}
142
116
  </p>
143
117
  )}
144
118
  </div>
@@ -0,0 +1,52 @@
1
+ # Fragment for ProductDetail / ProductPage component.
2
+ #
3
+ # Extends ProductCardFields with full product data needed
4
+ # for the product detail page: gallery, variants, SEO, description.
5
+ #
6
+ # Usage in components:
7
+ # import type { ProductDetailFieldsFragment } from '@/generated/graphql';
8
+ # interface Props { product: ProductDetailFieldsFragment }
9
+ #
10
+ # Usage in custom queries:
11
+ # query ProductWithRecommendations($handle: String!) {
12
+ # product(handle: $handle) {
13
+ # ...ProductDetailFields
14
+ # }
15
+ # }
16
+
17
+ fragment ProductDetailFields on Product {
18
+ ...ProductCardFields
19
+ description
20
+ descriptionHtml
21
+ totalInventory
22
+ collectRecipientInfo
23
+ type
24
+ createdAt
25
+ updatedAt
26
+ seo {
27
+ title
28
+ description
29
+ }
30
+ images(first: 20) {
31
+ url
32
+ altText
33
+ width
34
+ height
35
+ }
36
+ variants(first: 100) {
37
+ ...ProductVariantFields
38
+ }
39
+ # Original prices (before currency conversion) for discount display
40
+ originalPriceRange {
41
+ minVariantPrice {
42
+ amount
43
+ currencyCode
44
+ }
45
+ }
46
+ originalCompareAtPriceRange {
47
+ minVariantPrice {
48
+ amount
49
+ currencyCode
50
+ }
51
+ }
52
+ }