@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,356 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { use, useState } from "react";
4
+ import { RecordTrace } from "@withpotter/components/connect/record-trace";
5
+ import { DetailPage } from "@withpotter/ui-kit/detail-page";
6
+ import { DetailStates } from "@withpotter/ui-kit/detail-states";
7
+ import { useDetailHeader } from "@withpotter/hooks/use-detail-header";
8
+ import { useAuth } from "@withpotter/lib/auth-context";
9
+ import { useIntentConfig } from "@withpotter/lib/intents/use-intent-config";
10
+ import { useModuleLabel } from "@withpotter/lib/use-module-label";
11
+ import { useRouter } from "next/navigation";
12
+ import { useBookingDetailData } from "./_hooks";
13
+ import { Button } from "@withpotter/ui-kit/button";
14
+ import { Banknote, CalendarClock, Receipt, Repeat, Undo2 } from "lucide-react";
15
+ import { OverflowItem, OverflowMenu } from "@withpotter/ui-kit";
16
+ import {
17
+ CancelBookingModal,
18
+ RescheduleBookingModal,
19
+ RefundBookingModal,
20
+ SettleDepositModal
21
+ } from "./_components";
22
+ import { RecordPaymentModal } from "@withpotter/components/features/record-payment-modal";
23
+ import { BookingMobileLayout } from "./_components/booking-mobile-layout";
24
+ import { AssignResourceModal } from "./_components/assign-resource-modal";
25
+ import { BookingDesktopLayout } from "./_components/booking-desktop-layout";
26
+ import { BookingMobileScreen } from "./_components/booking-mobile-screen";
27
+ import { useIsMobile } from "@withpotter/hooks/use-mobile";
28
+ import { useItemLinks } from "@withpotter/lib/use-item-links";
29
+ function BookingDetailPage({
30
+ params
31
+ }) {
32
+ const { bookingId } = use(params);
33
+ const {
34
+ formatCurrency,
35
+ refetchBooking,
36
+ booking,
37
+ tickets,
38
+ loading,
39
+ error,
40
+ updatingStatus,
41
+ showStatusDropdown,
42
+ setShowStatusDropdown,
43
+ showCancelModal,
44
+ setShowCancelModal,
45
+ cancelReason,
46
+ setCancelReason,
47
+ handleStatusUpdate,
48
+ handleCancel,
49
+ statusConfig,
50
+ isPaid,
51
+ bookingAmount,
52
+ bookingTotal,
53
+ paidAmount,
54
+ paymentReference,
55
+ paidAt,
56
+ allowedTransitions,
57
+ canReschedule,
58
+ showRescheduleModal,
59
+ setShowRescheduleModal,
60
+ rescheduling,
61
+ rescheduleError,
62
+ handleReschedule,
63
+ balanceDue,
64
+ canRecordPayment,
65
+ showRecordPaymentModal,
66
+ loyaltyBalance,
67
+ loyaltyProgram,
68
+ setShowRecordPaymentModal,
69
+ recordingPayment,
70
+ recordPaymentError,
71
+ handleRecordPayment,
72
+ finance,
73
+ split,
74
+ canRefund,
75
+ securityDeposit,
76
+ depositStatus,
77
+ showSettleDepositModal,
78
+ setShowSettleDepositModal,
79
+ settlingDeposit,
80
+ settleDepositError,
81
+ handleSettleDeposit,
82
+ showRefundModal,
83
+ setShowRefundModal,
84
+ refunding,
85
+ refundError,
86
+ handleRefund
87
+ } = useBookingDetailData(bookingId);
88
+ const [showAssignResource, setShowAssignResource] = useState(false);
89
+ const canChangeResource = booking?.status === "pending" || booking?.status === "confirmed";
90
+ const { tenant } = useAuth();
91
+ const intentConfig = useIntentConfig();
92
+ const links = useItemLinks();
93
+ const activeIntentConfig = intentConfig.primary;
94
+ const isIntentActive = activeIntentConfig.key !== "default";
95
+ const fallbackBookingSingular = useModuleLabel("bookings", "Booking");
96
+ const fallbackBookingPlural = useModuleLabel("bookings", "Bookings");
97
+ const bookingLabel = isIntentActive ? activeIntentConfig.entities.booking : void 0;
98
+ const bookingSingular = bookingLabel?.singular ?? fallbackBookingSingular;
99
+ const bookingPlural = bookingLabel?.plural ?? fallbackBookingPlural;
100
+ const router = useRouter();
101
+ useDetailHeader({
102
+ title: booking ? `${bookingSingular} #${booking.bookingNumber}` : bookingSingular,
103
+ onBack: () => router.push(links.bookings)
104
+ });
105
+ const isMobile = useIsMobile();
106
+ if (loading || error || !booking) {
107
+ return /* @__PURE__ */ jsx(
108
+ DetailStates,
109
+ {
110
+ loading,
111
+ error,
112
+ notFoundLabel: `${bookingSingular} not found`,
113
+ back: {
114
+ href: links.bookings,
115
+ label: `Back to ${bookingPlural}`
116
+ },
117
+ maxWidth: "max-w-6xl"
118
+ }
119
+ );
120
+ }
121
+ if (isMobile) {
122
+ return /* @__PURE__ */ jsx(
123
+ BookingMobileScreen,
124
+ {
125
+ booking,
126
+ bookingSingular,
127
+ statusConfig,
128
+ formatCurrency,
129
+ isPaid,
130
+ bookingAmount,
131
+ allowedTransitions,
132
+ handleStatusUpdate,
133
+ showCancelModal,
134
+ setShowCancelModal,
135
+ cancelReason,
136
+ setCancelReason,
137
+ updatingStatus,
138
+ handleCancel,
139
+ onBack: () => router.back()
140
+ }
141
+ );
142
+ }
143
+ const canRebook = booking.status === "completed" || booking.status === "no_show" || booking.status === "cancelled";
144
+ const canInvoice = booking.status !== "cancelled" && !booking.data?.isPaid;
145
+ const rebookHref = (() => {
146
+ const params2 = new URLSearchParams();
147
+ if (booking.contentId) params2.set("service", booking.contentId);
148
+ if (booking.resourceId) params2.set("resource", booking.resourceId);
149
+ if (booking.customerName) params2.set("name", booking.customerName);
150
+ if (booking.customerEmail) params2.set("email", booking.customerEmail);
151
+ if (booking.customerPhone) params2.set("phone", booking.customerPhone);
152
+ const qs = params2.toString();
153
+ return qs ? `/dashboard/bookings/new?${qs}` : "/dashboard/bookings/new";
154
+ })();
155
+ const actions = [
156
+ canRecordPayment && {
157
+ label: "Record payment",
158
+ icon: /* @__PURE__ */ jsx(Banknote, {}),
159
+ run: () => setShowRecordPaymentModal(true)
160
+ },
161
+ canRebook && {
162
+ label: `Book again`,
163
+ icon: /* @__PURE__ */ jsx(Repeat, {}),
164
+ run: () => router.push(rebookHref)
165
+ },
166
+ canReschedule && {
167
+ label: "Reschedule",
168
+ icon: /* @__PURE__ */ jsx(CalendarClock, {}),
169
+ run: () => setShowRescheduleModal(true)
170
+ },
171
+ canInvoice && {
172
+ label: "Invoice",
173
+ icon: /* @__PURE__ */ jsx(Receipt, {}),
174
+ run: () => router.push(`/dashboard/invoices/new?fromBooking=${booking.id}`)
175
+ },
176
+ canRefund && {
177
+ label: "Refund",
178
+ icon: /* @__PURE__ */ jsx(Undo2, {}),
179
+ run: () => setShowRefundModal(true),
180
+ destructive: true
181
+ }
182
+ ].filter(Boolean);
183
+ const [primaryAction, ...menuActions] = actions;
184
+ return /* @__PURE__ */ jsxs(
185
+ DetailPage,
186
+ {
187
+ maxWidth: "max-w-6xl",
188
+ breadcrumbs: [
189
+ {
190
+ label: bookingPlural,
191
+ href: links.bookings,
192
+ icon: /* @__PURE__ */ jsx(CalendarClock, {})
193
+ },
194
+ { label: `#${booking.bookingNumber}` }
195
+ ],
196
+ title: booking.customerName?.trim() || booking.customerEmail || `${bookingSingular} #${booking.bookingNumber}`,
197
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [
198
+ primaryAction && /* @__PURE__ */ jsx(Button, { onClick: primaryAction.run, children: primaryAction.label }),
199
+ menuActions.length > 0 && /* @__PURE__ */ jsx(OverflowMenu, { children: menuActions.map((action) => /* @__PURE__ */ jsx(
200
+ OverflowItem,
201
+ {
202
+ icon: action.icon,
203
+ destructive: action.destructive,
204
+ onClick: action.run,
205
+ children: action.label
206
+ },
207
+ action.label
208
+ )) })
209
+ ] }),
210
+ children: [
211
+ /* @__PURE__ */ jsx(
212
+ BookingMobileLayout,
213
+ {
214
+ booking,
215
+ tickets,
216
+ statusConfig,
217
+ formatCurrency,
218
+ isPaid,
219
+ bookingAmount,
220
+ bookingTotal,
221
+ paidAmount,
222
+ split,
223
+ paymentReference,
224
+ paidAt,
225
+ allowedTransitions,
226
+ updatingStatus,
227
+ showStatusDropdown,
228
+ setShowStatusDropdown,
229
+ handleStatusUpdate,
230
+ bookingSingular,
231
+ tenant
232
+ }
233
+ ),
234
+ /* @__PURE__ */ jsx(
235
+ BookingDesktopLayout,
236
+ {
237
+ booking,
238
+ tickets,
239
+ statusConfig,
240
+ formatCurrency,
241
+ isPaid,
242
+ bookingAmount,
243
+ bookingTotal,
244
+ paidAmount,
245
+ split,
246
+ paymentReference,
247
+ paidAt,
248
+ allowedTransitions,
249
+ updatingStatus,
250
+ showStatusDropdown,
251
+ setShowStatusDropdown,
252
+ handleStatusUpdate,
253
+ bookingSingular,
254
+ tenant,
255
+ securityDeposit,
256
+ depositStatus,
257
+ onSettleDeposit: () => setShowSettleDepositModal(true),
258
+ onRecordPayment: canRecordPayment ? () => setShowRecordPaymentModal(true) : void 0,
259
+ onChangeResource: canChangeResource ? () => setShowAssignResource(true) : void 0
260
+ }
261
+ ),
262
+ /* @__PURE__ */ jsx(
263
+ AssignResourceModal,
264
+ {
265
+ booking,
266
+ open: showAssignResource,
267
+ onClose: () => setShowAssignResource(false),
268
+ onAssigned: refetchBooking
269
+ }
270
+ ),
271
+ /* @__PURE__ */ jsx(RecordTrace, { kind: "booking", id: bookingId, className: "mt-4" }),
272
+ showCancelModal && /* @__PURE__ */ jsx(
273
+ CancelBookingModal,
274
+ {
275
+ bookingNumber: booking.bookingNumber,
276
+ customerName: booking.customerName,
277
+ bookingDate: booking.date?.slice(0, 10),
278
+ resourceId: booking.resourceId,
279
+ cancelReason,
280
+ setCancelReason,
281
+ handleCancel,
282
+ updatingStatus,
283
+ onClose: () => {
284
+ setShowCancelModal(false);
285
+ setCancelReason("");
286
+ }
287
+ }
288
+ ),
289
+ showRescheduleModal && /* @__PURE__ */ jsx(
290
+ RescheduleBookingModal,
291
+ {
292
+ entityLabel: bookingSingular,
293
+ bookingNumber: booking.bookingNumber,
294
+ initialDate: booking.date,
295
+ initialStartTime: booking.startTime,
296
+ initialEndTime: booking.endTime,
297
+ rescheduling,
298
+ error: rescheduleError,
299
+ onReschedule: handleReschedule,
300
+ onClose: () => setShowRescheduleModal(false)
301
+ }
302
+ ),
303
+ showRecordPaymentModal && /* @__PURE__ */ jsx(
304
+ RecordPaymentModal,
305
+ {
306
+ loyalty: loyaltyBalance && loyaltyProgram ? {
307
+ memberId: loyaltyBalance.memberId,
308
+ points: loyaltyBalance.currentPoints,
309
+ pointsName: loyaltyProgram.pointsName,
310
+ currencyPerPoint: Number(
311
+ loyaltyProgram.currencyPerPoint ?? 0
312
+ ),
313
+ minRedeemPoints: loyaltyProgram.minRedeemPoints ?? 0,
314
+ customerName: booking.customerName ?? void 0
315
+ } : null,
316
+ subject: `#${booking.bookingNumber}`,
317
+ balanceDue,
318
+ formatCurrency,
319
+ recording: recordingPayment,
320
+ error: recordPaymentError,
321
+ onRecord: handleRecordPayment,
322
+ onClose: () => setShowRecordPaymentModal(false)
323
+ }
324
+ ),
325
+ showSettleDepositModal && securityDeposit != null && /* @__PURE__ */ jsx(
326
+ SettleDepositModal,
327
+ {
328
+ bookingNumber: booking.bookingNumber,
329
+ deposit: securityDeposit,
330
+ formatCurrency,
331
+ settling: settlingDeposit,
332
+ error: settleDepositError,
333
+ onSettle: handleSettleDeposit,
334
+ onClose: () => setShowSettleDepositModal(false)
335
+ }
336
+ ),
337
+ showRefundModal && /* @__PURE__ */ jsx(
338
+ RefundBookingModal,
339
+ {
340
+ bookingNumber: booking.bookingNumber,
341
+ entries: finance?.entries ?? [],
342
+ formatCurrency,
343
+ refunding,
344
+ error: refundError,
345
+ onRefund: handleRefund,
346
+ onClose: () => setShowRefundModal(false)
347
+ }
348
+ )
349
+ ]
350
+ }
351
+ );
352
+ }
353
+ export {
354
+ BookingDetailPage as default
355
+ };
356
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/bookings/%5BbookingId%5D/page.tsx"],"sourcesContent":["'use client';\n\nimport { use, useState } from 'react';\nimport { RecordTrace } from '@withpotter/components/connect/record-trace';\nimport { DetailPage } from '@withpotter/ui-kit/detail-page';\nimport { DetailStates } from '@withpotter/ui-kit/detail-states';\nimport { useDetailHeader } from '@withpotter/hooks/use-detail-header';\nimport { useAuth } from '@withpotter/lib/auth-context';\nimport { useIntentConfig } from '@withpotter/lib/intents/use-intent-config';\nimport { useModuleLabel } from '@withpotter/lib/use-module-label';\nimport { useRouter } from 'next/navigation';\nimport { useBookingDetailData } from './_hooks';\nimport { Button } from '@withpotter/ui-kit/button';\nimport type { ReactNode } from 'react';\nimport { Banknote, CalendarClock, Receipt, Repeat, Undo2 } from 'lucide-react';\nimport { OverflowItem, OverflowMenu } from '@withpotter/ui-kit';\nimport {\n CancelBookingModal,\n RescheduleBookingModal,\n RefundBookingModal,\n SettleDepositModal,\n} from './_components';\nimport { RecordPaymentModal } from '@withpotter/components/features/record-payment-modal';\nimport { BookingMobileLayout } from './_components/booking-mobile-layout';\nimport { AssignResourceModal } from './_components/assign-resource-modal';\nimport { BookingDesktopLayout } from './_components/booking-desktop-layout';\nimport { BookingMobileScreen } from './_components/booking-mobile-screen';\nimport { useIsMobile } from '@withpotter/hooks/use-mobile';\nimport { useItemLinks } from '@withpotter/lib/use-item-links';\n\nexport default function BookingDetailPage({\n params,\n}: {\n params: Promise<{ bookingId: string }>;\n}) {\n const { bookingId } = use(params);\n const {\n formatCurrency,\n refetchBooking,\n booking,\n tickets,\n loading,\n error,\n updatingStatus,\n showStatusDropdown,\n setShowStatusDropdown,\n showCancelModal,\n setShowCancelModal,\n cancelReason,\n setCancelReason,\n handleStatusUpdate,\n handleCancel,\n statusConfig,\n isPaid,\n bookingAmount,\n bookingTotal,\n paidAmount,\n paymentReference,\n paidAt,\n allowedTransitions,\n canReschedule,\n showRescheduleModal,\n setShowRescheduleModal,\n rescheduling,\n rescheduleError,\n handleReschedule,\n balanceDue,\n canRecordPayment,\n showRecordPaymentModal,\n loyaltyBalance,\n loyaltyProgram,\n setShowRecordPaymentModal,\n recordingPayment,\n recordPaymentError,\n handleRecordPayment,\n finance,\n split,\n canRefund,\n securityDeposit,\n depositStatus,\n showSettleDepositModal,\n setShowSettleDepositModal,\n settlingDeposit,\n settleDepositError,\n handleSettleDeposit,\n showRefundModal,\n setShowRefundModal,\n refunding,\n refundError,\n handleRefund,\n } = useBookingDetailData(bookingId);\n\n /**\n * Who this booking is with, changed after it exists.\n *\n * Gated on the booking still being open, and on nothing else. NOT on there\n * being a service: a booking taken without one is exactly the case most\n * likely to have nobody on it, and the API only runs the eligibility check\n * where there is a service to be eligible against — the double-booking check\n * runs either way. Assigning somebody to a cancelled appointment is the case\n * nobody needs, and the API refuses it, so the row stays a plain fact there.\n */\n const [showAssignResource, setShowAssignResource] = useState(false);\n const canChangeResource =\n booking?.status === 'pending' || booking?.status === 'confirmed';\n\n const { tenant } = useAuth();\n const intentConfig = useIntentConfig();\n const links = useItemLinks();\n const activeIntentConfig = intentConfig.primary;\n const isIntentActive = activeIntentConfig.key !== 'default';\n const fallbackBookingSingular = useModuleLabel('bookings', 'Booking');\n const fallbackBookingPlural = useModuleLabel('bookings', 'Bookings');\n const bookingLabel = isIntentActive\n ? activeIntentConfig.entities.booking\n : undefined;\n const bookingSingular = bookingLabel?.singular ?? fallbackBookingSingular;\n const bookingPlural = bookingLabel?.plural ?? fallbackBookingPlural;\n const router = useRouter();\n\n useDetailHeader({\n title: booking\n ? `${bookingSingular} #${booking.bookingNumber}`\n : bookingSingular,\n onBack: () => router.push(links.bookings),\n });\n\n const isMobile = useIsMobile();\n\n if (loading || error || !booking) {\n return (\n <DetailStates\n loading={loading}\n error={error}\n notFoundLabel={`${bookingSingular} not found`}\n back={{\n href: links.bookings,\n label: `Back to ${bookingPlural}`,\n }}\n maxWidth=\"max-w-6xl\"\n />\n );\n }\n\n if (isMobile) {\n return (\n <BookingMobileScreen\n booking={booking}\n bookingSingular={bookingSingular}\n statusConfig={statusConfig}\n formatCurrency={formatCurrency}\n isPaid={isPaid}\n bookingAmount={bookingAmount}\n allowedTransitions={allowedTransitions}\n handleStatusUpdate={handleStatusUpdate}\n showCancelModal={showCancelModal}\n setShowCancelModal={setShowCancelModal}\n cancelReason={cancelReason}\n setCancelReason={setCancelReason}\n updatingStatus={updatingStatus}\n handleCancel={handleCancel}\n onBack={() => router.back()}\n />\n );\n }\n\n /**\n * Only once the visit is behind them. Offering \"book again\" on a booking\n * that has not happened yet is offering to double-book the same person.\n */\n const canRebook =\n booking.status === 'completed' ||\n booking.status === 'no_show' ||\n booking.status === 'cancelled';\n\n /**\n * Bill it, for the businesses that do the work first and invoice after.\n *\n * A wedding photographer, a diagnostic lab, a caterer: the booking IS the\n * work, and the money moment is a document sent afterwards. `Invoice` has\n * carried `relatedType` / `relatedId` since the table was written and nothing\n * had ever set them, so billing a job meant opening a blank invoice and\n * retyping the client and the price — after which neither record knew about\n * the other.\n *\n * Not gated on the billing archetype: every business now has an Invoices row\n * under Money, and a salon that bills one corporate client for a month of\n * appointments is the ordinary case rather than the exception. Not offered on\n * a cancelled booking, and not on one that is already settled — there is\n * nothing left to ask for.\n */\n const canInvoice =\n booking.status !== 'cancelled' &&\n !(booking.data as { isPaid?: boolean } | null)?.isPaid;\n\n const rebookHref = (() => {\n const params = new URLSearchParams();\n if (booking.contentId) params.set('service', booking.contentId);\n if (booking.resourceId) params.set('resource', booking.resourceId);\n if (booking.customerName) params.set('name', booking.customerName);\n if (booking.customerEmail) params.set('email', booking.customerEmail);\n if (booking.customerPhone) params.set('phone', booking.customerPhone);\n const qs = params.toString();\n return qs ? `/dashboard/bookings/new?${qs}` : '/dashboard/bookings/new';\n })();\n\n /**\n * What can be done to this booking, most useful first.\n *\n * The order is the desk's: money owed outranks everything, because a booking\n * that is happening and unpaid is the one thing on this screen that costs the\n * business something. A visit that is over cannot be moved or paid for, so\n * its act is the next one.\n */\n const actions: {\n label: string;\n icon: ReactNode;\n run: () => void;\n destructive?: boolean;\n }[] = [\n canRecordPayment && {\n label: 'Record payment',\n icon: <Banknote />,\n run: () => setShowRecordPaymentModal(true),\n },\n canRebook && {\n label: `Book again`,\n icon: <Repeat />,\n run: () => router.push(rebookHref),\n },\n canReschedule && {\n label: 'Reschedule',\n icon: <CalendarClock />,\n run: () => setShowRescheduleModal(true),\n },\n canInvoice && {\n label: 'Invoice',\n icon: <Receipt />,\n run: () =>\n router.push(`/dashboard/invoices/new?fromBooking=${booking.id}`),\n },\n canRefund && {\n label: 'Refund',\n icon: <Undo2 />,\n run: () => setShowRefundModal(true),\n destructive: true,\n },\n ].filter(Boolean) as {\n label: string;\n icon: ReactNode;\n run: () => void;\n destructive?: boolean;\n }[];\n const [primaryAction, ...menuActions] = actions;\n\n return (\n <DetailPage\n maxWidth=\"max-w-6xl\"\n /**\n * Crumbs, not `back`. DetailPage's own type calls breadcrumbs \"the\n * preferred back affordance\" and marks `back` legacy, and every other\n * record in the app — orders, customers, segments, products — carries an\n * iconed trail. This one kept the arrow, which is why it reads as a\n * different product from the page next to it.\n */\n breadcrumbs={[\n {\n label: bookingPlural,\n href: links.bookings,\n icon: <CalendarClock />,\n },\n { label: `#${booking.bookingNumber}` },\n ]}\n /**\n * WHOSE BOOKING IT IS, not what it is filed under.\n *\n * `Appointment #BKMT75KB8WCAX` was the page title, the heading of the\n * first card and a row in the sidebar — the reference number three times\n * on one screen, twice at the top of it, and the breadcrumb under it says\n * the same thing a fourth time. A merchant looking at a booking is\n * looking at a person and a time; the code is how it is retrieved, not\n * what it is. It survives in the crumb and in the line at the foot.\n *\n * No subtitle. Page titles ship alone here, and this one carried\n * `createdAt` — so the header read \"Sep 10, 4:00 PM\" directly above a\n * body that said the appointment was Sep 11 at 11:00.\n */\n title={\n booking.customerName?.trim() ||\n booking.customerEmail ||\n `${bookingSingular} #${booking.bookingNumber}`\n }\n /**\n * ONE ACT, THEN THE MENU.\n *\n * Five secondary buttons could stand in this row at once — Book again,\n * Record payment, Reschedule, Refund, Invoice — each with its own icon,\n * all the same weight, none of them the thing you came to do. A header of\n * equal buttons is a header with no answer in it, and it squeezed the\n * title down to an ellipsis to hold them.\n *\n * So the row carries the ONE act this booking's state implies — money\n * owed means take it, a finished visit means book the next one, otherwise\n * move it — and everything else goes behind the ⋯, which is where the\n * rest of the app puts a monthly action sharing a row with a daily one.\n */\n actions={\n <>\n {primaryAction && (\n <Button onClick={primaryAction.run}>{primaryAction.label}</Button>\n )}\n {menuActions.length > 0 && (\n <OverflowMenu>\n {menuActions.map((action) => (\n <OverflowItem\n key={action.label}\n icon={action.icon}\n destructive={action.destructive}\n onClick={action.run}\n >\n {action.label}\n </OverflowItem>\n ))}\n </OverflowMenu>\n )}\n </>\n }\n >\n {/* ── Narrow-viewport layout (below lg) ── */}\n <BookingMobileLayout\n booking={booking}\n tickets={tickets}\n statusConfig={statusConfig}\n formatCurrency={formatCurrency}\n isPaid={isPaid}\n bookingAmount={bookingAmount}\n bookingTotal={bookingTotal}\n paidAmount={paidAmount}\n split={split}\n paymentReference={paymentReference}\n paidAt={paidAt}\n allowedTransitions={allowedTransitions}\n updatingStatus={updatingStatus}\n showStatusDropdown={showStatusDropdown}\n setShowStatusDropdown={setShowStatusDropdown}\n handleStatusUpdate={handleStatusUpdate}\n bookingSingular={bookingSingular}\n tenant={tenant}\n />\n\n {/* ── Desktop layout ── */}\n <BookingDesktopLayout\n booking={booking}\n tickets={tickets}\n statusConfig={statusConfig}\n formatCurrency={formatCurrency}\n isPaid={isPaid}\n bookingAmount={bookingAmount}\n bookingTotal={bookingTotal}\n paidAmount={paidAmount}\n split={split}\n paymentReference={paymentReference}\n paidAt={paidAt}\n allowedTransitions={allowedTransitions}\n updatingStatus={updatingStatus}\n showStatusDropdown={showStatusDropdown}\n setShowStatusDropdown={setShowStatusDropdown}\n handleStatusUpdate={handleStatusUpdate}\n bookingSingular={bookingSingular}\n tenant={tenant}\n securityDeposit={securityDeposit}\n depositStatus={depositStatus}\n onSettleDeposit={() => setShowSettleDepositModal(true)}\n /* Only when there is a balance and the API takes desk payments —\n otherwise the badge stays the plain fact it always was. */\n onRecordPayment={\n canRecordPayment ? () => setShowRecordPaymentModal(true) : undefined\n }\n onChangeResource={\n canChangeResource ? () => setShowAssignResource(true) : undefined\n }\n />\n\n {/* Kept mounted and handed `open`, so the close animates. */}\n <AssignResourceModal\n booking={booking}\n open={showAssignResource}\n onClose={() => setShowAssignResource(false)}\n onAssigned={refetchBooking}\n />\n\n {/* Whether the diary the customer actually reads got this booking. A\n calendar sync that stopped is silent on every screen but this one. */}\n <RecordTrace kind=\"booking\" id={bookingId} className=\"mt-4\" />\n\n {/* Cancel Booking Modal */}\n {showCancelModal && (\n <CancelBookingModal\n bookingNumber={booking.bookingNumber}\n customerName={booking.customerName}\n bookingDate={booking.date?.slice(0, 10)}\n resourceId={booking.resourceId}\n cancelReason={cancelReason}\n setCancelReason={setCancelReason}\n handleCancel={handleCancel}\n updatingStatus={updatingStatus}\n onClose={() => {\n setShowCancelModal(false);\n setCancelReason('');\n }}\n />\n )}\n\n {/* Reschedule Modal */}\n {showRescheduleModal && (\n <RescheduleBookingModal\n entityLabel={bookingSingular}\n bookingNumber={booking.bookingNumber}\n initialDate={booking.date}\n initialStartTime={booking.startTime}\n initialEndTime={booking.endTime}\n rescheduling={rescheduling}\n error={rescheduleError}\n onReschedule={handleReschedule}\n onClose={() => setShowRescheduleModal(false)}\n />\n )}\n\n {/* Record Payment Modal */}\n {showRecordPaymentModal && (\n <RecordPaymentModal\n /* The balance, offered where the money is taken. Null when the\n customer is not a member or the programme has no conversion, in\n which case this is the plain payment form it always was. */\n loyalty={\n loyaltyBalance && loyaltyProgram\n ? {\n memberId: loyaltyBalance.memberId,\n points: loyaltyBalance.currentPoints,\n pointsName: loyaltyProgram.pointsName,\n currencyPerPoint: Number(\n loyaltyProgram.currencyPerPoint ?? 0,\n ),\n minRedeemPoints: loyaltyProgram.minRedeemPoints ?? 0,\n customerName: booking.customerName ?? undefined,\n }\n : null\n }\n subject={`#${booking.bookingNumber}`}\n balanceDue={balanceDue}\n formatCurrency={formatCurrency}\n recording={recordingPayment}\n error={recordPaymentError}\n onRecord={handleRecordPayment}\n onClose={() => setShowRecordPaymentModal(false)}\n />\n )}\n\n {/* Settle the security deposit at checkout */}\n {showSettleDepositModal && securityDeposit != null && (\n <SettleDepositModal\n bookingNumber={booking.bookingNumber}\n deposit={securityDeposit}\n formatCurrency={formatCurrency}\n settling={settlingDeposit}\n error={settleDepositError}\n onSettle={handleSettleDeposit}\n onClose={() => setShowSettleDepositModal(false)}\n />\n )}\n\n {/* Refund Modal */}\n {showRefundModal && (\n <RefundBookingModal\n bookingNumber={booking.bookingNumber}\n entries={finance?.entries ?? []}\n formatCurrency={formatCurrency}\n refunding={refunding}\n error={refundError}\n onRefund={handleRefund}\n onClose={() => setShowRefundModal(false)}\n />\n )}\n </DetailPage>\n );\n}\n"],"mappings":"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","names":["params"]}
@@ -0,0 +1,34 @@
1
+ function timeToMinutes(time) {
2
+ if (!time) return 0;
3
+ const [hours, minutes] = time.split(":").map(Number);
4
+ return hours * 60 + minutes;
5
+ }
6
+ function appointmentsOverlap(first, second) {
7
+ if (first.resourceId !== second.resourceId || first.id === second.id) {
8
+ return false;
9
+ }
10
+ const firstStart = timeToMinutes(first.startTime);
11
+ const firstEnd = timeToMinutes(first.endTime) || firstStart + 60;
12
+ const secondStart = timeToMinutes(second.startTime);
13
+ const secondEnd = timeToMinutes(second.endTime) || secondStart + 60;
14
+ return firstStart < secondEnd && secondStart < firstEnd;
15
+ }
16
+ function getAppointmentLayout(booking, rowBookings, dayStartMinutes, gridMinutes) {
17
+ const start = timeToMinutes(booking.startTime);
18
+ const end = timeToMinutes(booking.endTime) + (booking.endTime ? 0 : booking.durationMinutes || 60);
19
+ const group = rowBookings.filter(
20
+ (candidate) => candidate.id === booking.id || appointmentsOverlap(booking, candidate)
21
+ ).sort((first, second) => first.id.localeCompare(second.id));
22
+ const index = group.findIndex((candidate) => candidate.id === booking.id);
23
+ const baseLeft = Math.max(0, (start - dayStartMinutes) / gridMinutes * 100);
24
+ const baseWidth = Math.max(3, (end - start) / gridMinutes * 100);
25
+ return {
26
+ left: baseLeft + baseWidth / group.length * index,
27
+ width: baseWidth / group.length
28
+ };
29
+ }
30
+ export {
31
+ appointmentsOverlap,
32
+ getAppointmentLayout
33
+ };
34
+ //# sourceMappingURL=appointment-calendar-layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/bookings/_components/appointment-calendar-layout.ts"],"sourcesContent":["import type { BookingItem } from '@withpotter/lib/api';\n\nfunction timeToMinutes(time?: string | null): number {\n if (!time) return 0;\n const [hours, minutes] = time.split(':').map(Number);\n return hours * 60 + minutes;\n}\n\nexport function appointmentsOverlap(\n first: BookingItem,\n second: BookingItem,\n): boolean {\n if (first.resourceId !== second.resourceId || first.id === second.id) {\n return false;\n }\n const firstStart = timeToMinutes(first.startTime);\n const firstEnd = timeToMinutes(first.endTime) || firstStart + 60;\n const secondStart = timeToMinutes(second.startTime);\n const secondEnd = timeToMinutes(second.endTime) || secondStart + 60;\n return firstStart < secondEnd && secondStart < firstEnd;\n}\n\nexport function getAppointmentLayout(\n booking: BookingItem,\n rowBookings: BookingItem[],\n dayStartMinutes: number,\n gridMinutes: number,\n) {\n const start = timeToMinutes(booking.startTime);\n const end =\n timeToMinutes(booking.endTime) +\n (booking.endTime ? 0 : booking.durationMinutes || 60);\n const group = rowBookings\n .filter(\n (candidate) =>\n candidate.id === booking.id || appointmentsOverlap(booking, candidate),\n )\n .sort((first, second) => first.id.localeCompare(second.id));\n const index = group.findIndex((candidate) => candidate.id === booking.id);\n const baseLeft = Math.max(0, ((start - dayStartMinutes) / gridMinutes) * 100);\n const baseWidth = Math.max(3, ((end - start) / gridMinutes) * 100);\n return {\n left: baseLeft + (baseWidth / group.length) * index,\n width: baseWidth / group.length,\n };\n}\n"],"mappings":"AAEA,SAAS,cAAc,MAA8B;AACnD,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,CAAC,OAAO,OAAO,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,MAAM;AACnD,SAAO,QAAQ,KAAK;AACtB;AAEO,SAAS,oBACd,OACA,QACS;AACT,MAAI,MAAM,eAAe,OAAO,cAAc,MAAM,OAAO,OAAO,IAAI;AACpE,WAAO;AAAA,EACT;AACA,QAAM,aAAa,cAAc,MAAM,SAAS;AAChD,QAAM,WAAW,cAAc,MAAM,OAAO,KAAK,aAAa;AAC9D,QAAM,cAAc,cAAc,OAAO,SAAS;AAClD,QAAM,YAAY,cAAc,OAAO,OAAO,KAAK,cAAc;AACjE,SAAO,aAAa,aAAa,cAAc;AACjD;AAEO,SAAS,qBACd,SACA,aACA,iBACA,aACA;AACA,QAAM,QAAQ,cAAc,QAAQ,SAAS;AAC7C,QAAM,MACJ,cAAc,QAAQ,OAAO,KAC5B,QAAQ,UAAU,IAAI,QAAQ,mBAAmB;AACpD,QAAM,QAAQ,YACX;AAAA,IACC,CAAC,cACC,UAAU,OAAO,QAAQ,MAAM,oBAAoB,SAAS,SAAS;AAAA,EACzE,EACC,KAAK,CAAC,OAAO,WAAW,MAAM,GAAG,cAAc,OAAO,EAAE,CAAC;AAC5D,QAAM,QAAQ,MAAM,UAAU,CAAC,cAAc,UAAU,OAAO,QAAQ,EAAE;AACxE,QAAM,WAAW,KAAK,IAAI,IAAK,QAAQ,mBAAmB,cAAe,GAAG;AAC5E,QAAM,YAAY,KAAK,IAAI,IAAK,MAAM,SAAS,cAAe,GAAG;AACjE,SAAO;AAAA,IACL,MAAM,WAAY,YAAY,MAAM,SAAU;AAAA,IAC9C,OAAO,YAAY,MAAM;AAAA,EAC3B;AACF;","names":[]}
@@ -0,0 +1,92 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useMemo } from "react";
4
+ import { CheckCircle2, Clock, XCircle, RefreshCw, UserX } from "lucide-react";
5
+ import { useIntentConfig } from "@withpotter/lib/intents/use-intent-config";
6
+ const BOOKING_STATUS_CONFIG = {
7
+ pending: {
8
+ label: "Pending",
9
+ color: "text-[var(--text-secondary)]",
10
+ bgColor: "bg-[var(--bg-muted)]",
11
+ icon: /* @__PURE__ */ jsx(Clock, {})
12
+ },
13
+ confirmed: {
14
+ label: "Confirmed",
15
+ color: "text-[var(--text-secondary)]",
16
+ bgColor: "bg-[var(--bg-muted)]",
17
+ icon: /* @__PURE__ */ jsx(CheckCircle2, {})
18
+ },
19
+ checked_in: {
20
+ label: "Checked in",
21
+ color: "text-[var(--text-secondary)]",
22
+ bgColor: "bg-[var(--bg-muted)]",
23
+ icon: /* @__PURE__ */ jsx(CheckCircle2, {})
24
+ },
25
+ in_progress: {
26
+ label: "In progress",
27
+ color: "text-[var(--text-secondary)]",
28
+ bgColor: "bg-[var(--bg-muted)]",
29
+ icon: /* @__PURE__ */ jsx(RefreshCw, {})
30
+ },
31
+ completed: {
32
+ label: "Completed",
33
+ color: "text-[var(--text-secondary)]",
34
+ bgColor: "bg-[var(--bg-muted)]",
35
+ icon: /* @__PURE__ */ jsx(CheckCircle2, {})
36
+ },
37
+ cancelled: {
38
+ label: "Cancelled",
39
+ color: "text-[var(--text-secondary)]",
40
+ bgColor: "bg-[var(--bg-muted)]",
41
+ icon: /* @__PURE__ */ jsx(XCircle, {})
42
+ },
43
+ no_show: {
44
+ label: "No show",
45
+ color: "text-[var(--text-secondary)]",
46
+ bgColor: "bg-[var(--bg-muted)]",
47
+ icon: /* @__PURE__ */ jsx(UserX, {})
48
+ },
49
+ waitlist: {
50
+ label: "Waitlist",
51
+ color: "text-[var(--text-secondary)]",
52
+ bgColor: "bg-[var(--bg-muted)]",
53
+ icon: /* @__PURE__ */ jsx(Clock, {})
54
+ }
55
+ };
56
+ const ARCHETYPE_BY_BOOKING_TYPE = {
57
+ table: "dine-in",
58
+ room: "rent-property",
59
+ event: "event-tickets",
60
+ appointment: "take-bookings",
61
+ class: "take-bookings",
62
+ resource: "take-bookings"
63
+ };
64
+ function useBookingStatusConfig() {
65
+ const { all, primary } = useIntentConfig();
66
+ return useMemo(() => {
67
+ const byKey = new Map(all.map((config) => [config.key, config]));
68
+ const wordsOf = (config) => {
69
+ const merged = { ...BOOKING_STATUS_CONFIG };
70
+ for (const [status, label] of Object.entries(
71
+ config.orderDisplay.statusLabels
72
+ )) {
73
+ const base = merged[status];
74
+ if (base) merged[status] = { ...base, label };
75
+ }
76
+ return merged;
77
+ };
78
+ const fallback = wordsOf(primary);
79
+ const byType = Object.fromEntries(
80
+ Object.entries(ARCHETYPE_BY_BOOKING_TYPE).map(([type, key]) => {
81
+ const owner = byKey.get(key);
82
+ return [type, owner ? wordsOf(owner) : fallback];
83
+ })
84
+ );
85
+ return (bookingType) => bookingType && byType[bookingType] || fallback;
86
+ }, [all, primary]);
87
+ }
88
+ export {
89
+ BOOKING_STATUS_CONFIG,
90
+ useBookingStatusConfig
91
+ };
92
+ //# sourceMappingURL=booking-constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/bookings/_components/booking-constants.tsx"],"sourcesContent":["'use client';\n\nimport { useMemo } from 'react';\nimport { CheckCircle2, Clock, XCircle, RefreshCw, UserX } from 'lucide-react';\nimport { useIntentConfig } from '@withpotter/lib/intents/use-intent-config';\n\nexport type BookingStatus =\n | 'pending'\n | 'confirmed'\n | 'checked_in'\n | 'in_progress'\n | 'completed'\n | 'cancelled'\n | 'no_show'\n | 'waitlist';\n\n/**\n * One neutral chip per status, matching orders and the waitlist.\n *\n * A door list came out as a column of eight hues restating the words beside\n * them, and the hues ranked the rows wrong: \"Checked In\" in green was the\n * loudest thing on a screen whose job is finding the people who have NOT\n * arrived. The icon still separates the states at a glance; colour was saying\n * the label a second time. Each status keeps its label and its glyph.\n */\nexport const BOOKING_STATUS_CONFIG: Record<\n BookingStatus,\n { label: string; color: string; bgColor: string; icon: React.ReactNode }\n> = {\n pending: {\n label: 'Pending',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <Clock />,\n },\n confirmed: {\n label: 'Confirmed',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <CheckCircle2 />,\n },\n checked_in: {\n label: 'Checked in',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <CheckCircle2 />,\n },\n in_progress: {\n label: 'In progress',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <RefreshCw />,\n },\n completed: {\n label: 'Completed',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <CheckCircle2 />,\n },\n cancelled: {\n label: 'Cancelled',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <XCircle />,\n },\n no_show: {\n label: 'No show',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <UserX />,\n },\n waitlist: {\n label: 'Waitlist',\n color: 'text-[var(--text-secondary)]',\n bgColor: 'bg-[var(--bg-muted)]',\n icon: <Clock />,\n },\n};\n\n/**\n * The same statuses, in this business's words.\n *\n * `checked_in` is one row in the database and four different events in a\n * merchant's day: a guest checking into a room, a ticket holder coming through\n * the door, a table being **Served**, a takeaway being **Ready for Pickup**.\n * Every intent config already says which — `orderDisplay.statusLabels` — and\n * this screen read the map above instead, so a restaurant opening Reservations\n * was told its table had \"Checked In\".\n *\n * Labels come from the archetype; glyph and colour stay here, because those\n * separate the states rather than name them.\n *\n * Resolved per ROW, from the booking's own type, not from `primary`. A\n * business running a dining room and a treatment room has both in one list,\n * and wording taken from whichever archetype happens to be primary labelled a\n * massage \"Served\". This was impossible until fulfilment stopped writing\n * APPOINTMENT for everything (potter-api `bookingTypeForIntent`), because\n * before that the type could not say what the thing was.\n *\n * A type this business does not run, or a row from before that fix, falls back\n * to `primary` — the previous behaviour, which is right for every\n * single-archetype business.\n */\nconst ARCHETYPE_BY_BOOKING_TYPE: Record<string, string> = {\n table: 'dine-in',\n room: 'rent-property',\n event: 'event-tickets',\n appointment: 'take-bookings',\n class: 'take-bookings',\n resource: 'take-bookings',\n};\n\nexport function useBookingStatusConfig(): (\n bookingType?: string | null,\n) => typeof BOOKING_STATUS_CONFIG {\n const { all, primary } = useIntentConfig();\n\n return useMemo(() => {\n const byKey = new Map(all.map((config) => [config.key, config]));\n\n const wordsOf = (config: (typeof all)[number]) => {\n const merged = { ...BOOKING_STATUS_CONFIG };\n for (const [status, label] of Object.entries(\n config.orderDisplay.statusLabels,\n )) {\n const base = merged[status as BookingStatus];\n if (base) merged[status as BookingStatus] = { ...base, label };\n }\n return merged;\n };\n\n // Built once for every type this business could show, so the lookup below\n // is pure — no cache filled during render.\n const fallback = wordsOf(primary);\n const byType = Object.fromEntries(\n Object.entries(ARCHETYPE_BY_BOOKING_TYPE).map(([type, key]) => {\n const owner = byKey.get(key);\n return [type, owner ? wordsOf(owner) : fallback];\n }),\n );\n\n return (bookingType?: string | null) =>\n (bookingType && byType[bookingType]) || fallback;\n }, [all, primary]);\n}\n"],"mappings":";AAiCU;AA/BV,SAAS,eAAe;AACxB,SAAS,cAAc,OAAO,SAAS,WAAW,aAAa;AAC/D,SAAS,uBAAuB;AAqBzB,MAAM,wBAGT;AAAA,EACF,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,SAAM;AAAA,EACf;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,gBAAa;AAAA,EACtB;AAAA,EACA,YAAY;AAAA,IACV,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,gBAAa;AAAA,EACtB;AAAA,EACA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,aAAU;AAAA,EACnB;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,gBAAa;AAAA,EACtB;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,WAAQ;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,SAAM;AAAA,EACf;AAAA,EACA,UAAU;AAAA,IACR,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM,oBAAC,SAAM;AAAA,EACf;AACF;AA0BA,MAAM,4BAAoD;AAAA,EACxD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,OAAO;AAAA,EACP,UAAU;AACZ;AAEO,SAAS,yBAEkB;AAChC,QAAM,EAAE,KAAK,QAAQ,IAAI,gBAAgB;AAEzC,SAAO,QAAQ,MAAM;AACnB,UAAM,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC;AAE/D,UAAM,UAAU,CAAC,WAAiC;AAChD,YAAM,SAAS,EAAE,GAAG,sBAAsB;AAC1C,iBAAW,CAAC,QAAQ,KAAK,KAAK,OAAO;AAAA,QACnC,OAAO,aAAa;AAAA,MACtB,GAAG;AACD,cAAM,OAAO,OAAO,MAAuB;AAC3C,YAAI,KAAM,QAAO,MAAuB,IAAI,EAAE,GAAG,MAAM,MAAM;AAAA,MAC/D;AACA,aAAO;AAAA,IACT;AAIA,UAAM,WAAW,QAAQ,OAAO;AAChC,UAAM,SAAS,OAAO;AAAA,MACpB,OAAO,QAAQ,yBAAyB,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AAC7D,cAAM,QAAQ,MAAM,IAAI,GAAG;AAC3B,eAAO,CAAC,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ;AAAA,MACjD,CAAC;AAAA,IACH;AAEA,WAAO,CAAC,gBACL,eAAe,OAAO,WAAW,KAAM;AAAA,EAC5C,GAAG,CAAC,KAAK,OAAO,CAAC;AACnB;","names":[]}
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ function bookingTabHintId(idPrefix, tab) {
4
+ return tab.description ? `${idPrefix}-${tab.key}` : void 0;
5
+ }
6
+ function BookingTabHints({
7
+ tabs,
8
+ idPrefix,
9
+ className = ""
10
+ }) {
11
+ const described = tabs.filter((tab) => tab.description);
12
+ if (described.length === 0) return null;
13
+ return /* @__PURE__ */ jsx(
14
+ "p",
15
+ {
16
+ className: `flex flex-wrap gap-x-4 gap-y-1 text-xs text-[var(--text-muted)] ${className}`,
17
+ children: described.map((tab) => /* @__PURE__ */ jsxs("span", { id: bookingTabHintId(idPrefix, tab), children: [
18
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-[var(--text-secondary)]", children: [
19
+ tab.label,
20
+ ":"
21
+ ] }),
22
+ " ",
23
+ tab.description
24
+ ] }, tab.key))
25
+ }
26
+ );
27
+ }
28
+ export {
29
+ BookingTabHints,
30
+ bookingTabHintId
31
+ };
32
+ //# sourceMappingURL=booking-tab-hints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/bookings/_components/booking-tab-hints.tsx"],"sourcesContent":["'use client';\n\ninterface TabWithHint {\n key: string;\n label: string;\n description?: string;\n}\n\n/** The id a tab button points at with aria-describedby, or undefined when the tab has no hint. */\nexport function bookingTabHintId(\n idPrefix: string,\n tab: TabWithHint,\n): string | undefined {\n return tab.description ? `${idPrefix}-${tab.key}` : undefined;\n}\n\n/**\n * The meaning of each status tab, written out under the tabs so it can be read\n * without hovering. Tabs without a description are left out.\n */\nexport function BookingTabHints({\n tabs,\n idPrefix,\n className = '',\n}: {\n tabs: TabWithHint[];\n idPrefix: string;\n className?: string;\n}) {\n const described = tabs.filter((tab) => tab.description);\n if (described.length === 0) return null;\n\n return (\n <p\n className={`flex flex-wrap gap-x-4 gap-y-1 text-xs text-[var(--text-muted)] ${className}`}\n >\n {described.map((tab) => (\n <span key={tab.key} id={bookingTabHintId(idPrefix, tab)}>\n <span className=\"font-medium text-[var(--text-secondary)]\">\n {tab.label}:\n </span>{' '}\n {tab.description}\n </span>\n ))}\n </p>\n );\n}\n"],"mappings":";AAiCI,cAKM,YALN;AAxBG,SAAS,iBACd,UACA,KACoB;AACpB,SAAO,IAAI,cAAc,GAAG,QAAQ,IAAI,IAAI,GAAG,KAAK;AACtD;AAMO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAIG;AACD,QAAM,YAAY,KAAK,OAAO,CAAC,QAAQ,IAAI,WAAW;AACtD,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,mEAAmE,SAAS;AAAA,MAEtF,oBAAU,IAAI,CAAC,QACd,qBAAC,UAAmB,IAAI,iBAAiB,UAAU,GAAG,GACpD;AAAA,6BAAC,UAAK,WAAU,4CACb;AAAA,cAAI;AAAA,UAAM;AAAA,WACb;AAAA,QAAQ;AAAA,QACP,IAAI;AAAA,WAJI,IAAI,GAKf,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}