@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,194 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Plus, X } from "lucide-react";
5
+ import { Button } from "@withpotter/ui-kit/button";
6
+ import { FormDialog } from "@withpotter/ui-kit/form-dialog";
7
+ import { ErrorBanner } from "@withpotter/ui-kit/error-banner";
8
+ import { Field } from "@withpotter/ui-kit/field";
9
+ import { Input } from "@withpotter/ui-kit";
10
+ import { TimeField } from "@withpotter/ui-kit/time-field";
11
+ import { ToggleRow } from "@withpotter/ui-kit/toggle";
12
+ import {
13
+ DAY_LONG,
14
+ WEEK_DAYS,
15
+ blocksOn,
16
+ businessSlots,
17
+ daySlots,
18
+ isoDay
19
+ } from "../_lib/week";
20
+ function DayEditor({
21
+ row,
22
+ date,
23
+ hours,
24
+ blocks,
25
+ saving,
26
+ onSave,
27
+ onClose
28
+ }) {
29
+ const dow = date.getDay();
30
+ const iso = isoDay(date);
31
+ const own = daySlots(row.schedule, dow);
32
+ const inherited = own === void 0;
33
+ const resolved = inherited ? businessSlots(hours, dow) : own;
34
+ const existing = blocksOn(blocks, row.id, iso);
35
+ const [working, setWorking] = useState(!!resolved);
36
+ const [slots, setSlots] = useState(
37
+ resolved?.length ? resolved : [{ start: "09:00", end: "17:00" }]
38
+ );
39
+ const [timeOff, setTimeOff] = useState(existing.length > 0);
40
+ const [reason, setReason] = useState(existing[0]?.title ?? "");
41
+ const [error, setError] = useState(null);
42
+ const dateLabel = date.toLocaleDateString("en-GB", {
43
+ weekday: "short",
44
+ day: "numeric",
45
+ month: "short"
46
+ });
47
+ const setSlot = (index, part, value) => setSlots(
48
+ (prev) => prev.map((slot, i) => i === index ? { ...slot, [part]: value } : slot)
49
+ );
50
+ const nextSchedule = () => {
51
+ const week = {};
52
+ for (const day of WEEK_DAYS) {
53
+ const existingDay = daySlots(row.schedule, day);
54
+ const base = existingDay === void 0 ? businessSlots(hours, day) : existingDay;
55
+ week[day] = base ? { available: true, slots: base } : { available: false };
56
+ }
57
+ week[dow] = working ? { available: true, slots } : { available: false };
58
+ return week;
59
+ };
60
+ const handleSave = async () => {
61
+ if (working) {
62
+ const bad = slots.find((s) => !s.start || !s.end || s.end <= s.start);
63
+ if (bad) {
64
+ setError("Each shift needs an end time after its start.");
65
+ return;
66
+ }
67
+ }
68
+ setError(null);
69
+ const change = { schedule: nextSchedule() };
70
+ if (timeOff && existing.length === 0) {
71
+ const first = working && slots.length ? slots[0].start : "00:00";
72
+ const last = working && slots.length ? slots[slots.length - 1].end : "23:59";
73
+ change.block = {
74
+ date: iso,
75
+ startTime: first,
76
+ endTime: last,
77
+ reason: reason.trim() || void 0
78
+ };
79
+ }
80
+ if (!timeOff && existing.length > 0) {
81
+ change.unblock = {
82
+ date: iso,
83
+ startTime: new Date(existing[0].start).toTimeString().slice(0, 5)
84
+ };
85
+ }
86
+ await onSave(change);
87
+ };
88
+ return /* @__PURE__ */ jsx(
89
+ FormDialog,
90
+ {
91
+ title: `${row.name}, ${DAY_LONG[dow]}`,
92
+ onClose,
93
+ footer: /* @__PURE__ */ jsxs(Fragment, { children: [
94
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Cancel" }),
95
+ /* @__PURE__ */ jsx(Button, { onClick: handleSave, loading: saving, children: "Save" })
96
+ ] }),
97
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
98
+ /* @__PURE__ */ jsx(ErrorBanner, { children: error }),
99
+ /* @__PURE__ */ jsx("div", { className: "surface-inset rounded-lg", children: /* @__PURE__ */ jsx(
100
+ ToggleRow,
101
+ {
102
+ label: `Works every ${DAY_LONG[dow]}`,
103
+ hint: inherited ? "Follows the business hours until you change it here." : void 0,
104
+ checked: working,
105
+ onChange: setWorking
106
+ }
107
+ ) }),
108
+ working && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
109
+ slots.map((slot, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
110
+ /* @__PURE__ */ jsx("div", { className: "grid flex-1 grid-cols-2 gap-2", children: index === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
111
+ /* @__PURE__ */ jsx(Field, { label: "From", children: /* @__PURE__ */ jsx(
112
+ TimeField,
113
+ {
114
+ value: slot.start,
115
+ onChange: (v) => setSlot(index, "start", v)
116
+ }
117
+ ) }),
118
+ /* @__PURE__ */ jsx(Field, { label: "Until", children: /* @__PURE__ */ jsx(
119
+ TimeField,
120
+ {
121
+ value: slot.end,
122
+ onChange: (v) => setSlot(index, "end", v)
123
+ }
124
+ ) })
125
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
126
+ /* @__PURE__ */ jsx(
127
+ TimeField,
128
+ {
129
+ "aria-label": "From",
130
+ value: slot.start,
131
+ onChange: (v) => setSlot(index, "start", v)
132
+ }
133
+ ),
134
+ /* @__PURE__ */ jsx(
135
+ TimeField,
136
+ {
137
+ "aria-label": "Until",
138
+ value: slot.end,
139
+ onChange: (v) => setSlot(index, "end", v)
140
+ }
141
+ )
142
+ ] }) }),
143
+ slots.length > 1 && /* @__PURE__ */ jsx(
144
+ Button,
145
+ {
146
+ size: "icon",
147
+ variant: "ghost",
148
+ "aria-label": "Remove this shift",
149
+ onClick: () => setSlots((prev) => prev.filter((_, i) => i !== index)),
150
+ children: /* @__PURE__ */ jsx(X, {})
151
+ }
152
+ )
153
+ ] }, index)),
154
+ slots.length < 2 && /* @__PURE__ */ jsxs(
155
+ Button,
156
+ {
157
+ size: "md",
158
+ variant: "ghost",
159
+ onClick: () => setSlots((prev) => [
160
+ ...prev,
161
+ { start: "14:00", end: "18:00" }
162
+ ]),
163
+ children: [
164
+ /* @__PURE__ */ jsx(Plus, {}),
165
+ "Split the day"
166
+ ]
167
+ }
168
+ )
169
+ ] }),
170
+ /* @__PURE__ */ jsx("div", { className: "surface-inset rounded-lg", children: /* @__PURE__ */ jsx(
171
+ ToggleRow,
172
+ {
173
+ label: `Time off on ${dateLabel}`,
174
+ hint: "This date only. The week above keeps its shape.",
175
+ checked: timeOff,
176
+ onChange: setTimeOff
177
+ }
178
+ ) }),
179
+ timeOff && existing.length === 0 && /* @__PURE__ */ jsx(Field, { label: "Reason", hint: "Shown to you, never to a customer.", children: /* @__PURE__ */ jsx(
180
+ Input,
181
+ {
182
+ value: reason,
183
+ onChange: (e) => setReason(e.target.value),
184
+ placeholder: "e.g. deep clean, private hire, annual leave"
185
+ }
186
+ ) })
187
+ ] })
188
+ }
189
+ );
190
+ }
191
+ export {
192
+ DayEditor
193
+ };
194
+ //# sourceMappingURL=day-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_components/day-editor.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { Plus, X } from 'lucide-react';\nimport { Button } from '@withpotter/ui-kit/button';\nimport { FormDialog } from '@withpotter/ui-kit/form-dialog';\nimport { ErrorBanner } from '@withpotter/ui-kit/error-banner';\nimport { Field } from '@withpotter/ui-kit/field';\nimport { Input } from '@withpotter/ui-kit';\nimport { TimeField } from '@withpotter/ui-kit/time-field';\nimport { ToggleRow } from '@withpotter/ui-kit/toggle';\nimport type { WeeklyHours } from '@withpotter/hooks/use-hours-data';\nimport type { CalendarEventItem } from '@withpotter/lib/api/types';\nimport type { ScheduleSlot, WeeklySchedule } from '@withpotter/lib/resource-types';\nimport type { RosterRow } from '../_hooks/use-roster';\nimport {\n DAY_LONG,\n WEEK_DAYS,\n blocksOn,\n businessSlots,\n daySlots,\n isoDay,\n} from '../_lib/week';\n\n/**\n * One resource, one day: the pattern and the exception, told apart.\n *\n * These are two different sentences and the old surface could only say one of\n * them. Editing the weekly schedule to close one Tuesday closed every Tuesday;\n * the block endpoints that close exactly one day had no door at all. Both are\n * here, named for what they do — \"every Tuesday\" against \"Tue 26 Aug\" — because\n * a merchant who cannot see the difference will reach for whichever is nearer.\n */\nexport function DayEditor({\n row,\n date,\n hours,\n blocks,\n saving,\n onSave,\n onClose,\n}: {\n row: RosterRow;\n date: Date;\n hours: WeeklyHours;\n blocks: CalendarEventItem[];\n saving: boolean;\n onSave: (change: {\n schedule?: WeeklySchedule;\n block?: {\n date: string;\n startTime: string;\n endTime: string;\n reason?: string;\n };\n unblock?: { date: string; startTime: string };\n }) => Promise<void>;\n onClose: () => void;\n}) {\n const dow = date.getDay();\n const iso = isoDay(date);\n const own = daySlots(row.schedule, dow);\n const inherited = own === undefined;\n const resolved = inherited ? businessSlots(hours, dow) : own;\n const existing = blocksOn(blocks, row.id, iso);\n\n const [working, setWorking] = useState(!!resolved);\n const [slots, setSlots] = useState<ScheduleSlot[]>(\n resolved?.length ? resolved : [{ start: '09:00', end: '17:00' }],\n );\n const [timeOff, setTimeOff] = useState(existing.length > 0);\n const [reason, setReason] = useState(existing[0]?.title ?? '');\n const [error, setError] = useState<string | null>(null);\n\n const dateLabel = date.toLocaleDateString('en-GB', {\n weekday: 'short',\n day: 'numeric',\n month: 'short',\n });\n\n const setSlot = (index: number, part: 'start' | 'end', value: string) =>\n setSlots((prev) =>\n prev.map((slot, i) => (i === index ? { ...slot, [part]: value } : slot)),\n );\n\n /**\n * Every day the resource has an answer for, not just the one being edited.\n *\n * A `WeeklySchedule` is the whole week, so writing back only the edited day\n * would erase the other six. A resource that has never had one inherits the\n * business's week here, which is what it was already being booked against.\n */\n const nextSchedule = (): WeeklySchedule => {\n const week: WeeklySchedule = {};\n for (const day of WEEK_DAYS) {\n const existingDay = daySlots(row.schedule, day);\n const base =\n existingDay === undefined ? businessSlots(hours, day) : existingDay;\n week[day] = base\n ? { available: true, slots: base }\n : { available: false };\n }\n week[dow] = working ? { available: true, slots } : { available: false };\n return week;\n };\n\n const handleSave = async () => {\n if (working) {\n const bad = slots.find((s) => !s.start || !s.end || s.end <= s.start);\n if (bad) {\n setError('Each shift needs an end time after its start.');\n return;\n }\n }\n setError(null);\n\n const change: Parameters<typeof onSave>[0] = { schedule: nextSchedule() };\n\n if (timeOff && existing.length === 0) {\n const first = working && slots.length ? slots[0].start : '00:00';\n const last =\n working && slots.length ? slots[slots.length - 1].end : '23:59';\n change.block = {\n date: iso,\n startTime: first,\n endTime: last,\n reason: reason.trim() || undefined,\n };\n }\n if (!timeOff && existing.length > 0) {\n change.unblock = {\n date: iso,\n startTime: new Date(existing[0].start).toTimeString().slice(0, 5),\n };\n }\n\n await onSave(change);\n };\n\n return (\n <FormDialog\n title={`${row.name}, ${DAY_LONG[dow]}`}\n onClose={onClose}\n footer={\n <>\n <Button variant=\"secondary\" onClick={onClose}>\n Cancel\n </Button>\n <Button onClick={handleSave} loading={saving}>\n Save\n </Button>\n </>\n }\n >\n <div className=\"space-y-4\">\n <ErrorBanner>{error}</ErrorBanner>\n\n <div className=\"surface-inset rounded-lg\">\n <ToggleRow\n label={`Works every ${DAY_LONG[dow]}`}\n hint={\n inherited\n ? 'Follows the business hours until you change it here.'\n : undefined\n }\n checked={working}\n onChange={setWorking}\n />\n </div>\n\n {working && (\n <div className=\"space-y-2\">\n {slots.map((slot, index) => (\n <div key={index} className=\"flex items-end gap-2\">\n {/* The pair is labelled once. A second \"From / Until\" over the\n split shift labels the same two things twice. */}\n <div className=\"grid flex-1 grid-cols-2 gap-2\">\n {index === 0 ? (\n <>\n <Field label=\"From\">\n <TimeField\n value={slot.start}\n onChange={(v) => setSlot(index, 'start', v)}\n />\n </Field>\n <Field label=\"Until\">\n <TimeField\n value={slot.end}\n onChange={(v) => setSlot(index, 'end', v)}\n />\n </Field>\n </>\n ) : (\n <>\n <TimeField\n aria-label=\"From\"\n value={slot.start}\n onChange={(v) => setSlot(index, 'start', v)}\n />\n <TimeField\n aria-label=\"Until\"\n value={slot.end}\n onChange={(v) => setSlot(index, 'end', v)}\n />\n </>\n )}\n </div>\n {slots.length > 1 && (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n aria-label=\"Remove this shift\"\n onClick={() =>\n setSlots((prev) => prev.filter((_, i) => i !== index))\n }\n >\n <X />\n </Button>\n )}\n </div>\n ))}\n {slots.length < 2 && (\n <Button\n size=\"md\"\n variant=\"ghost\"\n onClick={() =>\n setSlots((prev) => [\n ...prev,\n { start: '14:00', end: '18:00' },\n ])\n }\n >\n <Plus />\n Split the day\n </Button>\n )}\n </div>\n )}\n\n <div className=\"surface-inset rounded-lg\">\n <ToggleRow\n label={`Time off on ${dateLabel}`}\n hint=\"This date only. The week above keeps its shape.\"\n checked={timeOff}\n onChange={setTimeOff}\n />\n </div>\n\n {timeOff && existing.length === 0 && (\n <Field label=\"Reason\" hint=\"Shown to you, never to a customer.\">\n <Input\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n placeholder=\"e.g. deep clean, private hire, annual leave\"\n />\n </Field>\n )}\n </div>\n </FormDialog>\n );\n}\n"],"mappings":";AAgJQ,mBACE,KADF;AA9IR,SAAS,gBAAgB;AACzB,SAAS,MAAM,SAAS;AACxB,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAK1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAWA,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAiBG;AACD,QAAM,MAAM,KAAK,OAAO;AACxB,QAAM,MAAM,OAAO,IAAI;AACvB,QAAM,MAAM,SAAS,IAAI,UAAU,GAAG;AACtC,QAAM,YAAY,QAAQ;AAC1B,QAAM,WAAW,YAAY,cAAc,OAAO,GAAG,IAAI;AACzD,QAAM,WAAW,SAAS,QAAQ,IAAI,IAAI,GAAG;AAE7C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,CAAC,CAAC,QAAQ;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAI;AAAA,IACxB,UAAU,SAAS,WAAW,CAAC,EAAE,OAAO,SAAS,KAAK,QAAQ,CAAC;AAAA,EACjE;AACA,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,SAAS,SAAS,CAAC;AAC1D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,SAAS,CAAC,GAAG,SAAS,EAAE;AAC7D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,QAAM,YAAY,KAAK,mBAAmB,SAAS;AAAA,IACjD,SAAS;AAAA,IACT,KAAK;AAAA,IACL,OAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,CAAC,OAAe,MAAuB,UACrD;AAAA,IAAS,CAAC,SACR,KAAK,IAAI,CAAC,MAAM,MAAO,MAAM,QAAQ,EAAE,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,IAAI,IAAK;AAAA,EACzE;AASF,QAAM,eAAe,MAAsB;AACzC,UAAM,OAAuB,CAAC;AAC9B,eAAW,OAAO,WAAW;AAC3B,YAAM,cAAc,SAAS,IAAI,UAAU,GAAG;AAC9C,YAAM,OACJ,gBAAgB,SAAY,cAAc,OAAO,GAAG,IAAI;AAC1D,WAAK,GAAG,IAAI,OACR,EAAE,WAAW,MAAM,OAAO,KAAK,IAC/B,EAAE,WAAW,MAAM;AAAA,IACzB;AACA,SAAK,GAAG,IAAI,UAAU,EAAE,WAAW,MAAM,MAAM,IAAI,EAAE,WAAW,MAAM;AACtE,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,YAAY;AAC7B,QAAI,SAAS;AACX,YAAM,MAAM,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK;AACpE,UAAI,KAAK;AACP,iBAAS,+CAA+C;AACxD;AAAA,MACF;AAAA,IACF;AACA,aAAS,IAAI;AAEb,UAAM,SAAuC,EAAE,UAAU,aAAa,EAAE;AAExE,QAAI,WAAW,SAAS,WAAW,GAAG;AACpC,YAAM,QAAQ,WAAW,MAAM,SAAS,MAAM,CAAC,EAAE,QAAQ;AACzD,YAAM,OACJ,WAAW,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,EAAE,MAAM;AAC1D,aAAO,QAAQ;AAAA,QACb,MAAM;AAAA,QACN,WAAW;AAAA,QACX,SAAS;AAAA,QACT,QAAQ,OAAO,KAAK,KAAK;AAAA,MAC3B;AAAA,IACF;AACA,QAAI,CAAC,WAAW,SAAS,SAAS,GAAG;AACnC,aAAO,UAAU;AAAA,QACf,MAAM;AAAA,QACN,WAAW,IAAI,KAAK,SAAS,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,GAAG,CAAC;AAAA,MAClE;AAAA,IACF;AAEA,UAAM,OAAO,MAAM;AAAA,EACrB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,GAAG,IAAI,IAAI,KAAK,SAAS,GAAG,CAAC;AAAA,MACpC;AAAA,MACA,QACE,iCACE;AAAA,4BAAC,UAAO,SAAQ,aAAY,SAAS,SAAS,oBAE9C;AAAA,QACA,oBAAC,UAAO,SAAS,YAAY,SAAS,QAAQ,kBAE9C;AAAA,SACF;AAAA,MAGF,+BAAC,SAAI,WAAU,aACb;AAAA,4BAAC,eAAa,iBAAM;AAAA,QAEpB,oBAAC,SAAI,WAAU,4BACb;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,eAAe,SAAS,GAAG,CAAC;AAAA,YACnC,MACE,YACI,yDACA;AAAA,YAEN,SAAS;AAAA,YACT,UAAU;AAAA;AAAA,QACZ,GACF;AAAA,QAEC,WACC,qBAAC,SAAI,WAAU,aACZ;AAAA,gBAAM,IAAI,CAAC,MAAM,UAChB,qBAAC,SAAgB,WAAU,wBAGzB;AAAA,gCAAC,SAAI,WAAU,iCACZ,oBAAU,IACT,iCACE;AAAA,kCAAC,SAAM,OAAM,QACX;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,KAAK;AAAA,kBACZ,UAAU,CAAC,MAAM,QAAQ,OAAO,SAAS,CAAC;AAAA;AAAA,cAC5C,GACF;AAAA,cACA,oBAAC,SAAM,OAAM,SACX;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,KAAK;AAAA,kBACZ,UAAU,CAAC,MAAM,QAAQ,OAAO,OAAO,CAAC;AAAA;AAAA,cAC1C,GACF;AAAA,eACF,IAEA,iCACE;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,cAAW;AAAA,kBACX,OAAO,KAAK;AAAA,kBACZ,UAAU,CAAC,MAAM,QAAQ,OAAO,SAAS,CAAC;AAAA;AAAA,cAC5C;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,cAAW;AAAA,kBACX,OAAO,KAAK;AAAA,kBACZ,UAAU,CAAC,MAAM,QAAQ,OAAO,OAAO,CAAC;AAAA;AAAA,cAC1C;AAAA,eACF,GAEJ;AAAA,YACC,MAAM,SAAS,KACd;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAQ;AAAA,gBACR,cAAW;AAAA,gBACX,SAAS,MACP,SAAS,CAAC,SAAS,KAAK,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC;AAAA,gBAGvD,8BAAC,KAAE;AAAA;AAAA,YACL;AAAA,eA5CM,KA8CV,CACD;AAAA,UACA,MAAM,SAAS,KACd;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,SAAS,MACP,SAAS,CAAC,SAAS;AAAA,gBACjB,GAAG;AAAA,gBACH,EAAE,OAAO,SAAS,KAAK,QAAQ;AAAA,cACjC,CAAC;AAAA,cAGH;AAAA,oCAAC,QAAK;AAAA,gBAAE;AAAA;AAAA;AAAA,UAEV;AAAA,WAEJ;AAAA,QAGF,oBAAC,SAAI,WAAU,4BACb;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,eAAe,SAAS;AAAA,YAC/B,MAAK;AAAA,YACL,SAAS;AAAA,YACT,UAAU;AAAA;AAAA,QACZ,GACF;AAAA,QAEC,WAAW,SAAS,WAAW,KAC9B,oBAAC,SAAM,OAAM,UAAS,MAAK,sCACzB;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,UAAU,CAAC,MAAM,UAAU,EAAE,OAAO,KAAK;AAAA,YACzC,aAAY;AAAA;AAAA,QACd,GACF;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -0,0 +1,170 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Building2, DoorOpen, Users, Wrench } from "lucide-react";
5
+ import { Button } from "@withpotter/ui-kit/button";
6
+ import { FormDialog } from "@withpotter/ui-kit/form-dialog";
7
+ import { ErrorBanner } from "@withpotter/ui-kit/error-banner";
8
+ import { Field } from "@withpotter/ui-kit/field";
9
+ import { Input } from "@withpotter/ui-kit";
10
+ import { InlineDeleteButton } from "@withpotter/ui-kit/inline-delete-button";
11
+ import { OptionButton } from "@withpotter/ui-kit/option-button";
12
+ import { singularise } from "@withpotter/lib/intents/use-entity-label";
13
+ import { ResourcePicker } from "./resource-picker";
14
+ import { SHAPES, shapeExamples, shapesFor } from "../_lib/shapes";
15
+ const ICON_BY_KIND = {
16
+ person: Users,
17
+ space: DoorOpen,
18
+ equipment: Wrench,
19
+ unit: Building2
20
+ };
21
+ function GroupDialog({
22
+ category,
23
+ intentKey,
24
+ saving,
25
+ onSave,
26
+ onDelete,
27
+ onClose
28
+ }) {
29
+ const editing = !!category;
30
+ const [shape, setShape] = useState(
31
+ category ? SHAPES.find((s) => s.kind === category.kind) ?? null : null
32
+ );
33
+ const [plural, setPlural] = useState(category?.labelPlural ?? "");
34
+ const [error, setError] = useState(null);
35
+ const [presetId, setPresetId] = useState(null);
36
+ const [showingAll] = useState(false);
37
+ const [pickerStep, setPickerStep] = useState(
38
+ null
39
+ );
40
+ const [freeform, setFreeform] = useState(false);
41
+ const pick = (preset) => {
42
+ setPresetId(preset.id);
43
+ setShape({
44
+ kind: preset.kind,
45
+ type: preset.type,
46
+ title: preset.plural,
47
+ description: "",
48
+ suggestion: preset.plural
49
+ });
50
+ setPlural(preset.plural);
51
+ };
52
+ const singular = plural.trim() ? singularise(plural.trim()) : "";
53
+ const handleSave = async () => {
54
+ if (!shape) return;
55
+ if (!plural.trim()) {
56
+ setError("Give them a name.");
57
+ return;
58
+ }
59
+ setError(null);
60
+ await onSave({
61
+ label: singular || plural.trim(),
62
+ labelPlural: plural.trim(),
63
+ kind: shape.kind
64
+ });
65
+ };
66
+ return /* @__PURE__ */ jsx(
67
+ FormDialog,
68
+ {
69
+ title: editing ? `Rename ${category.labelPlural}` : pickerStep ? `Choose a ${pickerStep === "person" ? "people" : pickerStep} type` : "Add a group",
70
+ description: editing ? void 0 : "A group is one kind of thing a booking takes up. A club has two: its courts and its coaches.",
71
+ size: shape || editing ? "md" : "lg",
72
+ onBack: pickerStep ? () => setPickerStep(null) : void 0,
73
+ onClose,
74
+ footer: /* @__PURE__ */ jsxs(Fragment, { children: [
75
+ editing && onDelete ? /* @__PURE__ */ jsx(
76
+ InlineDeleteButton,
77
+ {
78
+ onDelete: async () => {
79
+ try {
80
+ await onDelete(category.id);
81
+ } catch (err) {
82
+ setError(
83
+ err instanceof Error ? err.message : `Something still books ${category.labelPlural.toLowerCase()}.`
84
+ );
85
+ }
86
+ },
87
+ confirmText: `Delete ${category.labelPlural}?`
88
+ }
89
+ ) : /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Cancel" }),
90
+ /* @__PURE__ */ jsx(Button, { onClick: handleSave, loading: saving, disabled: !shape, children: editing ? "Save" : "Add" })
91
+ ] }),
92
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
93
+ /* @__PURE__ */ jsx(ErrorBanner, { children: error }),
94
+ !editing && !freeform && /* @__PURE__ */ jsx(
95
+ ResourcePicker,
96
+ {
97
+ category: pickerStep,
98
+ intentKeys: intentKey ? [intentKey] : [],
99
+ selectedId: presetId,
100
+ showingAll,
101
+ onPick: pick,
102
+ onCategoryChange: setPickerStep
103
+ }
104
+ ),
105
+ !editing && freeform && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
106
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: shapesFor(intentKey).map((option) => {
107
+ const Icon = ICON_BY_KIND[option.kind];
108
+ const picked = shape?.kind === option.kind;
109
+ return /* @__PURE__ */ jsxs(
110
+ OptionButton,
111
+ {
112
+ shape: "card",
113
+ selected: picked,
114
+ className: "w-full flex-col items-start gap-1 text-left",
115
+ onClick: () => {
116
+ setShape(option);
117
+ setPresetId(null);
118
+ if (!plural.trim()) setPlural(option.suggestion);
119
+ },
120
+ children: [
121
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
122
+ /* @__PURE__ */ jsx(Icon, { className: "size-4 text-[var(--text-tertiary)]" }),
123
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--text-primary)]", children: option.title })
124
+ ] }),
125
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--text-secondary)]", children: option.description }),
126
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--text-muted)]", children: shapeExamples(option.kind, intentKey) })
127
+ ]
128
+ },
129
+ option.kind
130
+ );
131
+ }) }),
132
+ /* @__PURE__ */ jsx(
133
+ Button,
134
+ {
135
+ variant: "ghost",
136
+ size: "md",
137
+ onClick: () => {
138
+ setFreeform(false);
139
+ setShape(null);
140
+ setPlural("");
141
+ },
142
+ children: "Back to the list"
143
+ }
144
+ )
145
+ ] }),
146
+ (shape || editing) && /* @__PURE__ */ jsx(
147
+ Field,
148
+ {
149
+ label: "What do you call them?",
150
+ hint: singular ? `One of them is a ${singular.toLowerCase()}.` : void 0,
151
+ required: true,
152
+ children: /* @__PURE__ */ jsx(
153
+ Input,
154
+ {
155
+ value: plural,
156
+ onChange: (e) => setPlural(e.target.value),
157
+ placeholder: shape?.suggestion ?? "Courts",
158
+ autoFocus: true
159
+ }
160
+ )
161
+ }
162
+ )
163
+ ] })
164
+ }
165
+ );
166
+ }
167
+ export {
168
+ GroupDialog
169
+ };
170
+ //# sourceMappingURL=group-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_components/group-dialog.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { Building2, DoorOpen, Users, Wrench } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport { Button } from '@withpotter/ui-kit/button';\nimport { FormDialog } from '@withpotter/ui-kit/form-dialog';\nimport { ErrorBanner } from '@withpotter/ui-kit/error-banner';\nimport { Field } from '@withpotter/ui-kit/field';\nimport { Input } from '@withpotter/ui-kit';\nimport { InlineDeleteButton } from '@withpotter/ui-kit/inline-delete-button';\nimport { OptionButton } from '@withpotter/ui-kit/option-button';\nimport { singularise } from '@withpotter/lib/intents/use-entity-label';\nimport type {\n CreateResourceCategoryInput,\n ResourceCategory,\n ResourceCategoryKind,\n UpdateResourceCategoryInput,\n} from '@withpotter/lib/resource-types';\nimport { ResourcePicker } from './resource-picker';\nimport type { ResourcePreset } from '../_lib/presets';\nimport { SHAPES, shapeExamples, shapesFor, type Shape } from '../_lib/shapes';\n\nconst ICON_BY_KIND: Record<ResourceCategoryKind, LucideIcon> = {\n person: Users,\n space: DoorOpen,\n equipment: Wrench,\n unit: Building2,\n};\n\n/**\n * Adding a group of bookable things: what shape it is, then what you call it.\n *\n * Two questions in the order they can be answered. The old dialog asked for a\n * label, a plural label and a `kind` — our word for the shape — in one form,\n * behind a hand-drawn overlay that closed on neither Escape nor a click\n * outside, with the shape offered as a select of five options one of which was\n * a team size. A merchant naming their courts had to know what we meant by\n * \"space\" before they could type \"Courts\".\n *\n * The shape is asked first because it is the answer that cannot be changed\n * casually later: availability and assignment key off it.\n */\nexport function GroupDialog({\n category,\n intentKey,\n saving,\n onSave,\n onDelete,\n onClose,\n}: {\n /** Present when renaming an existing group; absent when adding one. */\n category?: ResourceCategory | null;\n intentKey?: string | null;\n saving: boolean;\n onSave: (\n data: CreateResourceCategoryInput & Partial<UpdateResourceCategoryInput>,\n ) => Promise<void>;\n onDelete?: (id: string) => void | Promise<void>;\n onClose: () => void;\n}) {\n const editing = !!category;\n const [shape, setShape] = useState<Shape | null>(\n category ? (SHAPES.find((s) => s.kind === category.kind) ?? null) : null,\n );\n const [plural, setPlural] = useState(category?.labelPlural ?? '');\n const [error, setError] = useState<string | null>(null);\n const [presetId, setPresetId] = useState<string | null>(null);\n const [showingAll] = useState(false);\n const [pickerStep, setPickerStep] = useState<ResourceCategoryKind | null>(\n null,\n );\n /** The four shapes and a blank field — the route out of the catalogue. */\n const [freeform, setFreeform] = useState(false);\n\n /** One press carries the shape, the row type and both words. */\n const pick = (preset: ResourcePreset) => {\n setPresetId(preset.id);\n setShape({\n kind: preset.kind,\n type: preset.type,\n title: preset.plural,\n description: '',\n suggestion: preset.plural,\n });\n setPlural(preset.plural);\n };\n\n const singular = plural.trim() ? singularise(plural.trim()) : '';\n\n const handleSave = async () => {\n if (!shape) return;\n if (!plural.trim()) {\n setError('Give them a name.');\n return;\n }\n setError(null);\n await onSave({\n label: singular || plural.trim(),\n labelPlural: plural.trim(),\n kind: shape.kind,\n });\n };\n\n return (\n <FormDialog\n title={\n editing\n ? `Rename ${category.labelPlural}`\n : pickerStep\n ? `Choose a ${pickerStep === 'person' ? 'people' : pickerStep} type`\n : 'Add a group'\n }\n description={\n editing\n ? undefined\n : 'A group is one kind of thing a booking takes up. A club has two: its courts and its coaches.'\n }\n size={shape || editing ? 'md' : 'lg'}\n onBack={pickerStep ? () => setPickerStep(null) : undefined}\n onClose={onClose}\n footer={\n <>\n {editing && onDelete ? (\n <InlineDeleteButton\n onDelete={async () => {\n /**\n * The API refuses while a service still asks for this group,\n * and says which count — a 409 carrying the only sentence that\n * makes the refusal actionable. Swallowing it left a Delete\n * that appeared to do nothing.\n */\n try {\n await onDelete(category.id);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : `Something still books ${category.labelPlural.toLowerCase()}.`,\n );\n }\n }}\n confirmText={`Delete ${category.labelPlural}?`}\n />\n ) : (\n <Button variant=\"secondary\" onClick={onClose}>\n Cancel\n </Button>\n )}\n <Button onClick={handleSave} loading={saving} disabled={!shape}>\n {editing ? 'Save' : 'Add'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-4\">\n <ErrorBanner>{error}</ErrorBanner>\n\n {!editing && !freeform && (\n <ResourcePicker\n category={pickerStep}\n intentKeys={intentKey ? [intentKey] : []}\n selectedId={presetId}\n showingAll={showingAll}\n onPick={pick}\n onCategoryChange={setPickerStep}\n />\n )}\n\n {!editing && freeform && (\n <div className=\"space-y-2\">\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n {shapesFor(intentKey).map((option) => {\n const Icon = ICON_BY_KIND[option.kind];\n const picked = shape?.kind === option.kind;\n return (\n <OptionButton\n key={option.kind}\n shape=\"card\"\n selected={picked}\n className=\"w-full flex-col items-start gap-1 text-left\"\n onClick={() => {\n setShape(option);\n setPresetId(null);\n if (!plural.trim()) setPlural(option.suggestion);\n }}\n >\n <span className=\"flex items-center gap-2\">\n <Icon className=\"size-4 text-[var(--text-tertiary)]\" />\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">\n {option.title}\n </span>\n </span>\n <span className=\"text-sm text-[var(--text-secondary)]\">\n {option.description}\n </span>\n <span className=\"text-xs text-[var(--text-muted)]\">\n {shapeExamples(option.kind, intentKey)}\n </span>\n </OptionButton>\n );\n })}\n </div>\n <Button\n variant=\"ghost\"\n size=\"md\"\n onClick={() => {\n setFreeform(false);\n setShape(null);\n setPlural('');\n }}\n >\n Back to the list\n </Button>\n </div>\n )}\n\n {(shape || editing) && (\n <Field\n label=\"What do you call them?\"\n hint={\n singular\n ? `One of them is a ${singular.toLowerCase()}.`\n : undefined\n }\n required\n >\n <Input\n value={plural}\n onChange={(e) => setPlural(e.target.value)}\n placeholder={shape?.suggestion ?? 'Courts'}\n autoFocus\n />\n </Field>\n )}\n </div>\n </FormDialog>\n );\n}\n"],"mappings":";AA0HQ,mBAEI,KAFJ;AAxHR,SAAS,gBAAgB;AACzB,SAAS,WAAW,UAAU,OAAO,cAAc;AAEnD,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAO5B,SAAS,sBAAsB;AAE/B,SAAS,QAAQ,eAAe,iBAA6B;AAE7D,MAAM,eAAyD;AAAA,EAC7D,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX,MAAM;AACR;AAeO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAUG;AACD,QAAM,UAAU,CAAC,CAAC;AAClB,QAAM,CAAC,OAAO,QAAQ,IAAI;AAAA,IACxB,WAAY,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS,IAAI,KAAK,OAAQ;AAAA,EACtE;AACA,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,UAAU,eAAe,EAAE;AAChE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,IAAI;AAC5D,QAAM,CAAC,UAAU,IAAI,SAAS,KAAK;AACnC,QAAM,CAAC,YAAY,aAAa,IAAI;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAG9C,QAAM,OAAO,CAAC,WAA2B;AACvC,gBAAY,OAAO,EAAE;AACrB,aAAS;AAAA,MACP,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,OAAO,OAAO;AAAA,MACd,aAAa;AAAA,MACb,YAAY,OAAO;AAAA,IACrB,CAAC;AACD,cAAU,OAAO,MAAM;AAAA,EACzB;AAEA,QAAM,WAAW,OAAO,KAAK,IAAI,YAAY,OAAO,KAAK,CAAC,IAAI;AAE9D,QAAM,aAAa,YAAY;AAC7B,QAAI,CAAC,MAAO;AACZ,QAAI,CAAC,OAAO,KAAK,GAAG;AAClB,eAAS,mBAAmB;AAC5B;AAAA,IACF;AACA,aAAS,IAAI;AACb,UAAM,OAAO;AAAA,MACX,OAAO,YAAY,OAAO,KAAK;AAAA,MAC/B,aAAa,OAAO,KAAK;AAAA,MACzB,MAAM,MAAM;AAAA,IACd,CAAC;AAAA,EACH;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OACE,UACI,UAAU,SAAS,WAAW,KAC9B,aACE,YAAY,eAAe,WAAW,WAAW,UAAU,UAC3D;AAAA,MAER,aACE,UACI,SACA;AAAA,MAEN,MAAM,SAAS,UAAU,OAAO;AAAA,MAChC,QAAQ,aAAa,MAAM,cAAc,IAAI,IAAI;AAAA,MACjD;AAAA,MACA,QACE,iCACG;AAAA,mBAAW,WACV;AAAA,UAAC;AAAA;AAAA,YACC,UAAU,YAAY;AAOpB,kBAAI;AACF,sBAAM,SAAS,SAAS,EAAE;AAAA,cAC5B,SAAS,KAAK;AACZ;AAAA,kBACE,eAAe,QACX,IAAI,UACJ,yBAAyB,SAAS,YAAY,YAAY,CAAC;AAAA,gBACjE;AAAA,cACF;AAAA,YACF;AAAA,YACA,aAAa,UAAU,SAAS,WAAW;AAAA;AAAA,QAC7C,IAEA,oBAAC,UAAO,SAAQ,aAAY,SAAS,SAAS,oBAE9C;AAAA,QAEF,oBAAC,UAAO,SAAS,YAAY,SAAS,QAAQ,UAAU,CAAC,OACtD,oBAAU,SAAS,OACtB;AAAA,SACF;AAAA,MAGF,+BAAC,SAAI,WAAU,aACb;AAAA,4BAAC,eAAa,iBAAM;AAAA,QAEnB,CAAC,WAAW,CAAC,YACZ;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,YAAY,YAAY,CAAC,SAAS,IAAI,CAAC;AAAA,YACvC,YAAY;AAAA,YACZ;AAAA,YACA,QAAQ;AAAA,YACR,kBAAkB;AAAA;AAAA,QACpB;AAAA,QAGD,CAAC,WAAW,YACX,qBAAC,SAAI,WAAU,aACb;AAAA,8BAAC,SAAI,WAAU,yCACZ,oBAAU,SAAS,EAAE,IAAI,CAAC,WAAW;AACpC,kBAAM,OAAO,aAAa,OAAO,IAAI;AACrC,kBAAM,SAAS,OAAO,SAAS,OAAO;AACtC,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,OAAM;AAAA,gBACN,UAAU;AAAA,gBACV,WAAU;AAAA,gBACV,SAAS,MAAM;AACb,2BAAS,MAAM;AACf,8BAAY,IAAI;AAChB,sBAAI,CAAC,OAAO,KAAK,EAAG,WAAU,OAAO,UAAU;AAAA,gBACjD;AAAA,gBAEA;AAAA,uCAAC,UAAK,WAAU,2BACd;AAAA,wCAAC,QAAK,WAAU,sCAAqC;AAAA,oBACrD,oBAAC,UAAK,WAAU,kDACb,iBAAO,OACV;AAAA,qBACF;AAAA,kBACA,oBAAC,UAAK,WAAU,wCACb,iBAAO,aACV;AAAA,kBACA,oBAAC,UAAK,WAAU,oCACb,wBAAc,OAAO,MAAM,SAAS,GACvC;AAAA;AAAA;AAAA,cArBK,OAAO;AAAA,YAsBd;AAAA,UAEJ,CAAC,GACH;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM;AACb,4BAAY,KAAK;AACjB,yBAAS,IAAI;AACb,0BAAU,EAAE;AAAA,cACd;AAAA,cACD;AAAA;AAAA,UAED;AAAA,WACF;AAAA,SAGA,SAAS,YACT;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,MACE,WACI,oBAAoB,SAAS,YAAY,CAAC,MAC1C;AAAA,YAEN,UAAQ;AAAA,YAER;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,gBACP,UAAU,CAAC,MAAM,UAAU,EAAE,OAAO,KAAK;AAAA,gBACzC,aAAa,OAAO,cAAc;AAAA,gBAClC,WAAS;AAAA;AAAA,YACX;AAAA;AAAA,QACF;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -0,0 +1,90 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import Link from "next/link";
4
+ import { Plus, Settings } from "lucide-react";
5
+ import { Button } from "@withpotter/ui-kit/button";
6
+ import { Badge } from "@withpotter/ui-kit/badge";
7
+ function GroupBand({
8
+ span,
9
+ category,
10
+ count,
11
+ usage,
12
+ onAdd,
13
+ onRename
14
+ }) {
15
+ return /* @__PURE__ */ jsx("tr", { className: "bg-[var(--bg-muted)]", children: /* @__PURE__ */ jsx("td", { colSpan: span, className: "px-4 py-2", children: /* @__PURE__ */ jsx(
16
+ GroupHeadingContent,
17
+ {
18
+ category,
19
+ count,
20
+ onAdd,
21
+ onRename
22
+ }
23
+ ) }) });
24
+ }
25
+ function GroupHeading({
26
+ category,
27
+ count,
28
+ onAdd
29
+ }) {
30
+ return /* @__PURE__ */ jsx("div", { className: "mb-1", children: /* @__PURE__ */ jsx(GroupHeadingContent, { category, count, onAdd }) });
31
+ }
32
+ function GroupHeadingContent({
33
+ category,
34
+ count,
35
+ onAdd,
36
+ onRename
37
+ }) {
38
+ const title = category?.labelPlural ?? "No group";
39
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
40
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
41
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
42
+ /* @__PURE__ */ jsx("h2", { className: "truncate text-base font-semibold text-[var(--text-primary)]", children: title }),
43
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: count })
44
+ ] }),
45
+ !category ? /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--text-tertiary)]", children: "Open one to put it somewhere." }) : null
46
+ ] }),
47
+ category && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: onRename ? /* @__PURE__ */ jsxs(Fragment, { children: [
48
+ /* @__PURE__ */ jsx(
49
+ Button,
50
+ {
51
+ size: "icon",
52
+ variant: "secondary",
53
+ "aria-label": `Configure ${title}`,
54
+ onClick: () => onRename(category),
55
+ children: /* @__PURE__ */ jsx(Settings, {})
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsxs(
59
+ Button,
60
+ {
61
+ size: "md",
62
+ variant: "secondary",
63
+ onClick: () => onAdd(category),
64
+ children: [
65
+ /* @__PURE__ */ jsx(Plus, {}),
66
+ "Add ",
67
+ category.label.toLowerCase()
68
+ ]
69
+ }
70
+ )
71
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
72
+ /* @__PURE__ */ jsx(
73
+ Button,
74
+ {
75
+ size: "icon",
76
+ variant: "secondary",
77
+ "aria-label": `Add ${category.label.toLowerCase()}`,
78
+ onClick: () => onAdd(category),
79
+ children: /* @__PURE__ */ jsx(Plus, {})
80
+ }
81
+ ),
82
+ /* @__PURE__ */ jsx(Button, { asChild: true, size: "md", variant: "secondary", children: /* @__PURE__ */ jsx(Link, { href: `/dashboard/resources?group=${category.id}`, children: "View all" }) })
83
+ ] }) })
84
+ ] });
85
+ }
86
+ export {
87
+ GroupBand,
88
+ GroupHeading
89
+ };
90
+ //# sourceMappingURL=group-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_components/group-header.tsx"],"sourcesContent":["'use client';\n\nimport Link from 'next/link';\nimport { Plus, Settings } from 'lucide-react';\nimport { Button } from '@withpotter/ui-kit/button';\nimport { Badge } from '@withpotter/ui-kit/badge';\nimport type { CategoryUsage, ResourceCategory } from '@withpotter/lib/resource-types';\n\n/**\n * A group of bookable things, drawn as a band INSIDE the table it heads.\n *\n * It used to be a block above its own table, which meant every group redrew\n * the column header under it — four groups, four \"Name / Week / Today /\n * Status\" rows down one screen — and in the week view four copies of the week\n * navigator too. One table, one header, and the groups are bands in it.\n *\n * The band also says which services ask for this group, because that is the\n * sentence the screen was missing. A merchant adds a coach and expects a\n * customer to be able to book one; nothing happens, because a booking is\n * assigned through a SERVICE that declares what it needs, and until some\n * service asks for a coach the coaches are names in a list. John, 2026-08-23:\n * *\"i have coaches so i add them there, so on the website people can book a\n * court then book a coach\"* — true, and true only after that one link is made.\n *\n * That sentence only earns its line when the group HAS members. An empty\n * group has nothing that could be unreachable, so saying \"nothing books\n * stylists yet\" under a group with no stylists is the page answering a\n * question nobody asked — three times over, in three identical sentences,\n * which is exactly how this screen filled up with words that said nothing.\n */\nexport function GroupBand({\n span,\n category,\n count,\n usage,\n onAdd,\n onRename,\n}: {\n /** Columns to span — the table it sits in owns the number. */\n span: number;\n /** `null` for the rows that are in no group at all. */\n category: ResourceCategory | null;\n count: number;\n usage: CategoryUsage | undefined;\n onAdd: (category: ResourceCategory) => void;\n onRename: (category: ResourceCategory) => void;\n}) {\n return (\n <tr className=\"bg-[var(--bg-muted)]\">\n <td colSpan={span} className=\"px-4 py-2\">\n <GroupHeadingContent\n category={category}\n count={count}\n onAdd={onAdd}\n onRename={onRename}\n />\n </td>\n </tr>\n );\n}\n\n/**\n * The same heading, outside a table — the grid's section head.\n *\n * No band fill here: in the grid the cards are the surfaces and the ground\n * between them is the page, so painting a strip behind the title would put a\n * second surface under things that are already surfaces.\n */\nexport function GroupHeading({\n category,\n count,\n onAdd,\n}: {\n category: ResourceCategory | null;\n count: number;\n onAdd: (category: ResourceCategory) => void;\n}) {\n return (\n <div className=\"mb-1\">\n <GroupHeadingContent category={category} count={count} onAdd={onAdd} />\n </div>\n );\n}\n\nfunction GroupHeadingContent({\n category,\n count,\n onAdd,\n onRename,\n}: {\n category: ResourceCategory | null;\n count: number;\n onAdd: (category: ResourceCategory) => void;\n onRename?: (category: ResourceCategory) => void;\n}) {\n const title = category?.labelPlural ?? 'No group';\n\n return (\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"truncate text-base font-semibold text-[var(--text-primary)]\">\n {title}\n </h2>\n <Badge size=\"sm\">{count}</Badge>\n </div>\n\n {!category ? (\n <p className=\"text-sm text-[var(--text-tertiary)]\">\n Open one to put it somewhere.\n </p>\n ) : null}\n </div>\n\n {category && (\n <div className=\"flex items-center gap-2\">\n {onRename ? (\n <>\n <Button\n size=\"icon\"\n variant=\"secondary\"\n aria-label={`Configure ${title}`}\n onClick={() => onRename(category)}\n >\n <Settings />\n </Button>\n <Button\n size=\"md\"\n variant=\"secondary\"\n onClick={() => onAdd(category)}\n >\n <Plus />\n Add {category.label.toLowerCase()}\n </Button>\n </>\n ) : (\n <>\n <Button\n size=\"icon\"\n variant=\"secondary\"\n aria-label={`Add ${category.label.toLowerCase()}`}\n onClick={() => onAdd(category)}\n >\n <Plus />\n </Button>\n <Button asChild size=\"md\" variant=\"secondary\">\n <Link href={`/dashboard/resources?group=${category.id}`}>\n View all\n </Link>\n </Button>\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";AAkDQ,SAmEI,UAnEJ,KAkDA,YAlDA;AAhDR,OAAO,UAAU;AACjB,SAAS,MAAM,gBAAgB;AAC/B,SAAS,cAAc;AACvB,SAAS,aAAa;AAyBf,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASG;AACD,SACE,oBAAC,QAAG,WAAU,wBACZ,8BAAC,QAAG,SAAS,MAAM,WAAU,aAC3B;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF,GACF,GACF;AAEJ;AASO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,oBAAC,SAAI,WAAU,QACb,8BAAC,uBAAoB,UAAoB,OAAc,OAAc,GACvE;AAEJ;AAEA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAQ,UAAU,eAAe;AAEvC,SACE,qBAAC,SAAI,WAAU,qDACb;AAAA,yBAAC,SAAI,WAAU,WACb;AAAA,2BAAC,SAAI,WAAU,2BACb;AAAA,4BAAC,QAAG,WAAU,+DACX,iBACH;AAAA,QACA,oBAAC,SAAM,MAAK,MAAM,iBAAM;AAAA,SAC1B;AAAA,MAEC,CAAC,WACA,oBAAC,OAAE,WAAU,uCAAsC,2CAEnD,IACE;AAAA,OACN;AAAA,IAEC,YACC,oBAAC,SAAI,WAAU,2BACZ,qBACC,iCACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,cAAY,aAAa,KAAK;AAAA,UAC9B,SAAS,MAAM,SAAS,QAAQ;AAAA,UAEhC,8BAAC,YAAS;AAAA;AAAA,MACZ;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,SAAS,MAAM,MAAM,QAAQ;AAAA,UAE7B;AAAA,gCAAC,QAAK;AAAA,YAAE;AAAA,YACH,SAAS,MAAM,YAAY;AAAA;AAAA;AAAA,MAClC;AAAA,OACF,IAEA,iCACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,cAAY,OAAO,SAAS,MAAM,YAAY,CAAC;AAAA,UAC/C,SAAS,MAAM,MAAM,QAAQ;AAAA,UAE7B,8BAAC,QAAK;AAAA;AAAA,MACR;AAAA,MACA,oBAAC,UAAO,SAAO,MAAC,MAAK,MAAK,SAAQ,aAChC,8BAAC,QAAK,MAAM,8BAA8B,SAAS,EAAE,IAAI,sBAEzD,GACF;AAAA,OACF,GAEJ;AAAA,KAEJ;AAEJ;","names":[]}
@@ -0,0 +1,22 @@
1
+ import { BlockTimeModal } from "./block-time-modal";
2
+ import { DayEditor } from "./day-editor";
3
+ import { GroupDialog } from "./group-dialog";
4
+ import { GroupBand } from "./group-header";
5
+ import { ResourceForm } from "./resource-form";
6
+ import { RosterEmpty } from "./roster-empty";
7
+ import { RosterGrid } from "./roster-grid";
8
+ import { ScheduleEditor, getDefaultSchedule } from "./schedule-editor";
9
+ import { WeekGrid } from "./week-grid";
10
+ export {
11
+ BlockTimeModal,
12
+ DayEditor,
13
+ GroupBand,
14
+ GroupDialog,
15
+ ResourceForm,
16
+ RosterEmpty,
17
+ RosterGrid,
18
+ ScheduleEditor,
19
+ WeekGrid,
20
+ getDefaultSchedule
21
+ };
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/_components/index.ts"],"sourcesContent":["export { BlockTimeModal } from './block-time-modal';\nexport { DayEditor } from './day-editor';\nexport { GroupDialog } from './group-dialog';\nexport { GroupBand } from './group-header';\nexport { ResourceForm } from './resource-form';\nexport { RosterEmpty } from './roster-empty';\nexport { RosterGrid } from './roster-grid';\nexport { ScheduleEditor, getDefaultSchedule } from './schedule-editor';\nexport { WeekGrid } from './week-grid';\n"],"mappings":"AAAA,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB,0BAA0B;AACnD,SAAS,gBAAgB;","names":[]}