@wix/agent-skills 1.20.1 → 1.22.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.
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +71 -113
- package/skills/wix-app/references/APP_TOOLS.md +2 -1
- package/skills/wix-app/references/BACKEND_EVENT.md +3 -3
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +41 -152
- package/skills/wix-app/references/DASHBOARD_MODAL.md +4 -4
- package/skills/wix-app/references/DASHBOARD_PAGE.md +11 -25
- package/skills/wix-app/references/DATA_COLLECTION.md +16 -219
- package/skills/wix-app/references/SDK_MODULE_MAP.md +44 -0
- package/skills/wix-app/references/SITE_PLUGIN.md +36 -190
- package/skills/wix-app/references/app-tools/TOOLS.md +3 -1
- package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +21 -0
- package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +182 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +97 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md +184 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +203 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_SETTINGS.md +44 -0
- package/skills/wix-app/references/dashboard-page/ECOM_NAVIGATION.md +17 -0
- package/skills/wix-app/references/dashboard-page/QUERY_AND_PAGING.md +182 -0
- package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +133 -0
- package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +10 -5
- package/skills/wix-app/references/dashboard-plugin/SLOTS.md +4 -18
- package/skills/wix-app/references/data-collection/LIFECYCLE.md +68 -0
- package/skills/wix-app/references/data-collection/PERMISSIONS.md +47 -0
- package/skills/wix-app/references/data-collection/SCHEMA.md +181 -0
- package/skills/wix-app/references/data-collection/WIX_DATA.md +38 -66
- package/skills/wix-app/references/site-plugin/EXAMPLES.md +1 -1
- package/skills/wix-headless-fast/SKILL.md +144 -221
- package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
- package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +15 -15
- package/skills/wix-headless-fast/guides/existing-site.md +76 -0
- package/skills/wix-headless-fast/guides/reference-mode.md +97 -0
- package/skills/wix-headless-fast/install/AGENTS.md +35 -0
- package/skills/wix-headless-fast/install/agents-md.mjs +39 -0
- package/skills/wix-headless-fast/install/attach.mjs +161 -86
- package/skills/wix-headless-fast/install/deploy.mjs +21 -60
- package/skills/wix-headless-fast/install/lock.mjs +55 -0
- package/skills/wix-headless-fast/install/setup.mjs +259 -0
- package/skills/wix-headless-fast/install/templates.mjs +168 -0
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-coupon.md +10 -19
- package/skills/wix-manage/references/events/create-wix-event.md +5 -1
- package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +27 -0
- package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +83 -37
- package/skills/wix-headless-fast/install/fast-path.mjs +0 -181
- package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -301
- package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +0 -136
- package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +0 -112
- package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +0 -42
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +0 -31
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +0 -22
- package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +0 -137
- package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +0 -78
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +0 -117
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +0 -52
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +0 -47
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +0 -58
- package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +0 -62
- package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +0 -97
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +0 -24
- package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +0 -16156
- package/skills/wix-headless-fast/references/blog/rest/posts.ts +0 -42
- package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +0 -62
- package/skills/wix-headless-fast/references/blog/seed/SEED.md +0 -81
- package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +0 -287
- package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -275
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +0 -144
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +0 -119
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +0 -32
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +0 -23
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +0 -218
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +0 -169
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +0 -121
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +0 -92
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +0 -90
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +0 -57
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +0 -72
- package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +0 -76
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +0 -22
- package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +0 -11962
- package/skills/wix-headless-fast/references/bookings/rest/booking.ts +0 -113
- package/skills/wix-headless-fast/references/bookings/rest/services.ts +0 -55
- package/skills/wix-headless-fast/references/bookings/seed/SEED.md +0 -71
- package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +0 -302
- package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -353
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +0 -50
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +0 -37
- package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +0 -158
- package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +0 -93
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +0 -177
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +0 -123
- package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +0 -75
- package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +0 -41
- package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +0 -11262
- package/skills/wix-headless-fast/references/cms/rest/items.ts +0 -125
- package/skills/wix-headless-fast/references/cms/seed/SEED.md +0 -112
- package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +0 -324
- package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -305
- package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +0 -66
- package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +0 -178
- package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +0 -118
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +0 -35
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +0 -24
- package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +0 -130
- package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +0 -97
- package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +0 -55
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +0 -113
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +0 -156
- package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +0 -97
- package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +0 -61
- package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +0 -12
- package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +0 -80
- package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +0 -21
- package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +0 -11884
- package/skills/wix-headless-fast/references/events/rest/events.ts +0 -57
- package/skills/wix-headless-fast/references/events/rest/registration.ts +0 -83
- package/skills/wix-headless-fast/references/events/seed/SEED.md +0 -95
- package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +0 -276
- package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +0 -338
- package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +0 -85
- package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +0 -332
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +0 -238
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +0 -54
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +0 -216
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +0 -59
- package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +0 -135
- package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +0 -10593
- package/skills/wix-headless-fast/references/forms/rest/forms.ts +0 -34
- package/skills/wix-headless-fast/references/forms/rest/submissions.ts +0 -56
- package/skills/wix-headless-fast/references/forms/seed/SEED.md +0 -116
- package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +0 -327
- package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -314
- package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +0 -60
- package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +0 -155
- package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +0 -78
- package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +0 -47
- package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +0 -66
- package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +0 -105
- package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +0 -59
- package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +0 -53
- package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +0 -122
- package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +0 -43
- package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +0 -29
- package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +0 -21
- package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +0 -42
- package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +0 -10
- package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +0 -11
- package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +0 -10329
- package/skills/wix-headless-fast/references/members/rest/auth.ts +0 -215
- package/skills/wix-headless-fast/references/members/rest/members.ts +0 -26
- package/skills/wix-headless-fast/references/members/seed/SEED.md +0 -39
- package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +0 -94
- package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -313
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +0 -110
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +0 -90
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +0 -35
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +0 -85
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +0 -32
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +0 -21
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +0 -31
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +0 -82
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +0 -58
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +0 -177
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +0 -78
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +0 -81
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +0 -55
- package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +0 -30
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +0 -21
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +0 -29
- package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +0 -10197
- package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +0 -75
- package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +0 -86
- package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +0 -258
- package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -294
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +0 -47
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +0 -101
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +0 -41
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +0 -16
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +0 -22
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +0 -54
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +0 -106
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +0 -64
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +0 -27
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +0 -43
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +0 -22
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +0 -30
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +0 -41
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +0 -40
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +0 -21
- package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +0 -11226
- package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +0 -31
- package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +0 -20
- package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +0 -79
- package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +0 -279
- package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -358
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +0 -142
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +0 -26
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +0 -121
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +0 -155
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +0 -34
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +0 -43
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +0 -34
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +0 -155
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +0 -89
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +0 -71
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +0 -103
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +0 -124
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +0 -185
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +0 -193
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +0 -94
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +0 -74
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +0 -168
- package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +0 -47
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +0 -22
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +0 -12
- package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +0 -12560
- package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +0 -60
- package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +0 -169
- package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +0 -68
- package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +0 -89
- package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +0 -479
- package/skills/wix-headless-fast/references/shared/CONTENT.md +0 -22
- package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +0 -73
- package/skills/wix-headless-fast/references/shared/DESIGN.md +0 -26
- package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +0 -23
- package/skills/wix-headless-fast/references/shared/app/styles/global.css +0 -52
- package/skills/wix-headless-fast/references/shared/app/wix/config.ts +0 -15
- package/skills/wix-headless-fast/references/shared/app/wix/media.ts +0 -81
- package/skills/wix-headless-fast/references/shared/app/wix/money.ts +0 -24
- package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +0 -89
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +0 -46
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +0 -46
- package/skills/wix-headless-fast/references/shared/rest/client.ts +0 -155
- package/skills/wix-headless-fast/references/shared/rest/config.ts +0 -3
- package/skills/wix-headless-fast/references/shared/rest/media.ts +0 -65
- package/skills/wix-headless-fast/references/shared/seed/images.mjs +0 -145
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +0 -608
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +0 -26
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +0 -155
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +0 -266
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +0 -95
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +0 -136
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +0 -48
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +0 -39
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +0 -34
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +0 -121
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +0 -107
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +0 -138
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +0 -309
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +0 -133
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +0 -147
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +0 -289
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +0 -167
- package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +0 -65
- package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +0 -12247
- package/skills/wix-headless-fast/references/storefront/rest/cart.ts +0 -132
- package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +0 -123
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +0 -124
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -525
|
@@ -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
|
-
}
|
package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts
DELETED
|
@@ -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
|
-
}
|
package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts
DELETED
|
@@ -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
|
-
}
|