@salifbiaye/create-boutique 0.1.1

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 (316) hide show
  1. package/README.md +1 -0
  2. package/cli/dist/commands.js +382 -0
  3. package/cli/dist/create.js +194 -0
  4. package/cli/dist/docker.js +19 -0
  5. package/cli/dist/generate.js +322 -0
  6. package/cli/dist/guide.js +72 -0
  7. package/cli/dist/index.js +156 -0
  8. package/cli/dist/paths.js +29 -0
  9. package/cli/dist/ports.js +54 -0
  10. package/cli/dist/project.js +119 -0
  11. package/cli/dist/themes.js +24 -0
  12. package/docs/fiche-client.en.html +137 -0
  13. package/docs/fiche-client.html +137 -0
  14. package/docs/guide-complet.en.html +259 -0
  15. package/docs/guide-complet.fr.html +259 -0
  16. package/package.json +51 -0
  17. package/templates/backend/.dockerignore +9 -0
  18. package/templates/backend/Dockerfile +30 -0
  19. package/templates/backend/README.md +78 -0
  20. package/templates/backend/TEMPLATE_VERSION +1 -0
  21. package/templates/backend/docker/entrypoint.sh +28 -0
  22. package/templates/backend/instrumentation.ts +24 -0
  23. package/templates/backend/medusa-config.ts +114 -0
  24. package/templates/backend/package-lock.json +16222 -0
  25. package/templates/backend/package.json +39 -0
  26. package/templates/backend/src/admin/README.md +33 -0
  27. package/templates/backend/src/admin/components/image-field.tsx +61 -0
  28. package/templates/backend/src/admin/i18n/README.md +58 -0
  29. package/templates/backend/src/admin/i18n/index.ts +8 -0
  30. package/templates/backend/src/admin/i18n/json/en.json +66 -0
  31. package/templates/backend/src/admin/i18n/json/fr.json +66 -0
  32. package/templates/backend/src/admin/lib/client.ts +9 -0
  33. package/templates/backend/src/admin/routes/boutique-campaigns/campaign-drawer.tsx +286 -0
  34. package/templates/backend/src/admin/routes/boutique-campaigns/page.tsx +113 -0
  35. package/templates/backend/src/admin/tsconfig.json +24 -0
  36. package/templates/backend/src/admin/vite-env.d.ts +1 -0
  37. package/templates/backend/src/admin/widgets/category-image.tsx +56 -0
  38. package/templates/backend/src/api/README.md +135 -0
  39. package/templates/backend/src/api/admin/boutique-campaigns/[salesChannelId]/route.ts +30 -0
  40. package/templates/backend/src/api/admin/boutique-campaigns/route.ts +24 -0
  41. package/templates/backend/src/api/middlewares.ts +28 -0
  42. package/templates/backend/src/api/rate-limit.ts +30 -0
  43. package/templates/backend/src/api/route.ts +6 -0
  44. package/templates/backend/src/api/store/campaign/route.ts +25 -0
  45. package/templates/backend/src/api/store/order-lookup/route.ts +74 -0
  46. package/templates/backend/src/emails/en.json +64 -0
  47. package/templates/backend/src/emails/fr.json +64 -0
  48. package/templates/backend/src/jobs/README.md +38 -0
  49. package/templates/backend/src/lib/emails.ts +94 -0
  50. package/templates/backend/src/lib/notify.ts +148 -0
  51. package/templates/backend/src/lib/project.ts +146 -0
  52. package/templates/backend/src/links/README.md +26 -0
  53. package/templates/backend/src/links/campaign-sales-channel.ts +9 -0
  54. package/templates/backend/src/modules/README.md +117 -0
  55. package/templates/backend/src/modules/campaign/index.ts +9 -0
  56. package/templates/backend/src/modules/campaign/migrations/.snapshot-boutique-campaign.json +272 -0
  57. package/templates/backend/src/modules/campaign/migrations/Migration20260928141440.ts +16 -0
  58. package/templates/backend/src/modules/campaign/migrations/Migration20260928145243.ts +13 -0
  59. package/templates/backend/src/modules/campaign/models/campaign.ts +28 -0
  60. package/templates/backend/src/modules/campaign/service.ts +6 -0
  61. package/templates/backend/src/modules/campaign/validators.ts +94 -0
  62. package/templates/backend/src/modules/resend/index.ts +6 -0
  63. package/templates/backend/src/modules/resend/service.ts +63 -0
  64. package/templates/backend/src/scripts/README.md +63 -0
  65. package/templates/backend/src/scripts/campaign-export.ts +15 -0
  66. package/templates/backend/src/scripts/campaign-import.ts +38 -0
  67. package/templates/backend/src/scripts/price-report.ts +34 -0
  68. package/templates/backend/src/scripts/seed.ts +418 -0
  69. package/templates/backend/src/scripts/storage.ts +63 -0
  70. package/templates/backend/src/subscribers/README.md +61 -0
  71. package/templates/backend/src/subscribers/account-emails.ts +27 -0
  72. package/templates/backend/src/subscribers/fulfillment-emails.ts +42 -0
  73. package/templates/backend/src/subscribers/order-emails.ts +12 -0
  74. package/templates/backend/src/subscribers/return-refund-emails.ts +50 -0
  75. package/templates/backend/src/workflows/README.md +81 -0
  76. package/templates/backend/src/workflows/steps/upsert-campaign.ts +53 -0
  77. package/templates/backend/src/workflows/upsert-campaign.ts +30 -0
  78. package/templates/backend/tsconfig.json +36 -0
  79. package/templates/storefront/.dockerignore +7 -0
  80. package/templates/storefront/.github/ISSUE_TEMPLATE/bug-report.yml +71 -0
  81. package/templates/storefront/.prettierrc +8 -0
  82. package/templates/storefront/Dockerfile +37 -0
  83. package/templates/storefront/LICENSE +21 -0
  84. package/templates/storefront/README.md +127 -0
  85. package/templates/storefront/locales/en.json +269 -0
  86. package/templates/storefront/locales/fr.json +269 -0
  87. package/templates/storefront/next-env.d.ts +7 -0
  88. package/templates/storefront/next-sitemap.js +19 -0
  89. package/templates/storefront/next.config.js +29 -0
  90. package/templates/storefront/package-lock.json +9031 -0
  91. package/templates/storefront/package.json +49 -0
  92. package/templates/storefront/postcss.config.js +6 -0
  93. package/templates/storefront/public/favicon.ico +0 -0
  94. package/templates/storefront/scripts/sync-design.mjs +30 -0
  95. package/templates/storefront/src/app/(checkout)/checkout/page.tsx +31 -0
  96. package/templates/storefront/src/app/(checkout)/layout.tsx +29 -0
  97. package/templates/storefront/src/app/(checkout)/not-found.tsx +20 -0
  98. package/templates/storefront/src/app/(main)/account/@dashboard/addresses/page.tsx +34 -0
  99. package/templates/storefront/src/app/(main)/account/@dashboard/loading.tsx +9 -0
  100. package/templates/storefront/src/app/(main)/account/@dashboard/orders/details/[id]/page.tsx +33 -0
  101. package/templates/storefront/src/app/(main)/account/@dashboard/orders/page.tsx +37 -0
  102. package/templates/storefront/src/app/(main)/account/@dashboard/page.tsx +22 -0
  103. package/templates/storefront/src/app/(main)/account/@dashboard/profile/page.tsx +53 -0
  104. package/templates/storefront/src/app/(main)/account/@login/page.tsx +12 -0
  105. package/templates/storefront/src/app/(main)/account/layout.tsx +20 -0
  106. package/templates/storefront/src/app/(main)/account/loading.tsx +9 -0
  107. package/templates/storefront/src/app/(main)/cart/loading.tsx +5 -0
  108. package/templates/storefront/src/app/(main)/cart/not-found.tsx +21 -0
  109. package/templates/storefront/src/app/(main)/cart/page.tsx +21 -0
  110. package/templates/storefront/src/app/(main)/categories/[...category]/page.tsx +55 -0
  111. package/templates/storefront/src/app/(main)/collections/[handle]/page.tsx +55 -0
  112. package/templates/storefront/src/app/(main)/layout.tsx +43 -0
  113. package/templates/storefront/src/app/(main)/legal/[page]/page.tsx +42 -0
  114. package/templates/storefront/src/app/(main)/not-found.tsx +21 -0
  115. package/templates/storefront/src/app/(main)/order/[id]/confirmed/loading.tsx +5 -0
  116. package/templates/storefront/src/app/(main)/order/[id]/confirmed/page.tsx +23 -0
  117. package/templates/storefront/src/app/(main)/order/[id]/transfer/[token]/accept/page.tsx +42 -0
  118. package/templates/storefront/src/app/(main)/order/[id]/transfer/[token]/decline/page.tsx +42 -0
  119. package/templates/storefront/src/app/(main)/order/[id]/transfer/[token]/page.tsx +35 -0
  120. package/templates/storefront/src/app/(main)/order/track/page.tsx +32 -0
  121. package/templates/storefront/src/app/(main)/page.tsx +68 -0
  122. package/templates/storefront/src/app/(main)/products/[handle]/page.tsx +86 -0
  123. package/templates/storefront/src/app/(main)/store/page.tsx +28 -0
  124. package/templates/storefront/src/app/api/health/route.ts +13 -0
  125. package/templates/storefront/src/app/layout.tsx +42 -0
  126. package/templates/storefront/src/app/not-found.tsx +21 -0
  127. package/templates/storefront/src/app/opengraph-image.jpg +0 -0
  128. package/templates/storefront/src/app/twitter-image.jpg +0 -0
  129. package/templates/storefront/src/instrumentation-node.ts +18 -0
  130. package/templates/storefront/src/instrumentation.ts +9 -0
  131. package/templates/storefront/src/lib/boutique/campaign.ts +116 -0
  132. package/templates/storefront/src/lib/boutique/config.ts +152 -0
  133. package/templates/storefront/src/lib/boutique/fonts.ts +29 -0
  134. package/templates/storefront/src/lib/boutique/i18n-client.tsx +34 -0
  135. package/templates/storefront/src/lib/boutique/i18n.ts +43 -0
  136. package/templates/storefront/src/lib/boutique/schema.ts +131 -0
  137. package/templates/storefront/src/lib/config.ts +39 -0
  138. package/templates/storefront/src/lib/constants.tsx +75 -0
  139. package/templates/storefront/src/lib/context/modal-context.tsx +34 -0
  140. package/templates/storefront/src/lib/data/cart.ts +434 -0
  141. package/templates/storefront/src/lib/data/categories.ts +49 -0
  142. package/templates/storefront/src/lib/data/collections.ts +59 -0
  143. package/templates/storefront/src/lib/data/cookies.ts +103 -0
  144. package/templates/storefront/src/lib/data/customer.ts +261 -0
  145. package/templates/storefront/src/lib/data/fulfillment.ts +68 -0
  146. package/templates/storefront/src/lib/data/onboarding.ts +9 -0
  147. package/templates/storefront/src/lib/data/order-lookup.ts +34 -0
  148. package/templates/storefront/src/lib/data/orders.ts +112 -0
  149. package/templates/storefront/src/lib/data/payment.ts +35 -0
  150. package/templates/storefront/src/lib/data/products.ts +127 -0
  151. package/templates/storefront/src/lib/data/regions.ts +70 -0
  152. package/templates/storefront/src/lib/data/variants.ts +38 -0
  153. package/templates/storefront/src/lib/hooks/use-in-view.tsx +29 -0
  154. package/templates/storefront/src/lib/hooks/use-toggle-state.tsx +46 -0
  155. package/templates/storefront/src/lib/util/compare-addresses.ts +28 -0
  156. package/templates/storefront/src/lib/util/get-percentage-diff.ts +6 -0
  157. package/templates/storefront/src/lib/util/get-product-price.ts +79 -0
  158. package/templates/storefront/src/lib/util/isEmpty.ts +11 -0
  159. package/templates/storefront/src/lib/util/medusa-error.ts +22 -0
  160. package/templates/storefront/src/lib/util/money.ts +35 -0
  161. package/templates/storefront/src/lib/util/product.ts +5 -0
  162. package/templates/storefront/src/lib/util/repeat.ts +5 -0
  163. package/templates/storefront/src/lib/util/sort-products.ts +50 -0
  164. package/templates/storefront/src/modules/account/components/account-info/index.tsx +140 -0
  165. package/templates/storefront/src/modules/account/components/account-nav/index.tsx +198 -0
  166. package/templates/storefront/src/modules/account/components/address-book/index.tsx +28 -0
  167. package/templates/storefront/src/modules/account/components/address-card/add-address.tsx +169 -0
  168. package/templates/storefront/src/modules/account/components/address-card/edit-address-modal.tsx +241 -0
  169. package/templates/storefront/src/modules/account/components/login/index.tsx +65 -0
  170. package/templates/storefront/src/modules/account/components/order-card/index.tsx +88 -0
  171. package/templates/storefront/src/modules/account/components/order-overview/index.tsx +47 -0
  172. package/templates/storefront/src/modules/account/components/overview/index.tsx +169 -0
  173. package/templates/storefront/src/modules/account/components/profile-billing-address/index.tsx +193 -0
  174. package/templates/storefront/src/modules/account/components/profile-email/index.tsx +75 -0
  175. package/templates/storefront/src/modules/account/components/profile-name/index.tsx +79 -0
  176. package/templates/storefront/src/modules/account/components/profile-password/index.tsx +72 -0
  177. package/templates/storefront/src/modules/account/components/profile-phone/index.tsx +74 -0
  178. package/templates/storefront/src/modules/account/components/register/index.tsx +107 -0
  179. package/templates/storefront/src/modules/account/components/transfer-request-form/index.tsx +83 -0
  180. package/templates/storefront/src/modules/account/templates/account-layout.tsx +43 -0
  181. package/templates/storefront/src/modules/account/templates/login-template.tsx +27 -0
  182. package/templates/storefront/src/modules/cart/components/cart-item-select/index.tsx +75 -0
  183. package/templates/storefront/src/modules/cart/components/empty-cart-message/index.tsx +25 -0
  184. package/templates/storefront/src/modules/cart/components/item/index.tsx +144 -0
  185. package/templates/storefront/src/modules/cart/components/sign-in-prompt/index.tsx +27 -0
  186. package/templates/storefront/src/modules/cart/templates/index.tsx +51 -0
  187. package/templates/storefront/src/modules/cart/templates/items.tsx +58 -0
  188. package/templates/storefront/src/modules/cart/templates/preview.tsx +51 -0
  189. package/templates/storefront/src/modules/cart/templates/summary.tsx +50 -0
  190. package/templates/storefront/src/modules/categories/templates/index.tsx +94 -0
  191. package/templates/storefront/src/modules/checkout/components/address-select/index.tsx +117 -0
  192. package/templates/storefront/src/modules/checkout/components/addresses/index.tsx +186 -0
  193. package/templates/storefront/src/modules/checkout/components/billing_address/index.tsx +114 -0
  194. package/templates/storefront/src/modules/checkout/components/country-select/index.tsx +50 -0
  195. package/templates/storefront/src/modules/checkout/components/discount-code/index.tsx +181 -0
  196. package/templates/storefront/src/modules/checkout/components/error-message/index.tsx +13 -0
  197. package/templates/storefront/src/modules/checkout/components/payment/index.tsx +261 -0
  198. package/templates/storefront/src/modules/checkout/components/payment-button/index.tsx +195 -0
  199. package/templates/storefront/src/modules/checkout/components/payment-container/index.tsx +130 -0
  200. package/templates/storefront/src/modules/checkout/components/payment-test/index.tsx +12 -0
  201. package/templates/storefront/src/modules/checkout/components/payment-wrapper/index.tsx +42 -0
  202. package/templates/storefront/src/modules/checkout/components/payment-wrapper/stripe-wrapper.tsx +54 -0
  203. package/templates/storefront/src/modules/checkout/components/review/index.tsx +54 -0
  204. package/templates/storefront/src/modules/checkout/components/shipping/index.tsx +417 -0
  205. package/templates/storefront/src/modules/checkout/components/shipping-address/index.tsx +219 -0
  206. package/templates/storefront/src/modules/checkout/components/submit-button/index.tsx +32 -0
  207. package/templates/storefront/src/modules/checkout/templates/checkout-form/index.tsx +38 -0
  208. package/templates/storefront/src/modules/checkout/templates/checkout-summary/index.tsx +31 -0
  209. package/templates/storefront/src/modules/collections/templates/index.tsx +44 -0
  210. package/templates/storefront/src/modules/common/components/cart-totals/index.tsx +84 -0
  211. package/templates/storefront/src/modules/common/components/checkbox/index.tsx +44 -0
  212. package/templates/storefront/src/modules/common/components/delete-button/index.tsx +42 -0
  213. package/templates/storefront/src/modules/common/components/divider/index.tsx +9 -0
  214. package/templates/storefront/src/modules/common/components/filter-radio-group/index.tsx +61 -0
  215. package/templates/storefront/src/modules/common/components/input/index.tsx +79 -0
  216. package/templates/storefront/src/modules/common/components/interactive-link/index.tsx +33 -0
  217. package/templates/storefront/src/modules/common/components/line-item-options/index.tsx +26 -0
  218. package/templates/storefront/src/modules/common/components/line-item-price/index.tsx +63 -0
  219. package/templates/storefront/src/modules/common/components/line-item-unit-price/index.tsx +62 -0
  220. package/templates/storefront/src/modules/common/components/localized-client-link/index.tsx +29 -0
  221. package/templates/storefront/src/modules/common/components/modal/index.tsx +118 -0
  222. package/templates/storefront/src/modules/common/components/native-select/index.tsx +76 -0
  223. package/templates/storefront/src/modules/common/components/radio/index.tsx +27 -0
  224. package/templates/storefront/src/modules/common/icons/back.tsx +37 -0
  225. package/templates/storefront/src/modules/common/icons/bancontact.tsx +26 -0
  226. package/templates/storefront/src/modules/common/icons/chevron-down.tsx +30 -0
  227. package/templates/storefront/src/modules/common/icons/eye-off.tsx +37 -0
  228. package/templates/storefront/src/modules/common/icons/eye.tsx +37 -0
  229. package/templates/storefront/src/modules/common/icons/fast-delivery.tsx +65 -0
  230. package/templates/storefront/src/modules/common/icons/ideal.tsx +26 -0
  231. package/templates/storefront/src/modules/common/icons/map-pin.tsx +37 -0
  232. package/templates/storefront/src/modules/common/icons/package.tsx +44 -0
  233. package/templates/storefront/src/modules/common/icons/paypal.tsx +30 -0
  234. package/templates/storefront/src/modules/common/icons/placeholder-image.tsx +44 -0
  235. package/templates/storefront/src/modules/common/icons/refresh.tsx +51 -0
  236. package/templates/storefront/src/modules/common/icons/spinner.tsx +37 -0
  237. package/templates/storefront/src/modules/common/icons/trash.tsx +51 -0
  238. package/templates/storefront/src/modules/common/icons/user.tsx +37 -0
  239. package/templates/storefront/src/modules/common/icons/x.tsx +37 -0
  240. package/templates/storefront/src/modules/layout/components/cart-mismatch-banner/index.tsx +59 -0
  241. package/templates/storefront/src/modules/order/components/help/index.tsx +26 -0
  242. package/templates/storefront/src/modules/order/components/item/index.tsx +57 -0
  243. package/templates/storefront/src/modules/order/components/items/index.tsx +44 -0
  244. package/templates/storefront/src/modules/order/components/onboarding-cta/index.tsx +28 -0
  245. package/templates/storefront/src/modules/order/components/order-details/index.tsx +64 -0
  246. package/templates/storefront/src/modules/order/components/order-summary/index.tsx +61 -0
  247. package/templates/storefront/src/modules/order/components/payment-details/index.tsx +64 -0
  248. package/templates/storefront/src/modules/order/components/shipping-details/index.tsx +74 -0
  249. package/templates/storefront/src/modules/order/components/transfer-actions/index.tsx +83 -0
  250. package/templates/storefront/src/modules/order/components/transfer-image/index.tsx +275 -0
  251. package/templates/storefront/src/modules/order/templates/order-completed-template.tsx +53 -0
  252. package/templates/storefront/src/modules/order/templates/order-details-template.tsx +46 -0
  253. package/templates/storefront/src/modules/products/components/thumbnail/index.tsx +70 -0
  254. package/templates/storefront/src/modules/products/templates/index.tsx +118 -0
  255. package/templates/storefront/src/modules/shipping/components/free-shipping-price-nudge/index.tsx +285 -0
  256. package/templates/storefront/src/modules/skeletons/components/skeleton-button/index.tsx +5 -0
  257. package/templates/storefront/src/modules/skeletons/components/skeleton-card-details/index.tsx +10 -0
  258. package/templates/storefront/src/modules/skeletons/components/skeleton-cart-item/index.tsx +35 -0
  259. package/templates/storefront/src/modules/skeletons/components/skeleton-cart-totals/index.tsx +30 -0
  260. package/templates/storefront/src/modules/skeletons/components/skeleton-code-form/index.tsx +13 -0
  261. package/templates/storefront/src/modules/skeletons/components/skeleton-line-item/index.tsx +35 -0
  262. package/templates/storefront/src/modules/skeletons/components/skeleton-order-confirmed-header/index.tsx +14 -0
  263. package/templates/storefront/src/modules/skeletons/components/skeleton-order-information/index.tsx +36 -0
  264. package/templates/storefront/src/modules/skeletons/components/skeleton-order-items/index.tsx +43 -0
  265. package/templates/storefront/src/modules/skeletons/components/skeleton-order-summary/index.tsx +15 -0
  266. package/templates/storefront/src/modules/skeletons/components/skeleton-product-preview/index.tsx +15 -0
  267. package/templates/storefront/src/modules/skeletons/templates/skeleton-cart-page/index.tsx +65 -0
  268. package/templates/storefront/src/modules/skeletons/templates/skeleton-order-confirmed/index.tsx +21 -0
  269. package/templates/storefront/src/modules/skeletons/templates/skeleton-product-grid/index.tsx +23 -0
  270. package/templates/storefront/src/modules/store/components/pagination/index.tsx +114 -0
  271. package/templates/storefront/src/modules/store/components/refinement-list/index.tsx +41 -0
  272. package/templates/storefront/src/modules/store/components/refinement-list/sort-products/index.tsx +48 -0
  273. package/templates/storefront/src/modules/store/templates/index.tsx +42 -0
  274. package/templates/storefront/src/modules/store/templates/paginated-products.tsx +80 -0
  275. package/templates/storefront/src/modules/ub/button.tsx +41 -0
  276. package/templates/storefront/src/modules/ub/campaign-blocks.tsx +197 -0
  277. package/templates/storefront/src/modules/ub/campaign-ended.tsx +28 -0
  278. package/templates/storefront/src/modules/ub/category-tiles.tsx +41 -0
  279. package/templates/storefront/src/modules/ub/countdown.tsx +46 -0
  280. package/templates/storefront/src/modules/ub/footer.tsx +56 -0
  281. package/templates/storefront/src/modules/ub/icons.tsx +42 -0
  282. package/templates/storefront/src/modules/ub/nav.tsx +90 -0
  283. package/templates/storefront/src/modules/ub/pdp/buy-box.tsx +140 -0
  284. package/templates/storefront/src/modules/ub/pdp/gallery.tsx +40 -0
  285. package/templates/storefront/src/modules/ub/product-card.tsx +66 -0
  286. package/templates/storefront/src/modules/ub/top-bar.tsx +20 -0
  287. package/templates/storefront/src/modules/ub/track-form.tsx +92 -0
  288. package/templates/storefront/src/proxy.ts +89 -0
  289. package/templates/storefront/src/styles/globals.css +98 -0
  290. package/templates/storefront/src/styles/ub/bundle.css +372 -0
  291. package/templates/storefront/src/styles/ub/fonts.css +17 -0
  292. package/templates/storefront/src/styles/ub/medusa-ui.css +90 -0
  293. package/templates/storefront/src/styles/ub/overrides.css +12 -0
  294. package/templates/storefront/src/styles/ub/tokens.css +9 -0
  295. package/templates/storefront/src/types/global.ts +24 -0
  296. package/templates/storefront/src/types/icon.ts +4 -0
  297. package/templates/storefront/tailwind.config.js +164 -0
  298. package/templates/storefront/themes/black-friday/campaign.en.json +31 -0
  299. package/templates/storefront/themes/black-friday/campaign.fr.json +31 -0
  300. package/templates/storefront/themes/black-friday/theme.json +9 -0
  301. package/templates/storefront/themes/cyber-monday/campaign.en.json +31 -0
  302. package/templates/storefront/themes/cyber-monday/campaign.fr.json +31 -0
  303. package/templates/storefront/themes/cyber-monday/theme.json +9 -0
  304. package/templates/storefront/themes/halloween/campaign.en.json +31 -0
  305. package/templates/storefront/themes/halloween/campaign.fr.json +31 -0
  306. package/templates/storefront/themes/halloween/theme.json +9 -0
  307. package/templates/storefront/themes/noel/campaign.en.json +31 -0
  308. package/templates/storefront/themes/noel/campaign.fr.json +31 -0
  309. package/templates/storefront/themes/noel/theme.json +9 -0
  310. package/templates/storefront/themes/nouvel-an/campaign.en.json +31 -0
  311. package/templates/storefront/themes/nouvel-an/campaign.fr.json +31 -0
  312. package/templates/storefront/themes/nouvel-an/theme.json +9 -0
  313. package/templates/storefront/themes/thanksgiving/campaign.en.json +31 -0
  314. package/templates/storefront/themes/thanksgiving/campaign.fr.json +31 -0
  315. package/templates/storefront/themes/thanksgiving/theme.json +9 -0
  316. package/templates/storefront/tsconfig.json +53 -0
@@ -0,0 +1,65 @@
1
+ import { T } from "@lib/boutique/i18n-client"
2
+ import { login } from "@lib/data/customer"
3
+ import { LOGIN_VIEW } from "@modules/account/templates/login-template"
4
+ import ErrorMessage from "@modules/checkout/components/error-message"
5
+ import { SubmitButton } from "@modules/checkout/components/submit-button"
6
+ import Input from "@modules/common/components/input"
7
+ import { useActionState } from "react"
8
+
9
+ type Props = {
10
+ setCurrentView: (view: LOGIN_VIEW) => void
11
+ }
12
+
13
+ const Login = ({ setCurrentView }: Props) => {
14
+ const [message, formAction] = useActionState(login, null)
15
+
16
+ return (
17
+ <div
18
+ className="max-w-sm w-full flex flex-col items-center"
19
+ data-testid="login-page"
20
+ >
21
+ <h1 className="text-large-semi uppercase mb-6"><T k="account.welcomeBack" /></h1>
22
+ <p className="text-center text-base-regular text-ui-fg-base mb-8">
23
+ <T k="account.signInText" />
24
+ </p>
25
+ <form className="w-full" action={formAction}>
26
+ <div className="flex flex-col w-full gap-y-2">
27
+ <Input
28
+ label="form.email"
29
+ name="email"
30
+ type="email"
31
+ title="form.emailInvalid"
32
+ autoComplete="email"
33
+ required
34
+ data-testid="email-input"
35
+ />
36
+ <Input
37
+ label="form.password"
38
+ name="password"
39
+ type="password"
40
+ autoComplete="current-password"
41
+ required
42
+ data-testid="password-input"
43
+ />
44
+ </div>
45
+ <ErrorMessage error={message} data-testid="login-error-message" />
46
+ <SubmitButton data-testid="sign-in-button" className="w-full mt-6">
47
+ <T k="account.signIn" />
48
+ </SubmitButton>
49
+ </form>
50
+ <span className="text-center text-ui-fg-base text-small-regular mt-6">
51
+ <T k="account.notMember" />{" "}
52
+ <button
53
+ onClick={() => setCurrentView(LOGIN_VIEW.REGISTER)}
54
+ className="underline"
55
+ data-testid="register-button"
56
+ >
57
+ <T k="account.joinUs" />
58
+ </button>
59
+ .
60
+ </span>
61
+ </div>
62
+ )
63
+ }
64
+
65
+ export default Login
@@ -0,0 +1,88 @@
1
+ import { T } from "@lib/boutique/i18n-client"
2
+ import { Button } from "@medusajs/ui"
3
+ import { useMemo } from "react"
4
+
5
+ import Thumbnail from "@modules/products/components/thumbnail"
6
+ import LocalizedClientLink from "@modules/common/components/localized-client-link"
7
+ import { convertToLocale } from "@lib/util/money"
8
+ import { HttpTypes } from "@medusajs/types"
9
+
10
+ type OrderCardProps = {
11
+ order: HttpTypes.StoreOrder
12
+ }
13
+
14
+ const OrderCard = ({ order }: OrderCardProps) => {
15
+ const numberOfLines = useMemo(() => {
16
+ return (
17
+ order.items?.reduce((acc, item) => {
18
+ return acc + item.quantity
19
+ }, 0) ?? 0
20
+ )
21
+ }, [order])
22
+
23
+ const numberOfProducts = useMemo(() => {
24
+ return order.items?.length ?? 0
25
+ }, [order])
26
+
27
+ return (
28
+ <div className="bg-white flex flex-col" data-testid="order-card">
29
+ <div className="uppercase text-large-semi mb-1">
30
+ #<span data-testid="order-display-id">{order.display_id}</span>
31
+ </div>
32
+ <div className="flex items-center divide-x divide-gray-200 text-small-regular text-ui-fg-base">
33
+ <span className="pr-2" data-testid="order-created-at">
34
+ {new Date(order.created_at).toDateString()}
35
+ </span>
36
+ <span className="px-2" data-testid="order-amount">
37
+ {convertToLocale({
38
+ amount: order.total,
39
+ currency_code: order.currency_code,
40
+ })}
41
+ </span>
42
+ <span className="pl-2">{`${numberOfLines} ${
43
+ numberOfLines > 1 ? "items" : "item"
44
+ }`}</span>
45
+ </div>
46
+ <div className="grid grid-cols-2 small:grid-cols-4 gap-4 my-4">
47
+ {order.items?.slice(0, 3).map((i) => {
48
+ return (
49
+ <div
50
+ key={i.id}
51
+ className="flex flex-col gap-y-2"
52
+ data-testid="order-item"
53
+ >
54
+ <Thumbnail thumbnail={i.thumbnail} images={[]} size="full" />
55
+ <div className="flex items-center text-small-regular text-ui-fg-base">
56
+ <span
57
+ className="text-ui-fg-base font-semibold"
58
+ data-testid="item-title"
59
+ >
60
+ {i.title}
61
+ </span>
62
+ <span className="ml-2">x</span>
63
+ <span data-testid="item-quantity">{i.quantity}</span>
64
+ </div>
65
+ </div>
66
+ )
67
+ })}
68
+ {numberOfProducts > 4 && (
69
+ <div className="w-full h-full flex flex-col items-center justify-center">
70
+ <span className="text-small-regular text-ui-fg-base">
71
+ + {numberOfLines - 4}
72
+ </span>
73
+ <span className="text-small-regular text-ui-fg-base">more</span>
74
+ </div>
75
+ )}
76
+ </div>
77
+ <div className="flex justify-end">
78
+ <LocalizedClientLink href={`/account/orders/details/${order.id}`}>
79
+ <Button data-testid="order-details-link" variant="secondary">
80
+ <T k="order.seeDetails" />
81
+ </Button>
82
+ </LocalizedClientLink>
83
+ </div>
84
+ </div>
85
+ )
86
+ }
87
+
88
+ export default OrderCard
@@ -0,0 +1,47 @@
1
+ "use client"
2
+
3
+
4
+ import { T } from "@lib/boutique/i18n-client"
5
+ import { Button } from "@medusajs/ui"
6
+
7
+ import OrderCard from "../order-card"
8
+ import LocalizedClientLink from "@modules/common/components/localized-client-link"
9
+ import { HttpTypes } from "@medusajs/types"
10
+
11
+ const OrderOverview = ({ orders }: { orders: HttpTypes.StoreOrder[] }) => {
12
+ if (orders?.length) {
13
+ return (
14
+ <div className="flex flex-col gap-y-8 w-full">
15
+ {orders.map((o) => (
16
+ <div
17
+ key={o.id}
18
+ className="border-b border-gray-200 pb-6 last:pb-0 last:border-none"
19
+ >
20
+ <OrderCard order={o} />
21
+ </div>
22
+ ))}
23
+ </div>
24
+ )
25
+ }
26
+
27
+ return (
28
+ <div
29
+ className="w-full flex flex-col items-center gap-y-4"
30
+ data-testid="no-orders-container"
31
+ >
32
+ <h2 className="text-large-semi"><T k="account.nothingToSee" /></h2>
33
+ <p className="text-base-regular">
34
+ You don&apos;t have any orders yet, let us change that {":)"}
35
+ </p>
36
+ <div className="mt-4">
37
+ <LocalizedClientLink href="/" passHref>
38
+ <Button data-testid="continue-shopping-button">
39
+ <T k="order.continueShopping" />
40
+ </Button>
41
+ </LocalizedClientLink>
42
+ </div>
43
+ </div>
44
+ )
45
+ }
46
+
47
+ export default OrderOverview
@@ -0,0 +1,169 @@
1
+ import { T } from "@lib/boutique/i18n-client"
2
+ import { Container } from "@medusajs/ui"
3
+
4
+ import ChevronDown from "@modules/common/icons/chevron-down"
5
+ import LocalizedClientLink from "@modules/common/components/localized-client-link"
6
+ import { convertToLocale } from "@lib/util/money"
7
+ import { HttpTypes } from "@medusajs/types"
8
+
9
+ type OverviewProps = {
10
+ customer: HttpTypes.StoreCustomer | null
11
+ orders: HttpTypes.StoreOrder[] | null
12
+ }
13
+
14
+ const Overview = ({ customer, orders }: OverviewProps) => {
15
+ return (
16
+ <div data-testid="overview-page-wrapper">
17
+ <div className="hidden small:block">
18
+ <div className="text-xl-semi flex justify-between items-center mb-4">
19
+ <span data-testid="welcome-message" data-value={customer?.first_name}>
20
+ <T k="account.hello" vars={{ name: customer?.first_name ?? "" }} />
21
+ </span>
22
+ <span className="text-small-regular text-ui-fg-base">
23
+ <T k="account.signedInAs" />{" "}
24
+ <span
25
+ className="font-semibold"
26
+ data-testid="customer-email"
27
+ data-value={customer?.email}
28
+ >
29
+ {customer?.email}
30
+ </span>
31
+ </span>
32
+ </div>
33
+ <div className="flex flex-col py-8 border-t border-gray-200">
34
+ <div className="flex flex-col gap-y-4 h-full col-span-1 row-span-2 flex-1">
35
+ <div className="flex items-start gap-x-16 mb-6">
36
+ <div className="flex flex-col gap-y-4">
37
+ <h3 className="text-large-semi"><T k="account.profile" /></h3>
38
+ <div className="flex items-end gap-x-2">
39
+ <span
40
+ className="text-3xl-semi leading-none"
41
+ data-testid="customer-profile-completion"
42
+ data-value={getProfileCompletion(customer)}
43
+ >
44
+ {getProfileCompletion(customer)}%
45
+ </span>
46
+ <span className="uppercase text-base-regular text-ui-fg-subtle">
47
+ <T k="account.completed" />
48
+ </span>
49
+ </div>
50
+ </div>
51
+
52
+ <div className="flex flex-col gap-y-4">
53
+ <h3 className="text-large-semi"><T k="account.addresses" /></h3>
54
+ <div className="flex items-end gap-x-2">
55
+ <span
56
+ className="text-3xl-semi leading-none"
57
+ data-testid="addresses-count"
58
+ data-value={customer?.addresses?.length || 0}
59
+ >
60
+ {customer?.addresses?.length || 0}
61
+ </span>
62
+ <span className="uppercase text-base-regular text-ui-fg-subtle">
63
+ <T k="account.saved" />
64
+ </span>
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <div className="flex flex-col gap-y-4">
70
+ <div className="flex items-center gap-x-2">
71
+ <h3 className="text-large-semi"><T k="account.recentOrders" /></h3>
72
+ </div>
73
+ <ul
74
+ className="flex flex-col gap-y-4"
75
+ data-testid="orders-wrapper"
76
+ >
77
+ {orders && orders.length > 0 ? (
78
+ orders.slice(0, 5).map((order) => {
79
+ return (
80
+ <li
81
+ key={order.id}
82
+ data-testid="order-wrapper"
83
+ data-value={order.id}
84
+ >
85
+ <LocalizedClientLink
86
+ href={`/account/orders/details/${order.id}`}
87
+ >
88
+ <Container className="bg-gray-50 flex justify-between items-center p-4">
89
+ <div className="grid grid-cols-3 grid-rows-2 text-small-regular gap-x-4 flex-1">
90
+ <span className="font-semibold">Date placed</span>
91
+ <span className="font-semibold">
92
+ <T k="account.orderNumber" />
93
+ </span>
94
+ <span className="font-semibold">
95
+ <T k="account.totalAmount" />
96
+ </span>
97
+ <span data-testid="order-created-date">
98
+ {new Date(order.created_at).toDateString()}
99
+ </span>
100
+ <span
101
+ data-testid="order-id"
102
+ data-value={order.display_id}
103
+ >
104
+ #{order.display_id}
105
+ </span>
106
+ <span data-testid="order-amount">
107
+ {convertToLocale({
108
+ amount: order.total,
109
+ currency_code: order.currency_code,
110
+ })}
111
+ </span>
112
+ </div>
113
+ <button
114
+ className="flex items-center justify-between"
115
+ data-testid="open-order-button"
116
+ >
117
+ <span className="sr-only">
118
+ Go to order #{order.display_id}
119
+ </span>
120
+ <ChevronDown className="-rotate-90" />
121
+ </button>
122
+ </Container>
123
+ </LocalizedClientLink>
124
+ </li>
125
+ )
126
+ })
127
+ ) : (
128
+ <span data-testid="no-orders-message"><T k="account.noRecentOrders" /></span>
129
+ )}
130
+ </ul>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ )
137
+ }
138
+
139
+ const getProfileCompletion = (customer: HttpTypes.StoreCustomer | null) => {
140
+ let count = 0
141
+
142
+ if (!customer) {
143
+ return 0
144
+ }
145
+
146
+ if (customer.email) {
147
+ count++
148
+ }
149
+
150
+ if (customer.first_name && customer.last_name) {
151
+ count++
152
+ }
153
+
154
+ if (customer.phone) {
155
+ count++
156
+ }
157
+
158
+ const billingAddress = customer.addresses?.find(
159
+ (addr) => addr.is_default_billing
160
+ )
161
+
162
+ if (billingAddress) {
163
+ count++
164
+ }
165
+
166
+ return (count / 4) * 100
167
+ }
168
+
169
+ export default Overview
@@ -0,0 +1,193 @@
1
+ "use client"
2
+
3
+ import React, { useEffect, useMemo, useActionState } from "react"
4
+
5
+ import { useT } from "@lib/boutique/i18n-client"
6
+ import Input from "@modules/common/components/input"
7
+ import NativeSelect from "@modules/common/components/native-select"
8
+
9
+ import AccountInfo from "../account-info"
10
+ import { HttpTypes } from "@medusajs/types"
11
+ import { addCustomerAddress, updateCustomerAddress } from "@lib/data/customer"
12
+
13
+ type MyInformationProps = {
14
+ customer: HttpTypes.StoreCustomer
15
+ regions: HttpTypes.StoreRegion[]
16
+ }
17
+
18
+ const ProfileBillingAddress: React.FC<MyInformationProps> = ({
19
+ customer,
20
+ regions,
21
+ }) => {
22
+ const t = useT()
23
+ const regionOptions = useMemo(() => {
24
+ return (
25
+ regions
26
+ ?.map((region) => {
27
+ return region.countries?.map((country) => ({
28
+ value: country.iso_2,
29
+ label: country.display_name,
30
+ }))
31
+ })
32
+ .flat() || []
33
+ )
34
+ }, [regions])
35
+
36
+ const [successState, setSuccessState] = React.useState(false)
37
+
38
+ const billingAddress = customer.addresses?.find(
39
+ (addr) => addr.is_default_billing
40
+ )
41
+
42
+ const initialState: Record<string, any> = {
43
+ isDefaultBilling: true,
44
+ isDefaultShipping: false,
45
+ error: false,
46
+ success: false,
47
+ }
48
+
49
+ if (billingAddress) {
50
+ initialState.addressId = billingAddress.id
51
+ }
52
+
53
+ const [state, formAction] = useActionState(
54
+ billingAddress ? updateCustomerAddress : addCustomerAddress,
55
+ initialState
56
+ )
57
+
58
+ const clearState = () => {
59
+ setSuccessState(false)
60
+ }
61
+
62
+ useEffect(() => {
63
+ setSuccessState(state.success)
64
+ }, [state])
65
+
66
+ const currentInfo = useMemo(() => {
67
+ if (!billingAddress) {
68
+ return t("account.noBilling")
69
+ }
70
+
71
+ const country =
72
+ regionOptions?.find(
73
+ (country) => country?.value === billingAddress.country_code
74
+ )?.label || billingAddress.country_code?.toUpperCase()
75
+
76
+ return (
77
+ <div className="flex flex-col font-semibold" data-testid="current-info">
78
+ <span>
79
+ {billingAddress.first_name} {billingAddress.last_name}
80
+ </span>
81
+ <span>{billingAddress.company}</span>
82
+ <span>
83
+ {billingAddress.address_1}
84
+ {billingAddress.address_2 ? `, ${billingAddress.address_2}` : ""}
85
+ </span>
86
+ <span>
87
+ {billingAddress.postal_code}, {billingAddress.city}
88
+ </span>
89
+ <span>{country}</span>
90
+ </div>
91
+ )
92
+ }, [billingAddress, regionOptions])
93
+
94
+ return (
95
+ <form action={formAction} onReset={() => clearState()} className="w-full">
96
+ <input type="hidden" name="addressId" value={billingAddress?.id} />
97
+ <AccountInfo
98
+ label="form.billingAddress"
99
+ currentInfo={currentInfo}
100
+ isSuccess={successState}
101
+ isError={!!state.error}
102
+ clearState={clearState}
103
+ data-testid="account-billing-address-editor"
104
+ >
105
+ <div className="grid grid-cols-1 gap-y-2">
106
+ <div className="grid grid-cols-2 gap-x-2">
107
+ <Input
108
+ label="form.firstName"
109
+ name="first_name"
110
+ defaultValue={billingAddress?.first_name || undefined}
111
+ required
112
+ data-testid="billing-first-name-input"
113
+ />
114
+ <Input
115
+ label="form.lastName"
116
+ name="last_name"
117
+ defaultValue={billingAddress?.last_name || undefined}
118
+ required
119
+ data-testid="billing-last-name-input"
120
+ />
121
+ </div>
122
+ <Input
123
+ label="form.company"
124
+ name="company"
125
+ defaultValue={billingAddress?.company || undefined}
126
+ data-testid="billing-company-input"
127
+ />
128
+ <Input
129
+ label="form.phone"
130
+ name="phone"
131
+ type="phone"
132
+ autoComplete="phone"
133
+ required
134
+ defaultValue={billingAddress?.phone ?? customer?.phone ?? ""}
135
+ data-testid="billing-phone-input"
136
+ />
137
+ <Input
138
+ label="form.address"
139
+ name="address_1"
140
+ defaultValue={billingAddress?.address_1 || undefined}
141
+ required
142
+ data-testid="billing-address-1-input"
143
+ />
144
+ <Input
145
+ label="form.address2"
146
+ name="address_2"
147
+ defaultValue={billingAddress?.address_2 || undefined}
148
+ data-testid="billing-address-2-input"
149
+ />
150
+ <div className="grid grid-cols-[144px_1fr] gap-x-2">
151
+ <Input
152
+ label="form.postalCode"
153
+ name="postal_code"
154
+ defaultValue={billingAddress?.postal_code || undefined}
155
+ required
156
+ data-testid="billing-postcal-code-input"
157
+ />
158
+ <Input
159
+ label="form.city"
160
+ name="city"
161
+ defaultValue={billingAddress?.city || undefined}
162
+ required
163
+ data-testid="billing-city-input"
164
+ />
165
+ </div>
166
+ <Input
167
+ label="form.province"
168
+ name="province"
169
+ defaultValue={billingAddress?.province || undefined}
170
+ data-testid="billing-province-input"
171
+ />
172
+ <NativeSelect
173
+ name="country_code"
174
+ defaultValue={billingAddress?.country_code || undefined}
175
+ required
176
+ data-testid="billing-country-code-select"
177
+ >
178
+ <option value="">-</option>
179
+ {regionOptions.map((option, i) => {
180
+ return (
181
+ <option key={i} value={option?.value}>
182
+ {option?.label}
183
+ </option>
184
+ )
185
+ })}
186
+ </NativeSelect>
187
+ </div>
188
+ </AccountInfo>
189
+ </form>
190
+ )
191
+ }
192
+
193
+ export default ProfileBillingAddress
@@ -0,0 +1,75 @@
1
+ "use client"
2
+
3
+ import React, { useEffect, useActionState } from "react";
4
+
5
+ import Input from "@modules/common/components/input"
6
+
7
+ import AccountInfo from "../account-info"
8
+ import { HttpTypes } from "@medusajs/types"
9
+ // import { updateCustomer } from "@lib/data/customer"
10
+
11
+ type MyInformationProps = {
12
+ customer: HttpTypes.StoreCustomer
13
+ }
14
+
15
+ const ProfileEmail: React.FC<MyInformationProps> = ({ customer }) => {
16
+ const [successState, setSuccessState] = React.useState(false)
17
+
18
+ // TODO: It seems we don't support updating emails now?
19
+ const updateCustomerEmail = (
20
+ _currentState: Record<string, unknown>,
21
+ formData: FormData
22
+ ) => {
23
+ const customer = {
24
+ email: formData.get("email") as string,
25
+ }
26
+
27
+ try {
28
+ // await updateCustomer(customer)
29
+ return { success: true, error: null }
30
+ } catch (error: any) {
31
+ return { success: false, error: error.toString() }
32
+ }
33
+ }
34
+
35
+ const [state, formAction] = useActionState(updateCustomerEmail, {
36
+ error: false,
37
+ success: false,
38
+ })
39
+
40
+ const clearState = () => {
41
+ setSuccessState(false)
42
+ }
43
+
44
+ useEffect(() => {
45
+ setSuccessState(state.success)
46
+ }, [state])
47
+
48
+ return (
49
+ <form action={formAction} className="w-full">
50
+ <AccountInfo
51
+ label="form.email"
52
+ currentInfo={`${customer.email}`}
53
+ isSuccess={successState}
54
+ isError={!!state.error}
55
+ errorMessage={state.error}
56
+ clearState={clearState}
57
+ data-testid="account-email-editor"
58
+ >
59
+ <div className="grid grid-cols-1 gap-y-2">
60
+ <Input
61
+ label="form.email"
62
+ name="email"
63
+ type="email"
64
+ autoComplete="email"
65
+ required
66
+ defaultValue={customer.email}
67
+ data-testid="email-input"
68
+ />
69
+ </div>
70
+ </AccountInfo>
71
+ </form>
72
+ )
73
+ }
74
+
75
+ export default ProfileEmail