@wix/agent-skills 1.17.0 → 1.18.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 (246) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +115 -12
  3. package/skills/wix-app/references/APP_MARKET_REVIEW.md +1 -1
  4. package/skills/wix-app/references/BACKEND_API.md +18 -0
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +6 -0
  6. package/skills/wix-app/references/DASHBOARD_MODAL.md +10 -2
  7. package/skills/wix-app/references/DASHBOARD_PAGE.md +32 -70
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +14 -3
  9. package/skills/wix-app/references/SITE_PLUGIN.md +12 -0
  10. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +74 -68
  11. package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +79 -0
  12. package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +73 -0
  13. package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +52 -0
  14. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +184 -0
  15. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +12 -11
  16. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +1 -0
  17. package/skills/wix-app/references/editor-react-component/BROWSER-SUPPORT.md +56 -0
  18. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +16 -8
  19. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +19 -1
  20. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +3 -0
  21. package/skills/wix-base44-connector/SKILL.md +133 -44
  22. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +78 -0
  23. package/skills/wix-base44-connector/scripts/utils.js +216 -30
  24. package/skills/wix-headless/entry/skill.md +1 -1
  25. package/skills/wix-headless/references/CAPABILITIES.md +9 -1
  26. package/skills/wix-headless/references/DESIGN.md +1 -0
  27. package/skills/wix-headless/references/DISCOVERY.md +2 -1
  28. package/skills/wix-headless/references/IMAGE_GENERATION.md +1 -0
  29. package/skills/wix-headless/references/SDK_HANDOFF.md +4 -1
  30. package/skills/wix-headless/references/SEED.md +2 -1
  31. package/skills/wix-headless/references/SETUP.md +1 -0
  32. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +2 -2
  33. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +26 -8
  34. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +26 -10
  35. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +8 -8
  36. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +1 -1
  37. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +1 -1
  38. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +254 -0
  39. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +13 -0
  40. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +254 -0
  41. package/skills/wix-headless/references/non-astro.md +1 -1
  42. package/skills/wix-headless-fast/SKILL.md +166 -0
  43. package/skills/wix-headless-fast/entry/skill.md +99 -0
  44. package/skills/wix-headless-fast/install/deploy.mjs +433 -0
  45. package/skills/wix-headless-fast/install/fast-path.mjs +141 -0
  46. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +137 -0
  47. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +137 -0
  48. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +113 -0
  49. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +42 -0
  50. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +123 -0
  51. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +70 -0
  52. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +99 -0
  53. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +76 -0
  54. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +62 -0
  55. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +40 -0
  56. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +99 -0
  57. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +24 -0
  58. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +16156 -0
  59. package/skills/wix-headless-fast/references/blog/seed/SEED.md +72 -0
  60. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +287 -0
  61. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +129 -0
  62. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +143 -0
  63. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +119 -0
  64. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +138 -0
  65. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +54 -0
  66. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +206 -0
  67. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +96 -0
  68. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +70 -0
  69. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +40 -0
  70. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +76 -0
  71. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +22 -0
  72. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +11962 -0
  73. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +61 -0
  74. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +302 -0
  75. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +179 -0
  76. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +83 -0
  77. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +57 -0
  78. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +151 -0
  79. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +75 -0
  80. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +41 -0
  81. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +11262 -0
  82. package/skills/wix-headless-fast/references/cms/seed/SEED.md +103 -0
  83. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +324 -0
  84. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +149 -0
  85. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +66 -0
  86. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +176 -0
  87. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +118 -0
  88. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +117 -0
  89. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +59 -0
  90. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +136 -0
  91. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +128 -0
  92. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +61 -0
  93. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +40 -0
  94. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +12 -0
  95. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +80 -0
  96. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +21 -0
  97. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +11884 -0
  98. package/skills/wix-headless-fast/references/events/seed/SEED.md +86 -0
  99. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +276 -0
  100. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +150 -0
  101. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +317 -0
  102. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +269 -0
  103. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +231 -0
  104. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +135 -0
  105. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +10593 -0
  106. package/skills/wix-headless-fast/references/forms/seed/SEED.md +108 -0
  107. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +320 -0
  108. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +63 -0
  109. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +60 -0
  110. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +155 -0
  111. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +78 -0
  112. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +47 -0
  113. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +66 -0
  114. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +88 -0
  115. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +53 -0
  116. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +122 -0
  117. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +50 -0
  118. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +21 -0
  119. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +42 -0
  120. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +10 -0
  121. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +11 -0
  122. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +10329 -0
  123. package/skills/wix-headless-fast/references/members/seed/SEED.md +39 -0
  124. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +94 -0
  125. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +134 -0
  126. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
  127. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
  128. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +115 -0
  129. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +59 -0
  130. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +39 -0
  131. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +58 -0
  132. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +165 -0
  133. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +55 -0
  134. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
  135. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
  136. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +21 -0
  137. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +29 -0
  138. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +10197 -0
  139. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +78 -0
  140. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +258 -0
  141. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +133 -0
  142. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +58 -0
  143. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +126 -0
  144. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +37 -0
  145. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +39 -0
  146. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +75 -0
  147. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +45 -0
  148. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +30 -0
  149. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
  150. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +40 -0
  151. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +21 -0
  152. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +11226 -0
  153. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +71 -0
  154. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +279 -0
  155. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +165 -0
  156. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +142 -0
  157. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
  158. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
  159. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +155 -0
  160. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +55 -0
  161. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +43 -0
  162. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +177 -0
  163. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +165 -0
  164. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +103 -0
  165. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +254 -0
  166. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +146 -0
  167. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +168 -0
  168. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
  169. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +22 -0
  170. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +12 -0
  171. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +12560 -0
  172. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +81 -0
  173. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +479 -0
  174. package/skills/wix-headless-fast/references/shared/CONTENT.md +22 -0
  175. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +73 -0
  176. package/skills/wix-headless-fast/references/shared/DESIGN.md +26 -0
  177. package/skills/wix-headless-fast/references/shared/app/styles/global.css +52 -0
  178. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +15 -0
  179. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +27 -0
  180. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +24 -0
  181. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +76 -0
  182. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
  183. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +46 -0
  184. package/skills/wix-headless-fast/references/shared/seed/images.mjs +145 -0
  185. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +149 -0
  186. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +26 -0
  187. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +121 -0
  188. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +100 -0
  189. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +130 -0
  190. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +48 -0
  191. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +66 -0
  192. package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +103 -0
  193. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +48 -0
  194. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +140 -0
  195. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +80 -0
  196. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +101 -0
  197. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +221 -0
  198. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +215 -0
  199. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +109 -0
  200. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +46 -0
  201. package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +56 -0
  202. package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +23 -0
  203. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +12247 -0
  204. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +85 -0
  205. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +415 -0
  206. package/skills/wix-manage/SKILL.md +18 -2
  207. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +141 -0
  208. package/skills/wix-manage/references/google-business-profile/connect-google-business-profile.md +134 -0
  209. package/skills/wix-manage/references/google-business-profile/manage-google-business-profile-locations.md +182 -0
  210. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +3 -0
  211. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +21 -6
  212. package/skills/wix-manage/references/stores/update-product-with-options.md +83 -0
  213. package/skills/wix-vibe-headless/SKILL.md +18 -4
  214. package/skills/wix-vibe-headless/install/deploy.cjs +12 -4
  215. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +2 -1
  216. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +3 -1
  217. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +3 -1
  218. package/skills/wix-vibe-headless/platforms/base44.md +23 -61
  219. package/skills/wix-vibe-headless/platforms/generic.md +6 -3
  220. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +43 -0
  221. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +67 -0
  222. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +128 -0
  223. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +5 -3
  224. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +250 -0
  225. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +12 -5
  226. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +41 -0
  227. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.js +267 -0
  228. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +6 -3
  229. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +470 -0
  230. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +425 -0
  231. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +187 -0
  232. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +238 -0
  233. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +108 -0
  234. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1762 -0
  235. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +13 -0
  236. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +137 -84
  237. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +15 -8
  238. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +37 -0
  239. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +18 -6
  240. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +30 -7
  241. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +46 -10
  242. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +0 -110
  243. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +0 -51
  244. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +0 -49
  245. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +0 -92
  246. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +0 -139
@@ -0,0 +1,26 @@
1
+ // REFERENCE header order button with a live count badge — opens the OrderCartDrawer.
2
+ // Correct and complete; per the skill's model you design your own chrome on useOrderCart.
3
+ import { useOrderCart } from "../../hooks/restaurants/useOrderCart";
4
+
5
+ export default function OrderCartButton() {
6
+ const { itemCount, openCart } = useOrderCart();
7
+ return (
8
+ <button
9
+ type="button"
10
+ aria-label={`Order, ${itemCount} items`}
11
+ onClick={openCart}
12
+ className="relative inline-flex items-center p-1.5 text-foreground transition-opacity hover:opacity-70"
13
+ >
14
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6">
15
+ <path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z" />
16
+ <line x1="3" y1="6" x2="21" y2="6" />
17
+ <path d="M16 10a4 4 0 01-8 0" />
18
+ </svg>
19
+ {itemCount > 0 && (
20
+ <span className="absolute -right-1 -top-1 flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1 text-[10px] font-bold text-primary-foreground">
21
+ {itemCount}
22
+ </span>
23
+ )}
24
+ </button>
25
+ );
26
+ }
@@ -0,0 +1,121 @@
1
+ // REFERENCE slide-over order cart with quantity stepper, remove, live subtotal, and the
2
+ // Wix-hosted checkout. Mount ONCE per page; opens via useOrderCart().openCart(). Correct and
3
+ // complete; per the skill's model you design your own chrome on useOrderCart.
4
+ import { useOrderCart } from "../../hooks/restaurants/useOrderCart";
5
+
6
+ export default function OrderCartDrawer() {
7
+ const { cart, open, closeCart, busy, error, updateQuantity, removeLine, checkout } = useOrderCart();
8
+ if (!open) return null;
9
+ const lines = cart?.lines ?? [];
10
+
11
+ return (
12
+ <div
13
+ className="fixed inset-0 z-50 flex justify-end bg-foreground/40 backdrop-blur-[2px]"
14
+ onClick={closeCart}
15
+ >
16
+ <aside
17
+ role="dialog"
18
+ aria-label="Your order"
19
+ onClick={(e) => e.stopPropagation()}
20
+ className="flex h-full w-full max-w-md flex-col bg-background text-foreground shadow-2xl"
21
+ >
22
+ <div className="flex items-center justify-between border-b border-border px-6 py-5">
23
+ <span className="text-base font-semibold">
24
+ Your order{cart && cart.itemCount > 0 ? ` (${cart.itemCount})` : ""}
25
+ </span>
26
+ <button
27
+ type="button"
28
+ aria-label="Close order"
29
+ onClick={closeCart}
30
+ className="text-xl leading-none text-muted-foreground transition-colors hover:text-foreground"
31
+ >
32
+ ×
33
+ </button>
34
+ </div>
35
+
36
+ <div className="flex-1 overflow-y-auto px-6 py-5">
37
+ {lines.length === 0 && (
38
+ <p className="py-16 text-center text-sm text-muted-foreground">Your order is empty.</p>
39
+ )}
40
+ {lines.map((line) => (
41
+ <div className="mb-6 flex gap-4" key={line.lineItemId}>
42
+ {line.imageUrl ? (
43
+ <img
44
+ src={line.imageUrl}
45
+ alt=""
46
+ loading="lazy"
47
+ className="h-16 w-16 flex-shrink-0 rounded-md bg-secondary object-cover"
48
+ />
49
+ ) : (
50
+ <div aria-hidden="true" className="h-16 w-16 flex-shrink-0 rounded-md bg-secondary" />
51
+ )}
52
+ <div className="min-w-0 flex-1">
53
+ <p className="text-sm font-medium">{line.itemName}</p>
54
+ {line.descriptionLines.map((d) => (
55
+ <p className="mt-0.5 text-xs text-muted-foreground" key={d}>
56
+ {d}
57
+ </p>
58
+ ))}
59
+ {line.status !== "IN_STOCK" && (
60
+ <p className="mt-1 text-xs text-red-600">No longer available</p>
61
+ )}
62
+ <div className="mt-2 flex items-center">
63
+ <div className="inline-flex items-center gap-3 rounded-full border border-border px-2 py-0.5">
64
+ <button
65
+ type="button"
66
+ aria-label="Decrease quantity"
67
+ disabled={busy || line.quantity <= 1}
68
+ onClick={() => updateQuantity(line.lineItemId, line.quantity - 1).catch(() => {})}
69
+ className="px-1 text-base disabled:opacity-40"
70
+ >
71
+ −
72
+ </button>
73
+ <span className="text-sm tabular-nums">{line.quantity}</span>
74
+ <button
75
+ type="button"
76
+ aria-label="Increase quantity"
77
+ disabled={busy}
78
+ onClick={() => updateQuantity(line.lineItemId, line.quantity + 1).catch(() => {})}
79
+ className="px-1 text-base disabled:opacity-40"
80
+ >
81
+ +
82
+ </button>
83
+ </div>
84
+ <button
85
+ type="button"
86
+ disabled={busy}
87
+ onClick={() => removeLine(line.lineItemId).catch(() => {})}
88
+ className="ml-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground disabled:opacity-40"
89
+ >
90
+ Remove
91
+ </button>
92
+ </div>
93
+ </div>
94
+ <p className="text-sm font-medium">{line.linePrice}</p>
95
+ </div>
96
+ ))}
97
+ </div>
98
+
99
+ {lines.length > 0 && (
100
+ <div className="border-t border-border px-6 py-5">
101
+ {cart?.subtotal && (
102
+ <div className="mb-4 flex justify-between text-sm">
103
+ <span className="text-muted-foreground">Subtotal</span>
104
+ <strong className="font-semibold">{cart.subtotal}</strong>
105
+ </div>
106
+ )}
107
+ {error && <p className="mb-3 text-xs text-red-600">{error}</p>}
108
+ <button
109
+ type="button"
110
+ disabled={busy}
111
+ onClick={() => checkout().catch(() => {})}
112
+ className="w-full rounded-full bg-primary py-3.5 text-sm font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-50"
113
+ >
114
+ {busy ? "One moment…" : "Checkout"}
115
+ </button>
116
+ </div>
117
+ )}
118
+ </aside>
119
+ </div>
120
+ );
121
+ }
@@ -0,0 +1,155 @@
1
+ // REFERENCE reservations surface: party/date/time query → AVAILABLE slot pills → hold →
2
+ // details form → confirmed, on the @theme tokens. Correct and complete; per the skill's
3
+ // model you design and build your own on useReservation (which owns ALL booking logic).
4
+ import { useReservation } from "../../hooks/restaurants/useReservation";
5
+
6
+ const input =
7
+ "w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary";
8
+
9
+ export default function ReservationView() {
10
+ const r = useReservation();
11
+
12
+ if (r.locations === null) {
13
+ return <div className="h-64 animate-pulse rounded-lg bg-secondary" aria-busy="true" />;
14
+ }
15
+ if (r.locations.length === 0 || !r.location) {
16
+ return (
17
+ <p className="py-16 text-center text-muted-foreground">
18
+ Table reservations aren't set up yet — call us to book.
19
+ </p>
20
+ );
21
+ }
22
+ if (!r.location.onlineReservationsEnabled) {
23
+ // Premium-gated toggle is off — slots/booking would fail; be honest, don't fake a form.
24
+ return (
25
+ <p className="py-16 text-center text-muted-foreground">
26
+ Online reservations aren't open yet — call us to book a table.
27
+ </p>
28
+ );
29
+ }
30
+
31
+ if (r.confirmed) {
32
+ return (
33
+ <div className="mx-auto max-w-md rounded-lg border border-border p-8 text-center">
34
+ <p className="text-lg font-semibold">
35
+ {r.confirmed.status === "RESERVED" ? "Table reserved" : "Request sent"}
36
+ </p>
37
+ <p className="mt-2 text-sm text-muted-foreground">
38
+ {r.confirmed.status === "RESERVED"
39
+ ? "See you soon — a confirmation is on its way."
40
+ : "The restaurant will confirm your reservation shortly."}
41
+ </p>
42
+ <button
43
+ type="button"
44
+ onClick={r.reset}
45
+ className="mt-6 rounded-full border border-border px-5 py-2 text-sm font-medium hover:bg-secondary"
46
+ >
47
+ Make another reservation
48
+ </button>
49
+ </div>
50
+ );
51
+ }
52
+
53
+ return (
54
+ <div className="mx-auto max-w-xl">
55
+ <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
56
+ <label className="block text-sm">
57
+ <span className="text-muted-foreground">Guests</span>
58
+ <input
59
+ type="number"
60
+ min={r.location.partySizeMin}
61
+ max={r.location.partySizeMax}
62
+ value={r.partySize}
63
+ onChange={(e) => r.setPartySize(Number(e.target.value))}
64
+ className={`mt-1 ${input}`}
65
+ />
66
+ </label>
67
+ <label className="block text-sm">
68
+ <span className="text-muted-foreground">Date</span>
69
+ <input type="date" value={r.date} onChange={(e) => r.setDate(e.target.value)} className={`mt-1 ${input}`} />
70
+ </label>
71
+ <label className="block text-sm">
72
+ <span className="text-muted-foreground">Around</span>
73
+ <input type="time" value={r.time} onChange={(e) => r.setTime(e.target.value)} className={`mt-1 ${input}`} />
74
+ </label>
75
+ </div>
76
+ <button
77
+ type="button"
78
+ disabled={r.loading}
79
+ onClick={() => void r.findSlots()}
80
+ className="mt-4 w-full rounded-full bg-primary py-3 text-sm font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-50"
81
+ >
82
+ {r.loading && r.slots === null ? "Finding times…" : "Find a table"}
83
+ </button>
84
+
85
+ {r.error && <p className="mt-4 text-sm text-red-600">{r.error}</p>}
86
+
87
+ {r.slots !== null && r.slots.length === 0 && !r.error && (
88
+ <p className="mt-6 text-center text-sm text-muted-foreground">
89
+ No tables around that time — try another time or party size.
90
+ </p>
91
+ )}
92
+
93
+ {r.slots !== null && r.slots.length > 0 && !r.held && (
94
+ <div className="mt-6 flex flex-wrap gap-2" role="group" aria-label="Available times">
95
+ {r.slots.map((slot) => (
96
+ <button
97
+ key={slot.startIso}
98
+ type="button"
99
+ disabled={r.loading}
100
+ onClick={() => void r.holdSlot(slot)}
101
+ className="rounded-full border border-border px-4 py-1.5 text-sm font-medium transition-colors hover:bg-secondary disabled:opacity-40"
102
+ >
103
+ {slot.label}
104
+ </button>
105
+ ))}
106
+ </div>
107
+ )}
108
+
109
+ {r.held && (
110
+ <div className="mt-6 rounded-lg border border-border p-5">
111
+ <p className="text-sm font-medium">
112
+ Holding {new Date(r.held.startIso).toLocaleString(undefined, { weekday: "short", month: "short", day: "numeric", hour: "numeric", minute: "2-digit" })}{" "}
113
+ for {r.held.partySize} — complete within 10 minutes.
114
+ </p>
115
+ <div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2">
116
+ <input
117
+ placeholder="First name *"
118
+ value={r.reservee.firstName}
119
+ onChange={(e) => r.setReserveeField("firstName", e.target.value)}
120
+ className={input}
121
+ />
122
+ <input
123
+ placeholder="Last name"
124
+ value={r.reservee.lastName ?? ""}
125
+ onChange={(e) => r.setReserveeField("lastName", e.target.value)}
126
+ className={input}
127
+ />
128
+ <input
129
+ placeholder="Phone (+15551234567) *"
130
+ type="tel"
131
+ value={r.reservee.phone}
132
+ onChange={(e) => r.setReserveeField("phone", e.target.value)}
133
+ className={input}
134
+ />
135
+ <input
136
+ placeholder="Email"
137
+ type="email"
138
+ value={r.reservee.email ?? ""}
139
+ onChange={(e) => r.setReserveeField("email", e.target.value)}
140
+ className={input}
141
+ />
142
+ </div>
143
+ <button
144
+ type="button"
145
+ disabled={!r.canConfirm}
146
+ onClick={() => void r.confirm()}
147
+ className="mt-4 w-full rounded-full bg-primary py-3 text-sm font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-50"
148
+ >
149
+ {r.loading ? "Reserving…" : "Complete reservation"}
150
+ </button>
151
+ </div>
152
+ )}
153
+ </div>
154
+ );
155
+ }
@@ -0,0 +1,55 @@
1
+ // Menu browsing. SSR-friendly: pass server-fetched menus as `initialMenus` (Astro
2
+ // frontmatter) and no client fetch happens; a SPA passes nothing. Menu switching is
3
+ // client-side (the whole tree is fetched once).
4
+ import { useEffect, useMemo, useState } from "react";
5
+ import { fetchMenus } from "../../wix/restaurants/menu";
6
+ import type { MenuData } from "../../wix/restaurants/types";
7
+
8
+ export interface UseMenusOptions {
9
+ initialMenus?: MenuData[];
10
+ }
11
+
12
+ export interface UseMenus {
13
+ /** null while the first load is in flight — render skeletons, not an empty state. */
14
+ menus: MenuData[] | null;
15
+ /** Defaults to the first menu once loaded. */
16
+ activeMenuId: string | null;
17
+ setActiveMenuId: (id: string) => void;
18
+ /** The menu to render (its sections/items are display-ordered). */
19
+ activeMenu: MenuData | null;
20
+ error: string | null;
21
+ }
22
+
23
+ export function useMenus({ initialMenus }: UseMenusOptions = {}): UseMenus {
24
+ const [menus, setMenus] = useState<MenuData[] | null>(initialMenus ?? null);
25
+ const [activeMenuId, setActiveMenuId] = useState<string | null>(initialMenus?.[0]?.id ?? null);
26
+ const [error, setError] = useState<string | null>(null);
27
+
28
+ useEffect(() => {
29
+ let alive = true;
30
+ if (!initialMenus) {
31
+ fetchMenus()
32
+ .then((m) => {
33
+ if (!alive) return;
34
+ setMenus(m);
35
+ setActiveMenuId((id) => id ?? m[0]?.id ?? null);
36
+ })
37
+ .catch((e) => {
38
+ if (!alive) return;
39
+ setMenus([]);
40
+ setError(e instanceof Error ? e.message : String(e));
41
+ });
42
+ }
43
+ return () => {
44
+ alive = false;
45
+ };
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ }, []);
48
+
49
+ const activeMenu = useMemo(() => {
50
+ if (!menus) return null;
51
+ return menus.find((m) => m.id === activeMenuId) ?? menus[0] ?? null;
52
+ }, [menus, activeMenuId]);
53
+
54
+ return { menus, activeMenuId: activeMenu?.id ?? null, setActiveMenuId, activeMenu, error };
55
+ }
@@ -0,0 +1,43 @@
1
+ // React binding for the order-cart store. Works in any React root — Astro islands (several
2
+ // on one page share the same store) and SPAs alike.
3
+ import { useSyncExternalStore } from "react";
4
+ import {
5
+ addOrderLine,
6
+ getOrderCartState,
7
+ goToOrderCheckout,
8
+ refreshOrderCart,
9
+ removeLineFromOrder,
10
+ setOrderCartOpen,
11
+ subscribeOrderCart,
12
+ updateOrderLineQuantity,
13
+ type OrderCartState,
14
+ } from "../../wix/restaurants/order-store";
15
+
16
+ const SERVER_STATE = getOrderCartState();
17
+
18
+ export interface UseOrderCart extends OrderCartState {
19
+ itemCount: number;
20
+ /** menuId/sectionId come from the render context (the fetchMenus tree) — pass both. */
21
+ addToOrder: (itemId: string, context: { menuId: string; sectionId: string }, quantity?: number) => Promise<void>;
22
+ updateQuantity: (lineItemId: string, quantity: number) => Promise<void>;
23
+ removeLine: (lineItemId: string) => Promise<void>;
24
+ checkout: () => Promise<void>;
25
+ openCart: () => void;
26
+ closeCart: () => void;
27
+ refresh: () => Promise<void>;
28
+ }
29
+
30
+ export function useOrderCart(): UseOrderCart {
31
+ const state = useSyncExternalStore(subscribeOrderCart, getOrderCartState, () => SERVER_STATE);
32
+ return {
33
+ ...state,
34
+ itemCount: state.cart?.itemCount ?? 0,
35
+ addToOrder: addOrderLine,
36
+ updateQuantity: updateOrderLineQuantity,
37
+ removeLine: removeLineFromOrder,
38
+ checkout: goToOrderCheckout,
39
+ openCart: () => setOrderCartOpen(true),
40
+ closeCart: () => setOrderCartOpen(false),
41
+ refresh: refreshOrderCart,
42
+ };
43
+ }
@@ -0,0 +1,177 @@
1
+ // The whole table-reservation state machine: location, date + party size, AVAILABLE slots,
2
+ // the 10-minute hold, the details form, and confirm. All correctness (AVAILABLE-only slots,
3
+ // hold → reserve with the revision, firstName + E.164 phone, RESERVED vs REQUESTED) lives in
4
+ // the data layer — this hook orchestrates; you own how it looks. Client-only: availability
5
+ // is timezone-specific, so render the surface with client:only="react" in Astro.
6
+ import { useEffect, useState } from "react";
7
+ import {
8
+ completeReservation,
9
+ fetchReservationLocations,
10
+ fetchReservationSlots,
11
+ holdReservation,
12
+ } from "../../wix/restaurants/reservations";
13
+ import type {
14
+ ReservationConfirmation,
15
+ ReservationHold,
16
+ ReservationLocationInfo,
17
+ ReservationReservee,
18
+ ReservationSlot,
19
+ } from "../../wix/restaurants/types";
20
+
21
+ const todayKey = (): string => {
22
+ const d = new Date();
23
+ const pad = (n: number) => String(n).padStart(2, "0");
24
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
25
+ };
26
+
27
+ export interface UseReservation {
28
+ /** null while loading; [] when Table Reservations isn't set up (honest empty state). */
29
+ locations: ReservationLocationInfo[] | null;
30
+ /** The active location (default first). Render a picker only when locations.length > 1. */
31
+ location: ReservationLocationInfo | null;
32
+ setLocationId: (id: string) => void;
33
+ /** "YYYY-MM-DD" for a date input. */
34
+ date: string;
35
+ setDate: (date: string) => void;
36
+ /** "HH:mm" anchor for the slot fan-out. */
37
+ time: string;
38
+ setTime: (time: string) => void;
39
+ /** Clamped to the location's partySizeMin/Max. */
40
+ partySize: number;
41
+ setPartySize: (size: number) => void;
42
+ /** AVAILABLE slots for the current query; null until findSlots ran. */
43
+ slots: ReservationSlot[] | null;
44
+ findSlots: () => Promise<void>;
45
+ /** Set after holdSlot — the visitor has 10 minutes to confirm. */
46
+ held: ReservationHold | null;
47
+ holdSlot: (slot: ReservationSlot) => Promise<void>;
48
+ reservee: ReservationReservee;
49
+ setReserveeField: (field: keyof ReservationReservee, value: string) => void;
50
+ /** True when a slot is held and firstName + phone are filled — gate the confirm CTA. */
51
+ canConfirm: boolean;
52
+ confirm: () => Promise<void>;
53
+ /** Set on success. REQUESTED → tell the visitor approval is pending, not confirmed. */
54
+ confirmed: ReservationConfirmation | null;
55
+ /** Back to slot picking (keeps date/party). */
56
+ reset: () => void;
57
+ loading: boolean;
58
+ error: string | null;
59
+ }
60
+
61
+ export function useReservation(): UseReservation {
62
+ const [locations, setLocations] = useState<ReservationLocationInfo[] | null>(null);
63
+ const [locationId, setLocationId] = useState<string | null>(null);
64
+ const [date, setDate] = useState<string>(todayKey());
65
+ const [time, setTime] = useState<string>("19:00");
66
+ const [partySize, setPartySizeRaw] = useState<number>(2);
67
+ const [slots, setSlots] = useState<ReservationSlot[] | null>(null);
68
+ const [held, setHeld] = useState<ReservationHold | null>(null);
69
+ const [reservee, setReservee] = useState<ReservationReservee>({ firstName: "", phone: "" });
70
+ const [confirmed, setConfirmed] = useState<ReservationConfirmation | null>(null);
71
+ const [loading, setLoading] = useState(false);
72
+ const [error, setError] = useState<string | null>(null);
73
+
74
+ useEffect(() => {
75
+ let alive = true;
76
+ fetchReservationLocations()
77
+ .then((locs) => {
78
+ if (!alive) return;
79
+ setLocations(locs);
80
+ setLocationId((id) => id ?? locs[0]?.id ?? null);
81
+ })
82
+ .catch((e) => {
83
+ if (!alive) return;
84
+ setLocations([]);
85
+ setError(e instanceof Error ? e.message : String(e));
86
+ });
87
+ return () => {
88
+ alive = false;
89
+ };
90
+ }, []);
91
+
92
+ const location = locations?.find((l) => l.id === locationId) ?? locations?.[0] ?? null;
93
+
94
+ const setPartySize = (size: number) => {
95
+ const min = location?.partySizeMin ?? 1;
96
+ const max = location?.partySizeMax ?? 20;
97
+ setPartySizeRaw(Math.min(Math.max(size, min), max));
98
+ };
99
+
100
+ async function findSlots(): Promise<void> {
101
+ if (!location) return;
102
+ setError(null);
103
+ setSlots(null);
104
+ setHeld(null);
105
+ setConfirmed(null);
106
+ setLoading(true);
107
+ try {
108
+ const aroundIso = new Date(`${date}T${time}:00`).toISOString();
109
+ setSlots(await fetchReservationSlots(location.id, aroundIso, partySize));
110
+ } catch (e) {
111
+ setSlots([]);
112
+ setError(e instanceof Error ? e.message : String(e));
113
+ } finally {
114
+ setLoading(false);
115
+ }
116
+ }
117
+
118
+ async function holdSlot(slot: ReservationSlot): Promise<void> {
119
+ if (!location) return;
120
+ setError(null);
121
+ setLoading(true);
122
+ try {
123
+ setHeld(await holdReservation(location.id, slot.startIso, partySize));
124
+ } catch (e) {
125
+ setError(e instanceof Error ? e.message : String(e));
126
+ } finally {
127
+ setLoading(false);
128
+ }
129
+ }
130
+
131
+ const canConfirm =
132
+ !!held && reservee.firstName.trim().length > 0 && reservee.phone.trim().length > 0 && !loading;
133
+
134
+ async function confirm(): Promise<void> {
135
+ if (!held) return;
136
+ setError(null);
137
+ setLoading(true);
138
+ try {
139
+ setConfirmed(await completeReservation(held, reservee));
140
+ } catch (e) {
141
+ // An expired hold can't be reserved — send the visitor back to slot picking.
142
+ setError(e instanceof Error ? e.message : String(e));
143
+ setHeld(null);
144
+ } finally {
145
+ setLoading(false);
146
+ }
147
+ }
148
+
149
+ return {
150
+ locations,
151
+ location,
152
+ setLocationId,
153
+ date,
154
+ setDate,
155
+ time,
156
+ setTime,
157
+ partySize,
158
+ setPartySize,
159
+ slots,
160
+ findSlots,
161
+ held,
162
+ holdSlot,
163
+ reservee,
164
+ setReserveeField: (field, value) => setReservee((r) => ({ ...r, [field]: value })),
165
+ canConfirm,
166
+ confirm,
167
+ confirmed,
168
+ reset: () => {
169
+ setHeld(null);
170
+ setConfirmed(null);
171
+ setSlots(null);
172
+ setError(null);
173
+ },
174
+ loading,
175
+ error,
176
+ };
177
+ }