@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,142 @@
1
+ const TODAY = "2026-08-11";
2
+ const at = (time) => `${TODAY}T${time}:00.000Z`;
3
+ function mkBooking(b) {
4
+ return {
5
+ tenantId: "demo",
6
+ type: "resource",
7
+ date: TODAY,
8
+ quantity: 1,
9
+ createdAt: at("08:00"),
10
+ updatedAt: at("08:00"),
11
+ ...b
12
+ };
13
+ }
14
+ const DEMO_TODAY_BOOKINGS = [
15
+ mkBooking({
16
+ id: "demo-t1",
17
+ bookingNumber: "BK-4101",
18
+ customerName: "Ifeanyi Obi",
19
+ customerPhone: "+2348031120945",
20
+ status: "checked_in",
21
+ resourceId: "demo-r1",
22
+ resourceName: "Ada",
23
+ startTime: "09:00",
24
+ endTime: "10:00",
25
+ checkedInAt: at("09:02"),
26
+ data: { isPaid: true, total: 24e3 }
27
+ }),
28
+ mkBooking({
29
+ id: "demo-t2",
30
+ bookingNumber: "BK-4102",
31
+ customerName: "Chidinma Eze",
32
+ customerPhone: "+2348024410982",
33
+ status: "confirmed",
34
+ resourceId: "demo-r1",
35
+ resourceName: "Ada",
36
+ startTime: "10:00",
37
+ endTime: "11:00",
38
+ data: { isPaid: true, total: 24e3 }
39
+ }),
40
+ mkBooking({
41
+ id: "demo-t3",
42
+ bookingNumber: "BK-4103",
43
+ customerName: "Tunde Bakare",
44
+ customerPhone: "+2347066120114",
45
+ status: "confirmed",
46
+ resourceId: "demo-r2",
47
+ resourceName: "Ngozi",
48
+ startTime: "10:00",
49
+ endTime: "11:30",
50
+ // Unpaid and about to start: the row the board exists to surface.
51
+ data: { isPaid: false, total: 36e3 }
52
+ }),
53
+ mkBooking({
54
+ id: "demo-t4",
55
+ bookingNumber: "BK-4104",
56
+ customerName: "Amaka Nwosu",
57
+ status: "completed",
58
+ resourceId: "demo-r2",
59
+ resourceName: "Ngozi",
60
+ startTime: "07:00",
61
+ endTime: "08:00",
62
+ checkedInAt: at("07:01"),
63
+ data: { isPaid: true, total: 24e3 }
64
+ }),
65
+ mkBooking({
66
+ id: "demo-t5",
67
+ bookingNumber: "BK-4105",
68
+ customerName: "Zainab Musa",
69
+ customerPhone: "+2348139902411",
70
+ status: "confirmed",
71
+ // No resource. Deliberately: a booking against nothing has to land in the
72
+ // Unassigned lane, and that lane is the one nobody notices is missing.
73
+ startTime: "12:00",
74
+ endTime: "13:00",
75
+ data: { isPaid: true, total: 24e3 }
76
+ })
77
+ ];
78
+ const DEMO_TODAY_RESOURCES = [
79
+ { id: "demo-r1", name: "Ada", isActive: true },
80
+ { id: "demo-r2", name: "Ngozi", isActive: true },
81
+ { id: "demo-r3", name: "Tunde", isActive: true }
82
+ ];
83
+ const DEMO_TODAY_QUEUE = [
84
+ {
85
+ id: "demo-q1",
86
+ tenantId: "demo",
87
+ customerName: "Segun Adeyemi",
88
+ customerEmail: "segun.a@gmail.com",
89
+ customerPhone: "+2348090011223",
90
+ requestedDate: TODAY,
91
+ requestedStartTime: "18:00",
92
+ requestedEndTime: "19:00",
93
+ status: "waiting",
94
+ position: 1,
95
+ priority: "high",
96
+ createdAt: at("08:15"),
97
+ updatedAt: at("08:15")
98
+ },
99
+ {
100
+ id: "demo-q2",
101
+ tenantId: "demo",
102
+ customerName: "Ngozi Umeh",
103
+ customerEmail: "ngozi.umeh@gmail.com",
104
+ requestedDate: TODAY,
105
+ requestedStartTime: "18:00",
106
+ requestedEndTime: "19:00",
107
+ status: "waiting",
108
+ position: 2,
109
+ priority: "normal",
110
+ createdAt: at("09:40"),
111
+ updatedAt: at("09:40")
112
+ }
113
+ ];
114
+ const DEMO_TODAY_TABS = [
115
+ {
116
+ id: "demo-tab1",
117
+ tenantId: "demo",
118
+ tableLabel: "Ada",
119
+ customerName: "Ifeanyi Obi",
120
+ status: "open",
121
+ currency: "NGN",
122
+ total: 18500,
123
+ items: [
124
+ { contentId: "demo-m1", title: "Chapman", quantity: 2, unitPrice: 4500 },
125
+ {
126
+ contentId: "demo-m2",
127
+ title: "Suya Platter",
128
+ quantity: 1,
129
+ unitPrice: 9500
130
+ }
131
+ ],
132
+ createdAt: at("09:10"),
133
+ updatedAt: at("09:35")
134
+ }
135
+ ];
136
+ export {
137
+ DEMO_TODAY_BOOKINGS,
138
+ DEMO_TODAY_QUEUE,
139
+ DEMO_TODAY_RESOURCES,
140
+ DEMO_TODAY_TABS
141
+ };
142
+ //# sourceMappingURL=demo-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/dashboard/%28bookings%29/bookings/_components/today/demo-data.ts"],"sourcesContent":["import type { BookingItem, WaitlistItem } from '@withpotter/lib/api/types';\n\n/**\n * Seed for the Today board under `?demo=1`.\n *\n * The board is four feeds read together — today's bookings, the resources they\n * sit in, who is queued for a slot, and any open tabs — so a seed that covers\n * only one of them produces a board with lanes and nothing in them, which is\n * the same empty screen with more structure. All four are here.\n *\n * Times are fixed rather than relative to now. A board whose rows move every\n * render cannot be talked about, and \"on now\" has to stay \"on now\" long enough\n * to look at.\n */\n\nconst TODAY = '2026-08-11';\nconst at = (time: string) => `${TODAY}T${time}:00.000Z`;\n\nfunction mkBooking(b: Partial<BookingItem> & { id: string }): BookingItem {\n return {\n tenantId: 'demo',\n type: 'resource',\n date: TODAY,\n quantity: 1,\n createdAt: at('08:00'),\n updatedAt: at('08:00'),\n ...b,\n } as BookingItem;\n}\n\n/**\n * A day in progress, not a day that has not started: something running now,\n * something due next, an arrival still to check in, and one already finished.\n * A board where every row is \"upcoming\" never shows the state an operator is\n * actually standing in front of.\n */\nexport const DEMO_TODAY_BOOKINGS: BookingItem[] = [\n mkBooking({\n id: 'demo-t1',\n bookingNumber: 'BK-4101',\n customerName: 'Ifeanyi Obi',\n customerPhone: '+2348031120945',\n status: 'checked_in',\n resourceId: 'demo-r1',\n resourceName: 'Ada',\n startTime: '09:00',\n endTime: '10:00',\n checkedInAt: at('09:02'),\n data: { isPaid: true, total: 24000 },\n }),\n mkBooking({\n id: 'demo-t2',\n bookingNumber: 'BK-4102',\n customerName: 'Chidinma Eze',\n customerPhone: '+2348024410982',\n status: 'confirmed',\n resourceId: 'demo-r1',\n resourceName: 'Ada',\n startTime: '10:00',\n endTime: '11:00',\n data: { isPaid: true, total: 24000 },\n }),\n mkBooking({\n id: 'demo-t3',\n bookingNumber: 'BK-4103',\n customerName: 'Tunde Bakare',\n customerPhone: '+2347066120114',\n status: 'confirmed',\n resourceId: 'demo-r2',\n resourceName: 'Ngozi',\n startTime: '10:00',\n endTime: '11:30',\n // Unpaid and about to start: the row the board exists to surface.\n data: { isPaid: false, total: 36000 },\n }),\n mkBooking({\n id: 'demo-t4',\n bookingNumber: 'BK-4104',\n customerName: 'Amaka Nwosu',\n status: 'completed',\n resourceId: 'demo-r2',\n resourceName: 'Ngozi',\n startTime: '07:00',\n endTime: '08:00',\n checkedInAt: at('07:01'),\n data: { isPaid: true, total: 24000 },\n }),\n mkBooking({\n id: 'demo-t5',\n bookingNumber: 'BK-4105',\n customerName: 'Zainab Musa',\n customerPhone: '+2348139902411',\n status: 'confirmed',\n // No resource. Deliberately: a booking against nothing has to land in the\n // Unassigned lane, and that lane is the one nobody notices is missing.\n startTime: '12:00',\n endTime: '13:00',\n data: { isPaid: true, total: 24000 },\n }),\n];\n\n/** The lanes the board draws, whether or not anything is booked into them. */\nexport const DEMO_TODAY_RESOURCES = [\n { id: 'demo-r1', name: 'Ada', isActive: true },\n { id: 'demo-r2', name: 'Ngozi', isActive: true },\n { id: 'demo-r3', name: 'Tunde', isActive: true },\n];\n\n/** Who is waiting for a slot to come free today. */\nexport const DEMO_TODAY_QUEUE: WaitlistItem[] = [\n {\n id: 'demo-q1',\n tenantId: 'demo',\n customerName: 'Segun Adeyemi',\n customerEmail: 'segun.a@gmail.com',\n customerPhone: '+2348090011223',\n requestedDate: TODAY,\n requestedStartTime: '18:00',\n requestedEndTime: '19:00',\n status: 'waiting',\n position: 1,\n priority: 'high',\n createdAt: at('08:15'),\n updatedAt: at('08:15'),\n } as unknown as WaitlistItem,\n {\n id: 'demo-q2',\n tenantId: 'demo',\n customerName: 'Ngozi Umeh',\n customerEmail: 'ngozi.umeh@gmail.com',\n requestedDate: TODAY,\n requestedStartTime: '18:00',\n requestedEndTime: '19:00',\n status: 'waiting',\n position: 2,\n priority: 'normal',\n createdAt: at('09:40'),\n updatedAt: at('09:40'),\n } as unknown as WaitlistItem,\n];\n\n/**\n * One open tab, so the dine-in lane shows a running bill rather than the empty\n * state. Only dine-in fetches these, so only dine-in sees them.\n */\nexport const DEMO_TODAY_TABS = [\n {\n id: 'demo-tab1',\n tenantId: 'demo',\n tableLabel: 'Ada',\n customerName: 'Ifeanyi Obi',\n status: 'open',\n currency: 'NGN',\n total: 18500,\n items: [\n { contentId: 'demo-m1', title: 'Chapman', quantity: 2, unitPrice: 4500 },\n {\n contentId: 'demo-m2',\n title: 'Suya Platter',\n quantity: 1,\n unitPrice: 9500,\n },\n ],\n createdAt: at('09:10'),\n updatedAt: at('09:35'),\n },\n];\n"],"mappings":"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","names":[]}
@@ -0,0 +1,128 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useState } from "react";
4
+ import { useAuth } from "@withpotter/lib/auth-context";
5
+ import { shiftNotesApi } from "@withpotter/lib/api/shift-notes";
6
+ import { Button } from "@withpotter/ui-kit/button";
7
+ import { groupByDay } from "@withpotter/lib/group-activity";
8
+ import { Card, Textarea } from "@withpotter/ui-kit";
9
+ function Handover({ place = "head" }) {
10
+ const { tenant } = useAuth();
11
+ const slug = tenant?.slug;
12
+ const [notes, setNotes] = useState([]);
13
+ const [writing, setWriting] = useState(false);
14
+ const [loading, setLoading] = useState(true);
15
+ const [body, setBody] = useState("");
16
+ const [saving, setSaving] = useState(false);
17
+ const [error, setError] = useState(null);
18
+ const load = useCallback(async () => {
19
+ if (!slug) return;
20
+ try {
21
+ const rows = await shiftNotesApi.list(slug);
22
+ setNotes(Array.isArray(rows) ? rows : []);
23
+ } catch {
24
+ setNotes([]);
25
+ } finally {
26
+ setLoading(false);
27
+ }
28
+ }, [slug]);
29
+ useEffect(() => {
30
+ void load();
31
+ }, [load]);
32
+ const save = async () => {
33
+ const text = body.trim();
34
+ if (!slug || !text) return;
35
+ setSaving(true);
36
+ setError(null);
37
+ try {
38
+ await shiftNotesApi.create(slug, text);
39
+ setBody("");
40
+ setWriting(false);
41
+ await load();
42
+ } catch (err) {
43
+ setError(err instanceof Error ? err.message : "Couldn't leave the note");
44
+ } finally {
45
+ setSaving(false);
46
+ }
47
+ };
48
+ if (loading) return null;
49
+ if (!writing && notes.length === 0) {
50
+ if (place === "head") return null;
51
+ return /* @__PURE__ */ jsx(
52
+ "button",
53
+ {
54
+ type: "button",
55
+ onClick: () => setWriting(true),
56
+ className: "w-fit text-sm text-[var(--text-tertiary)] transition-colors hover:text-[var(--text-primary)]",
57
+ children: "Leave a note for the next shift"
58
+ }
59
+ );
60
+ }
61
+ if (place === "foot" && notes.length > 0 && !writing) return null;
62
+ return /* @__PURE__ */ jsxs(Card, { children: [
63
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [
64
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-medium text-[var(--text-primary)]", children: "Handover" }),
65
+ !writing && /* @__PURE__ */ jsx(
66
+ "button",
67
+ {
68
+ type: "button",
69
+ onClick: () => setWriting(true),
70
+ className: "text-xs text-[var(--text-tertiary)] transition-colors hover:text-[var(--text-primary)]",
71
+ children: "Leave a note"
72
+ }
73
+ )
74
+ ] }),
75
+ writing && /* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
76
+ /* @__PURE__ */ jsx(
77
+ Textarea,
78
+ {
79
+ autoFocus: true,
80
+ value: body,
81
+ onChange: (e) => setBody(e.target.value),
82
+ maxLength: 2e3,
83
+ rows: 2,
84
+ placeholder: "What does the next person need to know?",
85
+ className: "resize-none"
86
+ }
87
+ ),
88
+ error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-[var(--error)]", children: error }),
89
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
90
+ /* @__PURE__ */ jsx(
91
+ Button,
92
+ {
93
+ onClick: () => void save(),
94
+ loading: saving,
95
+ disabled: !body.trim(),
96
+ children: "Leave note"
97
+ }
98
+ ),
99
+ /* @__PURE__ */ jsx(
100
+ Button,
101
+ {
102
+ variant: "secondary",
103
+ onClick: () => {
104
+ setWriting(false);
105
+ setBody("");
106
+ setError(null);
107
+ },
108
+ children: "Cancel"
109
+ }
110
+ )
111
+ ] })
112
+ ] }),
113
+ notes.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-col gap-3", children: groupByDay(notes).map((group) => /* @__PURE__ */ jsxs("div", { children: [
114
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-2xs font-medium uppercase tracking-wide text-[var(--text-tertiary)]", children: group.label }),
115
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: group.entries.map((note) => /* @__PURE__ */ jsxs("li", { className: "text-sm", children: [
116
+ /* @__PURE__ */ jsx("span", { className: "text-[var(--text-primary)]", children: note.body }),
117
+ note.authorName && /* @__PURE__ */ jsxs("span", { className: "text-[var(--text-tertiary)]", children: [
118
+ " \u2014 ",
119
+ note.authorName
120
+ ] })
121
+ ] }, note.id)) })
122
+ ] }, group.label)) })
123
+ ] });
124
+ }
125
+ export {
126
+ Handover
127
+ };
128
+ //# sourceMappingURL=handover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/dashboard/%28bookings%29/bookings/_components/today/handover.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { useAuth } from '@withpotter/lib/auth-context';\nimport { shiftNotesApi, type ShiftNote } from '@withpotter/lib/api/shift-notes';\nimport { Button } from '@withpotter/ui-kit/button';\nimport { groupByDay } from '@withpotter/lib/group-activity';\nimport { Card, Textarea } from '@withpotter/ui-kit';\n\n/**\n * What the last shift needs the next one to know.\n *\n * The delivery that never came, the customer who will call back, the till that\n * is short. Today this lives in WhatsApp or in nobody's head, and whoever opens\n * up starts by guessing.\n *\n * It sits at the TOP of Today, above the day's board. A handover read after you\n * have already started is a handover you did not get — the whole value is that\n * it is the first thing on the screen you open at the beginning of a shift.\n *\n * NOTHING SAID, NOTHING DRAWN. This used to render a full-width card whose\n * entire content was the sentence \"Nothing from the last shift.\" — the largest\n * block on the screen, spending the top of the day on an absence, on every\n * morning nobody had left a note. The comment above it even said \"no empty card\n * at the top of a busy screen\", which was only honoured while loading.\n *\n * So the card IS the notes. With none, this is one line of tertiary text — the\n * door, and nothing but the door — and `place=\"foot\"` puts that line at the\n * BOTTOM of the day, under the board.\n *\n * The two jobs have two homes and it took John asking whether the line was\n * needed at all to see why. READING a handover has to happen before you start,\n * so a note that exists sits above the board. WRITING one happens at the end of\n * a shift, when the day is behind you — offering it above the board is offering\n * it at the one moment nobody wants it, and it was the second line of a screen\n * whose first line was already an absence.\n *\n * Deliberately not a thread, a task list or an assignment. One note, from one\n * person, for whoever is on next. See the api migration for the full argument.\n */\nexport function Handover({ place = 'head' }: { place?: 'head' | 'foot' }) {\n const { tenant } = useAuth();\n const slug = tenant?.slug;\n\n const [notes, setNotes] = useState<ShiftNote[]>([]);\n const [writing, setWriting] = useState(false);\n const [loading, setLoading] = useState(true);\n const [body, setBody] = useState('');\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const load = useCallback(async () => {\n if (!slug) return;\n try {\n const rows = await shiftNotesApi.list(slug);\n setNotes(Array.isArray(rows) ? rows : []);\n } catch {\n // A handover that cannot load must not take the day's board down with\n // it. Silence here, and the section simply does not render.\n setNotes([]);\n } finally {\n setLoading(false);\n }\n }, [slug]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const save = async () => {\n const text = body.trim();\n if (!slug || !text) return;\n setSaving(true);\n setError(null);\n try {\n await shiftNotesApi.create(slug, text);\n setBody('');\n setWriting(false);\n await load();\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Couldn't leave the note\");\n } finally {\n setSaving(false);\n }\n };\n\n // Nothing to say and nothing said: no card at all. The day starts on the\n // board, not on a panel reporting an absence — just the door, one line high.\n if (loading) return null;\n if (!writing && notes.length === 0) {\n // The door only, and only at the foot: at the head of the day it was a\n // control offering the one thing nobody does at the start of a shift.\n if (place === 'head') return null;\n return (\n <button\n type=\"button\"\n onClick={() => setWriting(true)}\n className=\"w-fit text-sm text-[var(--text-tertiary)] transition-colors hover:text-[var(--text-primary)]\"\n >\n Leave a note for the next shift\n </button>\n );\n }\n\n // A note being written, or notes to read: the card, wherever it was placed.\n if (place === 'foot' && notes.length > 0 && !writing) return null;\n\n return (\n <Card>\n <div className=\"flex items-baseline justify-between gap-3\">\n <h2 className=\"text-sm font-medium text-[var(--text-primary)]\">\n Handover\n </h2>\n {!writing && (\n <button\n type=\"button\"\n onClick={() => setWriting(true)}\n className=\"text-xs text-[var(--text-tertiary)] transition-colors hover:text-[var(--text-primary)]\"\n >\n Leave a note\n </button>\n )}\n </div>\n\n {writing && (\n <div className=\"mt-3\">\n <Textarea\n autoFocus\n value={body}\n onChange={(e) => setBody(e.target.value)}\n maxLength={2000}\n rows={2}\n placeholder=\"What does the next person need to know?\"\n className=\"resize-none\"\n />\n {error && <p className=\"mt-1 text-xs text-[var(--error)]\">{error}</p>}\n <div className=\"mt-2 flex items-center gap-2\">\n <Button\n onClick={() => void save()}\n loading={saving}\n disabled={!body.trim()}\n >\n Leave note\n </Button>\n <Button\n variant=\"secondary\"\n onClick={() => {\n setWriting(false);\n setBody('');\n setError(null);\n }}\n >\n Cancel\n </Button>\n </div>\n </div>\n )}\n\n {notes.length > 0 && (\n <div className=\"mt-3 flex flex-col gap-3\">\n {groupByDay(notes).map((group) => (\n <div key={group.label}>\n <p className=\"mb-1 text-2xs font-medium uppercase tracking-wide text-[var(--text-tertiary)]\">\n {group.label}\n </p>\n <ul className=\"flex flex-col gap-2\">\n {group.entries.map((note) => (\n <li key={note.id} className=\"text-sm\">\n <span className=\"text-[var(--text-primary)]\">\n {note.body}\n </span>\n {note.authorName && (\n <span className=\"text-[var(--text-tertiary)]\">\n {' — '}\n {note.authorName}\n </span>\n )}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n )}\n </Card>\n );\n}\n"],"mappings":";AA8FM,cAeA,YAfA;AA5FN,SAAS,aAAa,WAAW,gBAAgB;AACjD,SAAS,eAAe;AACxB,SAAS,qBAAqC;AAC9C,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,MAAM,gBAAgB;AAiCxB,SAAS,SAAS,EAAE,QAAQ,OAAO,GAAgC;AACxE,QAAM,EAAE,OAAO,IAAI,QAAQ;AAC3B,QAAM,OAAO,QAAQ;AAErB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAsB,CAAC,CAAC;AAClD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,QAAM,OAAO,YAAY,YAAY;AACnC,QAAI,CAAC,KAAM;AACX,QAAI;AACF,YAAM,OAAO,MAAM,cAAc,KAAK,IAAI;AAC1C,eAAS,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,CAAC;AAAA,IAC1C,QAAQ;AAGN,eAAS,CAAC,CAAC;AAAA,IACb,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,YAAU,MAAM;AACd,SAAK,KAAK;AAAA,EACZ,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,OAAO,YAAY;AACvB,UAAM,OAAO,KAAK,KAAK;AACvB,QAAI,CAAC,QAAQ,CAAC,KAAM;AACpB,cAAU,IAAI;AACd,aAAS,IAAI;AACb,QAAI;AACF,YAAM,cAAc,OAAO,MAAM,IAAI;AACrC,cAAQ,EAAE;AACV,iBAAW,KAAK;AAChB,YAAM,KAAK;AAAA,IACb,SAAS,KAAK;AACZ,eAAS,eAAe,QAAQ,IAAI,UAAU,yBAAyB;AAAA,IACzE,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAIA,MAAI,QAAS,QAAO;AACpB,MAAI,CAAC,WAAW,MAAM,WAAW,GAAG;AAGlC,QAAI,UAAU,OAAQ,QAAO;AAC7B,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,WAAW,IAAI;AAAA,QAC9B,WAAU;AAAA,QACX;AAAA;AAAA,IAED;AAAA,EAEJ;AAGA,MAAI,UAAU,UAAU,MAAM,SAAS,KAAK,CAAC,QAAS,QAAO;AAE7D,SACE,qBAAC,QACC;AAAA,yBAAC,SAAI,WAAU,6CACb;AAAA,0BAAC,QAAG,WAAU,kDAAiD,sBAE/D;AAAA,MACC,CAAC,WACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM,WAAW,IAAI;AAAA,UAC9B,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,OAEJ;AAAA,IAEC,WACC,qBAAC,SAAI,WAAU,QACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAS;AAAA,UACT,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,QAAQ,EAAE,OAAO,KAAK;AAAA,UACvC,WAAW;AAAA,UACX,MAAM;AAAA,UACN,aAAY;AAAA,UACZ,WAAU;AAAA;AAAA,MACZ;AAAA,MACC,SAAS,oBAAC,OAAE,WAAU,oCAAoC,iBAAM;AAAA,MACjE,qBAAC,SAAI,WAAU,gCACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,KAAK,KAAK;AAAA,YACzB,SAAS;AAAA,YACT,UAAU,CAAC,KAAK,KAAK;AAAA,YACtB;AAAA;AAAA,QAED;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,SAAS,MAAM;AACb,yBAAW,KAAK;AAChB,sBAAQ,EAAE;AACV,uBAAS,IAAI;AAAA,YACf;AAAA,YACD;AAAA;AAAA,QAED;AAAA,SACF;AAAA,OACF;AAAA,IAGD,MAAM,SAAS,KACd,oBAAC,SAAI,WAAU,4BACZ,qBAAW,KAAK,EAAE,IAAI,CAAC,UACtB,qBAAC,SACC;AAAA,0BAAC,OAAE,WAAU,iFACV,gBAAM,OACT;AAAA,MACA,oBAAC,QAAG,WAAU,uBACX,gBAAM,QAAQ,IAAI,CAAC,SAClB,qBAAC,QAAiB,WAAU,WAC1B;AAAA,4BAAC,UAAK,WAAU,8BACb,eAAK,MACR;AAAA,QACC,KAAK,cACJ,qBAAC,UAAK,WAAU,+BACb;AAAA;AAAA,UACA,KAAK;AAAA,WACR;AAAA,WARK,KAAK,EAUd,CACD,GACH;AAAA,SAlBQ,MAAM,KAmBhB,CACD,GACH;AAAA,KAEJ;AAEJ;","names":[]}
@@ -0,0 +1,17 @@
1
+ import { TodayBand } from "./today-band";
2
+ import { ResourceBoard } from "./resource-board";
3
+ import { BookingCard } from "./booking-card";
4
+ import { WaitingQueue } from "./waiting-queue";
5
+ import { Handover } from "./handover";
6
+ import { UpcomingBand } from "./upcoming-band";
7
+ import { PastBand } from "./past-band";
8
+ export {
9
+ BookingCard,
10
+ Handover,
11
+ PastBand,
12
+ ResourceBoard,
13
+ TodayBand,
14
+ UpcomingBand,
15
+ WaitingQueue
16
+ };
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/dashboard/%28bookings%29/bookings/_components/today/index.ts"],"sourcesContent":["export { TodayBand } from './today-band';\nexport { ResourceBoard } from './resource-board';\nexport { BookingCard } from './booking-card';\nexport { WaitingQueue } from './waiting-queue';\nexport { Handover } from './handover';\nexport { UpcomingBand } from './upcoming-band';\nexport { PastBand } from './past-band';\n"],"mappings":"AAAA,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;","names":[]}
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import Link from "next/link";
4
+ import { useApiQuery } from "@withpotter/hooks/use-api-query";
5
+ import { useLocationScope } from "@withpotter/lib/location-scope-context";
6
+ import { bookingsApi } from "@withpotter/lib/api/bookings";
7
+ import { StatusBadge } from "@withpotter/components/shared/status-badge";
8
+ import { InlineListSkeleton } from "@withpotter/ui-kit/page-skeletons";
9
+ const HORIZON = 8;
10
+ function yesterday() {
11
+ const date = /* @__PURE__ */ new Date();
12
+ date.setDate(date.getDate() - 1);
13
+ return date.toISOString().slice(0, 10);
14
+ }
15
+ function dayKey(iso) {
16
+ return new Date(iso).toLocaleDateString("en-GB", {
17
+ weekday: "long",
18
+ day: "numeric",
19
+ month: "short"
20
+ });
21
+ }
22
+ function timeLabel(booking) {
23
+ if (!booking.startTime) return "No time set";
24
+ const [hourValue, minute] = booking.startTime.split(":").map(Number);
25
+ return `${hourValue % 12 || 12}:${String(minute).padStart(2, "0")} ${hourValue >= 12 ? "pm" : "am"}`;
26
+ }
27
+ function PastBand({ types }) {
28
+ const { locationFilter } = useLocationScope();
29
+ const { data, isLoading } = useApiQuery(
30
+ ["bookings-past", locationFilter, types?.join("+") ?? "all"],
31
+ (slug) => bookingsApi.list(slug, {
32
+ dateTo: yesterday(),
33
+ type: types ? [...types] : void 0,
34
+ sortOrder: "DESC",
35
+ limit: HORIZON,
36
+ locationIds: locationFilter
37
+ })
38
+ );
39
+ const bookings = data?.data ?? [];
40
+ if (isLoading) return /* @__PURE__ */ jsx(InlineListSkeleton, {});
41
+ if (bookings.length === 0) return null;
42
+ return /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
43
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-[var(--text-primary)]", children: "Past appointments" }),
44
+ /* @__PURE__ */ jsx("div", { className: "surface divide-y divide-[var(--border-subtle)]", children: bookings.map((booking) => /* @__PURE__ */ jsxs(
45
+ "div",
46
+ {
47
+ className: "flex items-center gap-3 px-3 py-2 transition-colors hover:bg-[var(--interactive-hover)]",
48
+ children: [
49
+ /* @__PURE__ */ jsx("span", { className: "w-24 shrink-0 text-xs text-[var(--text-tertiary)]", children: dayKey(booking.date) }),
50
+ /* @__PURE__ */ jsx("span", { className: "w-20 shrink-0 text-sm tabular-nums text-[var(--text-secondary)]", children: timeLabel(booking) }),
51
+ /* @__PURE__ */ jsx(
52
+ Link,
53
+ {
54
+ href: `/dashboard/bookings/${booking.id}`,
55
+ className: "min-w-0 flex-1 truncate text-sm font-medium text-[var(--text-primary)]",
56
+ children: booking.customerName || "Guest"
57
+ }
58
+ ),
59
+ /* @__PURE__ */ jsx(StatusBadge, { neutral: true, status: booking.status })
60
+ ]
61
+ },
62
+ booking.id
63
+ )) })
64
+ ] });
65
+ }
66
+ export {
67
+ PastBand
68
+ };
69
+ //# sourceMappingURL=past-band.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/dashboard/%28bookings%29/bookings/_components/today/past-band.tsx"],"sourcesContent":["'use client';\n\nimport Link from 'next/link';\nimport { useApiQuery } from '@withpotter/hooks/use-api-query';\nimport { useLocationScope } from '@withpotter/lib/location-scope-context';\nimport { bookingsApi } from '@withpotter/lib/api/bookings';\nimport type { BookingItem } from '@withpotter/lib/api/types';\nimport { StatusBadge } from '@withpotter/components/shared/status-badge';\nimport { InlineListSkeleton } from '@withpotter/ui-kit/page-skeletons';\n\nconst HORIZON = 8;\n\nfunction yesterday(): string {\n const date = new Date();\n date.setDate(date.getDate() - 1);\n return date.toISOString().slice(0, 10);\n}\n\nfunction dayKey(iso: string): string {\n return new Date(iso).toLocaleDateString('en-GB', {\n weekday: 'long',\n day: 'numeric',\n month: 'short',\n });\n}\n\nfunction timeLabel(booking: BookingItem): string {\n if (!booking.startTime) return 'No time set';\n const [hourValue, minute] = booking.startTime.split(':').map(Number);\n return `${hourValue % 12 || 12}:${String(minute).padStart(2, '0')} ${\n hourValue >= 12 ? 'pm' : 'am'\n }`;\n}\n\nexport function PastBand({ types }: { types?: readonly string[] }) {\n const { locationFilter } = useLocationScope();\n const { data, isLoading } = useApiQuery(\n ['bookings-past', locationFilter, types?.join('+') ?? 'all'],\n (slug) =>\n bookingsApi.list(slug, {\n dateTo: yesterday(),\n type: types ? [...types] : undefined,\n sortOrder: 'DESC',\n limit: HORIZON,\n locationIds: locationFilter,\n }),\n );\n\n const bookings = data?.data ?? [];\n if (isLoading) return <InlineListSkeleton />;\n if (bookings.length === 0) return null;\n\n return (\n <section className=\"space-y-3\">\n <h2 className=\"text-sm font-semibold text-[var(--text-primary)]\">\n Past appointments\n </h2>\n <div className=\"surface divide-y divide-[var(--border-subtle)]\">\n {bookings.map((booking) => (\n <div\n key={booking.id}\n className=\"flex items-center gap-3 px-3 py-2 transition-colors hover:bg-[var(--interactive-hover)]\"\n >\n <span className=\"w-24 shrink-0 text-xs text-[var(--text-tertiary)]\">\n {dayKey(booking.date)}\n </span>\n <span className=\"w-20 shrink-0 text-sm tabular-nums text-[var(--text-secondary)]\">\n {timeLabel(booking)}\n </span>\n <Link\n href={`/dashboard/bookings/${booking.id}`}\n className=\"min-w-0 flex-1 truncate text-sm font-medium text-[var(--text-primary)]\"\n >\n {booking.customerName || 'Guest'}\n </Link>\n <StatusBadge neutral status={booking.status} />\n </div>\n ))}\n </div>\n </section>\n );\n}\n"],"mappings":";AAiDwB,cAUd,YAVc;AA/CxB,OAAO,UAAU;AACjB,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AAEnC,MAAM,UAAU;AAEhB,SAAS,YAAoB;AAC3B,QAAM,OAAO,oBAAI,KAAK;AACtB,OAAK,QAAQ,KAAK,QAAQ,IAAI,CAAC;AAC/B,SAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE;AACvC;AAEA,SAAS,OAAO,KAAqB;AACnC,SAAO,IAAI,KAAK,GAAG,EAAE,mBAAmB,SAAS;AAAA,IAC/C,SAAS;AAAA,IACT,KAAK;AAAA,IACL,OAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,UAAU,SAA8B;AAC/C,MAAI,CAAC,QAAQ,UAAW,QAAO;AAC/B,QAAM,CAAC,WAAW,MAAM,IAAI,QAAQ,UAAU,MAAM,GAAG,EAAE,IAAI,MAAM;AACnE,SAAO,GAAG,YAAY,MAAM,EAAE,IAAI,OAAO,MAAM,EAAE,SAAS,GAAG,GAAG,CAAC,IAC/D,aAAa,KAAK,OAAO,IAC3B;AACF;AAEO,SAAS,SAAS,EAAE,MAAM,GAAkC;AACjE,QAAM,EAAE,eAAe,IAAI,iBAAiB;AAC5C,QAAM,EAAE,MAAM,UAAU,IAAI;AAAA,IAC1B,CAAC,iBAAiB,gBAAgB,OAAO,KAAK,GAAG,KAAK,KAAK;AAAA,IAC3D,CAAC,SACC,YAAY,KAAK,MAAM;AAAA,MACrB,QAAQ,UAAU;AAAA,MAClB,MAAM,QAAQ,CAAC,GAAG,KAAK,IAAI;AAAA,MAC3B,WAAW;AAAA,MACX,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,EACL;AAEA,QAAM,WAAW,MAAM,QAAQ,CAAC;AAChC,MAAI,UAAW,QAAO,oBAAC,sBAAmB;AAC1C,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,SACE,qBAAC,aAAQ,WAAU,aACjB;AAAA,wBAAC,QAAG,WAAU,oDAAmD,+BAEjE;AAAA,IACA,oBAAC,SAAI,WAAU,kDACZ,mBAAS,IAAI,CAAC,YACb;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QAEV;AAAA,8BAAC,UAAK,WAAU,qDACb,iBAAO,QAAQ,IAAI,GACtB;AAAA,UACA,oBAAC,UAAK,WAAU,mEACb,oBAAU,OAAO,GACpB;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,uBAAuB,QAAQ,EAAE;AAAA,cACvC,WAAU;AAAA,cAET,kBAAQ,gBAAgB;AAAA;AAAA,UAC3B;AAAA,UACA,oBAAC,eAAY,SAAO,MAAC,QAAQ,QAAQ,QAAQ;AAAA;AAAA;AAAA,MAfxC,QAAQ;AAAA,IAgBf,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,111 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import Link from "next/link";
4
+ import { CalendarClock, Receipt } from "lucide-react";
5
+ import { EmptyNote, StateView } from "@withpotter/ui-kit";
6
+ import { BookingCard } from "./booking-card";
7
+ const COLUMNS = {
8
+ 1: "grid gap-4",
9
+ 2: "grid gap-4 sm:grid-cols-2",
10
+ 3: "grid gap-4 sm:grid-cols-2 2xl:grid-cols-3"
11
+ };
12
+ const MANY_COLUMNS = "grid gap-4 sm:grid-cols-2 2xl:grid-cols-4";
13
+ function OpenTab({
14
+ openTab,
15
+ formatCurrency
16
+ }) {
17
+ return /* @__PURE__ */ jsxs(
18
+ Link,
19
+ {
20
+ href: "/dashboard/tabs",
21
+ className: "flex items-center justify-between gap-2 rounded-lg border border-[var(--border-default)] bg-[var(--bg-subtle)] px-3 py-2 transition-colors hover:bg-[var(--interactive-hover)]",
22
+ children: [
23
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-xs text-[var(--text-secondary)]", children: [
24
+ /* @__PURE__ */ jsx(Receipt, {}),
25
+ "Open tab",
26
+ openTab.itemCount > 0 ? ` \xB7 ${openTab.itemCount}` : null
27
+ ] }),
28
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold tabular-nums text-[var(--text-primary)]", children: formatCurrency(openTab.total, openTab.currency) })
29
+ ]
30
+ }
31
+ );
32
+ }
33
+ function Column({
34
+ title,
35
+ count,
36
+ openTab,
37
+ formatCurrency,
38
+ children
39
+ }) {
40
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
41
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-1", children: [
42
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-[var(--text-primary)]", children: title }),
43
+ /* @__PURE__ */ jsx("span", { className: "text-2xs tabular-nums text-[var(--text-tertiary)]", children: count })
44
+ ] }),
45
+ openTab ? /* @__PURE__ */ jsx(OpenTab, { openTab, formatCurrency }) : null,
46
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children })
47
+ ] });
48
+ }
49
+ function ResourceBoard({
50
+ lanes,
51
+ formatCurrency,
52
+ pendingId,
53
+ pendingAction,
54
+ onCheckIn,
55
+ onRecordPayment,
56
+ onNoShow
57
+ }) {
58
+ const card = (b) => /* @__PURE__ */ jsx(
59
+ BookingCard,
60
+ {
61
+ booking: b,
62
+ formatCurrency,
63
+ pending: pendingId === b.id ? pendingAction : null,
64
+ onCheckIn: () => onCheckIn(b),
65
+ onRecordPayment: () => onRecordPayment(b),
66
+ onNoShow: () => onNoShow(b)
67
+ },
68
+ b.id
69
+ );
70
+ const bookings = lanes.flatMap((lane) => lane.bookings);
71
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
72
+ /* @__PURE__ */ jsx("div", { className: "space-y-3 lg:hidden", children: bookings.length > 0 ? bookings.map(card) : /* @__PURE__ */ jsx(
73
+ StateView,
74
+ {
75
+ kind: "empty",
76
+ icon: CalendarClock,
77
+ title: "Nothing scheduled today",
78
+ description: "Your day is clear. Add an appointment or check upcoming bookings.",
79
+ action: {
80
+ label: "Add appointment",
81
+ href: "/dashboard/bookings/new"
82
+ }
83
+ }
84
+ ) }),
85
+ /* @__PURE__ */ jsx(
86
+ "div",
87
+ {
88
+ className: `hidden lg:block ${COLUMNS[lanes.length] ?? MANY_COLUMNS}`,
89
+ children: lanes.map((lane) => /* @__PURE__ */ jsx(
90
+ Column,
91
+ {
92
+ title: lane.title,
93
+ count: lane.bookings.length,
94
+ openTab: lane.openTab,
95
+ formatCurrency,
96
+ children: lane.bookings.length ? lane.bookings.map(card) : (
97
+ /* One lane quiet on a day that is not: a line, not a box the
98
+ height of the cards beside it. */
99
+ /* @__PURE__ */ jsx(EmptyNote, { well: true, className: "py-4", children: "No bookings today" })
100
+ )
101
+ },
102
+ lane.id
103
+ ))
104
+ }
105
+ )
106
+ ] });
107
+ }
108
+ export {
109
+ ResourceBoard
110
+ };
111
+ //# sourceMappingURL=resource-board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/dashboard/%28bookings%29/bookings/_components/today/resource-board.tsx"],"sourcesContent":["'use client';\n\nimport Link from 'next/link';\nimport { CalendarClock, Receipt } from 'lucide-react';\nimport type { BookingItem } from '@withpotter/lib/api/types';\nimport { EmptyNote, StateView } from '@withpotter/ui-kit';\nimport type { DayLane } from '../../_hooks/use-today-data';\nimport { BookingCard } from './booking-card';\n\ntype Pending = 'checkin' | 'payment' | 'noshow' | null;\n\ntype FormatCurrency = (n: number, currency?: string) => string;\n\n/**\n * The board follows the day, not a fixed four.\n *\n * `xl:grid-cols-4` was hardcoded, so a business with two chairs drew its day in\n * the left half of the screen with a void to the right of it — the columns did\n * not read as \"these are your two chairs\", they read as two of four things\n * having failed to load.\n */\nconst COLUMNS: Record<number, string> = {\n 1: 'grid gap-4',\n 2: 'grid gap-4 sm:grid-cols-2',\n 3: 'grid gap-4 sm:grid-cols-2 2xl:grid-cols-3',\n};\nconst MANY_COLUMNS = 'grid gap-4 sm:grid-cols-2 2xl:grid-cols-4';\n\nfunction OpenTab({\n openTab,\n formatCurrency,\n}: {\n openTab: NonNullable<DayLane['openTab']>;\n formatCurrency: FormatCurrency;\n}) {\n return (\n <Link\n href=\"/dashboard/tabs\"\n className=\"flex items-center justify-between gap-2 rounded-lg border border-[var(--border-default)] bg-[var(--bg-subtle)] px-3 py-2 transition-colors hover:bg-[var(--interactive-hover)]\"\n >\n <span className=\"flex items-center gap-2 text-xs text-[var(--text-secondary)]\">\n <Receipt />\n Open tab\n {openTab.itemCount > 0 ? ` · ${openTab.itemCount}` : null}\n </span>\n <span className=\"text-xs font-semibold tabular-nums text-[var(--text-primary)]\">\n {formatCurrency(openTab.total, openTab.currency)}\n </span>\n </Link>\n );\n}\n\nfunction Column({\n title,\n count,\n openTab,\n formatCurrency,\n children,\n}: {\n title: string;\n count: number;\n openTab?: DayLane['openTab'];\n formatCurrency: FormatCurrency;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between px-1\">\n <h3 className=\"text-sm font-semibold text-[var(--text-primary)]\">\n {title}\n </h3>\n <span className=\"text-2xs tabular-nums text-[var(--text-tertiary)]\">\n {count}\n </span>\n </div>\n\n {/* A table can be reserved and be running a bill at the same time. The\n bill is the part that walks out of the door, so it sits on the lane\n rather than one screen away in Tabs. */}\n {openTab ? (\n <OpenTab openTab={openTab} formatCurrency={formatCurrency} />\n ) : null}\n\n <div className=\"flex flex-col gap-2\">{children}</div>\n </div>\n );\n}\n\n/**\n * The day, in columns.\n *\n * What a column IS comes from the hook, not from here: a court, a table, a\n * stylist, or a stretch of the afternoon for a business whose bookings are not\n * resource-backed. This renders whatever it is handed, which is why a short-let\n * operator now sees their day at all.\n */\nexport function ResourceBoard({\n lanes,\n formatCurrency,\n pendingId,\n pendingAction,\n onCheckIn,\n onRecordPayment,\n onNoShow,\n}: {\n lanes: DayLane[];\n formatCurrency: FormatCurrency;\n pendingId: string | null;\n pendingAction: Pending;\n onCheckIn: (b: BookingItem) => void;\n onRecordPayment: (b: BookingItem) => void;\n onNoShow: (b: BookingItem) => void;\n}) {\n const card = (b: BookingItem) => (\n <BookingCard\n key={b.id}\n booking={b}\n formatCurrency={formatCurrency}\n pending={pendingId === b.id ? pendingAction : null}\n onCheckIn={() => onCheckIn(b)}\n onRecordPayment={() => onRecordPayment(b)}\n onNoShow={() => onNoShow(b)}\n />\n );\n const bookings = lanes.flatMap((lane) => lane.bookings);\n\n return (\n <>\n <div className=\"space-y-3 lg:hidden\">\n {bookings.length > 0 ? (\n bookings.map(card)\n ) : (\n <StateView\n kind=\"empty\"\n icon={CalendarClock}\n title=\"Nothing scheduled today\"\n description=\"Your day is clear. Add an appointment or check upcoming bookings.\"\n action={{\n label: 'Add appointment',\n href: '/dashboard/bookings/new',\n }}\n />\n )}\n </div>\n <div\n className={`hidden lg:block ${COLUMNS[lanes.length] ?? MANY_COLUMNS}`}\n >\n {lanes.map((lane) => (\n <Column\n key={lane.id}\n title={lane.title}\n count={lane.bookings.length}\n openTab={lane.openTab}\n formatCurrency={formatCurrency}\n >\n {lane.bookings.length ? (\n lane.bookings.map(card)\n ) : (\n /* One lane quiet on a day that is not: a line, not a box the\n height of the cards beside it. */\n <EmptyNote well className=\"py-4\">\n No bookings today\n </EmptyNote>\n )}\n </Column>\n ))}\n </div>\n </>\n );\n}\n"],"mappings":";AAwCM,SAuFF,UAtFI,KADF;AAtCN,OAAO,UAAU;AACjB,SAAS,eAAe,eAAe;AAEvC,SAAS,WAAW,iBAAiB;AAErC,SAAS,mBAAmB;AAc5B,MAAM,UAAkC;AAAA,EACtC,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,eAAe;AAErB,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AACF,GAGG;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MAEV;AAAA,6BAAC,UAAK,WAAU,gEACd;AAAA,8BAAC,WAAQ;AAAA,UAAE;AAAA,UAEV,QAAQ,YAAY,IAAI,SAAM,QAAQ,SAAS,KAAK;AAAA,WACvD;AAAA,QACA,oBAAC,UAAK,WAAU,iEACb,yBAAe,QAAQ,OAAO,QAAQ,QAAQ,GACjD;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE,qBAAC,SAAI,WAAU,uBACb;AAAA,yBAAC,SAAI,WAAU,0CACb;AAAA,0BAAC,QAAG,WAAU,oDACX,iBACH;AAAA,MACA,oBAAC,UAAK,WAAU,qDACb,iBACH;AAAA,OACF;AAAA,IAKC,UACC,oBAAC,WAAQ,SAAkB,gBAAgC,IACzD;AAAA,IAEJ,oBAAC,SAAI,WAAU,uBAAuB,UAAS;AAAA,KACjD;AAEJ;AAUO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,QAAM,OAAO,CAAC,MACZ;AAAA,IAAC;AAAA;AAAA,MAEC,SAAS;AAAA,MACT;AAAA,MACA,SAAS,cAAc,EAAE,KAAK,gBAAgB;AAAA,MAC9C,WAAW,MAAM,UAAU,CAAC;AAAA,MAC5B,iBAAiB,MAAM,gBAAgB,CAAC;AAAA,MACxC,UAAU,MAAM,SAAS,CAAC;AAAA;AAAA,IANrB,EAAE;AAAA,EAOT;AAEF,QAAM,WAAW,MAAM,QAAQ,CAAC,SAAS,KAAK,QAAQ;AAEtD,SACE,iCACE;AAAA,wBAAC,SAAI,WAAU,uBACZ,mBAAS,SAAS,IACjB,SAAS,IAAI,IAAI,IAEjB;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,MAAM;AAAA,QACN,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,QAAQ;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA;AAAA,IACF,GAEJ;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,mBAAmB,QAAQ,MAAM,MAAM,KAAK,YAAY;AAAA,QAElE,gBAAM,IAAI,CAAC,SACV;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO,KAAK;AAAA,YACZ,OAAO,KAAK,SAAS;AAAA,YACrB,SAAS,KAAK;AAAA,YACd;AAAA,YAEC,eAAK,SAAS,SACb,KAAK,SAAS,IAAI,IAAI;AAAA;AAAA;AAAA,cAItB,oBAAC,aAAU,MAAI,MAAC,WAAU,QAAO,+BAEjC;AAAA;AAAA;AAAA,UAbG,KAAK;AAAA,QAeZ,CACD;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { LiveDot } from "@withpotter/ui-kit/live-dot";
4
+ import { RollingNumber } from "@withpotter/ui-kit/rolling-number";
5
+ const TONE = {
6
+ neutral: "text-[var(--text-primary)]",
7
+ warning: "text-[var(--warning)]",
8
+ info: "text-[var(--info)]"
9
+ };
10
+ function TodayBand({
11
+ onNow,
12
+ dueNext,
13
+ awaitingPayment,
14
+ toCheckIn,
15
+ stays
16
+ }) {
17
+ const readings = stays ? [
18
+ { key: "in", value: stays.arrivals, label: "arriving", tone: "info" },
19
+ { key: "out", value: stays.departures, label: "leaving", tone: "info" },
20
+ { key: "stay", value: stays.inHouse, label: "still in", live: true },
21
+ {
22
+ key: "owed",
23
+ value: awaitingPayment,
24
+ label: "awaiting payment",
25
+ tone: "warning"
26
+ }
27
+ ] : [
28
+ { key: "now", value: onNow, label: "on now", live: true },
29
+ { key: "due", value: dueNext, label: "due in 2 hours" },
30
+ {
31
+ key: "owed",
32
+ value: awaitingPayment,
33
+ label: "awaiting payment",
34
+ tone: "warning"
35
+ },
36
+ {
37
+ key: "in",
38
+ value: toCheckIn,
39
+ label: "to check in",
40
+ tone: "info"
41
+ }
42
+ ];
43
+ const shown = readings.filter((r) => r.value > 0);
44
+ if (shown.length === 0) return null;
45
+ return /* @__PURE__ */ jsx("p", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-sm text-[var(--text-tertiary)]", children: shown.map((r) => /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
46
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-[var(--text-muted)]", children: "\xB7" }),
47
+ r.live && /* @__PURE__ */ jsx(LiveDot, {}),
48
+ /* @__PURE__ */ jsx(
49
+ "span",
50
+ {
51
+ className: `font-medium tabular-nums ${TONE[r.tone ?? "neutral"]}`,
52
+ children: /* @__PURE__ */ jsx(RollingNumber, { value: r.value })
53
+ }
54
+ ),
55
+ r.label
56
+ ] }, r.key)) });
57
+ }
58
+ export {
59
+ TodayBand
60
+ };
61
+ //# sourceMappingURL=today-band.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/dashboard/%28bookings%29/bookings/_components/today/today-band.tsx"],"sourcesContent":["'use client';\n\nimport { LiveDot } from '@withpotter/ui-kit/live-dot';\nimport { RollingNumber } from '@withpotter/ui-kit/rolling-number';\n\ntype Tone = 'neutral' | 'warning' | 'info';\n\nconst TONE: Record<Tone, string> = {\n neutral: 'text-[var(--text-primary)]',\n warning: 'text-[var(--warning)]',\n info: 'text-[var(--info)]',\n};\n\ninterface Reading {\n key: string;\n value: number;\n label: string;\n tone?: Tone;\n /** The pulse, for the one reading that is about this exact minute. */\n live?: boolean;\n}\n\n/**\n * What the desk is watching, as a line rather than as four cards.\n *\n * THE ZEROS WERE THE BUG. This was a grid of four `surface` tiles, each with an\n * icon, a 20px figure and a caption, and it drew all four whether or not there\n * was anything to report — so the quietest possible morning opened on four\n * cards shouting 0, above a board of dashed empty boxes. A screen that looks\n * equally loud when nothing is happening cannot tell you that something is.\n *\n * So a reading with no number is not drawn, and a day with no readings at all\n * draws nothing: the same rule the home band already follows (\"it disappears at\n * zero\"), and the same shape, because \"somebody is on your site\" and \"two are\n * on court\" are the same sentence on two screens. A tile is for a figure you\n * compare; these are facts about right now, and a fact is a line of text.\n *\n * IT CONTINUES THE DAY ROW'S SENTENCE, which is why every reading carries its\n * own leading separator: \"Monday, August 24 · 2 on now · 1 awaiting payment\".\n * The date says which day, the readings say what is true on it, and they are\n * one line because they are one thought.\n *\n * WHAT THE DESK WATCHES is not one question for every business. A salon or a\n * court reads the clock: what is running, what is due shortly. A property reads\n * the door: who arrives, who leaves, who is still in — the clock reading is not\n * merely less useful for a stay, it is unanswerable, because \"on now\" compares\n * clock minutes and a stay crosses midnight. Money owed survives both readings.\n */\nexport function TodayBand({\n onNow,\n dueNext,\n awaitingPayment,\n toCheckIn,\n stays,\n}: {\n onNow: number;\n dueNext: number;\n awaitingPayment: number;\n toCheckIn: number;\n /** Present when the day contains bookings spanning more than one date. */\n stays?: { arrivals: number; departures: number; inHouse: number };\n}) {\n const readings: Reading[] = stays\n ? [\n { key: 'in', value: stays.arrivals, label: 'arriving', tone: 'info' },\n { key: 'out', value: stays.departures, label: 'leaving', tone: 'info' },\n { key: 'stay', value: stays.inHouse, label: 'still in', live: true },\n {\n key: 'owed',\n value: awaitingPayment,\n label: 'awaiting payment',\n tone: 'warning',\n },\n ]\n : [\n { key: 'now', value: onNow, label: 'on now', live: true },\n { key: 'due', value: dueNext, label: 'due in 2 hours' },\n {\n key: 'owed',\n value: awaitingPayment,\n label: 'awaiting payment',\n tone: 'warning',\n },\n {\n key: 'in',\n value: toCheckIn,\n label: 'to check in',\n tone: 'info',\n },\n ];\n\n const shown = readings.filter((r) => r.value > 0);\n if (shown.length === 0) return null;\n\n return (\n <p className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-sm text-[var(--text-tertiary)]\">\n {shown.map((r) => (\n <span key={r.key} className=\"inline-flex items-center gap-2\">\n <span aria-hidden=\"true\" className=\"text-[var(--text-muted)]\">\n ·\n </span>\n {r.live && <LiveDot />}\n <span\n className={`font-medium tabular-nums ${TONE[r.tone ?? 'neutral']}`}\n >\n <RollingNumber value={r.value} />\n </span>\n {r.label}\n </span>\n ))}\n </p>\n );\n}\n"],"mappings":";AAiGQ,SACE,KADF;AA/FR,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAI9B,MAAM,OAA6B;AAAA,EACjC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR;AAqCO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,WAAsB,QACxB;AAAA,IACE,EAAE,KAAK,MAAM,OAAO,MAAM,UAAU,OAAO,YAAY,MAAM,OAAO;AAAA,IACpE,EAAE,KAAK,OAAO,OAAO,MAAM,YAAY,OAAO,WAAW,MAAM,OAAO;AAAA,IACtE,EAAE,KAAK,QAAQ,OAAO,MAAM,SAAS,OAAO,YAAY,MAAM,KAAK;AAAA,IACnE;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAAA,EACF,IACA;AAAA,IACE,EAAE,KAAK,OAAO,OAAO,OAAO,OAAO,UAAU,MAAM,KAAK;AAAA,IACxD,EAAE,KAAK,OAAO,OAAO,SAAS,OAAO,iBAAiB;AAAA,IACtD;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAAA,EACF;AAEJ,QAAM,QAAQ,SAAS,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;AAChD,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,SACE,oBAAC,OAAE,WAAU,mFACV,gBAAM,IAAI,CAAC,MACV,qBAAC,UAAiB,WAAU,kCAC1B;AAAA,wBAAC,UAAK,eAAY,QAAO,WAAU,4BAA2B,kBAE9D;AAAA,IACC,EAAE,QAAQ,oBAAC,WAAQ;AAAA,IACpB;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,4BAA4B,KAAK,EAAE,QAAQ,SAAS,CAAC;AAAA,QAEhE,8BAAC,iBAAc,OAAO,EAAE,OAAO;AAAA;AAAA,IACjC;AAAA,IACC,EAAE;AAAA,OAVM,EAAE,GAWb,CACD,GACH;AAEJ;","names":[]}