@wix/agent-skills 1.21.0 → 1.23.0

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 (269) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +71 -7
  3. package/skills/wix-app/references/APP_VALIDATION.md +16 -10
  4. package/skills/wix-app/references/DASHBOARD_PAGE.md +11 -25
  5. package/skills/wix-app/references/DATA_COLLECTION.md +16 -219
  6. package/skills/wix-app/references/SDK_MODULE_MAP.md +2 -0
  7. package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +182 -0
  8. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +97 -0
  9. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md +184 -0
  10. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +203 -0
  11. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_SETTINGS.md +44 -0
  12. package/skills/wix-app/references/dashboard-page/QUERY_AND_PAGING.md +182 -0
  13. package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +133 -0
  14. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +10 -5
  15. package/skills/wix-app/references/data-collection/LIFECYCLE.md +68 -0
  16. package/skills/wix-app/references/data-collection/PERMISSIONS.md +47 -0
  17. package/skills/wix-app/references/data-collection/SCHEMA.md +181 -0
  18. package/skills/wix-app/references/data-collection/WIX_DATA.md +38 -66
  19. package/skills/wix-headless-fast/SKILL.md +95 -230
  20. package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
  21. package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +17 -14
  22. package/skills/wix-headless-fast/guides/existing-site.md +78 -0
  23. package/skills/wix-headless-fast/guides/migration.md +43 -0
  24. package/skills/wix-headless-fast/guides/reference-mode.md +100 -0
  25. package/skills/wix-headless-fast/install/AGENTS.md +9 -4
  26. package/skills/wix-headless-fast/install/agents-md.mjs +5 -1
  27. package/skills/wix-headless-fast/install/attach.mjs +25 -47
  28. package/skills/wix-headless-fast/install/check.mjs +87 -0
  29. package/skills/wix-headless-fast/install/context.mjs +126 -0
  30. package/skills/wix-headless-fast/install/deploy.mjs +106 -80
  31. package/skills/wix-headless-fast/install/lock.mjs +55 -0
  32. package/skills/wix-headless-fast/install/setup.mjs +83 -23
  33. package/skills/wix-headless-fast/install/templates.mjs +168 -0
  34. package/skills/wix-manage/SKILL.md +3 -3
  35. package/skills/wix-manage/references/app-installation/install-wix-apps.md +68 -2
  36. package/skills/wix-manage/references/contacts/bulk-label-and-unlabel-contacts.md +37 -4
  37. package/skills/wix-manage/references/ecommerce/ecom-pricing.md +29 -3
  38. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +27 -0
  39. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +83 -37
  40. package/skills/wix-manage/references/sites/site-import.md +101 -37
  41. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -303
  42. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +0 -136
  43. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +0 -112
  44. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +0 -42
  45. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +0 -31
  46. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +0 -22
  47. package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +0 -137
  48. package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +0 -78
  49. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +0 -117
  50. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +0 -52
  51. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +0 -47
  52. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +0 -58
  53. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +0 -62
  54. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +0 -40
  55. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +0 -97
  56. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +0 -24
  57. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +0 -16156
  58. package/skills/wix-headless-fast/references/blog/rest/posts.ts +0 -42
  59. package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +0 -62
  60. package/skills/wix-headless-fast/references/blog/seed/SEED.md +0 -81
  61. package/skills/wix-headless-fast/references/blog/seed/read-site.mjs +0 -22
  62. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +0 -287
  63. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -277
  64. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +0 -144
  65. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +0 -119
  66. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +0 -32
  67. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +0 -23
  68. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +0 -218
  69. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +0 -169
  70. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +0 -121
  71. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +0 -92
  72. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +0 -90
  73. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +0 -57
  74. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +0 -72
  75. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +0 -40
  76. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +0 -76
  77. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +0 -22
  78. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +0 -11962
  79. package/skills/wix-headless-fast/references/bookings/rest/booking.ts +0 -113
  80. package/skills/wix-headless-fast/references/bookings/rest/services.ts +0 -55
  81. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +0 -71
  82. package/skills/wix-headless-fast/references/bookings/seed/read-site.mjs +0 -28
  83. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +0 -302
  84. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -355
  85. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +0 -50
  86. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +0 -37
  87. package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +0 -158
  88. package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +0 -93
  89. package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +0 -177
  90. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +0 -123
  91. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +0 -75
  92. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +0 -41
  93. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +0 -11262
  94. package/skills/wix-headless-fast/references/cms/rest/items.ts +0 -125
  95. package/skills/wix-headless-fast/references/cms/seed/SEED.md +0 -112
  96. package/skills/wix-headless-fast/references/cms/seed/read-site.mjs +0 -20
  97. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +0 -324
  98. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -307
  99. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +0 -66
  100. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +0 -178
  101. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +0 -118
  102. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +0 -35
  103. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +0 -24
  104. package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +0 -130
  105. package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +0 -97
  106. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +0 -55
  107. package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +0 -113
  108. package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +0 -156
  109. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +0 -97
  110. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +0 -61
  111. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +0 -40
  112. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +0 -12
  113. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +0 -80
  114. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +0 -21
  115. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +0 -11884
  116. package/skills/wix-headless-fast/references/events/rest/events.ts +0 -57
  117. package/skills/wix-headless-fast/references/events/rest/registration.ts +0 -83
  118. package/skills/wix-headless-fast/references/events/seed/SEED.md +0 -95
  119. package/skills/wix-headless-fast/references/events/seed/read-site.mjs +0 -26
  120. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +0 -276
  121. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +0 -340
  122. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +0 -85
  123. package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +0 -332
  124. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +0 -238
  125. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +0 -54
  126. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +0 -216
  127. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +0 -59
  128. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +0 -135
  129. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +0 -10593
  130. package/skills/wix-headless-fast/references/forms/rest/forms.ts +0 -34
  131. package/skills/wix-headless-fast/references/forms/rest/submissions.ts +0 -56
  132. package/skills/wix-headless-fast/references/forms/seed/SEED.md +0 -116
  133. package/skills/wix-headless-fast/references/forms/seed/read-site.mjs +0 -20
  134. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +0 -327
  135. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -316
  136. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +0 -60
  137. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +0 -155
  138. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +0 -78
  139. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +0 -47
  140. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +0 -66
  141. package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +0 -105
  142. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +0 -59
  143. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +0 -53
  144. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +0 -122
  145. package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +0 -43
  146. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +0 -29
  147. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +0 -21
  148. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +0 -42
  149. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +0 -10
  150. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +0 -11
  151. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +0 -10329
  152. package/skills/wix-headless-fast/references/members/rest/auth.ts +0 -215
  153. package/skills/wix-headless-fast/references/members/rest/members.ts +0 -26
  154. package/skills/wix-headless-fast/references/members/seed/SEED.md +0 -39
  155. package/skills/wix-headless-fast/references/members/seed/read-site.mjs +0 -15
  156. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +0 -94
  157. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -315
  158. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +0 -110
  159. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +0 -90
  160. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +0 -35
  161. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +0 -85
  162. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +0 -32
  163. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +0 -21
  164. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +0 -31
  165. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +0 -82
  166. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +0 -58
  167. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +0 -177
  168. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +0 -78
  169. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +0 -81
  170. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +0 -55
  171. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +0 -40
  172. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +0 -30
  173. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +0 -21
  174. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +0 -29
  175. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +0 -10197
  176. package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +0 -75
  177. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +0 -86
  178. package/skills/wix-headless-fast/references/portfolio/seed/read-site.mjs +0 -20
  179. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +0 -256
  180. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -296
  181. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +0 -47
  182. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +0 -101
  183. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +0 -41
  184. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +0 -16
  185. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +0 -22
  186. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +0 -54
  187. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +0 -106
  188. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +0 -64
  189. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +0 -27
  190. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +0 -43
  191. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +0 -22
  192. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +0 -30
  193. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +0 -41
  194. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +0 -40
  195. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +0 -21
  196. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +0 -11226
  197. package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +0 -31
  198. package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +0 -20
  199. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +0 -79
  200. package/skills/wix-headless-fast/references/pricing-plans/seed/read-site.mjs +0 -21
  201. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +0 -279
  202. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -360
  203. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +0 -142
  204. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +0 -26
  205. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +0 -121
  206. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +0 -155
  207. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +0 -34
  208. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +0 -43
  209. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +0 -34
  210. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +0 -155
  211. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +0 -89
  212. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +0 -71
  213. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +0 -103
  214. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +0 -124
  215. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +0 -185
  216. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +0 -193
  217. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +0 -94
  218. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +0 -74
  219. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +0 -168
  220. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +0 -47
  221. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +0 -22
  222. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +0 -12
  223. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +0 -12560
  224. package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +0 -60
  225. package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +0 -169
  226. package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +0 -68
  227. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +0 -89
  228. package/skills/wix-headless-fast/references/restaurants/seed/read-site.mjs +0 -25
  229. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +0 -499
  230. package/skills/wix-headless-fast/references/shared/CONTENT.md +0 -22
  231. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +0 -73
  232. package/skills/wix-headless-fast/references/shared/DESIGN.md +0 -26
  233. package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +0 -23
  234. package/skills/wix-headless-fast/references/shared/app/styles/global.css +0 -52
  235. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +0 -15
  236. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +0 -81
  237. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +0 -24
  238. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +0 -89
  239. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +0 -46
  240. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +0 -46
  241. package/skills/wix-headless-fast/references/shared/rest/client.ts +0 -155
  242. package/skills/wix-headless-fast/references/shared/rest/config.ts +0 -3
  243. package/skills/wix-headless-fast/references/shared/rest/media.ts +0 -65
  244. package/skills/wix-headless-fast/references/shared/seed/images.mjs +0 -145
  245. package/skills/wix-headless-fast/references/shared/seed/read-site.mjs +0 -99
  246. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +0 -612
  247. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +0 -26
  248. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +0 -155
  249. package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +0 -266
  250. package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +0 -95
  251. package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +0 -136
  252. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +0 -48
  253. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +0 -39
  254. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +0 -34
  255. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +0 -121
  256. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +0 -107
  257. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +0 -138
  258. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +0 -314
  259. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +0 -133
  260. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +0 -147
  261. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +0 -289
  262. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +0 -169
  263. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +0 -65
  264. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +0 -12247
  265. package/skills/wix-headless-fast/references/storefront/rest/cart.ts +0 -132
  266. package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +0 -123
  267. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +0 -130
  268. package/skills/wix-headless-fast/references/storefront/seed/read-site.mjs +0 -38
  269. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -561
@@ -1,103 +0,0 @@
1
- // Client-side order-cart state — a module-scope store, deliberately NOT a React context.
2
- // A context can't span Astro islands (each island is its own React root); a module singleton
3
- // is shared by every island in the page bundle, and works identically in a single-root SPA.
4
- // Consume it through useOrderCart() (hooks/), or subscribe directly.
5
- import type { OrderCart } from "./types";
6
- import {
7
- addToOrder as apiAdd,
8
- fetchOrderCart,
9
- orderCheckoutUrl,
10
- removeOrderLine as apiRemove,
11
- resolveOperationId,
12
- updateOrderQuantity as apiUpdate,
13
- } from "./ordering";
14
-
15
- export interface OrderCartState {
16
- cart: OrderCart | null;
17
- /** null while resolving; false → no ordering operation configured (show "unavailable"). */
18
- ordering: boolean | null;
19
- /** True while any cart operation is in flight. */
20
- busy: boolean;
21
- /** Last failed operation's message — render it; a new operation clears it. */
22
- error: string | null;
23
- /** Order drawer visibility (OrderCartButton opens it, OrderCartDrawer renders by it). */
24
- open: boolean;
25
- }
26
-
27
- const EMPTY: OrderCartState = { cart: null, ordering: null, busy: false, error: null, open: false };
28
-
29
- let state: OrderCartState = EMPTY;
30
- const listeners = new Set<() => void>();
31
- let loaded = false;
32
-
33
- function setState(patch: Partial<OrderCartState>): void {
34
- state = { ...state, ...patch };
35
- for (const l of listeners) l();
36
- }
37
-
38
- export function getOrderCartState(): OrderCartState {
39
- return state;
40
- }
41
-
42
- export function subscribeOrderCart(listener: () => void): () => void {
43
- listeners.add(listener);
44
- // First subscriber triggers the initial load (browser only — SSR renders the empty state).
45
- if (!loaded && typeof window !== "undefined") {
46
- loaded = true;
47
- void refreshOrderCart();
48
- void resolveOperationId().then((id) => setState({ ordering: id !== null }));
49
- }
50
- return () => listeners.delete(listener);
51
- }
52
-
53
- async function run(op: () => Promise<OrderCart>): Promise<void> {
54
- setState({ busy: true, error: null });
55
- try {
56
- setState({ cart: await op(), busy: false });
57
- } catch (e) {
58
- setState({ busy: false, error: e instanceof Error ? e.message : String(e) });
59
- throw e;
60
- }
61
- }
62
-
63
- export async function refreshOrderCart(): Promise<void> {
64
- try {
65
- setState({ cart: await fetchOrderCart() });
66
- } catch {
67
- /* no cart yet — leave the empty state */
68
- }
69
- }
70
-
71
- /** Add a menu item to the order and open the drawer. Throws (and sets .error) on refusal. */
72
- export async function addOrderLine(
73
- itemId: string,
74
- context: { menuId: string; sectionId: string },
75
- quantity = 1,
76
- ): Promise<void> {
77
- await run(() => apiAdd(itemId, context, quantity));
78
- setState({ open: true });
79
- }
80
-
81
- export async function updateOrderLineQuantity(lineItemId: string, quantity: number): Promise<void> {
82
- await run(() => apiUpdate(lineItemId, quantity));
83
- }
84
-
85
- export async function removeLineFromOrder(lineItemId: string): Promise<void> {
86
- await run(() => apiRemove(lineItemId));
87
- }
88
-
89
- /** Navigate to the Wix-hosted checkout. Never hand-build a checkout URL. */
90
- export async function goToOrderCheckout(): Promise<void> {
91
- setState({ busy: true, error: null });
92
- try {
93
- const url = await orderCheckoutUrl();
94
- window.location.href = url;
95
- } catch (e) {
96
- setState({ busy: false, error: e instanceof Error ? e.message : String(e) });
97
- throw e;
98
- }
99
- }
100
-
101
- export function setOrderCartOpen(open: boolean): void {
102
- setState({ open });
103
- }
@@ -1,124 +0,0 @@
1
- // Online-ordering rules and DTO mapping — transport-agnostic, imported by both ./ordering.ts (SDK)
2
- // and the REST twin in references/restaurants/rest/ordering.ts (fetch). The restaurant cart rides
3
- // on the eCom current cart (Cart V2); what makes a line a RESTAURANT line is the catalogReference
4
- // built here: the Orders app id plus options { operationId, menuId, sectionId } — all three, and
5
- // no variantId. Raw entities carry `_id` (SDK) or `id` (REST). Has its own formatMoney (a copy of
6
- // ../money.ts) so it stands alone when stripped. Imports are type-only.
7
- import type { FulfillmentMethodInfo, OrderCart, OrderLine } from "./types";
8
- import type { ImgSrc, Raw } from "./menu-core";
9
-
10
- /** The Restaurants Orders app id — every restaurant cart line's catalogReference.appId. */
11
- export const RESTAURANTS_ORDERS_APP_ID = "9a5d83fd-8570-482e-81ab-cfa88942ee60";
12
-
13
- export const rawId = (raw: Raw | undefined | null): string => raw?._id ?? raw?.id ?? "";
14
-
15
- /**
16
- * Cart V2 money is ConvertedMoney { amount, convertedAmount } with NO formatted string, and the
17
- * currency lives on the cart, not on the money. Never hardcode a symbol or assume USD.
18
- */
19
- export function formatMoney(money: Raw | null | undefined, currencyCode: string | null | undefined): string {
20
- const value = money?.convertedAmount ?? money?.amount;
21
- if (value == null || value === "") return "";
22
- const currency = currencyCode || "USD";
23
- try {
24
- return new Intl.NumberFormat(undefined, { style: "currency", currency }).format(Number(value));
25
- } catch {
26
- return `${value} ${currency}`;
27
- }
28
- }
29
-
30
- export const cartCurrency = (raw: Raw | null | undefined): string =>
31
- raw?.customerInfo?.currencyCode ?? raw?.businessInfo?.currencyCode ?? "";
32
-
33
- /** The operation to order through: ENABLED, else the default, else the first; null when none exists. */
34
- export function pickOperationId(operations: Raw[]): string | null {
35
- const op = operations.find((o) => o.onlineOrderingStatus === "ENABLED") ?? operations.find((o) => o.default) ?? operations[0];
36
- return op ? rawId(op) || null : null;
37
- }
38
-
39
- /** Enabled pickup/delivery methods, for display — fees and minimums as decimal strings. */
40
- export function toFulfillmentMethods(raws: Raw[]): FulfillmentMethodInfo[] {
41
- return raws
42
- .filter((m) => m.enabled === true)
43
- .map((m): FulfillmentMethodInfo => ({
44
- id: rawId(m),
45
- type: m.type === "DELIVERY" ? "DELIVERY" : "PICKUP",
46
- name: m.name ?? "",
47
- fee: m.fee ?? "0",
48
- minOrderPrice: m.minOrderPrice ?? "0",
49
- }))
50
- .filter((m) => m.id);
51
- }
52
-
53
- export function toOrderLine(raw: Raw, currency: string, imgSrc: ImgSrc): OrderLine {
54
- return {
55
- lineItemId: rawId(raw), // the LINE id — what update/remove take, never the menu item id
56
- itemName: raw.name?.original ?? "",
57
- quantity: raw.quantityInfo?.confirmedQuantity ?? 0,
58
- unitPrice: formatMoney(raw.pricing?.unitPrice, currency),
59
- linePrice: formatMoney(raw.pricing?.totalPrice, currency),
60
- imageUrl: imgSrc(raw.attributes?.image, 300, 300),
61
- descriptionLines: ((raw.attributes?.descriptionLines ?? []) as Raw[])
62
- .map((d) => {
63
- const label = d.name?.original ?? "", value = d.plainText?.original ?? d.colorInfo?.original ?? "";
64
- return label && value ? `${label}: ${value}` : value || label;
65
- })
66
- .filter(Boolean),
67
- status: raw.status ?? "IN_STOCK", // not IN_STOCK → the line can't be checked out as-is
68
- };
69
- }
70
-
71
- export function toOrderCart(raw: Raw | null, subtotal: string, imgSrc: ImgSrc): OrderCart {
72
- const currency = cartCurrency(raw);
73
- const lines = ((raw?.lineItems ?? []) as Raw[]).map((l) => toOrderLine(l, currency, imgSrc));
74
- return { lines, itemCount: lines.reduce((n, l) => n + l.quantity, 0), subtotal, currency };
75
- }
76
-
77
- /** The after-discount subtotal from a cart estimate; "" when unknown. Fees, tax, delivery resolve at checkout. */
78
- export function estimateSubtotal(estimate: Raw | null | undefined, raw: Raw): string {
79
- return formatMoney(estimate?.summary?.priceSummary?.subtotal, cartCurrency(raw));
80
- }
81
-
82
- /** The line-refusal reasons an add can't recover from — checked before any call. */
83
- export function assertOrderContext(itemId: string, menuId: string, sectionId: string): void {
84
- if (!itemId || !menuId || !sectionId) throw new Error("addToOrder needs the item, menu, and section ids.");
85
- }
86
-
87
- /**
88
- * The one catalogItems entry of an add: the Orders app id and the three context ids — the
89
- * restaurant analog of the store's variantId. Modifier/variant selections are NOT sent (that
90
- * options shape isn't documented for a client add); quantity only.
91
- */
92
- export function orderCatalogItem(itemId: string, ctx: { operationId: string; menuId: string; sectionId: string }, quantity: number): Raw {
93
- return {
94
- quantity,
95
- catalogReference: {
96
- catalogItemId: itemId,
97
- appId: RESTAURANTS_ORDERS_APP_ID,
98
- options: { operationId: ctx.operationId, menuId: ctx.menuId, sectionId: ctx.sectionId },
99
- },
100
- };
101
- }
102
-
103
- /** Read the add result — a refused add still returns 200: a line whose status isn't IN_STOCK, or no line, is a refusal. */
104
- export function assertOrderAdded(cart: Raw | null | undefined, itemId: string): void {
105
- // V2 nests the reference under `source` — a top-level lineItem.catalogReference no longer exists.
106
- const line = ((cart?.lineItems ?? []) as Raw[]).find((l) => l.source?.catalogReference?.catalogItemId === itemId);
107
- if (line?.status && line.status !== "IN_STOCK") {
108
- throw new Error(`This dish isn't available right now (${String(line.status).toLowerCase().replace(/_/g, " ")}).`);
109
- }
110
- if (!line || line.quantityInfo?.confirmedQuantity === 0) {
111
- throw new Error("The dish couldn't be added to the order — please try again.");
112
- }
113
- }
114
-
115
- /** Refuse checkout for an empty order or any line not IN_STOCK — say which. */
116
- export function assertOrderCheckoutable(raw: Raw | null): void {
117
- const lines: Raw[] = raw?.lineItems ?? [];
118
- if (!lines.length) throw new Error("Your order is empty.");
119
- const unavailable = lines.filter((l) => l.status && l.status !== "IN_STOCK");
120
- if (unavailable.length) {
121
- throw new Error(`Some dishes are no longer available: ${unavailable.map((l) => l.name?.original).filter(Boolean).join(", ")}.`);
122
- }
123
- if (!rawId(raw)) throw new Error("Checkout couldn't start: the order has no id.");
124
- }
@@ -1,185 +0,0 @@
1
- // Online ordering (Restaurants Orders + Wix eCom Cart V2) over the SDK — the only file that
2
- // touches the raw cart and operation entities on this transport. Rules and mappers live in
3
- // ./ordering-core (shared with the REST twin in references/restaurants/rest/); this file is the
4
- // transport only. Copy as-is; extend by calling these exports, never by editing them. The request
5
- // shapes are exact and rewriting them is how carts break:
6
- // - the catalogReference appId is the ORDERS app (9a5d83fd-…), never the Stores id;
7
- // - options MUST carry operationId + menuId + sectionId (all three) — no variantId;
8
- // - modifier/variant selections are NOT sent on the line (undocumented for a client add).
9
- // Failures are loud: throws on a missing ordering operation, unavailable lines, and an empty
10
- // order at checkout — surface the message, don't swallow it.
11
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/restaurants/online-orders/operations/list-operations.md
12
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/restaurants/online-orders/fulfillment-methods/list-fulfillment-methods.md
13
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/restaurants/menus/items/items/list-items.md
14
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/get-current-cart.md
15
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/add-line-items-to-current-cart.md
16
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/update-line-items.md
17
- // docs: https://dev.wix.com/docs/api-reference/business-management/headless/redirects/create-redirect-session.md
18
- import { operations as operationsModule, fulfillmentMethods as fulfillmentModule, items as itemsModule } from "@wix/restaurants";
19
- import { currentCartV2 } from "@wix/ecom";
20
- import { redirects as redirectsModule } from "@wix/redirects";
21
- import { wixModule } from "../sdk";
22
- import { imgSrc } from "../media";
23
- import {
24
- RESTAURANTS_ORDERS_APP_ID,
25
- assertOrderAdded,
26
- assertOrderCheckoutable,
27
- assertOrderContext,
28
- estimateSubtotal,
29
- orderCatalogItem,
30
- pickOperationId,
31
- rawId,
32
- toFulfillmentMethods,
33
- toOrderCart,
34
- } from "./ordering-core";
35
- import type { Raw } from "./menu-core";
36
- import type { FulfillmentMethodInfo, OrderCart } from "./types";
37
-
38
- export { RESTAURANTS_ORDERS_APP_ID };
39
-
40
- const operationsApi = wixModule(operationsModule);
41
- const fulfillmentApi = wixModule(fulfillmentModule);
42
- const itemsApi = wixModule(itemsModule);
43
- const cartApi = wixModule(currentCartV2);
44
- const redirects = wixModule(redirectsModule);
45
-
46
- // The ordering operation is site config — resolve once, reuse for every add.
47
- let operationIdPromise: Promise<string | null> | null = null;
48
-
49
- /**
50
- * The id of the operation to order through (ENABLED, else default, else first) — null when
51
- * the site has no online ordering configured (show an "ordering unavailable" state).
52
- */
53
- export function resolveOperationId(): Promise<string | null> {
54
- operationIdPromise ??= operationsApi
55
- .listOperations()
56
- .then((res: Raw) => pickOperationId(res.operations ?? []))
57
- .catch(() => {
58
- operationIdPromise = null; // transient failure — allow a retry on the next call
59
- return null;
60
- });
61
- return operationIdPromise;
62
- }
63
-
64
- /** Enabled pickup/delivery methods, for display — the buyer picks one on the hosted checkout. */
65
- export async function fetchFulfillmentMethods(): Promise<FulfillmentMethodInfo[]> {
66
- try {
67
- const res: Raw = await fulfillmentApi.listFulfillmentMethods();
68
- return toFulfillmentMethods(res.fulfillmentMethods ?? []);
69
- } catch {
70
- return []; // display nicety — ordering still works without the list
71
- }
72
- }
73
-
74
- // A line's attributes.image may come back absent — join the menu items' images by the line's
75
- // catalogItemId and cache for the session.
76
- const lineImageCache = new Map<string, string>();
77
- async function fillLineImages(cart: OrderCart, raws: Raw[]): Promise<void> {
78
- const wanted = new Map<string, number[]>(); // itemId -> line indexes
79
- raws.forEach((raw, i) => {
80
- if (cart.lines[i].imageUrl) return;
81
- const itemId = raw.source?.catalogReference?.catalogItemId;
82
- if (!itemId) return;
83
- const cached = lineImageCache.get(itemId);
84
- if (cached !== undefined) {
85
- cart.lines[i].imageUrl = cached;
86
- return;
87
- }
88
- wanted.set(itemId, [...(wanted.get(itemId) ?? []), i]);
89
- });
90
- if (!wanted.size) return;
91
- try {
92
- const res: Raw = await itemsApi.listItems({ itemIds: [...wanted.keys()] });
93
- for (const item of (res.items ?? []) as Raw[]) {
94
- const url = imgSrc(item.image, 300, 300);
95
- lineImageCache.set(rawId(item), url);
96
- for (const i of wanted.get(rawId(item)) ?? []) cart.lines[i].imageUrl = url;
97
- }
98
- } catch {
99
- /* images are a nicety — the cart stays correct without them */
100
- }
101
- }
102
-
103
- async function readCartWithSubtotal(raw: Raw | null): Promise<OrderCart> {
104
- // Only estimate a cart WITH lines — on an absent/empty cart the endpoint returns 404.
105
- if (!raw?.lineItems?.length) return toOrderCart(raw, "", imgSrc);
106
- // The authoritative after-discount subtotal comes from the cart estimate, never from
107
- // hand-summing line items (fees, tax, and delivery resolve at checkout).
108
- let subtotal = "";
109
- try {
110
- subtotal = estimateSubtotal(await cartApi.estimateCurrentCart(), raw);
111
- } catch {
112
- /* estimate is a display nicety — the cart itself is still valid */
113
- }
114
- const cart = toOrderCart(raw, subtotal, imgSrc);
115
- await fillLineImages(cart, raw.lineItems as Raw[]);
116
- return cart;
117
- }
118
-
119
- /** Read the visitor's current order cart. An empty cart (not an error) when none exists yet. */
120
- export async function fetchOrderCart(): Promise<OrderCart> {
121
- try {
122
- const { cart } = await cartApi.getCurrentCart();
123
- return readCartWithSubtotal(cart as Raw);
124
- } catch {
125
- return toOrderCart(null, "", imgSrc);
126
- }
127
- }
128
-
129
- /**
130
- * Add a menu item to the current order. `menuId` and `sectionId` are the ids of the menu and
131
- * section the item is RENDERED UNDER — thread them from the render context (the fetchMenus
132
- * tree), never re-derive them. Throws when ordering isn't configured or the line is refused.
133
- */
134
- export async function addToOrder(
135
- itemId: string,
136
- { menuId, sectionId }: { menuId: string; sectionId: string },
137
- quantity = 1,
138
- ): Promise<OrderCart> {
139
- const operationId = await resolveOperationId();
140
- if (!operationId) throw new Error("Online ordering isn't available right now.");
141
- assertOrderContext(itemId, menuId, sectionId);
142
- const { cart } = await cartApi.addLineItemsToCurrentCart({
143
- catalogItems: [orderCatalogItem(itemId, { operationId, menuId, sectionId }, quantity)],
144
- });
145
- assertOrderAdded(cart as Raw, itemId);
146
- return readCartWithSubtotal(cart as Raw);
147
- }
148
-
149
- /** Change a line's quantity. `lineItemId` is OrderLine.lineItemId, never the menu item id. */
150
- export async function updateOrderQuantity(lineItemId: string, quantity: number): Promise<OrderCart> {
151
- const { cart } = await cartApi.updateLineItemsInCurrentCart({
152
- lineItems: [{ lineItemId, quantity: { newQuantity: quantity } }],
153
- });
154
- return readCartWithSubtotal(cart as Raw);
155
- }
156
-
157
- /** Remove a line from the order by OrderLine.lineItemId. */
158
- export async function removeOrderLine(lineItemId: string): Promise<OrderCart> {
159
- const { cart } = await cartApi.removeLineItemsFromCurrentCart([lineItemId]);
160
- return readCartWithSubtotal(cart as Raw);
161
- }
162
-
163
- /**
164
- * Start the Wix-hosted checkout for the current order and return the URL to navigate to.
165
- * The cart's id IS the checkout id — no separate checkout-creation call. Fulfillment
166
- * (pickup/delivery + time) and payment are collected on the hosted page. Call from the
167
- * browser: the return origin must be window.location.origin (https), never a server-derived
168
- * request origin (http behind the proxy → the return redirect 403s).
169
- */
170
- export async function orderCheckoutUrl(): Promise<string> {
171
- const { cart } = await cartApi.getCurrentCart();
172
- const raw = cart as Raw;
173
- assertOrderCheckoutable(raw);
174
- const origin = typeof window !== "undefined" ? window.location.origin : "";
175
- const session = await redirects.createRedirectSession({
176
- ecomCheckout: { checkoutId: rawId(raw) },
177
- callbacks: {
178
- postFlowUrl: origin ? `${origin}/` : undefined,
179
- thankYouPageUrl: origin ? `${origin}/` : undefined,
180
- },
181
- });
182
- const url = session?.redirectSession?.fullUrl;
183
- if (!url) throw new Error("Checkout couldn't start: no redirect URL returned.");
184
- return url;
185
- }
@@ -1,193 +0,0 @@
1
- // The table-reservation state machine as a framework-free store — the logic behind useReservation,
2
- // usable from React (useReservation wraps it), from a static page or Vue/Svelte, or as the
3
- // specification for a port. Location, date + party size, AVAILABLE slots, the 10-minute hold, the
4
- // details form, and confirm. All correctness (AVAILABLE-only slots, hold → reserve with the
5
- // revision, firstName + E.164 phone, RESERVED vs REQUESTED) lives in the data layer; this store
6
- // orchestrates. Browser-only: availability is timezone-specific. One store per mounted surface:
7
- // createReservationStore(), `start()` when mounted.
8
- import { completeReservation, fetchReservationLocations, fetchReservationSlots, holdReservation } from "./reservations";
9
- import type { ReservationConfirmation, ReservationHold, ReservationLocationInfo, ReservationReservee, ReservationSlot } from "./types";
10
-
11
- const todayKey = (): string => {
12
- const d = new Date();
13
- const pad = (n: number) => String(n).padStart(2, "0");
14
- return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
15
- };
16
-
17
- /** Everything a reservation surface renders from. Read it with getState() or through a subscription. */
18
- export interface ReservationState {
19
- /** null while loading; [] when Table Reservations isn't set up (honest empty state). */
20
- locations: ReservationLocationInfo[] | null;
21
- /** The active location (default first). Render a picker only when locations.length > 1. */
22
- location: ReservationLocationInfo | null;
23
- /** "YYYY-MM-DD" for a date input. */
24
- date: string;
25
- /** "HH:mm" anchor for the slot fan-out. */
26
- time: string;
27
- /** Clamped to the location's partySizeMin/Max. */
28
- partySize: number;
29
- /** AVAILABLE slots for the current query; null until findSlots ran. */
30
- slots: ReservationSlot[] | null;
31
- /** Set after holdSlot — the visitor has 10 minutes to confirm. */
32
- held: ReservationHold | null;
33
- reservee: ReservationReservee;
34
- /** True when a slot is held and firstName + phone are filled — gate the confirm CTA. */
35
- canConfirm: boolean;
36
- /** Set on success. REQUESTED → tell the visitor approval is pending, not confirmed. */
37
- confirmed: ReservationConfirmation | null;
38
- loading: boolean;
39
- error: string | null;
40
- }
41
-
42
- export interface ReservationStore {
43
- getState(): ReservationState;
44
- subscribe(listener: () => void): () => void;
45
- /** Load the locations. Call once when mounted (a browser). */
46
- start(): void;
47
- stop(): void;
48
- setLocationId(id: string): void;
49
- setDate(date: string): void;
50
- setTime(time: string): void;
51
- setPartySize(size: number): void;
52
- findSlots(): Promise<void>;
53
- holdSlot(slot: ReservationSlot): Promise<void>;
54
- setReserveeField(field: keyof ReservationReservee, value: string): void;
55
- confirm(): Promise<void>;
56
- /** Back to slot picking (keeps date/party). */
57
- reset(): void;
58
- }
59
-
60
- export function createReservationStore(): ReservationStore {
61
- let locations: ReservationLocationInfo[] | null = null;
62
- let locationId: string | null = null;
63
- let date = todayKey();
64
- let time = "19:00";
65
- let partySize = 2;
66
- let slots: ReservationSlot[] | null = null;
67
- let held: ReservationHold | null = null;
68
- let reservee: ReservationReservee = { firstName: "", phone: "" };
69
- let confirmed: ReservationConfirmation | null = null;
70
- let loading = false;
71
- let error: string | null = null;
72
- let started = false;
73
- const listeners = new Set<() => void>();
74
- let snapshot: ReservationState | null = null;
75
- const emit = () => {
76
- snapshot = null;
77
- for (const fn of listeners) fn();
78
- };
79
-
80
- const currentLocation = (): ReservationLocationInfo | null => locations?.find((l) => l.id === locationId) ?? locations?.[0] ?? null;
81
-
82
- function getState(): ReservationState {
83
- if (snapshot) return snapshot;
84
- snapshot = {
85
- locations,
86
- location: currentLocation(),
87
- date,
88
- time,
89
- partySize,
90
- slots,
91
- held,
92
- reservee,
93
- canConfirm: !!held && reservee.firstName.trim().length > 0 && reservee.phone.trim().length > 0 && !loading,
94
- confirmed,
95
- loading,
96
- error,
97
- };
98
- return snapshot;
99
- }
100
-
101
- const fail = (e: unknown) => (e instanceof Error ? e.message : String(e));
102
-
103
- return {
104
- getState,
105
- subscribe(fn) {
106
- listeners.add(fn);
107
- return () => listeners.delete(fn);
108
- },
109
- start() {
110
- if (started) return;
111
- started = true;
112
- fetchReservationLocations()
113
- .then((locs) => {
114
- if (!started) return;
115
- locations = locs;
116
- locationId ??= locs[0]?.id ?? null;
117
- emit();
118
- })
119
- .catch((e) => {
120
- if (!started) return;
121
- locations = [];
122
- error = fail(e);
123
- emit();
124
- });
125
- },
126
- stop() {
127
- started = false;
128
- },
129
- setLocationId(id) { locationId = id; emit(); },
130
- setDate(next) { date = next; emit(); },
131
- setTime(next) { time = next; emit(); },
132
- setPartySize(size) {
133
- const loc = currentLocation();
134
- const min = loc?.partySizeMin ?? 1;
135
- const max = loc?.partySizeMax ?? 20;
136
- partySize = Math.min(Math.max(size, min), max);
137
- emit();
138
- },
139
- async findSlots() {
140
- const loc = currentLocation();
141
- if (!loc) return;
142
- error = null; slots = null; held = null; confirmed = null; loading = true;
143
- emit();
144
- try {
145
- const aroundIso = new Date(`${date}T${time}:00`).toISOString();
146
- slots = await fetchReservationSlots(loc.id, aroundIso, partySize);
147
- } catch (e) {
148
- slots = [];
149
- error = fail(e);
150
- } finally {
151
- loading = false;
152
- emit();
153
- }
154
- },
155
- async holdSlot(slot) {
156
- const loc = currentLocation();
157
- if (!loc) return;
158
- error = null; loading = true;
159
- emit();
160
- try {
161
- held = await holdReservation(loc.id, slot.startIso, partySize);
162
- } catch (e) {
163
- error = fail(e);
164
- } finally {
165
- loading = false;
166
- emit();
167
- }
168
- },
169
- setReserveeField(field, value) {
170
- reservee = { ...reservee, [field]: value };
171
- emit();
172
- },
173
- async confirm() {
174
- if (!held) return;
175
- error = null; loading = true;
176
- emit();
177
- try {
178
- confirmed = await completeReservation(held, reservee);
179
- } catch (e) {
180
- // An expired hold can't be reserved — send the visitor back to slot picking.
181
- error = fail(e);
182
- held = null;
183
- } finally {
184
- loading = false;
185
- emit();
186
- }
187
- },
188
- reset() {
189
- held = null; confirmed = null; slots = null; error = null;
190
- emit();
191
- },
192
- };
193
- }