@withpotter/pages-bookings 0.13.0-next.101

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 (270) hide show
  1. package/dist/dashboard/(bookings)/attendees/page.js +8 -0
  2. package/dist/dashboard/(bookings)/attendees/page.js.map +1 -0
  3. package/dist/dashboard/(bookings)/availability/_components/availability-screen.js +714 -0
  4. package/dist/dashboard/(bookings)/availability/_components/availability-screen.js.map +1 -0
  5. package/dist/dashboard/(bookings)/availability/_components/month-availability.js +130 -0
  6. package/dist/dashboard/(bookings)/availability/_components/month-availability.js.map +1 -0
  7. package/dist/dashboard/(bookings)/availability/page.js +10 -0
  8. package/dist/dashboard/(bookings)/availability/page.js.map +1 -0
  9. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/assign-resource-modal.js +133 -0
  10. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/assign-resource-modal.js.map +1 -0
  11. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-constants.js +26 -0
  12. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-constants.js.map +1 -0
  13. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-desktop-layout.js +194 -0
  14. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-desktop-layout.js.map +1 -0
  15. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-layout-props.js +1 -0
  16. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-layout-props.js.map +1 -0
  17. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-lede.js +189 -0
  18. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-lede.js.map +1 -0
  19. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-meta.js +38 -0
  20. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-meta.js.map +1 -0
  21. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-layout.js +315 -0
  22. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-layout.js.map +1 -0
  23. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-screen.js +94 -0
  24. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-screen.js.map +1 -0
  25. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-money.js +54 -0
  26. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-money.js.map +1 -0
  27. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-split.js +71 -0
  28. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-split.js.map +1 -0
  29. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancel-booking-modal.js +102 -0
  30. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancel-booking-modal.js.map +1 -0
  31. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancellation-notice.js +33 -0
  32. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancellation-notice.js.map +1 -0
  33. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/customer-info-card.js +65 -0
  34. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/customer-info-card.js.map +1 -0
  35. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/index.js +23 -0
  36. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/index.js.map +1 -0
  37. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/intake-answers-card.js +19 -0
  38. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/intake-answers-card.js.map +1 -0
  39. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/refund-booking-modal.js +156 -0
  40. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/refund-booking-modal.js.map +1 -0
  41. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/reschedule-booking-modal.js +120 -0
  42. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/reschedule-booking-modal.js.map +1 -0
  43. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/security-deposit-card.js +63 -0
  44. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/security-deposit-card.js.map +1 -0
  45. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/settle-deposit-modal.js +141 -0
  46. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/settle-deposit-modal.js.map +1 -0
  47. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/ticket-row-actions.js +49 -0
  48. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/ticket-row-actions.js.map +1 -0
  49. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/waiting-queue-notice.js +42 -0
  50. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/waiting-queue-notice.js.map +1 -0
  51. package/dist/dashboard/(bookings)/bookings/[bookingId]/_components.js +1 -0
  52. package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/index.js +19 -0
  53. package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/index.js.map +1 -0
  54. package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/use-booking-detail-data.js +352 -0
  55. package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/use-booking-detail-data.js.map +1 -0
  56. package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks.js +1 -0
  57. package/dist/dashboard/(bookings)/bookings/[bookingId]/layout.js +33 -0
  58. package/dist/dashboard/(bookings)/bookings/[bookingId]/layout.js.map +1 -0
  59. package/dist/dashboard/(bookings)/bookings/[bookingId]/page.js +356 -0
  60. package/dist/dashboard/(bookings)/bookings/[bookingId]/page.js.map +1 -0
  61. package/dist/dashboard/(bookings)/bookings/_components/appointment-calendar-layout.js +34 -0
  62. package/dist/dashboard/(bookings)/bookings/_components/appointment-calendar-layout.js.map +1 -0
  63. package/dist/dashboard/(bookings)/bookings/_components/booking-constants.js +92 -0
  64. package/dist/dashboard/(bookings)/bookings/_components/booking-constants.js.map +1 -0
  65. package/dist/dashboard/(bookings)/bookings/_components/booking-tab-hints.js +32 -0
  66. package/dist/dashboard/(bookings)/bookings/_components/booking-tab-hints.js.map +1 -0
  67. package/dist/dashboard/(bookings)/bookings/_components/bookings-filter-bar.js +131 -0
  68. package/dist/dashboard/(bookings)/bookings/_components/bookings-filter-bar.js.map +1 -0
  69. package/dist/dashboard/(bookings)/bookings/_components/bookings-mobile-controls.js +119 -0
  70. package/dist/dashboard/(bookings)/bookings/_components/bookings-mobile-controls.js.map +1 -0
  71. package/dist/dashboard/(bookings)/bookings/_components/bookings-screen.js +414 -0
  72. package/dist/dashboard/(bookings)/bookings/_components/bookings-screen.js.map +1 -0
  73. package/dist/dashboard/(bookings)/bookings/_components/bookings-table.js +192 -0
  74. package/dist/dashboard/(bookings)/bookings/_components/bookings-table.js.map +1 -0
  75. package/dist/dashboard/(bookings)/bookings/_components/cannot-take-bookings.js +34 -0
  76. package/dist/dashboard/(bookings)/bookings/_components/cannot-take-bookings.js.map +1 -0
  77. package/dist/dashboard/(bookings)/bookings/_components/demo-data.js +176 -0
  78. package/dist/dashboard/(bookings)/bookings/_components/demo-data.js.map +1 -0
  79. package/dist/dashboard/(bookings)/bookings/_components/index.js +9 -0
  80. package/dist/dashboard/(bookings)/bookings/_components/index.js.map +1 -0
  81. package/dist/dashboard/(bookings)/bookings/_components/today/booking-card.js +126 -0
  82. package/dist/dashboard/(bookings)/bookings/_components/today/booking-card.js.map +1 -0
  83. package/dist/dashboard/(bookings)/bookings/_components/today/demo-data.js +142 -0
  84. package/dist/dashboard/(bookings)/bookings/_components/today/demo-data.js.map +1 -0
  85. package/dist/dashboard/(bookings)/bookings/_components/today/handover.js +128 -0
  86. package/dist/dashboard/(bookings)/bookings/_components/today/handover.js.map +1 -0
  87. package/dist/dashboard/(bookings)/bookings/_components/today/index.js +17 -0
  88. package/dist/dashboard/(bookings)/bookings/_components/today/index.js.map +1 -0
  89. package/dist/dashboard/(bookings)/bookings/_components/today/past-band.js +69 -0
  90. package/dist/dashboard/(bookings)/bookings/_components/today/past-band.js.map +1 -0
  91. package/dist/dashboard/(bookings)/bookings/_components/today/resource-board.js +111 -0
  92. package/dist/dashboard/(bookings)/bookings/_components/today/resource-board.js.map +1 -0
  93. package/dist/dashboard/(bookings)/bookings/_components/today/today-band.js +61 -0
  94. package/dist/dashboard/(bookings)/bookings/_components/today/today-band.js.map +1 -0
  95. package/dist/dashboard/(bookings)/bookings/_components/today/upcoming-band.js +113 -0
  96. package/dist/dashboard/(bookings)/bookings/_components/today/upcoming-band.js.map +1 -0
  97. package/dist/dashboard/(bookings)/bookings/_components/today/waiting-queue.js +62 -0
  98. package/dist/dashboard/(bookings)/bookings/_components/today/waiting-queue.js.map +1 -0
  99. package/dist/dashboard/(bookings)/bookings/_components/today-board.js +192 -0
  100. package/dist/dashboard/(bookings)/bookings/_components/today-board.js.map +1 -0
  101. package/dist/dashboard/(bookings)/bookings/_components/today.js +1 -0
  102. package/dist/dashboard/(bookings)/bookings/_components.js +1 -0
  103. package/dist/dashboard/(bookings)/bookings/_hooks/index.js +5 -0
  104. package/dist/dashboard/(bookings)/bookings/_hooks/index.js.map +1 -0
  105. package/dist/dashboard/(bookings)/bookings/_hooks/use-bookings-data.js +331 -0
  106. package/dist/dashboard/(bookings)/bookings/_hooks/use-bookings-data.js.map +1 -0
  107. package/dist/dashboard/(bookings)/bookings/_hooks/use-today-data.js +309 -0
  108. package/dist/dashboard/(bookings)/bookings/_hooks/use-today-data.js.map +1 -0
  109. package/dist/dashboard/(bookings)/bookings/_hooks.js +1 -0
  110. package/dist/dashboard/(bookings)/bookings/_lib/booking-link.js +13 -0
  111. package/dist/dashboard/(bookings)/bookings/_lib/booking-link.js.map +1 -0
  112. package/dist/dashboard/(bookings)/bookings/attendees/_components/attendee-cards.js +60 -0
  113. package/dist/dashboard/(bookings)/bookings/attendees/_components/attendee-cards.js.map +1 -0
  114. package/dist/dashboard/(bookings)/bookings/attendees/_components/qr-scanner-modal.js +225 -0
  115. package/dist/dashboard/(bookings)/bookings/attendees/_components/qr-scanner-modal.js.map +1 -0
  116. package/dist/dashboard/(bookings)/bookings/attendees/demo-data.js +195 -0
  117. package/dist/dashboard/(bookings)/bookings/attendees/demo-data.js.map +1 -0
  118. package/dist/dashboard/(bookings)/bookings/attendees/page.js +341 -0
  119. package/dist/dashboard/(bookings)/bookings/attendees/page.js.map +1 -0
  120. package/dist/dashboard/(bookings)/bookings/new/page.js +129 -0
  121. package/dist/dashboard/(bookings)/bookings/new/page.js.map +1 -0
  122. package/dist/dashboard/(bookings)/bookings/page.js +10 -0
  123. package/dist/dashboard/(bookings)/bookings/page.js.map +1 -0
  124. package/dist/dashboard/(bookings)/bookings/sessions/new/_components/save-buttons.js +36 -0
  125. package/dist/dashboard/(bookings)/bookings/sessions/new/_components/save-buttons.js.map +1 -0
  126. package/dist/dashboard/(bookings)/bookings/sessions/new/_components/session-creator.js +386 -0
  127. package/dist/dashboard/(bookings)/bookings/sessions/new/_components/session-creator.js.map +1 -0
  128. package/dist/dashboard/(bookings)/bookings/sessions/new/_lib/session-payload.js +62 -0
  129. package/dist/dashboard/(bookings)/bookings/sessions/new/_lib/session-payload.js.map +1 -0
  130. package/dist/dashboard/(bookings)/bookings/sessions/new/page.js +10 -0
  131. package/dist/dashboard/(bookings)/bookings/sessions/new/page.js.map +1 -0
  132. package/dist/dashboard/(bookings)/calendar/_components/calendar-nav.js +84 -0
  133. package/dist/dashboard/(bookings)/calendar/_components/calendar-nav.js.map +1 -0
  134. package/dist/dashboard/(bookings)/calendar/_components/calendar-range.js +84 -0
  135. package/dist/dashboard/(bookings)/calendar/_components/calendar-range.js.map +1 -0
  136. package/dist/dashboard/(bookings)/calendar/_components/day-board-view.js +279 -0
  137. package/dist/dashboard/(bookings)/calendar/_components/day-board-view.js.map +1 -0
  138. package/dist/dashboard/(bookings)/calendar/_components/event-detail-modal.js +113 -0
  139. package/dist/dashboard/(bookings)/calendar/_components/event-detail-modal.js.map +1 -0
  140. package/dist/dashboard/(bookings)/calendar/_components/format.js +22 -0
  141. package/dist/dashboard/(bookings)/calendar/_components/format.js.map +1 -0
  142. package/dist/dashboard/(bookings)/calendar/_components/month-grid.js +109 -0
  143. package/dist/dashboard/(bookings)/calendar/_components/month-grid.js.map +1 -0
  144. package/dist/dashboard/(bookings)/calendar/_components/resource-day-grid.js +325 -0
  145. package/dist/dashboard/(bookings)/calendar/_components/resource-day-grid.js.map +1 -0
  146. package/dist/dashboard/(bookings)/calendar/_components/slot-action-sheet.js +209 -0
  147. package/dist/dashboard/(bookings)/calendar/_components/slot-action-sheet.js.map +1 -0
  148. package/dist/dashboard/(bookings)/calendar/_components/use-block-drag.js +77 -0
  149. package/dist/dashboard/(bookings)/calendar/_components/use-block-drag.js.map +1 -0
  150. package/dist/dashboard/(bookings)/calendar/_components/use-calendar-nav.js +69 -0
  151. package/dist/dashboard/(bookings)/calendar/_components/use-calendar-nav.js.map +1 -0
  152. package/dist/dashboard/(bookings)/calendar/_components/week-grid.js +202 -0
  153. package/dist/dashboard/(bookings)/calendar/_components/week-grid.js.map +1 -0
  154. package/dist/dashboard/(bookings)/calendar/_components/year-grid.js +111 -0
  155. package/dist/dashboard/(bookings)/calendar/_components/year-grid.js.map +1 -0
  156. package/dist/dashboard/(bookings)/calendar/page.js +8 -0
  157. package/dist/dashboard/(bookings)/calendar/page.js.map +1 -0
  158. package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feed-modal.js +126 -0
  159. package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feed-modal.js.map +1 -0
  160. package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feeds-section.js +99 -0
  161. package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feeds-section.js.map +1 -0
  162. package/dist/dashboard/(bookings)/calendar-sync/demo-data.js +64 -0
  163. package/dist/dashboard/(bookings)/calendar-sync/demo-data.js.map +1 -0
  164. package/dist/dashboard/(bookings)/calendar-sync/page.js +15 -0
  165. package/dist/dashboard/(bookings)/calendar-sync/page.js.map +1 -0
  166. package/dist/dashboard/(bookings)/check-in/page.js +252 -0
  167. package/dist/dashboard/(bookings)/check-in/page.js.map +1 -0
  168. package/dist/dashboard/(bookings)/events/[eventId]/_components/event-attendees.js +108 -0
  169. package/dist/dashboard/(bookings)/events/[eventId]/_components/event-attendees.js.map +1 -0
  170. package/dist/dashboard/(bookings)/events/[eventId]/_components/event-share.js +73 -0
  171. package/dist/dashboard/(bookings)/events/[eventId]/_components/event-share.js.map +1 -0
  172. package/dist/dashboard/(bookings)/events/[eventId]/layout.js +10 -0
  173. package/dist/dashboard/(bookings)/events/[eventId]/layout.js.map +1 -0
  174. package/dist/dashboard/(bookings)/events/[eventId]/page.js +247 -0
  175. package/dist/dashboard/(bookings)/events/[eventId]/page.js.map +1 -0
  176. package/dist/dashboard/(bookings)/events/_components/event-grid.js +44 -0
  177. package/dist/dashboard/(bookings)/events/_components/event-grid.js.map +1 -0
  178. package/dist/dashboard/(bookings)/events/_components/event-poster.js +17 -0
  179. package/dist/dashboard/(bookings)/events/_components/event-poster.js.map +1 -0
  180. package/dist/dashboard/(bookings)/events/_hooks/use-events-data.js +55 -0
  181. package/dist/dashboard/(bookings)/events/_hooks/use-events-data.js.map +1 -0
  182. package/dist/dashboard/(bookings)/events/_lib/event-facts.js +68 -0
  183. package/dist/dashboard/(bookings)/events/_lib/event-facts.js.map +1 -0
  184. package/dist/dashboard/(bookings)/events/new/_components/event-composer.js +295 -0
  185. package/dist/dashboard/(bookings)/events/new/_components/event-composer.js.map +1 -0
  186. package/dist/dashboard/(bookings)/events/new/_components/event-poster.js +65 -0
  187. package/dist/dashboard/(bookings)/events/new/_components/event-poster.js.map +1 -0
  188. package/dist/dashboard/(bookings)/events/new/_components/ticket-tiers.js +75 -0
  189. package/dist/dashboard/(bookings)/events/new/_components/ticket-tiers.js.map +1 -0
  190. package/dist/dashboard/(bookings)/events/new/page.js +10 -0
  191. package/dist/dashboard/(bookings)/events/new/page.js.map +1 -0
  192. package/dist/dashboard/(bookings)/events/page.js +214 -0
  193. package/dist/dashboard/(bookings)/events/page.js.map +1 -0
  194. package/dist/dashboard/(bookings)/resources/[resourceId]/layout.js +36 -0
  195. package/dist/dashboard/(bookings)/resources/[resourceId]/layout.js.map +1 -0
  196. package/dist/dashboard/(bookings)/resources/[resourceId]/page.js +351 -0
  197. package/dist/dashboard/(bookings)/resources/[resourceId]/page.js.map +1 -0
  198. package/dist/dashboard/(bookings)/resources/_components/block-time-modal.js +130 -0
  199. package/dist/dashboard/(bookings)/resources/_components/block-time-modal.js.map +1 -0
  200. package/dist/dashboard/(bookings)/resources/_components/category-card.js +74 -0
  201. package/dist/dashboard/(bookings)/resources/_components/category-card.js.map +1 -0
  202. package/dist/dashboard/(bookings)/resources/_components/category-form-dialog.js +197 -0
  203. package/dist/dashboard/(bookings)/resources/_components/category-form-dialog.js.map +1 -0
  204. package/dist/dashboard/(bookings)/resources/_components/day-editor.js +194 -0
  205. package/dist/dashboard/(bookings)/resources/_components/day-editor.js.map +1 -0
  206. package/dist/dashboard/(bookings)/resources/_components/group-dialog.js +170 -0
  207. package/dist/dashboard/(bookings)/resources/_components/group-dialog.js.map +1 -0
  208. package/dist/dashboard/(bookings)/resources/_components/group-header.js +90 -0
  209. package/dist/dashboard/(bookings)/resources/_components/group-header.js.map +1 -0
  210. package/dist/dashboard/(bookings)/resources/_components/index.js +22 -0
  211. package/dist/dashboard/(bookings)/resources/_components/index.js.map +1 -0
  212. package/dist/dashboard/(bookings)/resources/_components/mobile-category-form-sheet.js +256 -0
  213. package/dist/dashboard/(bookings)/resources/_components/mobile-category-form-sheet.js.map +1 -0
  214. package/dist/dashboard/(bookings)/resources/_components/resource-form.js +420 -0
  215. package/dist/dashboard/(bookings)/resources/_components/resource-form.js.map +1 -0
  216. package/dist/dashboard/(bookings)/resources/_components/resource-picker.js +144 -0
  217. package/dist/dashboard/(bookings)/resources/_components/resource-picker.js.map +1 -0
  218. package/dist/dashboard/(bookings)/resources/_components/resource-type-picker-empty.js +109 -0
  219. package/dist/dashboard/(bookings)/resources/_components/resource-type-picker-empty.js.map +1 -0
  220. package/dist/dashboard/(bookings)/resources/_components/roster-empty.js +103 -0
  221. package/dist/dashboard/(bookings)/resources/_components/roster-empty.js.map +1 -0
  222. package/dist/dashboard/(bookings)/resources/_components/roster-grid.js +160 -0
  223. package/dist/dashboard/(bookings)/resources/_components/roster-grid.js.map +1 -0
  224. package/dist/dashboard/(bookings)/resources/_components/schedule-editor.js +244 -0
  225. package/dist/dashboard/(bookings)/resources/_components/schedule-editor.js.map +1 -0
  226. package/dist/dashboard/(bookings)/resources/_components/schedule-timezone-field.js +25 -0
  227. package/dist/dashboard/(bookings)/resources/_components/schedule-timezone-field.js.map +1 -0
  228. package/dist/dashboard/(bookings)/resources/_components/solo-schedule-view.js +146 -0
  229. package/dist/dashboard/(bookings)/resources/_components/solo-schedule-view.js.map +1 -0
  230. package/dist/dashboard/(bookings)/resources/_components/team-onboarding-dialog.js +161 -0
  231. package/dist/dashboard/(bookings)/resources/_components/team-onboarding-dialog.js.map +1 -0
  232. package/dist/dashboard/(bookings)/resources/_components/week-grid.js +175 -0
  233. package/dist/dashboard/(bookings)/resources/_components/week-grid.js.map +1 -0
  234. package/dist/dashboard/(bookings)/resources/_components.js +1 -0
  235. package/dist/dashboard/(bookings)/resources/_hooks/index.js +8 -0
  236. package/dist/dashboard/(bookings)/resources/_hooks/index.js.map +1 -0
  237. package/dist/dashboard/(bookings)/resources/_hooks/use-resource-categories-data.js +86 -0
  238. package/dist/dashboard/(bookings)/resources/_hooks/use-resource-categories-data.js.map +1 -0
  239. package/dist/dashboard/(bookings)/resources/_hooks/use-roster-page.js +138 -0
  240. package/dist/dashboard/(bookings)/resources/_hooks/use-roster-page.js.map +1 -0
  241. package/dist/dashboard/(bookings)/resources/_hooks/use-roster.js +182 -0
  242. package/dist/dashboard/(bookings)/resources/_hooks/use-roster.js.map +1 -0
  243. package/dist/dashboard/(bookings)/resources/_hooks.js +1 -0
  244. package/dist/dashboard/(bookings)/resources/_lib/presets.js +147 -0
  245. package/dist/dashboard/(bookings)/resources/_lib/presets.js.map +1 -0
  246. package/dist/dashboard/(bookings)/resources/_lib/schedule-timezone.js +17 -0
  247. package/dist/dashboard/(bookings)/resources/_lib/schedule-timezone.js.map +1 -0
  248. package/dist/dashboard/(bookings)/resources/_lib/shapes.js +105 -0
  249. package/dist/dashboard/(bookings)/resources/_lib/shapes.js.map +1 -0
  250. package/dist/dashboard/(bookings)/resources/_lib/week.js +122 -0
  251. package/dist/dashboard/(bookings)/resources/_lib/week.js.map +1 -0
  252. package/dist/dashboard/(bookings)/resources/page.js +391 -0
  253. package/dist/dashboard/(bookings)/resources/page.js.map +1 -0
  254. package/dist/dashboard/(bookings)/schedule/page.js +8 -0
  255. package/dist/dashboard/(bookings)/schedule/page.js.map +1 -0
  256. package/dist/dashboard/(bookings)/today/page.js +14 -0
  257. package/dist/dashboard/(bookings)/today/page.js.map +1 -0
  258. package/dist/dashboard/(bookings)/waitlist/_components/demo-data.js +99 -0
  259. package/dist/dashboard/(bookings)/waitlist/_components/demo-data.js.map +1 -0
  260. package/dist/dashboard/(bookings)/waitlist/_components/offer-spot-modal.js +71 -0
  261. package/dist/dashboard/(bookings)/waitlist/_components/offer-spot-modal.js.map +1 -0
  262. package/dist/dashboard/(bookings)/waitlist/_components/waitlist-entry-editor.js +150 -0
  263. package/dist/dashboard/(bookings)/waitlist/_components/waitlist-entry-editor.js.map +1 -0
  264. package/dist/dashboard/(bookings)/waitlist/new/page.js +59 -0
  265. package/dist/dashboard/(bookings)/waitlist/new/page.js.map +1 -0
  266. package/dist/dashboard/(bookings)/waitlist/page.js +317 -0
  267. package/dist/dashboard/(bookings)/waitlist/page.js.map +1 -0
  268. package/dist/index.js +1 -0
  269. package/dist/index.js.map +1 -0
  270. package/package.json +60 -0
@@ -0,0 +1,182 @@
1
+ "use client";
2
+ import { useCallback, useMemo, useState } from "react";
3
+ import { useQueryClient } from "@tanstack/react-query";
4
+ import { useAuth } from "@withpotter/lib/auth-context";
5
+ import { useApiQuery } from "@withpotter/hooks/use-api-query";
6
+ import { resourceCategoriesApi } from "@withpotter/lib/api/resource-categories";
7
+ import { resourcesApi } from "@withpotter/lib/api/resources";
8
+ import { bookingCalendarApi } from "@withpotter/lib/api/booking-calendar";
9
+ function asArray(value) {
10
+ if (Array.isArray(value)) return value;
11
+ const wrapped = value?.data;
12
+ return Array.isArray(wrapped) ? wrapped : [];
13
+ }
14
+ function useRoster() {
15
+ const { tenant } = useAuth();
16
+ const slug = tenant?.slug ?? "";
17
+ const [saving, setSaving] = useState(false);
18
+ const queryClient = useQueryClient();
19
+ const categoriesQuery = useApiQuery(
20
+ ["resource-categories"],
21
+ (s) => resourceCategoriesApi.list(s)
22
+ );
23
+ const resourcesQuery = useApiQuery(
24
+ ["resources", "all"],
25
+ (s) => resourcesApi.listFull(s)
26
+ );
27
+ const usageQuery = useApiQuery(
28
+ ["resource-category-usage"],
29
+ (s) => resourceCategoriesApi.usage(s)
30
+ );
31
+ const categories = useMemo(
32
+ () => asArray(categoriesQuery.data).filter(
33
+ (c) => c.isActive !== false
34
+ ),
35
+ [categoriesQuery.data]
36
+ );
37
+ const rows = useMemo(() => {
38
+ const byId = new Map(categories.map((c) => [c.id, c]));
39
+ return asArray(resourcesQuery.data).map((r) => ({ ...r, category: byId.get(r.categoryId ?? "") ?? null })).sort(
40
+ (a, b) => (a.category?.sortOrder ?? 0) - (b.category?.sortOrder ?? 0) || a.sortOrder - b.sortOrder || a.name.localeCompare(b.name)
41
+ );
42
+ }, [categories, resourcesQuery.data]);
43
+ const usage = useMemo(
44
+ () => asArray(usageQuery.data),
45
+ [usageQuery.data]
46
+ );
47
+ const refetch = useCallback(async () => {
48
+ await Promise.all([
49
+ categoriesQuery.refetch(),
50
+ resourcesQuery.refetch(),
51
+ usageQuery.refetch()
52
+ ]);
53
+ }, [categoriesQuery, resourcesQuery, usageQuery]);
54
+ const notifySidebar = () => window.dispatchEvent(new Event("resource-categories-changed"));
55
+ const run = useCallback(
56
+ async (work) => {
57
+ if (!slug) return;
58
+ setSaving(true);
59
+ try {
60
+ const result = await work();
61
+ await refetch();
62
+ await queryClient.invalidateQueries({
63
+ predicate: ({ queryKey }) => {
64
+ const key = String(queryKey[2] ?? "");
65
+ return key.startsWith("resource") || key === "availability" || key === "bookings-readiness" || key === "dashboard-storefront-readiness";
66
+ }
67
+ });
68
+ return result;
69
+ } finally {
70
+ setSaving(false);
71
+ }
72
+ },
73
+ [slug, refetch, queryClient]
74
+ );
75
+ const createGroup = useCallback(
76
+ (data) => run(async () => {
77
+ const created = await resourceCategoriesApi.create(slug, data);
78
+ notifySidebar();
79
+ return created;
80
+ }),
81
+ [run, slug]
82
+ );
83
+ const updateGroup = useCallback(
84
+ (id, data) => run(async () => {
85
+ await resourceCategoriesApi.update(slug, id, data);
86
+ notifySidebar();
87
+ }),
88
+ [run, slug]
89
+ );
90
+ const deleteGroup = useCallback(
91
+ (id) => run(async () => {
92
+ await resourceCategoriesApi.delete(slug, id);
93
+ notifySidebar();
94
+ }),
95
+ [run, slug]
96
+ );
97
+ const createResource = useCallback(
98
+ (data) => run(() => resourcesApi.create(slug, data)),
99
+ [run, slug]
100
+ );
101
+ const updateResource = useCallback(
102
+ (id, data) => run(() => resourcesApi.update(slug, id, data)),
103
+ [run, slug]
104
+ );
105
+ const deleteResource = useCallback(
106
+ (id) => run(() => resourcesApi.delete(slug, id)),
107
+ [run, slug]
108
+ );
109
+ const setResourceStatus = useCallback(
110
+ (id, status) => run(
111
+ () => status === "active" ? resourcesApi.activate(slug, id) : resourcesApi.deactivate(slug, id)
112
+ ),
113
+ [run, slug]
114
+ );
115
+ const quickAddResources = useCallback(
116
+ (names, options) => run(async () => {
117
+ let categoryId = options.categoryId;
118
+ if (!categoryId) {
119
+ const created = await resourceCategoriesApi.create(slug, {
120
+ label: options.label,
121
+ labelPlural: options.labelPlural,
122
+ ...options.kind && { kind: options.kind }
123
+ });
124
+ categoryId = created.id;
125
+ }
126
+ for (const name of names) {
127
+ await resourcesApi.create(slug, {
128
+ type: options.type,
129
+ name,
130
+ categoryId
131
+ });
132
+ }
133
+ notifySidebar();
134
+ }),
135
+ [run, slug]
136
+ );
137
+ const blockTime = useCallback(
138
+ (payload) => run(() => bookingCalendarApi.blockTime(slug, payload)),
139
+ [run, slug]
140
+ );
141
+ const unblockTime = useCallback(
142
+ (resourceId, date, startTime) => run(
143
+ () => bookingCalendarApi.unblockTime(slug, resourceId, date, startTime)
144
+ ),
145
+ [run, slug]
146
+ );
147
+ return {
148
+ categories,
149
+ rows,
150
+ usage,
151
+ loading: categoriesQuery.isLoading || resourcesQuery.isLoading,
152
+ error: categoriesQuery.error?.message ?? resourcesQuery.error?.message ?? null,
153
+ saving,
154
+ refetch,
155
+ createGroup,
156
+ updateGroup,
157
+ deleteGroup,
158
+ createResource,
159
+ updateResource,
160
+ deleteResource,
161
+ setResourceStatus,
162
+ quickAddResources,
163
+ blockTime,
164
+ unblockTime
165
+ };
166
+ }
167
+ function useTimeOff(startDate, endDate) {
168
+ const query = useApiQuery(
169
+ ["calendar-events", startDate, endDate],
170
+ (slug) => bookingCalendarApi.getEvents(slug, startDate, endDate)
171
+ );
172
+ const blocks = useMemo(
173
+ () => asArray(query.data).filter((e) => e.type === "block"),
174
+ [query.data]
175
+ );
176
+ return { blocks, refetch: query.refetch };
177
+ }
178
+ export {
179
+ useRoster,
180
+ useTimeOff
181
+ };
182
+ //# sourceMappingURL=use-roster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_hooks/use-roster.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useAuth } from '@withpotter/lib/auth-context';\nimport { useApiQuery } from '@withpotter/hooks/use-api-query';\nimport { resourceCategoriesApi } from '@withpotter/lib/api/resource-categories';\nimport { resourcesApi } from '@withpotter/lib/api/resources';\nimport { bookingCalendarApi } from '@withpotter/lib/api/booking-calendar';\nimport type { CalendarEventItem } from '@withpotter/lib/api/types';\nimport type {\n CategoryUsage,\n CreateResourceCategoryInput,\n CreateResourceInput,\n Resource,\n ResourceCategory,\n ResourceCategoryKind,\n ResourceType,\n UpdateResourceCategoryInput,\n UpdateResourceInput,\n} from '@withpotter/lib/resource-types';\n\n/** A resource with the group it belongs to already attached. */\nexport interface RosterRow extends Resource {\n category: ResourceCategory | null;\n}\n\n/**\n * A 200 with the wrong body slips past a `= []` default, so every list this\n * page reads is narrowed to an array before anything indexes it.\n */\nfunction asArray<T>(value: unknown): T[] {\n if (Array.isArray(value)) return value as T[];\n const wrapped = (value as { data?: unknown } | null)?.data;\n return Array.isArray(wrapped) ? (wrapped as T[]) : [];\n}\n\n/**\n * The whole roster in two requests.\n *\n * It used to be one request per group — `list categories`, then a full\n * `listFull` for each of them — so a business with six groups opened this page\n * with seven round trips to say what two would. `GET /bookings/resources`\n * already returns every resource with its `categoryId` on it, so the grouping\n * is a client-side join, not a fan-out.\n */\nexport function useRoster() {\n const { tenant } = useAuth();\n const slug = tenant?.slug ?? '';\n const [saving, setSaving] = useState(false);\n const queryClient = useQueryClient();\n\n const categoriesQuery = useApiQuery(['resource-categories'], (s) =>\n resourceCategoriesApi.list(s),\n );\n const resourcesQuery = useApiQuery(['resources', 'all'], (s) =>\n resourcesApi.listFull(s),\n );\n /**\n * What asks for each group.\n *\n * Its own request rather than a field on the categories: it reads a different\n * table, it is the only thing on the page that can be stale without the page\n * being wrong, and a screen that fails to answer \"what books these\" should\n * still list them.\n */\n const usageQuery = useApiQuery(['resource-category-usage'], (s) =>\n resourceCategoriesApi.usage(s),\n );\n\n const categories = useMemo(\n () =>\n asArray<ResourceCategory>(categoriesQuery.data).filter(\n (c) => c.isActive !== false,\n ),\n [categoriesQuery.data],\n );\n\n const rows = useMemo<RosterRow[]>(() => {\n const byId = new Map(categories.map((c) => [c.id, c]));\n return asArray<Resource>(resourcesQuery.data)\n .map((r) => ({ ...r, category: byId.get(r.categoryId ?? '') ?? null }))\n .sort(\n (a, b) =>\n (a.category?.sortOrder ?? 0) - (b.category?.sortOrder ?? 0) ||\n a.sortOrder - b.sortOrder ||\n a.name.localeCompare(b.name),\n );\n }, [categories, resourcesQuery.data]);\n\n const usage = useMemo(\n () => asArray<CategoryUsage>(usageQuery.data),\n [usageQuery.data],\n );\n\n const refetch = useCallback(async () => {\n await Promise.all([\n categoriesQuery.refetch(),\n resourcesQuery.refetch(),\n usageQuery.refetch(),\n ]);\n }, [categoriesQuery, resourcesQuery, usageQuery]);\n\n /** The sidebar reads categories separately and has no other way to know. */\n const notifySidebar = () =>\n window.dispatchEvent(new Event('resource-categories-changed'));\n\n const run = useCallback(\n async (work: () => Promise<unknown>) => {\n if (!slug) return;\n setSaving(true);\n try {\n const result = await work();\n await refetch();\n /* Every other screen that reads these. The roster refetched only its own\n three queries, so the day board, the availability screen and the\n go-live checks kept the answer from before — a table just added read\n \"No tables yet\" until the page was reloaded. */\n await queryClient.invalidateQueries({\n predicate: ({ queryKey }) => {\n const key = String(queryKey[2] ?? '');\n return (\n key.startsWith('resource') ||\n key === 'availability' ||\n key === 'bookings-readiness' ||\n key === 'dashboard-storefront-readiness'\n );\n },\n });\n return result;\n } finally {\n setSaving(false);\n }\n },\n [slug, refetch, queryClient],\n );\n\n const createGroup = useCallback(\n (data: CreateResourceCategoryInput) =>\n run(async () => {\n const created = await resourceCategoriesApi.create(slug, data);\n notifySidebar();\n return created;\n }),\n [run, slug],\n );\n\n const updateGroup = useCallback(\n (id: string, data: UpdateResourceCategoryInput) =>\n run(async () => {\n await resourceCategoriesApi.update(slug, id, data);\n notifySidebar();\n }),\n [run, slug],\n );\n\n const deleteGroup = useCallback(\n (id: string) =>\n run(async () => {\n await resourceCategoriesApi.delete(slug, id);\n notifySidebar();\n }),\n [run, slug],\n );\n\n const createResource = useCallback(\n (data: CreateResourceInput) => run(() => resourcesApi.create(slug, data)),\n [run, slug],\n );\n\n const updateResource = useCallback(\n (id: string, data: UpdateResourceInput) =>\n run(() => resourcesApi.update(slug, id, data)),\n [run, slug],\n );\n\n const deleteResource = useCallback(\n (id: string) => run(() => resourcesApi.delete(slug, id)),\n [run, slug],\n );\n\n const setResourceStatus = useCallback(\n (id: string, status: 'active' | 'inactive') =>\n run(() =>\n status === 'active'\n ? resourcesApi.activate(slug, id)\n : resourcesApi.deactivate(slug, id),\n ),\n [run, slug],\n );\n\n /**\n * Add several at once, creating the group behind them if there isn't one.\n *\n * The model is two levels and a merchant setting up a floor does not think\n * that way: they have twelve tables. Making them name a group before they can\n * name a table is ceremony charged on an empty screen.\n */\n const quickAddResources = useCallback(\n (\n names: string[],\n options: {\n categoryId?: string;\n kind?: ResourceCategoryKind;\n label: string;\n labelPlural: string;\n type: ResourceType;\n },\n ) =>\n run(async () => {\n let categoryId = options.categoryId;\n if (!categoryId) {\n const created = await resourceCategoriesApi.create(slug, {\n label: options.label,\n labelPlural: options.labelPlural,\n ...(options.kind && { kind: options.kind }),\n });\n categoryId = created.id;\n }\n // Sequential rather than parallel: one tenant's table, and a burst of\n // twelve writes is not worth the milliseconds.\n for (const name of names) {\n await resourcesApi.create(slug, {\n type: options.type,\n name,\n categoryId,\n });\n }\n notifySidebar();\n }),\n [run, slug],\n );\n\n /** A day off, a maintenance window, a private hire: one date, not every week. */\n const blockTime = useCallback(\n (payload: {\n resourceId: string;\n date: string;\n startTime: string;\n endTime: string;\n reason?: string;\n }) => run(() => bookingCalendarApi.blockTime(slug, payload)),\n [run, slug],\n );\n\n const unblockTime = useCallback(\n (resourceId: string, date: string, startTime: string) =>\n run(() =>\n bookingCalendarApi.unblockTime(slug, resourceId, date, startTime),\n ),\n [run, slug],\n );\n\n return {\n categories,\n rows,\n usage,\n loading: categoriesQuery.isLoading || resourcesQuery.isLoading,\n error:\n categoriesQuery.error?.message ?? resourcesQuery.error?.message ?? null,\n saving,\n refetch,\n createGroup,\n updateGroup,\n deleteGroup,\n createResource,\n updateResource,\n deleteResource,\n setResourceStatus,\n quickAddResources,\n blockTime,\n unblockTime,\n };\n}\n\n/**\n * The time nobody can book, for one window.\n *\n * Blocks and bookings come back from the same endpoint; only blocks are read\n * here, because this page answers \"can it be booked\" rather than \"what is on\".\n */\nexport function useTimeOff(startDate: string, endDate: string) {\n const query = useApiQuery(['calendar-events', startDate, endDate], (slug) =>\n bookingCalendarApi.getEvents(slug, startDate, endDate),\n );\n\n const blocks = useMemo(\n () =>\n asArray<CalendarEventItem>(query.data).filter((e) => e.type === 'block'),\n [query.data],\n );\n\n return { blocks, refetch: query.refetch };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1 @@
1
+ export * from './_hooks/index.js';
@@ -0,0 +1,147 @@
1
+ import { singularise } from "@withpotter/lib/intents/use-entity-label";
2
+ const BOOKINGS = "take-bookings";
3
+ const DINE = "dine-in";
4
+ const EVENTS = "event-tickets";
5
+ const RENT = "rent-property";
6
+ const preset = (kind, type, singular, plural, intents) => ({
7
+ id: `${kind}:${singular.toLowerCase().replace(/\s+/g, "-")}`,
8
+ kind,
9
+ type,
10
+ singular,
11
+ plural,
12
+ intents
13
+ });
14
+ const PEOPLE = [
15
+ preset("person", "staff", "Stylist", "Stylists", [BOOKINGS]),
16
+ preset("person", "staff", "Barber", "Barbers", [BOOKINGS]),
17
+ preset("person", "staff", "Therapist", "Therapists", [BOOKINGS]),
18
+ preset("person", "staff", "Coach", "Coaches", [BOOKINGS]),
19
+ preset("person", "staff", "Trainer", "Trainers", [BOOKINGS]),
20
+ preset("person", "staff", "Instructor", "Instructors", [BOOKINGS]),
21
+ preset("person", "staff", "Tutor", "Tutors", [BOOKINGS]),
22
+ preset("person", "staff", "Practitioner", "Practitioners", [BOOKINGS]),
23
+ preset("person", "staff", "Doctor", "Doctors", [BOOKINGS]),
24
+ preset("person", "staff", "Dentist", "Dentists", [BOOKINGS]),
25
+ preset("person", "staff", "Nurse", "Nurses", [BOOKINGS]),
26
+ preset("person", "staff", "Technician", "Technicians", [BOOKINGS, EVENTS]),
27
+ preset("person", "staff", "Photographer", "Photographers", [BOOKINGS]),
28
+ preset("person", "staff", "Consultant", "Consultants", [BOOKINGS]),
29
+ preset("person", "staff", "Cleaner", "Cleaners", [BOOKINGS, RENT]),
30
+ preset("person", "staff", "Guide", "Guides", [BOOKINGS]),
31
+ preset("person", "staff", "Server", "Servers", [DINE]),
32
+ preset("person", "staff", "Chef", "Chefs", [DINE]),
33
+ preset("person", "staff", "Bartender", "Bartenders", [DINE]),
34
+ preset("person", "staff", "Host", "Hosts", [DINE, EVENTS]),
35
+ preset("person", "staff", "Usher", "Ushers", [EVENTS]),
36
+ preset("person", "staff", "Security", "Security", [EVENTS]),
37
+ preset("person", "staff", "Housekeeper", "Housekeepers", [RENT]),
38
+ preset("person", "staff", "Driver", "Drivers", [RENT]),
39
+ preset("person", "staff", "Concierge", "Concierges", [RENT])
40
+ ];
41
+ const SPACES = [
42
+ preset("space", "space", "Court", "Courts", [BOOKINGS]),
43
+ preset("space", "space", "Pitch", "Pitches", [BOOKINGS]),
44
+ preset("space", "space", "Lane", "Lanes", [BOOKINGS]),
45
+ preset("space", "space", "Bay", "Bays", [BOOKINGS]),
46
+ preset("space", "space", "Chair", "Chairs", [BOOKINGS]),
47
+ preset("space", "room", "Treatment room", "Treatment rooms", [BOOKINGS]),
48
+ preset("space", "room", "Consulting room", "Consulting rooms", [BOOKINGS]),
49
+ preset("space", "room", "Studio", "Studios", [BOOKINGS, EVENTS]),
50
+ preset("space", "room", "Classroom", "Classrooms", [BOOKINGS]),
51
+ preset("space", "room", "Meeting room", "Meeting rooms", [BOOKINGS, RENT]),
52
+ preset("space", "space", "Desk", "Desks", [RENT]),
53
+ preset("space", "space", "Pool", "Pools", [BOOKINGS, RENT]),
54
+ preset("space", "space", "Simulator", "Simulators", [BOOKINGS]),
55
+ preset("space", "space", "Parking bay", "Parking bays", [RENT]),
56
+ preset("space", "table", "Table", "Tables", [DINE]),
57
+ preset("space", "table", "Booth", "Booths", [DINE]),
58
+ preset("space", "table", "Bar seat", "Bar seats", [DINE]),
59
+ preset("space", "room", "Private room", "Private rooms", [DINE]),
60
+ preset("space", "space", "Terrace", "Terraces", [DINE, EVENTS]),
61
+ preset("space", "room", "Hall", "Halls", [EVENTS]),
62
+ preset("space", "space", "Stage", "Stages", [EVENTS]),
63
+ preset("space", "room", "Auditorium", "Auditoriums", [EVENTS]),
64
+ preset("space", "space", "Marquee", "Marquees", [EVENTS]),
65
+ preset("space", "space", "Exhibitor booth", "Exhibitor booths", [EVENTS]),
66
+ preset("space", "space", "Roof terrace", "Roof terraces", [RENT]),
67
+ preset("space", "space", "Event lawn", "Event lawns", [RENT, EVENTS])
68
+ ];
69
+ const EQUIPMENT = [
70
+ preset("equipment", "equipment", "Ball machine", "Ball machines", [BOOKINGS]),
71
+ preset("equipment", "equipment", "Racket", "Rackets", [BOOKINGS]),
72
+ preset("equipment", "equipment", "Camera", "Cameras", [BOOKINGS]),
73
+ preset("equipment", "equipment", "Rig", "Rigs", [BOOKINGS]),
74
+ preset("equipment", "equipment", "Console", "Consoles", [BOOKINGS]),
75
+ preset("equipment", "equipment", "VR headset", "VR headsets", [BOOKINGS]),
76
+ preset("equipment", "vehicle", "Kart", "Karts", [BOOKINGS]),
77
+ preset("equipment", "vehicle", "Bike", "Bikes", [BOOKINGS, RENT]),
78
+ preset("equipment", "vehicle", "Car", "Cars", [RENT]),
79
+ preset("equipment", "vehicle", "Boat", "Boats", [RENT]),
80
+ preset("equipment", "vehicle", "Jet ski", "Jet skis", [RENT]),
81
+ preset("equipment", "equipment", "PA system", "PA systems", [EVENTS]),
82
+ preset("equipment", "equipment", "Lighting rig", "Lighting rigs", [EVENTS]),
83
+ preset("equipment", "equipment", "Projector", "Projectors", [EVENTS, DINE]),
84
+ preset("equipment", "equipment", "Generator", "Generators", [EVENTS, RENT]),
85
+ preset("equipment", "equipment", "Canopy", "Canopies", [EVENTS, RENT]),
86
+ preset("equipment", "equipment", "Sound system", "Sound systems", [
87
+ EVENTS,
88
+ RENT
89
+ ])
90
+ ];
91
+ const UNITS = [
92
+ preset("unit", "room", "Apartment", "Apartments", [RENT]),
93
+ preset("unit", "room", "Villa", "Villas", [RENT]),
94
+ preset("unit", "room", "Hotel room", "Hotel rooms", [RENT]),
95
+ preset("unit", "room", "Suite", "Suites", [RENT]),
96
+ preset("unit", "room", "Studio flat", "Studio flats", [RENT]),
97
+ preset("unit", "room", "Cabin", "Cabins", [RENT, BOOKINGS]),
98
+ preset("unit", "room", "Chalet", "Chalets", [RENT, BOOKINGS]),
99
+ preset("unit", "room", "Lodge", "Lodges", [RENT]),
100
+ preset("unit", "room", "Tent", "Tents", [RENT]),
101
+ preset("unit", "room", "Serviced office", "Serviced offices", [RENT]),
102
+ preset("unit", "room", "Shop", "Shops", [RENT]),
103
+ preset("unit", "room", "Warehouse", "Warehouses", [RENT]),
104
+ preset("unit", "room", "Storage unit", "Storage units", [RENT]),
105
+ preset("unit", "room", "Parking space", "Parking spaces", [RENT]),
106
+ preset("unit", "room", "Venue", "Venues", [EVENTS]),
107
+ preset("unit", "room", "Whole floor", "Whole floors", [DINE])
108
+ ];
109
+ const PRESETS = [
110
+ ...PEOPLE,
111
+ ...SPACES,
112
+ ...EQUIPMENT,
113
+ ...UNITS
114
+ ];
115
+ function presetsFor(intentKeys) {
116
+ if (intentKeys.length === 0) return [];
117
+ const wanted = new Set(intentKeys);
118
+ return PRESETS.filter((p) => p.intents.some((i) => wanted.has(i)));
119
+ }
120
+ function allPresets() {
121
+ return PRESETS;
122
+ }
123
+ const TYPE_BY_KIND = {
124
+ person: "staff",
125
+ space: "space",
126
+ equipment: "equipment",
127
+ unit: "room"
128
+ };
129
+ function customPreset(kind, name) {
130
+ const plural = name.trim().replace(/\s+/g, " ");
131
+ if (!plural) return null;
132
+ return {
133
+ id: `${kind}:custom`,
134
+ kind,
135
+ type: TYPE_BY_KIND[kind],
136
+ singular: singularise(plural),
137
+ plural,
138
+ intents: []
139
+ };
140
+ }
141
+ export {
142
+ PRESETS,
143
+ allPresets,
144
+ customPreset,
145
+ presetsFor
146
+ };
147
+ //# sourceMappingURL=presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_lib/presets.ts"],"sourcesContent":["import type { ResourceCategoryKind, ResourceType } from '@withpotter/lib/resource-types';\nimport { singularise } from '@withpotter/lib/intents/use-entity-label';\n\n/**\n * THE THINGS A BUSINESS ACTUALLY BOOKS, said in its own words.\n *\n * Setting up the roster asked two questions before it asked anything useful:\n * which of four shapes a booking takes up (\"Someone\", \"Somewhere\",\n * \"Something\", \"A stay\"), and then, in a free text field, what the merchant\n * calls them. Both are OUR vocabulary standing in front of theirs. A barber\n * knows the answer is \"chairs\" and had to first agree that a chair is a\n * Somewhere, then type the word in — John, 2026-08-24: *\"i think we should\n * have grids of different resources we can create\"*.\n *\n * So the grid names them. A preset carries everything the two questions were\n * collecting — the shape, the row type, the singular and the plural — and one\n * press does what three steps did.\n *\n * `kind` is still the thing that matters underneath, because it decides real\n * behaviour: whether the thing keeps its own week or follows the business's,\n * whether several bookings fit in it at once, and how the assignment engine\n * picks one. The preset does not soften that, it just stops asking the\n * merchant to name it.\n *\n * ── On the ambiguous ones ────────────────────────────────────────────────\n * A few nouns genuinely sit between two shapes, and the tie-break is always\n * HOW IT IS SOLD, never what it is made of:\n *\n * a car, a boat, a bike `equipment` — it is checked out and brought\n * back, and `shapes.ts` has said so since the\n * rent-property examples were written\n * a storage unit, a shop `unit` — taken whole, by the night or the month,\n * and a week of opening hours is not a fact about\n * it\n * a parking bay `space` by the hour. A monthly bay is a `unit`,\n * which is why both are here\n * a barber's chair `space`. It is a station that a booking occupies,\n * and the barber is a separate group — which is\n * the whole reason a shop can book either\n *\n * ── On breadth ───────────────────────────────────────────────────────────\n * This list is deliberately longer than any one merchant needs. The grid shows\n * the trade's own first and keeps the rest behind \"Show everything\", so a\n * padel club is not scrolling past housekeepers, and the kart track that fits\n * no archetype cleanly still finds its word without typing it. Nothing here\n * NARROWS what can be created — `Something else` still opens the four shapes\n * and a free text field, because a list of nouns can never be finished.\n */\nexport interface ResourcePreset {\n /** Stable, for keys and for the test that says the catalogue has no twins. */\n id: string;\n kind: ResourceCategoryKind;\n /** The row type the engine stores. Defaults from `kind` where unset. */\n type: ResourceType;\n /** One of them. */\n singular: string;\n /** The group, which is the word the merchant then sees everywhere. */\n plural: string;\n /**\n * The trades that lead with this. Empty means it belongs to no trade in\n * particular and only ever appears under \"Show everything\".\n */\n intents: string[];\n}\n\nconst BOOKINGS = 'take-bookings';\nconst DINE = 'dine-in';\nconst EVENTS = 'event-tickets';\nconst RENT = 'rent-property';\n\n/**\n * `id` is `kind:slug` so it reads in a test failure and cannot collide by\n * accident between two shapes that share a noun — a studio is a `space` you\n * book by the hour AND a `unit` you let by the night, and both are real.\n */\nconst preset = (\n kind: ResourceCategoryKind,\n type: ResourceType,\n singular: string,\n plural: string,\n intents: string[],\n): ResourcePreset => ({\n id: `${kind}:${singular.toLowerCase().replace(/\\s+/g, '-')}`,\n kind,\n type,\n singular,\n plural,\n intents,\n});\n\n/** Somebody a customer books by name. */\nconst PEOPLE: ResourcePreset[] = [\n preset('person', 'staff', 'Stylist', 'Stylists', [BOOKINGS]),\n preset('person', 'staff', 'Barber', 'Barbers', [BOOKINGS]),\n preset('person', 'staff', 'Therapist', 'Therapists', [BOOKINGS]),\n preset('person', 'staff', 'Coach', 'Coaches', [BOOKINGS]),\n preset('person', 'staff', 'Trainer', 'Trainers', [BOOKINGS]),\n preset('person', 'staff', 'Instructor', 'Instructors', [BOOKINGS]),\n preset('person', 'staff', 'Tutor', 'Tutors', [BOOKINGS]),\n preset('person', 'staff', 'Practitioner', 'Practitioners', [BOOKINGS]),\n preset('person', 'staff', 'Doctor', 'Doctors', [BOOKINGS]),\n preset('person', 'staff', 'Dentist', 'Dentists', [BOOKINGS]),\n preset('person', 'staff', 'Nurse', 'Nurses', [BOOKINGS]),\n preset('person', 'staff', 'Technician', 'Technicians', [BOOKINGS, EVENTS]),\n preset('person', 'staff', 'Photographer', 'Photographers', [BOOKINGS]),\n preset('person', 'staff', 'Consultant', 'Consultants', [BOOKINGS]),\n preset('person', 'staff', 'Cleaner', 'Cleaners', [BOOKINGS, RENT]),\n preset('person', 'staff', 'Guide', 'Guides', [BOOKINGS]),\n preset('person', 'staff', 'Server', 'Servers', [DINE]),\n preset('person', 'staff', 'Chef', 'Chefs', [DINE]),\n preset('person', 'staff', 'Bartender', 'Bartenders', [DINE]),\n preset('person', 'staff', 'Host', 'Hosts', [DINE, EVENTS]),\n preset('person', 'staff', 'Usher', 'Ushers', [EVENTS]),\n preset('person', 'staff', 'Security', 'Security', [EVENTS]),\n preset('person', 'staff', 'Housekeeper', 'Housekeepers', [RENT]),\n preset('person', 'staff', 'Driver', 'Drivers', [RENT]),\n preset('person', 'staff', 'Concierge', 'Concierges', [RENT]),\n];\n\n/** Where it happens. Several bookings can sit in one at the same time. */\nconst SPACES: ResourcePreset[] = [\n preset('space', 'space', 'Court', 'Courts', [BOOKINGS]),\n preset('space', 'space', 'Pitch', 'Pitches', [BOOKINGS]),\n preset('space', 'space', 'Lane', 'Lanes', [BOOKINGS]),\n preset('space', 'space', 'Bay', 'Bays', [BOOKINGS]),\n preset('space', 'space', 'Chair', 'Chairs', [BOOKINGS]),\n preset('space', 'room', 'Treatment room', 'Treatment rooms', [BOOKINGS]),\n preset('space', 'room', 'Consulting room', 'Consulting rooms', [BOOKINGS]),\n preset('space', 'room', 'Studio', 'Studios', [BOOKINGS, EVENTS]),\n preset('space', 'room', 'Classroom', 'Classrooms', [BOOKINGS]),\n preset('space', 'room', 'Meeting room', 'Meeting rooms', [BOOKINGS, RENT]),\n preset('space', 'space', 'Desk', 'Desks', [RENT]),\n preset('space', 'space', 'Pool', 'Pools', [BOOKINGS, RENT]),\n preset('space', 'space', 'Simulator', 'Simulators', [BOOKINGS]),\n preset('space', 'space', 'Parking bay', 'Parking bays', [RENT]),\n preset('space', 'table', 'Table', 'Tables', [DINE]),\n preset('space', 'table', 'Booth', 'Booths', [DINE]),\n preset('space', 'table', 'Bar seat', 'Bar seats', [DINE]),\n preset('space', 'room', 'Private room', 'Private rooms', [DINE]),\n preset('space', 'space', 'Terrace', 'Terraces', [DINE, EVENTS]),\n preset('space', 'room', 'Hall', 'Halls', [EVENTS]),\n preset('space', 'space', 'Stage', 'Stages', [EVENTS]),\n preset('space', 'room', 'Auditorium', 'Auditoriums', [EVENTS]),\n preset('space', 'space', 'Marquee', 'Marquees', [EVENTS]),\n preset('space', 'space', 'Exhibitor booth', 'Exhibitor booths', [EVENTS]),\n preset('space', 'space', 'Roof terrace', 'Roof terraces', [RENT]),\n preset('space', 'space', 'Event lawn', 'Event lawns', [RENT, EVENTS]),\n];\n\n/** Kit that has to be free for the booking to go ahead. */\nconst EQUIPMENT: ResourcePreset[] = [\n preset('equipment', 'equipment', 'Ball machine', 'Ball machines', [BOOKINGS]),\n preset('equipment', 'equipment', 'Racket', 'Rackets', [BOOKINGS]),\n preset('equipment', 'equipment', 'Camera', 'Cameras', [BOOKINGS]),\n preset('equipment', 'equipment', 'Rig', 'Rigs', [BOOKINGS]),\n preset('equipment', 'equipment', 'Console', 'Consoles', [BOOKINGS]),\n preset('equipment', 'equipment', 'VR headset', 'VR headsets', [BOOKINGS]),\n preset('equipment', 'vehicle', 'Kart', 'Karts', [BOOKINGS]),\n preset('equipment', 'vehicle', 'Bike', 'Bikes', [BOOKINGS, RENT]),\n preset('equipment', 'vehicle', 'Car', 'Cars', [RENT]),\n preset('equipment', 'vehicle', 'Boat', 'Boats', [RENT]),\n preset('equipment', 'vehicle', 'Jet ski', 'Jet skis', [RENT]),\n preset('equipment', 'equipment', 'PA system', 'PA systems', [EVENTS]),\n preset('equipment', 'equipment', 'Lighting rig', 'Lighting rigs', [EVENTS]),\n preset('equipment', 'equipment', 'Projector', 'Projectors', [EVENTS, DINE]),\n preset('equipment', 'equipment', 'Generator', 'Generators', [EVENTS, RENT]),\n preset('equipment', 'equipment', 'Canopy', 'Canopies', [EVENTS, RENT]),\n preset('equipment', 'equipment', 'Sound system', 'Sound systems', [\n EVENTS,\n RENT,\n ]),\n];\n\n/** A whole place, taken by the night rather than by the hour. */\nconst UNITS: ResourcePreset[] = [\n preset('unit', 'room', 'Apartment', 'Apartments', [RENT]),\n preset('unit', 'room', 'Villa', 'Villas', [RENT]),\n preset('unit', 'room', 'Hotel room', 'Hotel rooms', [RENT]),\n preset('unit', 'room', 'Suite', 'Suites', [RENT]),\n preset('unit', 'room', 'Studio flat', 'Studio flats', [RENT]),\n preset('unit', 'room', 'Cabin', 'Cabins', [RENT, BOOKINGS]),\n preset('unit', 'room', 'Chalet', 'Chalets', [RENT, BOOKINGS]),\n preset('unit', 'room', 'Lodge', 'Lodges', [RENT]),\n preset('unit', 'room', 'Tent', 'Tents', [RENT]),\n preset('unit', 'room', 'Serviced office', 'Serviced offices', [RENT]),\n preset('unit', 'room', 'Shop', 'Shops', [RENT]),\n preset('unit', 'room', 'Warehouse', 'Warehouses', [RENT]),\n preset('unit', 'room', 'Storage unit', 'Storage units', [RENT]),\n preset('unit', 'room', 'Parking space', 'Parking spaces', [RENT]),\n preset('unit', 'room', 'Venue', 'Venues', [EVENTS]),\n preset('unit', 'room', 'Whole floor', 'Whole floors', [DINE]),\n];\n\nexport const PRESETS: ResourcePreset[] = [\n ...PEOPLE,\n ...SPACES,\n ...EQUIPMENT,\n ...UNITS,\n];\n\n/**\n * The trade's own, in the order the trade would say them.\n *\n * `shapesFor` already decides which SHAPE an archetype leads with; this is the\n * same idea one level down, so a restaurant opens on Tables and Booths rather\n * than on a wall of stylists. A merchant running two archetypes gets both\n * sets, deduped, in registry order — which is the honest answer for a hotel\n * with a restaurant in it.\n */\nexport function presetsFor(intentKeys: string[]): ResourcePreset[] {\n if (intentKeys.length === 0) return [];\n const wanted = new Set(intentKeys);\n return PRESETS.filter((p) => p.intents.some((i) => wanted.has(i)));\n}\n\n/** Everything, for the business whose word is not in its own trade's list. */\nexport function allPresets(): ResourcePreset[] {\n return PRESETS;\n}\n\n/** The row type the engine stores for each shape, for a word nobody listed. */\nconst TYPE_BY_KIND: Record<ResourceCategoryKind, ResourceType> = {\n person: 'staff',\n space: 'space',\n equipment: 'equipment',\n unit: 'room',\n};\n\n/**\n * A group in the merchant's own word.\n *\n * A list of nouns can never be finished — a barbershop's \"Master barbers\", a\n * kart track's \"Karts\" — so the picker ends in a blank the merchant fills in\n * and this makes it a preset like any other. Null for a name with nothing in\n * it, so the caller never creates a group called \"\".\n */\nexport function customPreset(\n kind: ResourceCategoryKind,\n name: string,\n): ResourcePreset | null {\n const plural = name.trim().replace(/\\s+/g, ' ');\n if (!plural) return null;\n return {\n id: `${kind}:custom`,\n kind,\n type: TYPE_BY_KIND[kind],\n singular: singularise(plural),\n plural,\n intents: [],\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,17 @@
1
+ import { HOURS_TIMEZONES } from "@withpotter/components/features/weekly-hours-editor";
2
+ function guessTimezone() {
3
+ try {
4
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || "Africa/Lagos";
5
+ } catch {
6
+ return "Africa/Lagos";
7
+ }
8
+ }
9
+ function timezoneOptions(current) {
10
+ const known = HOURS_TIMEZONES.some((t) => t.value === current);
11
+ return known ? HOURS_TIMEZONES : [{ value: current, label: current }, ...HOURS_TIMEZONES];
12
+ }
13
+ export {
14
+ guessTimezone,
15
+ timezoneOptions
16
+ };
17
+ //# sourceMappingURL=schedule-timezone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_lib/schedule-timezone.ts"],"sourcesContent":["import { HOURS_TIMEZONES } from '@withpotter/components/features/weekly-hours-editor';\n\n/**\n * The clock a resource's schedule is written against.\n *\n * \"09:00 to 17:00\" is not a time until you say where, and the API used to\n * decide by asking the container it happened to run in — so a Lagos merchant's\n * 12:00 came back as 13:00 on their own calendar and in the customer's\n * confirmation email. It was settable nowhere, which is the worst place for a\n * setting that moves every booking.\n */\nexport function guessTimezone(): string {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'Africa/Lagos';\n } catch {\n return 'Africa/Lagos';\n }\n}\n\n/**\n * The short list, plus wherever this browser actually is when that is not on\n * it — a merchant in Accra should not have to pick a city they are not in.\n */\nexport function timezoneOptions(current: string) {\n const known = HOURS_TIMEZONES.some((t) => t.value === current);\n return known\n ? HOURS_TIMEZONES\n : [{ value: current, label: current }, ...HOURS_TIMEZONES];\n}\n"],"mappings":"AAAA,SAAS,uBAAuB;AAWzB,SAAS,gBAAwB;AACtC,MAAI;AACF,WAAO,KAAK,eAAe,EAAE,gBAAgB,EAAE,YAAY;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,gBAAgB,SAAiB;AAC/C,QAAM,QAAQ,gBAAgB,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO;AAC7D,SAAO,QACH,kBACA,CAAC,EAAE,OAAO,SAAS,OAAO,QAAQ,GAAG,GAAG,eAAe;AAC7D;","names":[]}
@@ -0,0 +1,105 @@
1
+ const SOMEONE = {
2
+ kind: "person",
3
+ type: "staff",
4
+ title: "Someone",
5
+ description: "A person a customer books by name.",
6
+ suggestion: "Staff"
7
+ };
8
+ const SOMEWHERE = {
9
+ kind: "space",
10
+ type: "space",
11
+ title: "Somewhere",
12
+ description: "Where it happens. It can hold more than one booking at a time.",
13
+ suggestion: "Rooms"
14
+ };
15
+ const SOMETHING = {
16
+ kind: "equipment",
17
+ type: "equipment",
18
+ title: "Something",
19
+ description: "Kit that has to be free for the booking to go ahead.",
20
+ suggestion: "Equipment"
21
+ };
22
+ const A_STAY = {
23
+ kind: "unit",
24
+ type: "room",
25
+ title: "A stay",
26
+ description: "A whole place, taken by the night rather than by the hour.",
27
+ suggestion: "Units"
28
+ };
29
+ const SHAPES = [SOMEONE, SOMEWHERE, SOMETHING, A_STAY];
30
+ const EXAMPLES = {
31
+ "take-bookings": {
32
+ person: "coach, stylist, therapist, tutor",
33
+ space: "court, treatment room, studio, bay",
34
+ equipment: "ball machine, camera, rig",
35
+ unit: "cabin, chalet"
36
+ },
37
+ "dine-in": {
38
+ person: "server, chef",
39
+ space: "table, booth, private room",
40
+ equipment: "the grill, a projector",
41
+ unit: "the whole floor, by the night"
42
+ },
43
+ "event-tickets": {
44
+ person: "host, technician",
45
+ space: "the hall, the terrace, the studio",
46
+ equipment: "PA system, lighting rig, projector",
47
+ unit: "the venue, by the night"
48
+ },
49
+ "rent-property": {
50
+ person: "housekeeper, driver",
51
+ space: "the pool, the roof terrace",
52
+ equipment: "a car, a boat, a bike",
53
+ unit: "apartment, villa, hotel room"
54
+ }
55
+ };
56
+ const GENERIC = {
57
+ person: "staff, instructor, specialist",
58
+ space: "room, studio, table, court",
59
+ equipment: "machine, vehicle, kit",
60
+ unit: "apartment, room, cabin"
61
+ };
62
+ function shapeExamples(kind, intentKey) {
63
+ return (intentKey ? EXAMPLES[intentKey]?.[kind] : void 0) ?? GENERIC[kind];
64
+ }
65
+ const LEADS_WITH = {
66
+ "dine-in": "space",
67
+ "event-tickets": "space",
68
+ "rent-property": "unit"
69
+ // `take-bookings` absent on purpose: it books people OR places depending on
70
+ // the trade, and leading with Someone is what pushed a club's courts into a
71
+ // group called Staff.
72
+ };
73
+ function shapesFor(intentKey) {
74
+ const lead = intentKey ? LEADS_WITH[intentKey] : void 0;
75
+ if (!lead) return SHAPES;
76
+ return [...SHAPES].sort(
77
+ (a, b) => a.kind === lead ? -1 : b.kind === lead ? 1 : 0
78
+ );
79
+ }
80
+ function availabilityWords(kind) {
81
+ if (kind === "unit") {
82
+ return {
83
+ /** What the week column says instead of drawing hours. */
84
+ week: "Any night",
85
+ /** Today, with nothing blocking it. */
86
+ open: "Free",
87
+ /** Today, when it is off the board. */
88
+ closed: "Not letting",
89
+ byTheNight: true
90
+ };
91
+ }
92
+ return {
93
+ week: null,
94
+ open: null,
95
+ closed: kind === "person" ? "Not working" : "Closed",
96
+ byTheNight: false
97
+ };
98
+ }
99
+ export {
100
+ SHAPES,
101
+ availabilityWords,
102
+ shapeExamples,
103
+ shapesFor
104
+ };
105
+ //# sourceMappingURL=shapes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_lib/shapes.ts"],"sourcesContent":["import type { ResourceCategoryKind, ResourceType } from '@withpotter/lib/resource-types';\n\n/**\n * The four shapes a booking can take up, said the way a person would say them.\n *\n * `kind` is the word the data uses — person, space, equipment, unit — and it\n * decides real things: whether the thing has its own week or follows the\n * business's, whether several customers fit in it at once, and how the\n * assignment engine picks one. It was asked as \"Spaces & Rooms\" against\n * \"Units / Properties\", with a fifth card called \"Solo\" that is not a shape at\n * all but a team size, and a merchant could not tell which of them a tennis\n * court was.\n *\n * So the question is asked in the only four answers there are, and each one is\n * a sentence rather than a category name. The examples come from the\n * archetype, because \"somewhere it happens\" means a court to a club and a\n * table to a restaurant.\n */\nexport interface Shape {\n kind: ResourceCategoryKind;\n type: ResourceType;\n /** The answer, as the merchant would say it. */\n title: string;\n /** What makes this one different from the other three. */\n description: string;\n /** The word to put in the name field before they type their own. */\n suggestion: string;\n}\n\nconst SOMEONE: Shape = {\n kind: 'person',\n type: 'staff',\n title: 'Someone',\n description: 'A person a customer books by name.',\n suggestion: 'Staff',\n};\n\nconst SOMEWHERE: Shape = {\n kind: 'space',\n type: 'space',\n title: 'Somewhere',\n description: 'Where it happens. It can hold more than one booking at a time.',\n suggestion: 'Rooms',\n};\n\nconst SOMETHING: Shape = {\n kind: 'equipment',\n type: 'equipment',\n title: 'Something',\n description: 'Kit that has to be free for the booking to go ahead.',\n suggestion: 'Equipment',\n};\n\nconst A_STAY: Shape = {\n kind: 'unit',\n type: 'room',\n title: 'A stay',\n description: 'A whole place, taken by the night rather than by the hour.',\n suggestion: 'Units',\n};\n\nexport const SHAPES: Shape[] = [SOMEONE, SOMEWHERE, SOMETHING, A_STAY];\n\n/**\n * What each archetype would put in each answer.\n *\n * Not a filter: a restaurant CAN have a coffee machine that only one order at\n * a time can use, and a club can rent rackets. The archetype decides what the\n * examples say and which answer leads, never which answers exist — narrowing\n * the list is how the old picker sent a club booking courts toward Staff.\n */\nconst EXAMPLES: Record<\n string,\n Partial<Record<ResourceCategoryKind, string>>\n> = {\n 'take-bookings': {\n person: 'coach, stylist, therapist, tutor',\n space: 'court, treatment room, studio, bay',\n equipment: 'ball machine, camera, rig',\n unit: 'cabin, chalet',\n },\n 'dine-in': {\n person: 'server, chef',\n space: 'table, booth, private room',\n equipment: 'the grill, a projector',\n unit: 'the whole floor, by the night',\n },\n 'event-tickets': {\n person: 'host, technician',\n space: 'the hall, the terrace, the studio',\n equipment: 'PA system, lighting rig, projector',\n unit: 'the venue, by the night',\n },\n 'rent-property': {\n person: 'housekeeper, driver',\n space: 'the pool, the roof terrace',\n equipment: 'a car, a boat, a bike',\n unit: 'apartment, villa, hotel room',\n },\n};\n\nconst GENERIC: Record<ResourceCategoryKind, string> = {\n person: 'staff, instructor, specialist',\n space: 'room, studio, table, court',\n equipment: 'machine, vehicle, kit',\n unit: 'apartment, room, cabin',\n};\n\nexport function shapeExamples(\n kind: ResourceCategoryKind,\n intentKey?: string | null,\n): string {\n return (intentKey ? EXAMPLES[intentKey]?.[kind] : undefined) ?? GENERIC[kind];\n}\n\n/** Which answer an archetype means first, when it has already settled it. */\nconst LEADS_WITH: Record<string, ResourceCategoryKind> = {\n 'dine-in': 'space',\n 'event-tickets': 'space',\n 'rent-property': 'unit',\n // `take-bookings` absent on purpose: it books people OR places depending on\n // the trade, and leading with Someone is what pushed a club's courts into a\n // group called Staff.\n};\n\nexport function shapesFor(intentKey?: string | null): Shape[] {\n const lead = intentKey ? LEADS_WITH[intentKey] : undefined;\n if (!lead) return SHAPES;\n return [...SHAPES].sort((a, b) =>\n a.kind === lead ? -1 : b.kind === lead ? 1 : 0,\n );\n}\n\n/**\n * The words a row uses for \"when\", which is the only thing that genuinely\n * differs between the four shapes.\n *\n * A stylist is NOT WORKING on a Sunday; a treatment room is CLOSED; an\n * apartment is neither — it is let by the night, so a week of opening hours is\n * not a fact about it at all. Everything else on this screen is identical for\n * every shape on purpose: one page, one table, one set of controls. Only the\n * sentence changes, because only the sentence would otherwise be a lie.\n */\nexport function availabilityWords(kind: ResourceCategoryKind | undefined) {\n if (kind === 'unit') {\n return {\n /** What the week column says instead of drawing hours. */\n week: 'Any night',\n /** Today, with nothing blocking it. */\n open: 'Free',\n /** Today, when it is off the board. */\n closed: 'Not letting',\n byTheNight: true,\n };\n }\n return {\n week: null,\n open: null,\n closed: kind === 'person' ? 'Not working' : 'Closed',\n byTheNight: false,\n };\n}\n"],"mappings":"AA6BA,MAAM,UAAiB;AAAA,EACrB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,YAAY;AACd;AAEA,MAAM,YAAmB;AAAA,EACvB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,YAAY;AACd;AAEA,MAAM,YAAmB;AAAA,EACvB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,YAAY;AACd;AAEA,MAAM,SAAgB;AAAA,EACpB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,YAAY;AACd;AAEO,MAAM,SAAkB,CAAC,SAAS,WAAW,WAAW,MAAM;AAUrE,MAAM,WAGF;AAAA,EACF,iBAAiB;AAAA,IACf,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,EACR;AAAA,EACA,WAAW;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,EACR;AAAA,EACA,iBAAiB;AAAA,IACf,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,EACR;AAAA,EACA,iBAAiB;AAAA,IACf,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,EACR;AACF;AAEA,MAAM,UAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX,MAAM;AACR;AAEO,SAAS,cACd,MACA,WACQ;AACR,UAAQ,YAAY,SAAS,SAAS,IAAI,IAAI,IAAI,WAAc,QAAQ,IAAI;AAC9E;AAGA,MAAM,aAAmD;AAAA,EACvD,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,iBAAiB;AAAA;AAAA;AAAA;AAInB;AAEO,SAAS,UAAU,WAAoC;AAC5D,QAAM,OAAO,YAAY,WAAW,SAAS,IAAI;AACjD,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,CAAC,GAAG,MAAM,EAAE;AAAA,IAAK,CAAC,GAAG,MAC1B,EAAE,SAAS,OAAO,KAAK,EAAE,SAAS,OAAO,IAAI;AAAA,EAC/C;AACF;AAYO,SAAS,kBAAkB,MAAwC;AACxE,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA;AAAA,MAEL,MAAM;AAAA;AAAA,MAEN,MAAM;AAAA;AAAA,MAEN,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,SAAS,WAAW,gBAAgB;AAAA,IAC5C,YAAY;AAAA,EACd;AACF;","names":[]}