@wix/agent-skills 1.13.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +4 -1
  2. package/package.json +1 -1
  3. package/skills/README.md +23 -0
  4. package/skills/wix-app/SKILL.md +10 -2
  5. package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +326 -0
  6. package/skills/wix-app/references/CODE_QUALITY.md +1 -0
  7. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +124 -115
  8. package/skills/wix-app/references/DASHBOARD_PAGE.md +3 -0
  9. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +23 -9
  10. package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
  11. package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
  12. package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
  13. package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
  14. package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
  15. package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
  16. package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
  17. package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
  18. package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
  19. package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
  20. package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
  21. package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
  22. package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
  23. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
  24. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
  25. package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
  26. package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
  27. package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
  28. package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
  29. package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
  30. package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
  31. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
  32. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
  33. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
  34. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +17 -105
  35. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
  36. package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
  37. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +15 -15
  38. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
  39. package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
  40. package/skills/wix-auth/SKILL.md +12 -0
  41. package/skills/wix-auth/references/device-flow.md +140 -0
  42. package/skills/wix-docs/SKILL.md +188 -0
  43. package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
  44. package/skills/wix-docs/references/EXTRACTING.md +120 -0
  45. package/skills/wix-headless/SKILL.md +84 -130
  46. package/skills/wix-headless/entry/bootstrap.mjs +93 -0
  47. package/skills/wix-headless/entry/skill.md +78 -0
  48. package/skills/wix-headless/references/AI_FEATURES.md +178 -0
  49. package/skills/wix-headless/references/CAPABILITIES.md +84 -0
  50. package/skills/wix-headless/references/DISCOVERY.md +34 -56
  51. package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
  52. package/skills/wix-headless/references/FEEDBACK.md +118 -0
  53. package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
  54. package/skills/wix-headless/references/SDK_HANDOFF.md +97 -0
  55. package/skills/wix-headless/references/SEED.md +44 -188
  56. package/skills/wix-headless/references/SETUP.md +32 -103
  57. package/skills/wix-headless/references/astro.md +98 -0
  58. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
  59. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
  60. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
  61. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
  62. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
  63. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
  64. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
  65. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
  66. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
  67. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
  70. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +173 -0
  71. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
  72. package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
  73. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +228 -0
  74. package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
  75. package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
  76. package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
  77. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +176 -0
  78. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +153 -0
  79. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
  80. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +161 -0
  81. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +117 -0
  82. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
  83. package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
  84. package/skills/wix-headless/references/managed/CONNECT.md +74 -0
  85. package/skills/wix-headless/references/managed/CREATE.md +130 -0
  86. package/skills/wix-headless/references/managed/DEPLOYMENT.md +57 -0
  87. package/skills/wix-headless/references/non-astro.md +59 -0
  88. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
  89. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +7 -0
  90. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
  91. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +63 -0
  92. package/skills/wix-manage/SKILL.md +24 -1
  93. package/skills/wix-manage/references/analytics/query-site-analytics.md +241 -0
  94. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
  95. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +265 -0
  96. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +436 -0
  97. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +209 -0
  98. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
  99. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +51 -0
  100. package/skills/wix-vibe-headless/SKILL.md +136 -0
  101. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
  102. package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
  103. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +153 -0
  104. package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
  105. package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +215 -0
  106. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
  107. package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
  108. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
  109. package/skills/wix-vibe-headless/references/events/wix-events-browse.js +135 -0
  110. package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
  111. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
  112. package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
  113. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
  114. package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +194 -0
  115. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
  116. package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
  117. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
  118. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
  119. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
  120. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
  121. package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
  122. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +155 -0
  123. package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
  124. package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +142 -0
  125. package/skills/wix-headless/references/BUILD-astro.md +0 -244
  126. package/skills/wix-headless/references/BUILD-own-build.md +0 -167
  127. package/skills/wix-headless/references/BUILD.md +0 -105
  128. package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
  129. package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
  130. package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
  131. package/skills/wix-headless/references/PLAN-connect.md +0 -19
  132. package/skills/wix-headless/references/PLAN-create.md +0 -17
  133. package/skills/wix-headless/references/PLAN.md +0 -92
  134. package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
  135. package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
  136. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
  137. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
  138. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
  139. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
  140. package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
  141. package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
  142. package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
  143. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
  144. package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
  145. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
  146. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
  147. package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
  148. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
  149. package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
  150. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
  151. package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
  152. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
  153. package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
  154. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
  155. package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
  156. package/skills/wix-headless/references/astro/templates/Footer.astro +0 -27
  157. package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
  158. package/skills/wix-headless/references/astro/templates/Navigation.astro +0 -38
  159. package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
  160. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
  161. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
  162. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
  163. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
  164. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
  165. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
  166. package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
  167. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
  168. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
  169. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
  170. package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
  171. package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
  172. package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
  173. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
  174. package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
  175. package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
  176. package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
  177. package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
  178. package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
  179. package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
  180. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
  181. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
  182. package/skills/wix-headless/references/astro/templates/global.css +0 -288
  183. package/skills/wix-headless/references/astro/templates/index.astro +0 -56
  184. package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
  185. package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
  186. package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
  187. package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
  188. package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
  189. package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
  190. package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
  191. package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
  192. package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
  193. package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
  194. package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
  195. package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
  196. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
  197. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
  198. package/skills/wix-headless/references/bookings/FLOW.md +0 -246
  199. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
  200. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
  201. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
  202. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
  203. package/skills/wix-headless/references/commands/known-apps.json +0 -6
  204. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
  205. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
  206. package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
  207. package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
  208. package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
  209. package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
  210. package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
  211. package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
  212. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
  213. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
  214. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
  215. package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
  216. package/skills/wix-headless/references/seed-recipes.md +0 -49
  217. package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
  218. package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
  219. package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
  220. package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
  221. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
  222. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
  223. package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
  224. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
  225. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
  226. package/skills/wix-headless/references/shared/STYLING.md +0 -141
  227. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
  228. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
  229. package/skills/wix-headless/references/verticals/_schema.json +0 -74
  230. package/skills/wix-headless/references/verticals/_schema.md +0 -95
  231. package/skills/wix-headless/references/verticals/blog.md +0 -31
  232. package/skills/wix-headless/references/verticals/bookings.md +0 -41
  233. package/skills/wix-headless/references/verticals/cms.md +0 -30
  234. package/skills/wix-headless/references/verticals/ecom.md +0 -25
  235. package/skills/wix-headless/references/verticals/forms.md +0 -26
  236. package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
  237. package/skills/wix-headless/references/verticals/stores.md +0 -33
  238. package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
  239. package/skills/wix-headless/scripts/compose.mjs +0 -525
  240. package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
  241. package/skills/wix-headless/scripts/flatten.sh +0 -61
  242. package/skills/wix-headless/scripts/generate-images.mjs +0 -242
  243. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -148
  244. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
  245. package/skills/wix-headless/scripts/scaffold.sh +0 -139
  246. package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
  247. package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
  248. package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
  249. package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
  250. package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
@@ -1,424 +0,0 @@
1
- /* src/styles/components-bookings.css
2
- *
3
- * Bookings-pack component CSS. Pre-copied by the orchestrator before the build
4
- * wave (it is brand-agnostic var(--token) CSS). The designer's global.css does
5
- * NOT publish these classes — they live here. See references/shared/STYLING.md
6
- * § "Component-specific CSS is owned by the component, not the designer".
7
- *
8
- * Class groups:
9
- * - .service-card / .service-grid / .service-card-* → ServiceCard.astro, services/index.astro
10
- * - .booking-filter-bar / .booking-filter-chip* → services/index.astro (location + category filters)
11
- * - .availability-* / .time-slot* → AvailabilityCalendar.tsx (week calendar, slots, staff picker)
12
- * - .booking-* → BookingForm.tsx (schema-driven form)
13
- *
14
- * Primary actions (a selected slot, the confirm button) use var(--color-accent)
15
- * so the flow matches the site's primary-action styling.
16
- *
17
- * Direct var(--token) only (no @apply). Fallback chains for sometimes-published
18
- * tokens, e.g. var(--color-paper-warm, var(--color-paper, var(--color-cream))).
19
- */
20
-
21
- /* ── Service grid + card ────────────────────────────────────────────────────── */
22
- .service-grid {
23
- display: grid;
24
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
25
- gap: 2rem;
26
- transition: opacity 200ms ease;
27
- }
28
- body[data-navigating="true"] .service-grid {
29
- opacity: 0.55;
30
- pointer-events: none;
31
- }
32
-
33
- .service-card {
34
- position: relative;
35
- display: flex;
36
- flex-direction: column;
37
- background: var(--color-paper, var(--color-cream));
38
- border-radius: var(--radius-xl);
39
- overflow: hidden;
40
- text-decoration: none;
41
- color: inherit;
42
- transition: transform 280ms ease, box-shadow 280ms ease;
43
- box-shadow: var(--shadow-card, 0 4px 16px -8px rgba(0, 0, 0, 0.15));
44
- }
45
- .service-card:hover {
46
- transform: translateY(-4px);
47
- }
48
- .service-card:hover .service-card-image img {
49
- transform: scale(1.04);
50
- }
51
-
52
- .service-card-image {
53
- aspect-ratio: 3 / 2;
54
- overflow: hidden;
55
- background: var(--color-paper-warm, var(--color-surface-secondary, var(--color-cream)));
56
- }
57
- .service-card-image img {
58
- width: 100%;
59
- height: 100%;
60
- object-fit: cover;
61
- transition: transform 600ms ease;
62
- }
63
-
64
- .service-card-meta {
65
- display: flex;
66
- flex-direction: column;
67
- gap: 0.5rem;
68
- padding: 1rem 1rem 1.5rem;
69
- flex: 1;
70
- }
71
- .service-card-name {
72
- margin: 0;
73
- font-family: var(--font-display);
74
- font-size: 1.125rem;
75
- line-height: 1.25;
76
- color: var(--color-ink);
77
- }
78
- .service-card-tagline {
79
- margin: 0;
80
- font-family: var(--font-body);
81
- font-size: 0.875rem;
82
- color: var(--color-ink-soft, var(--color-mute));
83
- line-height: 1.45;
84
- }
85
- .service-card-price {
86
- display: flex;
87
- align-items: center;
88
- gap: 0.75rem;
89
- margin-top: auto;
90
- padding-top: 0.75rem;
91
- font-family: var(--font-body);
92
- font-size: 0.875rem;
93
- color: var(--color-mute);
94
- }
95
- .service-card-price span + span::before {
96
- content: "·";
97
- padding-right: 0.75rem;
98
- color: var(--color-rule);
99
- }
100
-
101
- /* ── Catalog filters (location + category) ──────────────────────────────────── */
102
- .booking-filter-bar {
103
- display: flex;
104
- flex-wrap: wrap;
105
- gap: 0.75rem;
106
- margin-bottom: 2rem;
107
- }
108
- .booking-filter-chip {
109
- padding: 0.5rem 1rem;
110
- border: 1px solid var(--color-rule);
111
- border-radius: var(--radius-pill, 999px);
112
- background: var(--color-paper, var(--color-cream));
113
- color: var(--color-ink);
114
- font-family: var(--font-body);
115
- font-size: 0.875rem;
116
- text-decoration: none;
117
- cursor: pointer;
118
- transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
119
- }
120
- .booking-filter-chip:hover {
121
- border-color: var(--color-ink);
122
- }
123
- .booking-filter-chip--active {
124
- background: var(--color-accent);
125
- border-color: var(--color-accent);
126
- color: var(--color-paper);
127
- }
128
-
129
- /* ── Availability — week calendar ───────────────────────────────────────────── */
130
- .availability-calendar {
131
- display: flex;
132
- flex-direction: column;
133
- gap: 1.5rem;
134
- }
135
-
136
- /* Filter row — holds the optional location + staff pickers side by side. */
137
- .availability-filters {
138
- display: flex;
139
- flex-wrap: wrap;
140
- gap: 1rem;
141
- }
142
- .availability-filters > * {
143
- flex: 1 1 12rem;
144
- }
145
-
146
- /* Location / staff picker (shown only when there's >1 option). */
147
- .availability-staff {
148
- display: flex;
149
- flex-direction: column;
150
- gap: 0.5rem;
151
- }
152
- .availability-staff-label {
153
- font-family: var(--font-display);
154
- font-size: 0.75rem;
155
- text-transform: uppercase;
156
- letter-spacing: 0.05em;
157
- color: var(--color-ink-soft, var(--color-mute));
158
- }
159
- .availability-staff-select {
160
- width: 100%;
161
- padding: 0.75rem 1rem;
162
- font-family: var(--font-body);
163
- font-size: 0.9375rem;
164
- border: 1px solid var(--color-rule);
165
- border-radius: var(--radius-sm);
166
- background: var(--color-paper, var(--color-cream));
167
- color: var(--color-ink);
168
- box-sizing: border-box;
169
- }
170
- .availability-staff-select:focus {
171
- outline: none;
172
- border-color: var(--color-accent);
173
- }
174
-
175
- .availability-week-nav {
176
- display: flex;
177
- align-items: center;
178
- justify-content: space-between;
179
- gap: 1rem;
180
- padding: 0.75rem 0;
181
- border-bottom: 1px solid var(--color-rule);
182
- }
183
- .availability-week-label {
184
- font-family: var(--font-display);
185
- font-size: 1rem;
186
- color: var(--color-ink);
187
- flex: 1;
188
- text-align: center;
189
- }
190
-
191
- .availability-nav-btn {
192
- padding: 0.75rem 1rem;
193
- background: transparent;
194
- border: 1px solid var(--color-rule);
195
- border-radius: var(--radius-sm);
196
- color: var(--color-ink);
197
- font-family: var(--font-body);
198
- font-size: 0.875rem;
199
- cursor: pointer;
200
- transition: background-color 150ms ease, border-color 150ms ease;
201
- }
202
- .availability-nav-btn:hover:not(:disabled) {
203
- background: var(--color-paper-warm, var(--color-cream));
204
- border-color: var(--color-ink);
205
- }
206
- .availability-nav-btn:disabled {
207
- opacity: 0.35;
208
- cursor: not-allowed;
209
- }
210
-
211
- /* The 7-day strip. */
212
- .availability-day-strip {
213
- display: grid;
214
- grid-template-columns: repeat(7, 1fr);
215
- gap: 0.75rem;
216
- }
217
- .availability-day {
218
- display: flex;
219
- flex-direction: column;
220
- align-items: center;
221
- gap: 2px;
222
- padding: 0.75rem 0;
223
- border: 1px solid var(--color-rule);
224
- border-radius: var(--radius-sm);
225
- background: var(--color-paper, var(--color-cream));
226
- color: var(--color-ink);
227
- font-family: var(--font-body);
228
- cursor: pointer;
229
- transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
230
- }
231
- .availability-day-name {
232
- font-size: 0.7rem;
233
- text-transform: uppercase;
234
- letter-spacing: 0.04em;
235
- color: var(--color-mute);
236
- }
237
- .availability-day-num {
238
- font-size: 1rem;
239
- font-weight: 600;
240
- }
241
- .availability-day--has-slots:hover {
242
- border-color: var(--color-accent);
243
- }
244
- .availability-day--empty {
245
- opacity: 0.4;
246
- cursor: not-allowed;
247
- }
248
- .availability-day--selected {
249
- background: var(--color-accent);
250
- border-color: var(--color-accent);
251
- color: var(--color-paper);
252
- }
253
- .availability-day--selected .availability-day-name {
254
- color: var(--color-paper);
255
- }
256
-
257
- .availability-slots {
258
- display: grid;
259
- grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
260
- gap: 0.75rem;
261
- }
262
- .availability-loading,
263
- .availability-empty,
264
- .availability-error {
265
- font-family: var(--font-body);
266
- font-size: 0.9375rem;
267
- color: var(--color-ink-soft, var(--color-mute));
268
- padding: 1.5rem 0;
269
- text-align: center;
270
- }
271
- .availability-empty {
272
- display: flex;
273
- flex-direction: column;
274
- align-items: center;
275
- gap: 1rem;
276
- }
277
- .availability-error {
278
- color: var(--color-error, var(--color-accent));
279
- }
280
-
281
- /* ── Time-slot buttons ──────────────────────────────────────────────────────── */
282
- .time-slot {
283
- padding: 0.75rem 1rem;
284
- border: 1px solid var(--color-rule);
285
- border-radius: var(--radius-sm);
286
- background: var(--color-paper, var(--color-cream));
287
- color: var(--color-ink);
288
- font-family: var(--font-body);
289
- font-size: 0.875rem;
290
- text-align: center;
291
- cursor: pointer;
292
- transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
293
- }
294
- .time-slot-time {
295
- font-weight: 500;
296
- }
297
- .time-slot--available {
298
- border-color: var(--color-ink);
299
- }
300
- .time-slot--available:hover {
301
- background: var(--color-accent);
302
- border-color: var(--color-accent);
303
- color: var(--color-paper);
304
- }
305
- .time-slot--selected {
306
- background: var(--color-accent);
307
- border-color: var(--color-accent);
308
- color: var(--color-paper);
309
- font-weight: 600;
310
- }
311
-
312
- /* ── Booking form (schema-driven) ───────────────────────────────────────────── */
313
- .booking-form {
314
- display: flex;
315
- flex-direction: column;
316
- gap: 1.5rem;
317
- padding: 2rem;
318
- border: 1px solid var(--color-rule);
319
- border-radius: var(--radius-md);
320
- background: var(--color-paper-warm, var(--color-paper, var(--color-cream)));
321
- }
322
-
323
- .booking-form-summary {
324
- display: flex;
325
- flex-direction: column;
326
- gap: 0.5rem;
327
- padding-bottom: 1rem;
328
- border-bottom: 1px solid var(--color-rule);
329
- }
330
- .booking-form-summary strong {
331
- font-family: var(--font-display);
332
- font-size: 1.125rem;
333
- color: var(--color-ink);
334
- }
335
- .booking-form-summary span {
336
- font-family: var(--font-body);
337
- font-size: 0.9375rem;
338
- color: var(--color-ink-soft, var(--color-mute));
339
- }
340
- .booking-form-change {
341
- align-self: flex-start;
342
- margin-top: 0.5rem;
343
- background: none;
344
- border: none;
345
- padding: 0;
346
- font-family: var(--font-body);
347
- font-size: 0.8125rem;
348
- color: var(--color-mute);
349
- text-decoration: underline;
350
- cursor: pointer;
351
- }
352
- .booking-form-change:hover {
353
- color: var(--color-ink);
354
- }
355
-
356
- .booking-field {
357
- display: flex;
358
- flex-direction: column;
359
- gap: 0.5rem;
360
- }
361
- .booking-label {
362
- font-family: var(--font-display);
363
- font-size: 0.75rem;
364
- text-transform: uppercase;
365
- letter-spacing: 0.05em;
366
- color: var(--color-ink-soft, var(--color-mute));
367
- }
368
- .booking-required {
369
- color: var(--color-accent);
370
- }
371
-
372
- .booking-input {
373
- width: 100%;
374
- padding: 0.75rem 1rem;
375
- font-family: var(--font-body);
376
- font-size: 0.9375rem;
377
- border: 1px solid var(--color-rule);
378
- border-radius: var(--radius-sm);
379
- background: var(--color-paper, var(--color-cream));
380
- color: var(--color-ink);
381
- transition: border-color 150ms ease;
382
- box-sizing: border-box;
383
- }
384
- .booking-input:focus {
385
- outline: none;
386
- border-color: var(--color-accent);
387
- }
388
- textarea.booking-input {
389
- resize: vertical;
390
- min-height: 6rem;
391
- }
392
-
393
- .booking-error {
394
- font-family: var(--font-body);
395
- font-size: 0.875rem;
396
- color: var(--color-error, var(--color-accent));
397
- padding: 0.75rem 1rem;
398
- border: 1px solid var(--color-error, var(--color-accent));
399
- border-radius: var(--radius-sm);
400
- }
401
-
402
- .booking-cta {
403
- display: inline-flex;
404
- align-items: center;
405
- justify-content: center;
406
- width: 100%;
407
- padding: 1rem 2rem;
408
- font-family: var(--font-display);
409
- font-size: 0.9375rem;
410
- font-weight: 500;
411
- background: var(--color-accent);
412
- color: var(--color-paper);
413
- border: 1px solid var(--color-accent);
414
- border-radius: var(--radius-sm);
415
- cursor: pointer;
416
- transition: opacity 150ms ease;
417
- }
418
- .booking-cta:hover:not(:disabled) {
419
- opacity: 0.9;
420
- }
421
- .booking-cta:disabled {
422
- opacity: 0.5;
423
- cursor: not-allowed;
424
- }
@@ -1,176 +0,0 @@
1
- ---
2
- // src/pages/services/[slug].astro — SSR service detail + client-side booking flow.
3
- // Two dirs deep inside src/ → import with ../../ (not three ../).
4
- import Layout from "../../layouts/Layout.astro";
5
- import SeoTags from "../../components/SeoTags.astro";
6
- import ServiceBookingFlow from "../../components/ServiceBookingFlow";
7
- import { services } from "@wix/bookings";
8
- import { forms } from "@wix/forms";
9
- import { auth } from "@wix/essentials";
10
-
11
- const BOOKING_APP_ID = "13d21c63-b5ec-5912-8397-c3a5ddb27a97";
12
- const { slug } = Astro.params;
13
-
14
- // Carried from the catalog's location selector (when the site has >1 location):
15
- // the default location the availability picker scopes to. Absent on single-location
16
- // sites (and on deep links — the picker then defaults to the service's first location).
17
- const reqUrl = new URL(Astro.request.url);
18
- const locationId = reqUrl.searchParams.get("locationId") ?? undefined;
19
-
20
- let service: any = null;
21
- try {
22
- // Ambient SSR via @wix/essentials. Single service by slug: the .eq() builder
23
- // chain on mainSlug.name + appId (the form the @wix/bookings SDK expects).
24
- const result = await auth
25
- .elevate(services.queryServices)({ conditionalFields: ["STAFF_MEMBER_DETAILS"] })
26
- .eq("mainSlug.name", slug)
27
- .eq("appId", BOOKING_APP_ID)
28
- .limit(1)
29
- .find();
30
- service = result.items?.[0] ?? null;
31
- } catch (err) {
32
- console.error(`[services/${slug}] detail query failed:`, err);
33
- }
34
-
35
- if (!service) return Astro.redirect("/services", 302);
36
-
37
- // Booking-form SCHEMA — the form belongs to the service (service.form._id) in the
38
- // bookings namespace. Read it server-side and pass the field list to the island.
39
- // Same renderer the forms vertical uses (references/astro/forms/CONTACT_FORM.md):
40
- // keep the field's `target` — that is the key createBooking expects in formSubmission.
41
- let formFields: any[] = [];
42
- try {
43
- const formId = service.form?._id;
44
- if (formId) {
45
- const res: any = await auth.elevate(forms.getForm)(formId);
46
- const form = res?.form ?? res;
47
- // Only render field types we can submit as a simple value. Skip complex,
48
- // object-valued fields (e.g. a multi-line ADDRESS) — they carry no string
49
- // `componentType`, and sending a string for them fails createBooking with
50
- // "must be object". The booking enforces only the contact basics
51
- // (first_name/last_name/email), so skipping optional complex fields is safe.
52
- const RENDERABLE = ["TEXT_INPUT", "PHONE_INPUT", "DROPDOWN"];
53
- formFields = (form?.formFields ?? [])
54
- .filter(
55
- (f: any) =>
56
- f.fieldType === "INPUT" &&
57
- !f.hidden &&
58
- RENDERABLE.includes(f.inputOptions?.stringOptions?.componentType),
59
- )
60
- .map((f: any) => {
61
- const opts = f.inputOptions;
62
- const str = opts?.stringOptions;
63
- const label =
64
- str?.textInputOptions?.label ??
65
- str?.dropdownOptions?.label ??
66
- str?.phoneInputOptions?.label ??
67
- "";
68
- return {
69
- label,
70
- target: opts?.target ?? "",
71
- required: opts?.required ?? false,
72
- componentType: str?.componentType ?? "TEXT_INPUT",
73
- identifier: f.identifier ?? "",
74
- options: str?.dropdownOptions?.options?.map((o: any) => ({
75
- value: o.value ?? o.label ?? "",
76
- label: o.label ?? o.value ?? "",
77
- })),
78
- };
79
- });
80
- }
81
- } catch (err) {
82
- console.error(`[services/${slug}] booking form schema failed:`, err);
83
- }
84
-
85
- const formatPrice = (p: any): string | undefined => {
86
- if (!p || p.rateType === "NO_FEE") return undefined;
87
- if (p.rateType === "FIXED" && p.fixed?.price) {
88
- const { value, currency } = p.fixed.price;
89
- if (!value) return undefined;
90
- return new Intl.NumberFormat("en-US", { style: "currency", currency: currency ?? "USD" }).format(Number(value));
91
- }
92
- return undefined;
93
- };
94
- const price = formatPrice(service.payment);
95
- const duration = service.schedule?.availabilityConstraints?.sessionDurations?.[0] ?? 60;
96
- const imageUrl = service.media?.mainMedia?.image?.url ?? service.media?.items?.[0]?.image?.url;
97
- const serviceName = service.name ?? "Service";
98
- const seoTags = service.seoData?.tags ?? [];
99
-
100
- // Staff for the optional staff picker — carried on the service via the
101
- // STAFF_MEMBER_DETAILS conditional field (already requested in the query above).
102
- // Each entry is { staffMemberId, name } — `staffMemberId` is, despite the name,
103
- // the resource id (the calendar filters availability + books by it). The calendar
104
- // shows the picker only when there is more than one; empty/absent → "any staff
105
- // member" (the ANY_RESOURCE fallback).
106
- const staffMembers = service.staffMemberDetails?.staffMembers ?? [];
107
-
108
- // Business locations the service is offered at — sourced from `queryLocations()`
109
- // (the site's real business locations, whose ids the availability engine
110
- // recognizes), intersected with the service's own location ids. Availability is
111
- // scoped to one of these so a multi-location service doesn't return duplicate
112
- // per-location time slots (listAvailabilityTimeSlots returns one slot per location
113
- // otherwise). Source from `queryLocations()`, NOT from `service.locations` alone:
114
- // a service's location entry can carry an id the availability engine doesn't
115
- // recognize, and scoping to it returns zero slots. When the site has no business
116
- // locations this resolves to [] and the calendar fetches unscoped.
117
- let serviceLocations: { _id: string; name?: string }[] = [];
118
- try {
119
- const locResult: any = await auth.elevate(services.queryLocations)();
120
- const businessLocations = locResult?.businessLocations?.locations ?? [];
121
- const serviceLocationIds = new Set(
122
- (service.locations ?? [])
123
- .filter((l: any) => (l.type ?? "BUSINESS") === "BUSINESS")
124
- .map((l: any) => l.business?._id ?? l._id)
125
- .filter(Boolean),
126
- );
127
- serviceLocations = businessLocations
128
- .filter((l: any) => serviceLocationIds.has(l._id))
129
- .map((l: any) => ({ _id: l._id, name: l.business?.name ?? "Location" }));
130
- } catch (err) {
131
- console.error(`[services/${slug}] queryLocations failed:`, err);
132
- }
133
- ---
134
-
135
- <!--
136
- Width: use `container-reading` (max-width: var(--container-prose) + auto margins)
137
- for a deliberate prose measure. Bare `max-w-<size>` keys resolve to Tailwind's
138
- --container-* scale, which is wider than ideal for reading text.
139
- -->
140
- <Layout title={serviceName} description={service.tagLine ?? service.description}>
141
- <SeoTags tags={seoTags} slot="head" />
142
- <section class="container-reading px-6 py-24">
143
- <a href="/services" class="inline-block text-sm text-mute hover:text-ink mb-8">← All services</a>
144
-
145
- <!-- Optional banner image — only when the service has media (image-less is the
146
- common seed case; rendering a fixed placeholder collapses the layout). -->
147
- {imageUrl && (
148
- <img src={imageUrl} alt={serviceName} class="w-full h-64 object-cover rounded-lg mb-8" />
149
- )}
150
-
151
- <div class="flex flex-col gap-4 mb-16">
152
- <hr class="editorial-rule w-16 ml-0" />
153
- <h1 class="font-display text-4xl md:text-5xl leading-tight">{serviceName}</h1>
154
- {service.tagLine && <p class="text-lg text-mute leading-relaxed max-w-prose">{service.tagLine}</p>}
155
- <div class="flex items-center gap-4 text-sm text-mute">
156
- <span>{duration} min</span>
157
- {price && <span class="text-ink font-medium">{price}</span>}
158
- </div>
159
- {service.description && <p class="text-ink leading-relaxed max-w-prose">{service.description}</p>}
160
- </div>
161
-
162
- <section class="border-t border-rule pt-12">
163
- <h2 class="font-display text-3xl leading-tight mb-8">Book this service</h2>
164
- <ServiceBookingFlow
165
- service={service}
166
- serviceName={serviceName}
167
- serviceType={service.type ?? "APPOINTMENT"}
168
- fields={formFields}
169
- staffMembers={staffMembers}
170
- locations={serviceLocations}
171
- locationId={locationId}
172
- client:only="react"
173
- />
174
- </section>
175
- </section>
176
- </Layout>