@wix/agent-skills 1.15.1 → 1.16.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/README.md +3 -7
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +4 -1
- package/skills/wix-app/references/APP_TOOLS.md +134 -0
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +1 -1
- package/skills/wix-app/references/DASHBOARD_PAGE.md +0 -10
- package/skills/wix-app/references/DATA_COLLECTION.md +1 -1
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +28 -9
- package/skills/wix-app/references/SERVICE_PLUGIN.md +12 -10
- package/skills/wix-app/references/app-tools/TOOLS.md +75 -0
- package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +2 -2
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +172 -0
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +138 -0
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +23 -2
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +29 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +1 -1
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +27 -2
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +5 -3
- package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +18 -1
- package/skills/wix-app/references/editor-react-component/PARTS.md +15 -2
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +2 -3
- package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +13 -9
- package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +4 -0
- package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
- package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +3 -1
- package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +4 -0
- package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +54 -0
- package/skills/wix-app/references/stores/QUERY.md +32 -0
- package/skills/wix-docs/SKILL.md +35 -3
- package/skills/wix-headless/SKILL.md +3 -1
- package/skills/wix-headless/references/CONTENT.md +36 -0
- package/skills/wix-headless/references/DESIGN.md +54 -0
- package/skills/wix-headless/references/DISCOVERY.md +24 -0
- package/skills/wix-headless/references/IMAGE_GENERATION.md +10 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +3 -2
- package/skills/wix-headless/references/inline-recipes/setup-online-store.md +32 -23
- package/skills/wix-headless/references/managed/CONNECT.md +1 -1
- package/skills/wix-headless/references/managed/CREATE.md +14 -0
- package/skills/wix-headless/references/managed/DEPLOYMENT.md +25 -0
- package/skills/wix-manage/SKILL.md +123 -7
- package/skills/wix-manage/references/analytics/analytics-dashboard-navigation.md +41 -0
- package/skills/wix-manage/references/app-installation/app-installation-dashboard-navigation.md +28 -0
- package/skills/wix-manage/references/blog/blog-dashboard-navigation.md +56 -0
- package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +31 -6
- package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -1
- package/skills/wix-manage/references/bookings/bookings-dashboard-navigation.md +63 -0
- package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +10 -1
- package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +44 -0
- package/skills/wix-manage/references/cms/cms-data-items-crud.md +31 -3
- package/skills/wix-manage/references/cms/cms-publishing-flow.md +287 -0
- package/skills/wix-manage/references/cms/cms-schema-management.md +27 -1
- package/skills/wix-manage/references/contacts/contacts-dashboard-navigation.md +46 -0
- package/skills/wix-manage/references/contacts/create-a-contact.md +82 -0
- package/skills/wix-manage/references/contacts/update-a-contact.md +119 -0
- package/skills/wix-manage/references/dashboard-navigation/dashboard-navigation.md +82 -0
- package/skills/wix-manage/references/dashboard-navigation/routes.json +1733 -0
- package/skills/wix-manage/references/domains/domains-dashboard-navigation.md +32 -0
- package/skills/wix-manage/references/ecommerce/ecom-pricing.md +4 -4
- package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
- package/skills/wix-manage/references/ecommerce/gift-cards/ecom-gift-cards-goal-sell-gift-cards.md +338 -0
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md +42 -78
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-bundle-and-save.md +1 -1
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md +1 -1
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md +1 -1
- package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +90 -92
- package/skills/wix-manage/references/events/create-wix-event.md +176 -0
- package/skills/wix-manage/references/events/manage-wix-events.md +174 -0
- package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +44 -0
- package/skills/wix-manage/references/get-paid/get-paid-dashboard-navigation.md +52 -0
- package/skills/wix-manage/references/google-ads/billing-and-payment.md +80 -0
- package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +212 -0
- package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +110 -0
- package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +25 -0
- package/skills/wix-manage/references/google-ads/install-and-create-account.md +155 -0
- package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +63 -0
- package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +155 -0
- package/skills/wix-manage/references/marketing/marketing-dashboard-navigation.md +52 -0
- package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +99 -1
- package/skills/wix-manage/references/pricing-plans/pricing-plans-dashboard-navigation.md +45 -0
- package/skills/wix-manage/references/restaurants/restaurants-dashboard-navigation.md +68 -0
- package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +94 -125
- package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +48 -9
- package/skills/wix-manage/references/site-properties/site-properties-dashboard-navigation.md +31 -0
- package/skills/wix-manage/references/sites/create-headless-site.md +52 -0
- package/skills/wix-manage/references/sites/create-site-from-template.md +2 -25
- package/skills/wix-manage/references/sites/site-import.md +163 -190
- package/skills/wix-manage/references/sites/sites-dashboard-navigation.md +29 -0
- package/skills/wix-manage/references/stores/add-store-pages-to-site.md +17 -1
- package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +26 -8
- package/skills/wix-manage/references/stores/stores-dashboard-navigation.md +65 -0
- package/skills/wix-manage/references/stores/update-product-with-options.md +39 -7
- package/skills/wix-replatform/.publish-manifest.json +8 -0
- package/skills/wix-replatform/SKILL.md +693 -0
- package/skills/wix-replatform/lib/artifact-freshness.js +215 -0
- package/skills/wix-replatform/lib/completion-report.js +200 -0
- package/skills/wix-replatform/lib/config-env.js +59 -0
- package/skills/wix-replatform/lib/execution-manifest.js +185 -0
- package/skills/wix-replatform/lib/execution-state.js +173 -0
- package/skills/wix-replatform/lib/import-recovery.js +313 -0
- package/skills/wix-replatform/lib/local-state.js +642 -0
- package/skills/wix-replatform/lib/orchestration-preflight.js +143 -0
- package/skills/wix-replatform/lib/orchestration-router.js +122 -0
- package/skills/wix-replatform/lib/orchestration-state.js +455 -0
- package/skills/wix-replatform/lib/progress-log.js +224 -0
- package/skills/wix-replatform/lib/progress-log.sh +140 -0
- package/skills/wix-replatform/lib/url-preservation-state.js +391 -0
- package/skills/wix-replatform/resources/rp-discovery/SKILL.md +184 -0
- package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +529 -0
- package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +316 -0
- package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +64 -0
- package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +1114 -0
- package/skills/wix-replatform/resources/rp-mapper/SKILL.md +430 -0
- package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +217 -0
- package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +148 -0
- package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +378 -0
- package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +183 -0
- package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +478 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +136 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +310 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +1081 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +618 -0
- package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +949 -0
- package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +196 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +66 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +60 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +95 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +82 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +256 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +249 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +444 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +774 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +71 -0
- package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +632 -0
- package/skills/wix-replatform/resources/rp-target-wix/SPEC-product-reviews-and-blog-authorship.md +330 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +21 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +19 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +39 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +35 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +14 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +35 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +36 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +35 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +14 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +131 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +21 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +97 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +528 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +14 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +38 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +13 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +53 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +84 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +25 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +38 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +90 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +64 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +141 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +384 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +260 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +238 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +237 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +238 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +2219 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +31 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +100 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +107 -0
- package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +344 -0
- package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +250 -0
- package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +1927 -0
- package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +83 -0
- package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +141 -0
- package/skills/wix-replatform/scripts/artifact-freshness.js +76 -0
- package/skills/wix-replatform/scripts/execution-manifest-validate.js +43 -0
- package/skills/wix-replatform/scripts/execution-state-prepare.js +128 -0
- package/skills/wix-replatform/scripts/orchestration-preflight.js +48 -0
- package/skills/wix-replatform/scripts/orchestration-route.js +46 -0
- package/skills/wix-replatform/scripts/orchestration-state.js +245 -0
- package/skills/wix-vibe-headless/SKILL.md +48 -25
- package/skills/wix-vibe-headless/install/deploy.cjs +95 -0
- package/skills/wix-vibe-headless/install/pin-agents-md.cjs +34 -0
- package/skills/wix-vibe-headless/platforms/README.md +8 -4
- package/skills/wix-vibe-headless/platforms/base44.md +133 -98
- package/skills/wix-vibe-headless/platforms/generic.md +99 -64
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +230 -119
- package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +43 -0
- package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +25 -0
- package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +15 -0
- package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +35 -0
- package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +38 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +40 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +54 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +65 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +50 -0
- package/skills/wix-vibe-headless/references/blog/seed/SEED.md +103 -0
- package/skills/wix-vibe-headless/references/blog/seed/seed-blog.js +270 -0
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +260 -149
- package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +65 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +47 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +13 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +126 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +108 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +58 -0
- package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +95 -0
- package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +94 -0
- package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +89 -0
- package/skills/wix-vibe-headless/references/bookings/{wix-bookings-checkout.js → app/rest/wix-bookings-checkout.js} +1 -1
- package/skills/wix-vibe-headless/references/bookings/{wix-bookings-services.js → app/rest/wix-bookings-services.js} +87 -11
- package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +117 -0
- package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.js +333 -0
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +169 -147
- package/skills/wix-vibe-headless/references/cms/app/collection.config.js +31 -0
- package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +18 -0
- package/skills/wix-vibe-headless/references/cms/{wix-cms.js → app/rest/wix-cms.js} +47 -2
- package/skills/wix-vibe-headless/references/cms/seed/SEED.md +145 -0
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +228 -131
- package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +23 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +43 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +13 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +29 -0
- package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +57 -0
- package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +78 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +27 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +54 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +40 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +81 -0
- package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +48 -0
- package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +36 -0
- package/skills/wix-vibe-headless/references/events/{wix-events-browse.js → app/rest/wix-events-browse.js} +1 -1
- package/skills/wix-vibe-headless/references/events/seed/SEED.md +107 -0
- package/skills/wix-vibe-headless/references/events/seed/seed-events.js +251 -0
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +276 -188
- package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +101 -0
- package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +33 -0
- package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +21 -0
- package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +29 -0
- package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +54 -0
- package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +77 -0
- package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +36 -0
- package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +32 -0
- package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +35 -0
- package/skills/wix-vibe-headless/references/members/{wix-members-auth.js → app/rest/wix-members-auth.js} +6 -3
- package/skills/wix-vibe-headless/references/members/install/Register.jsx +22 -0
- package/skills/wix-vibe-headless/references/members/seed/SEED.md +22 -0
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +233 -104
- package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +31 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +15 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +39 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +15 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +29 -0
- package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +35 -0
- package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +27 -0
- package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +25 -0
- package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +39 -0
- package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +27 -0
- package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +60 -0
- package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +94 -0
- package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js +236 -0
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +240 -117
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +35 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +48 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +16 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +35 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +25 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +28 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +30 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +30 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +53 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +28 -0
- package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +86 -0
- package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.js +251 -0
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +248 -124
- package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +81 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +71 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +43 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +21 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +60 -0
- package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +63 -0
- package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +32 -0
- package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +73 -0
- package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +28 -0
- package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +102 -0
- package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +180 -0
- package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.js +452 -0
- package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +56 -0
- package/skills/wix-vibe-headless/references/shared/{wix-client.js → app/rest/wix-client.js} +6 -8
- package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +6 -0
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +263 -157
- package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +20 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +150 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +167 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +51 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +54 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +119 -0
- package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +71 -0
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +109 -0
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +98 -0
- package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +27 -0
- package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +139 -0
- package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +75 -0
- package/skills/wix-vibe-headless/references/storefront/{wix-store-cart.js → app/rest/wix-store-cart.js} +1 -1
- package/skills/wix-vibe-headless/references/storefront/{wix-store-catalog.js → app/rest/wix-store-catalog.js} +20 -1
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +111 -0
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +299 -0
- /package/skills/wix-vibe-headless/references/blog/{wix-blog.js → app/rest/wix-blog.js} +0 -0
- /package/skills/wix-vibe-headless/references/events/{wix-events-registration.js → app/rest/wix-events-registration.js} +0 -0
- /package/skills/wix-vibe-headless/references/portfolio/{wix-portfolio.js → app/rest/wix-portfolio.js} +0 -0
- /package/skills/wix-vibe-headless/references/pricing-plans/{wix-pricing-plans.js → app/rest/wix-pricing-plans.js} +0 -0
- /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-menu.js → app/rest/wix-restaurants-menu.js} +0 -0
- /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-ordering.js → app/rest/wix-restaurants-ordering.js} +0 -0
- /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-reservations.js → app/rest/wix-restaurants-reservations.js} +0 -0
|
@@ -1,157 +1,268 @@
|
|
|
1
|
+
# Wix Bookings — ready-made client
|
|
1
2
|
|
|
2
|
-
|
|
3
|
+
The bookings client is **shipped as real files**, not snippets to regenerate. It's a complete
|
|
4
|
+
service catalog + detail page + slot picker + booking flow (create booking → hosted checkout),
|
|
5
|
+
styled with your app's design tokens (base44's `src/index.css` — the shadcn palette the design phase
|
|
6
|
+
already set). Copy it into the app and wire the routes —
|
|
7
|
+
you generate almost none of the booking code (the `{ services }` / `{ slots }` destructuring, the
|
|
8
|
+
local wall-clock date args, the null-slot re-validate guard, the participant cap, the eCom
|
|
9
|
+
redirect-session all ship and are correct).
|
|
3
10
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
> |---|---|
|
|
8
|
-
> | `wix-bookings-services.js` | Service listing, slot availability, media URL helper |
|
|
9
|
-
> | `wix-bookings-checkout.js` | Create booking, hosted checkout, bookAndCheckout convenience |
|
|
11
|
+
Talks to Wix directly over the public `WIX_CLIENT_ID` (anonymous visitor tokens). Never mock
|
|
12
|
+
services or slots; never hand-build a `/checkout` URL — the shipped flow creates the booking through
|
|
13
|
+
the API and completes it via the eCom redirect-session.
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
## Prerequisites
|
|
16
|
+
- The site's **Wix Bookings** setup is the read/book target. It's installed and seeded separately
|
|
17
|
+
(see **Seeding** below), in parallel with this build — so it may have no services at build time;
|
|
18
|
+
the client renders the shipped empty state until services (and staff/working hours, so slots are
|
|
19
|
+
bookable) land. This client is read-only over services — it does not provision them.
|
|
20
|
+
- The public headless **`WIX_CLIENT_ID`** from your prompt (buyer-facing, safe to hardcode/commit).
|
|
21
|
+
- For **paid** services, the site must accept payments and the deployed app domain must be
|
|
22
|
+
allow-listed on the OAuth client for the hosted checkout to return. Those are separate Wix setup
|
|
23
|
+
flows the user completes later — out of scope here; if checkout return fails before that, it's
|
|
24
|
+
expected, flag it and continue.
|
|
14
25
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
either slot. **COURSE (whole-course enrollment) is not covered** — see "Beyond the snippets".
|
|
26
|
+
## STEP 1 — The client is already in `src/`
|
|
27
|
+
The install step (base44.md STEP 1) deployed the whole bookings UI client + REST scaffolds into
|
|
28
|
+
`src/` (imports use the `@/` alias → `src/`). Here's every file and what it is — **this is your map,
|
|
29
|
+
so you don't need to open them:**
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
| file | what it is |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `hooks/useServices.js` | services-list data — one page + `loadMore` paging, plus the category menu (`categories` / `activeCategory` / `setActiveCategory`); `total === 0` → empty state |
|
|
34
|
+
| `hooks/useServiceDetail.js` | detail + booking flow — load service, list slots, hold slot/contact/participants, re-validate + book + checkout |
|
|
35
|
+
| `lib/serviceFacts.js` | price / duration / capacity / where / reschedule labels, derived from a service — rateType-aware, so VARIED and NO_FEE services still show a price |
|
|
36
|
+
| `components/ServiceCard.jsx`, `ServiceGrid.jsx` | service listing UI (grid + card, with empty state); the card shows price, tagline and a `60 min · 1-to-1` meta row |
|
|
37
|
+
| `components/SlotPicker.jsx` | bookable-slot chips + paging (pure UI, driven by `useServiceDetail`) |
|
|
38
|
+
| `components/BookingForm.jsx` | contact + participant form (pure UI, driven by `useServiceDetail`) |
|
|
39
|
+
| `components/WixManageBanner.jsx` | preview-only manage banner — drop it into your Layout (STEP 4) |
|
|
40
|
+
| `pages/Services.jsx`, `pages/ServiceDetail.jsx` | the two shipped routes (`/services`, `/service/:serviceId`); the detail page is two-column — service + a duration/price/where strip on the left, the sticky booking panel on the right |
|
|
41
|
+
| `rest/wix-config.js` | **you set the ids here** (STEP 2) |
|
|
42
|
+
| `rest/wix-client.js` | REST transport — mints/persists the anonymous visitor token |
|
|
43
|
+
| `rest/wix-bookings-services.js` | services + availability: `queryServices`, `queryServicesByCategory`, `categoriesOf`, `getService`, `countServices`, `listSlotsForService`, `listAvailableSlots`, `listEventTimeSlots`, `getAvailableSlot`, `mediaUrl` |
|
|
44
|
+
| `rest/wix-bookings-checkout.js` | booking + checkout: `createBooking`, `checkoutBooking`, `bookAndCheckout` |
|
|
26
45
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
the
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
46
|
+
They're already in place — go **straight to theming + wiring**, nothing to verify first. **Don't
|
|
47
|
+
`read_file` the shipped page/component/hook source to inspect it** — the table above says what each
|
|
48
|
+
is, and every field shape you need is in the snippets below. Read a shipped file's source **only**
|
|
49
|
+
on a real fallback — a runtime error, or a field the snippets don't cover (see "Fallback only" at
|
|
50
|
+
the end). (Files missing? the install's `deploy` result lists what it wrote; re-run install, or copy
|
|
51
|
+
`references/bookings/app/` → `src/`.)
|
|
52
|
+
|
|
53
|
+
## STEP 2 — Credentials
|
|
54
|
+
Write `src/rest/wix-config.js` with your `WIX_CLIENT_ID` and `WIX_METASITE_ID` from the prompt — the
|
|
55
|
+
one place both ids live.
|
|
56
|
+
|
|
57
|
+
## STEP 3 — Theme (nothing to style on the shipped components)
|
|
58
|
+
The shipped components carry **no palette of their own** — they render from base44's design tokens
|
|
59
|
+
in `src/index.css` (`:root`/`.dark`: `--background`, `--foreground`, `--card`, `--primary`,
|
|
60
|
+
`--muted`, `--border`, `--radius`, `--font-*`) via shadcn Tailwind classes (`bg-card`,
|
|
61
|
+
`text-foreground`, `bg-primary`, `text-muted-foreground`, `border-border`, `rounded-lg`,
|
|
62
|
+
`font-display`). Those tokens are **already set to the brand by the design phase**, so the shipped
|
|
63
|
+
pages are themed with zero work here. To adjust the palette, edit `index.css` (`:root` **and**
|
|
64
|
+
`.dark`) — the base44 way; **never add a parallel theme file (e.g. a `theme.css`) or restyle the
|
|
65
|
+
shipped JSX.** Build the Home/Header you add (STEP 4) from the **same** base44 tokens/classes so it
|
|
66
|
+
matches automatically. A dark brand is just base44's dark palette in `index.css` — no per-component work.
|
|
67
|
+
|
|
68
|
+
## STEP 4 — Wire routes (surgical `find_replace` on `src/App.jsx`, never a rewrite)
|
|
69
|
+
**No file reads needed to wire this.** Every shipped page and `WixManageBanner` is a default export that takes **no props** — wire them exactly as the snippet shows; nothing in those files needs looking up.
|
|
70
|
+
`App.jsx` carries required platform auth scaffolding (`AuthProvider`/`useAuth`) — edit it in, don't
|
|
71
|
+
replace it. Bookings needs **no cross-page provider** (there's no cart — each booking completes on
|
|
72
|
+
its own detail page), so there's nothing to wrap the tree in.
|
|
73
|
+
- Put your **header + footer in a `Layout`** that renders `<Outlet/>` between them, and nest every
|
|
74
|
+
route under one pathless `<Route element={<Layout/>}>`. Your brand chrome then wraps **every** page
|
|
75
|
+
— including the shipped `Services` / `ServiceDetail` — so you **never edit the shipped pages to add
|
|
76
|
+
a header/footer** (they render inside `<Outlet/>` as-is).
|
|
77
|
+
- **Pin the top chrome as one fixed block.** Put `<WixManageBanner/>` (shipped, preview-only) **above**
|
|
78
|
+
your `<Header/>` inside a single `position:fixed` top region — the header itself is plain in-flow
|
|
79
|
+
markup, the region owns the fixing — so banner + header ride together (no scroll drift/gap). Pad
|
|
80
|
+
the content by the region's **ResizeObserver-measured** height so it clears the chrome and
|
|
81
|
+
self-corrects when the banner is dismissed.
|
|
82
|
+
- Routes under the Layout: `/services` → `Services`, `/service/:serviceId` → `ServiceDetail` (both
|
|
83
|
+
shipped, as-is). **You add `/` → your own Home** page.
|
|
84
|
+
|
|
85
|
+
```jsx
|
|
86
|
+
import { useRef, useState, useEffect } from "react";
|
|
87
|
+
import { Routes, Route, Outlet } from "react-router-dom";
|
|
88
|
+
import WixManageBanner from "@/components/WixManageBanner"; // shipped, preview-only · default export, no props
|
|
89
|
+
import Services from "@/pages/Services"; // shipped · default export, no props
|
|
90
|
+
import ServiceDetail from "@/pages/ServiceDetail"; // shipped · default export, no props
|
|
91
|
+
import Home from "@/pages/Home"; // YOU build
|
|
92
|
+
import Header from "@/components/Header"; // YOU build — plain in-flow markup, NOT position:fixed
|
|
93
|
+
import Footer from "@/components/Footer"; // YOU build
|
|
94
|
+
|
|
95
|
+
function Layout() {
|
|
96
|
+
const topRef = useRef(null);
|
|
97
|
+
const [offset, setOffset] = useState(0);
|
|
98
|
+
useEffect(() => { // measure the fixed region → pad content below it
|
|
99
|
+
const ro = new ResizeObserver(() => setOffset(topRef.current?.offsetHeight ?? 0));
|
|
100
|
+
if (topRef.current) ro.observe(topRef.current);
|
|
101
|
+
return () => ro.disconnect();
|
|
102
|
+
}, []);
|
|
103
|
+
return (<>
|
|
104
|
+
<div ref={topRef} style={{ position: "fixed", top: 0, left: 0, right: 0, zIndex: 50 }}>
|
|
105
|
+
<WixManageBanner /> {/* null on the published site / when dismissed */}
|
|
106
|
+
<Header /> {/* your brand header, in-flow inside this fixed block */}
|
|
107
|
+
</div>
|
|
108
|
+
<div style={{ paddingTop: offset }}> {/* clears the chrome; shrinks when the banner is dismissed */}
|
|
109
|
+
<Outlet /> {/* shipped Services/ServiceDetail render here, untouched */}
|
|
110
|
+
<Footer />
|
|
111
|
+
</div>
|
|
112
|
+
</>);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
<Routes>
|
|
116
|
+
<Route element={<Layout />}> {/* chrome wraps all */}
|
|
117
|
+
<Route path="/" element={<Home />} /> {/* yours */}
|
|
118
|
+
<Route path="/services" element={<Services />} /> {/* shipped, as-is */}
|
|
119
|
+
<Route path="/service/:serviceId" element={<ServiceDetail />} /> {/* shipped, as-is */}
|
|
120
|
+
</Route>
|
|
121
|
+
</Routes>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## What you build (not shipped)
|
|
125
|
+
The **home / landing page**, the **`Header`** and a **`Footer`** — the two you drop into the
|
|
126
|
+
`Layout` (STEP 4) so they wrap every route — plus the overall brand story, styled with the same
|
|
127
|
+
base44 tokens/classes. **Compose the shipped pieces** — a "featured services" strip is just
|
|
128
|
+
`queryServices` + the shipped `ServiceGrid`; the nav is a link to `/services`:
|
|
129
|
+
|
|
130
|
+
```jsx
|
|
131
|
+
import { useState, useEffect } from "react";
|
|
132
|
+
import { Link } from "react-router-dom";
|
|
133
|
+
import { queryServices } from "@/rest/wix-bookings-services";
|
|
134
|
+
import ServiceGrid from "@/components/ServiceGrid";
|
|
135
|
+
|
|
136
|
+
// Responsive header: choose ONE branch with a state flag (copy this pattern). Do NOT render a
|
|
137
|
+
// desktop nav AND a mobile nav toggled by Tailwind `hidden md:flex` / `md:hidden`: these navs are
|
|
138
|
+
// inline-styled, and an inline `display` beats a Tailwind class, so `hidden` never applies — BOTH
|
|
139
|
+
// branches render. One branch = one nav.
|
|
140
|
+
export function Header() {
|
|
141
|
+
const [mobile, setMobile] = useState(() => window.innerWidth < 768);
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
const onResize = () => setMobile(window.innerWidth < 768);
|
|
144
|
+
window.addEventListener("resize", onResize); // keep it reactive to viewport changes
|
|
145
|
+
return () => window.removeEventListener("resize", onResize);
|
|
146
|
+
}, []);
|
|
147
|
+
return (
|
|
148
|
+
<nav style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
|
149
|
+
{/* brand/logo */}
|
|
150
|
+
{mobile ? <YourMenu /> : <Link to="/services">Services</Link>}
|
|
151
|
+
</nav>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
export function Featured() { // on your home page
|
|
155
|
+
const [services, setServices] = useState([]);
|
|
156
|
+
// NB: queryServices returns { services, total, nextOffset } — destructure the array.
|
|
157
|
+
useEffect(() => { queryServices({ limit: 6 }).then(({ services }) => setServices(services)); }, []);
|
|
158
|
+
return <ServiceGrid services={services} empty="Services coming soon." />;
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
Everything reads base44's design tokens (`index.css`), so your home/nav match the shipped pages automatically.
|
|
162
|
+
|
|
163
|
+
**Editing a component and the change doesn't show? It's the preview, not your code.** The dev
|
|
164
|
+
preview can serve a stale module after a write. Before diagnosing a visual bug you just "fixed", do a
|
|
165
|
+
fresh full navigate/reload of the preview and re-check — don't keep rewriting correct code against a
|
|
166
|
+
stale render.
|
|
167
|
+
|
|
168
|
+
## Using the client from your own UI
|
|
169
|
+
The two shipped hooks are the whole flow. If you build a custom surface, drive it the same way:
|
|
170
|
+
|
|
171
|
+
```jsx
|
|
172
|
+
// LIST — every list helper returns an OBJECT, not a bare array. Destructure it:
|
|
173
|
+
const { services, total, nextOffset } = await queryServices({ limit: 24 }); // total 0 → empty state
|
|
174
|
+
if ((await countServices()) === 0) { /* show the empty state — never invent services */ }
|
|
175
|
+
|
|
176
|
+
// DETAIL — getService(id) is keyed off the route param; returns null on a miss (not-found, never invent):
|
|
177
|
+
const service = await getService(serviceId);
|
|
178
|
+
|
|
179
|
+
// FACTS (price / duration / capacity / where / reschedule note) — lib/serviceFacts.js branches on
|
|
180
|
+
// payment.rateType and on APPOINTMENT-vs-CLASS for you. Reading payment.fixed.price yourself renders
|
|
181
|
+
// NOTHING for a VARIED or NO_FEE service, and duration is empty on a class:
|
|
182
|
+
const price = servicePriceLabel(service); // "€95.00" · "From €85.00" · "Free" · "" for CUSTOM
|
|
183
|
+
const minutes = serviceDuration(service); // 60 for an appointment; null for a class/course
|
|
184
|
+
const where = serviceLocationLabel(service); // from payment.options — service.locations has no name
|
|
185
|
+
|
|
186
|
+
// IMAGE — the primary image is media.mainMedia; resolve through mediaUrl (Wix media can be a bare
|
|
187
|
+
// handle, not a full URL). Fall back to the gallery/cover:
|
|
188
|
+
const img = mediaUrl(service.media?.mainMedia?.image ?? service.media?.items?.[0]?.image ?? service.media?.coverMedia?.image);
|
|
189
|
+
|
|
190
|
+
// SLOTS — listSlotsForService routes by service.type and returns { slots, nextCursor }; iterate .slots.
|
|
191
|
+
// Dates are LOCAL wall-clock "YYYY-MM-DDThh:mm:ss" (NO zone / Z). The LIST call takes
|
|
192
|
+
// fromLocalDate/toLocalDate — the single-slot re-validate (getAvailableSlot) takes
|
|
193
|
+
// localStartDate/localEndDate. They are NOT interchangeable.
|
|
194
|
+
// It also returns `timeZone` — the zone those localStartDate strings are in. Label the picker with
|
|
195
|
+
// that value rather than a locally guessed zone, so the times and the label can't disagree.
|
|
196
|
+
const { slots, nextCursor, timeZone } = await listSlotsForService(service, { fromLocalDate, toLocalDate });
|
|
197
|
+
|
|
198
|
+
// BOOK — re-validate the picked slot (getAvailableSlot returns the slot or NULL — guard it), then
|
|
199
|
+
// book + check out and redirect. Participants: cap at
|
|
200
|
+
// service.bookingPolicy.participantsPolicy.maxParticipantsPerBooking (commonly 1 → no selector);
|
|
201
|
+
// never use slot.remainingCapacity as the per-buyer limit.
|
|
202
|
+
const fresh = await getAvailableSlot(service.id, { localStartDate, localEndDate });
|
|
203
|
+
if (!fresh) { /* "that time was just taken — pick another" */ }
|
|
204
|
+
const { checkoutUrl } = await bookAndCheckout(fresh, { email, firstName, lastName, phone }, { totalParticipants });
|
|
205
|
+
window.location.href = checkoutUrl; // hosted checkout; on return the booking is CONFIRMED/PENDING
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Extending the client
|
|
209
|
+
The shipped flow covers **APPOINTMENT and CLASS** services (`listSlotsForService` routes by
|
|
210
|
+
`service.type`). For anything beyond that, add a helper on `wixApiRequest`, looking the endpoint up
|
|
211
|
+
in the **`wix-docs`** skill first (never guess):
|
|
212
|
+
- **COURSE** enrollment — a course is enrolled as a *whole*, not per session; `listEventTimeSlots`
|
|
213
|
+
returns no slots for it, so the slot-picker flow doesn't apply (course-specific flow).
|
|
214
|
+
- **Service variants / participants** (duration- or person-based pricing), **add-ons**, and
|
|
215
|
+
**custom booking form fields** (render `service.form.id`).
|
|
216
|
+
- **Member login + a "my bookings" view** → the **members** vertical
|
|
217
|
+
(`references/members/INSTRUCTIONS.md`): booking works anonymously, but signing a member in lets
|
|
218
|
+
them see their own appointments.
|
|
219
|
+
|
|
220
|
+
Fallback only — when you hit an error or need something not shown here: read the relevant shipped
|
|
221
|
+
file under `src/`, or look it up via the **`wix-docs`** skill. Each helper in
|
|
222
|
+
`wix-bookings-services.js` / `wix-bookings-checkout.js` links its own reference page inline; these are
|
|
223
|
+
the areas they sit in:
|
|
224
|
+
- Bookings (services, categories, bookings): https://dev.wix.com/docs/api-reference/business-solutions/bookings.md
|
|
225
|
+
- Availability time slots: https://dev.wix.com/docs/api-reference/business-solutions/bookings/time-slots.md
|
|
226
|
+
- eCommerce checkout (paid bookings): https://dev.wix.com/docs/api-reference/business-solutions/e-commerce.md
|
|
227
|
+
- Headless redirect session (hosted checkout): https://dev.wix.com/docs/api-reference/business-management/headless/redirects.md
|
|
228
|
+
|
|
229
|
+
## Hard rules
|
|
230
|
+
- Set `WIX_CLIENT_ID` (STEP 2) — not the placeholder.
|
|
231
|
+
- Style via base44 design tokens (`index.css` / shadcn Tailwind classes), never by rewriting the shipped components or adding a parallel theme file.
|
|
232
|
+
- Header/footer live in a `Layout` around `<Outlet/>` (STEP 4) — never edit the shipped
|
|
233
|
+
`Services`/`ServiceDetail` to add chrome.
|
|
234
|
+
- The Layout's fixed top region owns positioning: `<WixManageBanner/>` above `<Header/>`; your
|
|
235
|
+
`Header` is plain in-flow markup (not `position:fixed`).
|
|
236
|
+
- Send availability/booking dates as **local** `"YYYY-MM-DDThh:mm:ss"` strings + a `timeZone` — never
|
|
237
|
+
UTC `Z` timestamps to the slot APIs.
|
|
238
|
+
- Re-validate the slot with `getAvailableSlot()` before booking; guard the `null` — slots get taken.
|
|
239
|
+
- Cap participants at `maxParticipantsPerBooking` (no selector when 1); never offer a fixed range and
|
|
240
|
+
never use slot capacity as the per-buyer limit.
|
|
241
|
+
- Book only through the shipped flow (`bookAndCheckout` / `createBooking`→`checkoutBooking`) and
|
|
242
|
+
redirect to the returned URL — never a hand-built `/checkout` or calendar URL.
|
|
243
|
+
- Render live Wix data or the shipped empty state — never mock services, slots, or availability, and
|
|
244
|
+
never invent reviews, ratings, staff, or testimonials.
|
|
138
245
|
|
|
139
246
|
## Point the user to their dashboard
|
|
140
|
-
|
|
141
|
-
- **Booking Services** — `https://manage.wix.com/dashboard/{metaSiteId}/bookings/services` (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
##
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
- [ ]
|
|
152
|
-
- [ ]
|
|
153
|
-
- [ ] `
|
|
154
|
-
- [ ]
|
|
155
|
-
|
|
156
|
-
- [ ]
|
|
157
|
-
- [ ]
|
|
247
|
+
Provide deep links so the owner can manage bookings content (substitute the site's `metaSiteId`):
|
|
248
|
+
- **Booking Services** — `https://manage.wix.com/dashboard/{metaSiteId}/bookings/services` (add
|
|
249
|
+
services and service categories)
|
|
250
|
+
- **Staff** — `https://manage.wix.com/dashboard/{metaSiteId}/bookings/staff` (add staff and set
|
|
251
|
+
working hours, so slots are actually bookable)
|
|
252
|
+
|
|
253
|
+
## Seeding
|
|
254
|
+
Seed the services per `seed/SEED.md` (the build-time setup module) — separate from this client
|
|
255
|
+
build; run in parallel.
|
|
256
|
+
|
|
257
|
+
## Verify (before declaring done)
|
|
258
|
+
- [ ] Client files copied into `src/`; `WIX_CLIENT_ID` set (not the placeholder).
|
|
259
|
+
- [ ] Brand palette lives in `index.css` (`:root`/`.dark`); no parallel theme file; shipped components/pages not restyled or rewritten.
|
|
260
|
+
- [ ] **Opened `/services` and a service detail page** (not just the home page) and confirmed the shipped cards render themed (surface, text, brand color) with images.
|
|
261
|
+
- [ ] `Layout` (fixed `<WixManageBanner/>` + `<Header/>` region, then `<Outlet/>` + Footer) wraps all
|
|
262
|
+
routes; shipped `Services`/`ServiceDetail` untouched; content clears the fixed chrome.
|
|
263
|
+
- [ ] Visitor token persists across reload (same visitor identity across reloads).
|
|
264
|
+
- [ ] `queryServices()` renders live services; empty catalog shows the shipped empty state (no mock services).
|
|
265
|
+
- [ ] Slot picker shows real bookable slots; the slot is re-validated with `getAvailableSlot()` right before booking.
|
|
266
|
+
- [ ] Participant selector capped by `maxParticipantsPerBooking` (hidden when 1).
|
|
267
|
+
- [ ] Booking redirects to the hosted checkout URL the client returns; on return the booking is CONFIRMED/PENDING.
|
|
268
|
+
- [ ] No mock services, slots, or availability anywhere.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Contact + participants form — pure UI. All state/handlers (field setters, participant cap,
|
|
2
|
+
// submit, submitting, error) come from useServiceDetail; this only renders them. The participant
|
|
3
|
+
// selector shows ONLY when maxParticipants > 1 (commonly 1 → no selector, book exactly one).
|
|
4
|
+
// Styled with base44 design tokens (shadcn Tailwind classes).
|
|
5
|
+
const fieldCls =
|
|
6
|
+
"w-full px-3 py-2.5 box-border font-body border border-input rounded-sm bg-background text-foreground";
|
|
7
|
+
const labelCls = "block mb-1.5 text-[11px] uppercase tracking-wide text-muted-foreground";
|
|
8
|
+
|
|
9
|
+
export default function BookingForm({
|
|
10
|
+
contact, setContactField, maxParticipants, participants, setParticipants,
|
|
11
|
+
onSubmit, submitting, canSubmit, error, needsApproval, timeLabel, priceLabel,
|
|
12
|
+
}) {
|
|
13
|
+
// Naming the time and price on the button is the last confirmation before payment, so what the
|
|
14
|
+
// buyer clicks states exactly what they're committing to.
|
|
15
|
+
const what = [timeLabel, priceLabel].filter(Boolean).join(" · ");
|
|
16
|
+
return (
|
|
17
|
+
<form onSubmit={(e) => { e.preventDefault(); onSubmit(); }} className="flex flex-col gap-4">
|
|
18
|
+
<div className="flex gap-3">
|
|
19
|
+
<div className="flex-1">
|
|
20
|
+
<label className={labelCls} htmlFor="bk-first">First name</label>
|
|
21
|
+
<input id="bk-first" className={fieldCls} value={contact.firstName} onChange={setContactField("firstName")} />
|
|
22
|
+
</div>
|
|
23
|
+
<div className="flex-1">
|
|
24
|
+
<label className={labelCls} htmlFor="bk-last">Last name</label>
|
|
25
|
+
<input id="bk-last" className={fieldCls} value={contact.lastName} onChange={setContactField("lastName")} />
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div>
|
|
30
|
+
<label className={labelCls} htmlFor="bk-email">Email</label>
|
|
31
|
+
<input id="bk-email" required type="email" autoComplete="email" placeholder="you@example.com"
|
|
32
|
+
className={fieldCls} value={contact.email} onChange={setContactField("email")} />
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div>
|
|
36
|
+
<label className={labelCls} htmlFor="bk-phone">
|
|
37
|
+
Phone <span className="normal-case tracking-normal">optional</span>
|
|
38
|
+
</label>
|
|
39
|
+
<input id="bk-phone" type="tel" autoComplete="tel" className={fieldCls}
|
|
40
|
+
value={contact.phone} onChange={setContactField("phone")} />
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
{maxParticipants > 1 && (
|
|
44
|
+
<div>
|
|
45
|
+
<label className={labelCls} htmlFor="bk-participants">Participants</label>
|
|
46
|
+
<input id="bk-participants" type="number" min={1} max={maxParticipants} value={participants}
|
|
47
|
+
onChange={(e) => setParticipants(Math.max(1, Math.min(maxParticipants, Number(e.target.value) || 1)))}
|
|
48
|
+
className={`${fieldCls} w-[100px]`} />
|
|
49
|
+
</div>
|
|
50
|
+
)}
|
|
51
|
+
|
|
52
|
+
{error && <p role="alert" className="m-0 text-destructive text-sm">{error}</p>}
|
|
53
|
+
|
|
54
|
+
{/* The business confirms a manual-approval service after the fact, so this asks rather than books. */}
|
|
55
|
+
<button type="submit" disabled={!canSubmit}
|
|
56
|
+
className="px-6 py-3 cursor-pointer bg-primary text-primary-foreground border-none rounded-sm text-[15px] font-semibold disabled:opacity-50 disabled:cursor-not-allowed">
|
|
57
|
+
{submitting
|
|
58
|
+
? (needsApproval ? "Requesting…" : "Booking…")
|
|
59
|
+
: needsApproval
|
|
60
|
+
? (what ? `Request ${what}` : "Request appointment")
|
|
61
|
+
: (what ? `Book ${what}` : "Book appointment")}
|
|
62
|
+
</button>
|
|
63
|
+
</form>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Grid tile for one bookable service. Styled with base44 design tokens (shadcn Tailwind classes:
|
|
2
|
+
// bg-card / text-foreground / border-border / text-primary) — re-skin via the app's design tokens
|
|
3
|
+
// (src/index.css :root/.dark), not this JSX. Load-bearing: the image goes through mediaUrl() (Wix
|
|
4
|
+
// media can be a bare handle), the link uses `service.id`, and every price/duration/capacity label
|
|
5
|
+
// comes from lib/serviceFacts.js so the card and the detail page can't disagree.
|
|
6
|
+
import { Link } from "react-router-dom";
|
|
7
|
+
import { mediaUrl } from "@/rest/wix-bookings-services";
|
|
8
|
+
import { serviceCapacityLabel, serviceDuration, servicePriceLabel } from "@/lib/serviceFacts";
|
|
9
|
+
|
|
10
|
+
export default function ServiceCard({ service }) {
|
|
11
|
+
const image = mediaUrl(service.media?.mainMedia?.image ?? service.media?.items?.[0]?.image ?? service.media?.coverMedia?.image);
|
|
12
|
+
const price = servicePriceLabel(service);
|
|
13
|
+
const minutes = serviceDuration(service);
|
|
14
|
+
// A class has no duration on the service, so its meta row carries capacity alone rather than a gap.
|
|
15
|
+
const facts = [minutes && `${minutes} min`, serviceCapacityLabel(service)].filter(Boolean);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Link to={`/service/${service.id}`}
|
|
19
|
+
className="group flex flex-col no-underline text-foreground bg-card border border-border rounded-lg overflow-hidden shadow-sm">
|
|
20
|
+
<div className="relative aspect-[4/3] bg-background overflow-hidden">
|
|
21
|
+
{image
|
|
22
|
+
? <img src={image} alt={service.name} loading="lazy"
|
|
23
|
+
className="w-full h-full object-cover transition-transform duration-300 md:group-hover:scale-[1.03]" />
|
|
24
|
+
: <div className="w-full h-full bg-muted flex items-center justify-center" aria-hidden="true"><svg viewBox="0 0 24 24" className="w-8 h-8 text-muted-foreground/40" fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="3" y="3" width="18" height="18" rx="2" /><circle cx="8.5" cy="8.5" r="1.5" /><path d="m21 15-5-5L5 21" /></svg></div>}
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div className="p-3 flex flex-col gap-1">
|
|
28
|
+
{/* Name and price share a row on a wide tile and stack on a phone's narrow one, where a long
|
|
29
|
+
name against a top-right price wraps into a ragged block. */}
|
|
30
|
+
<div className="flex flex-col gap-1 md:flex-row md:items-baseline md:justify-between md:gap-3">
|
|
31
|
+
<h3 className="m-0 font-display text-[15px] font-semibold line-clamp-2">{service.name}</h3>
|
|
32
|
+
{price && <span className="font-semibold whitespace-nowrap">{price}</span>}
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
{service.tagLine && (
|
|
36
|
+
<p className="m-0 text-muted-foreground text-[13px] line-clamp-1">{service.tagLine}</p>
|
|
37
|
+
)}
|
|
38
|
+
|
|
39
|
+
{facts.length > 0 && (
|
|
40
|
+
<p className="m-0 mt-0.5 text-[11px] uppercase tracking-wide text-muted-foreground">
|
|
41
|
+
{facts.join(" · ")}
|
|
42
|
+
</p>
|
|
43
|
+
)}
|
|
44
|
+
</div>
|
|
45
|
+
</Link>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Responsive service grid + empty state. Styled with base44 design tokens (shadcn Tailwind classes).
|
|
2
|
+
import ServiceCard from "./ServiceCard";
|
|
3
|
+
|
|
4
|
+
export default function ServiceGrid({ services, empty = "No services yet." }) {
|
|
5
|
+
if (!services?.length) {
|
|
6
|
+
return <p className="text-muted-foreground p-4 text-center">{empty}</p>;
|
|
7
|
+
}
|
|
8
|
+
return (
|
|
9
|
+
<div className="grid gap-4 grid-cols-2 md:[grid-template-columns:repeat(auto-fill,minmax(240px,1fr))]">
|
|
10
|
+
{services.map((s) => <ServiceCard key={s.id} service={s} />)}
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
}
|