@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.
- package/dist/dashboard/(bookings)/attendees/page.js +8 -0
- package/dist/dashboard/(bookings)/attendees/page.js.map +1 -0
- package/dist/dashboard/(bookings)/availability/_components/availability-screen.js +714 -0
- package/dist/dashboard/(bookings)/availability/_components/availability-screen.js.map +1 -0
- package/dist/dashboard/(bookings)/availability/_components/month-availability.js +130 -0
- package/dist/dashboard/(bookings)/availability/_components/month-availability.js.map +1 -0
- package/dist/dashboard/(bookings)/availability/page.js +10 -0
- package/dist/dashboard/(bookings)/availability/page.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/assign-resource-modal.js +133 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/assign-resource-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-constants.js +26 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-constants.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-desktop-layout.js +194 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-desktop-layout.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-layout-props.js +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-layout-props.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-lede.js +189 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-lede.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-meta.js +38 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-meta.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-layout.js +315 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-layout.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-screen.js +94 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-mobile-screen.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-money.js +54 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-money.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-split.js +71 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/booking-split.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancel-booking-modal.js +102 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancel-booking-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancellation-notice.js +33 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/cancellation-notice.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/customer-info-card.js +65 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/customer-info-card.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/index.js +23 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/index.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/intake-answers-card.js +19 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/intake-answers-card.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/refund-booking-modal.js +156 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/refund-booking-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/reschedule-booking-modal.js +120 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/reschedule-booking-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/security-deposit-card.js +63 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/security-deposit-card.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/settle-deposit-modal.js +141 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/settle-deposit-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/ticket-row-actions.js +49 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/ticket-row-actions.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/waiting-queue-notice.js +42 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components/waiting-queue-notice.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_components.js +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/index.js +19 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/index.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/use-booking-detail-data.js +352 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks/use-booking-detail-data.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/_hooks.js +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/layout.js +33 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/layout.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/page.js +356 -0
- package/dist/dashboard/(bookings)/bookings/[bookingId]/page.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/appointment-calendar-layout.js +34 -0
- package/dist/dashboard/(bookings)/bookings/_components/appointment-calendar-layout.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/booking-constants.js +92 -0
- package/dist/dashboard/(bookings)/bookings/_components/booking-constants.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/booking-tab-hints.js +32 -0
- package/dist/dashboard/(bookings)/bookings/_components/booking-tab-hints.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-filter-bar.js +131 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-filter-bar.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-mobile-controls.js +119 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-mobile-controls.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-screen.js +414 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-screen.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-table.js +192 -0
- package/dist/dashboard/(bookings)/bookings/_components/bookings-table.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/cannot-take-bookings.js +34 -0
- package/dist/dashboard/(bookings)/bookings/_components/cannot-take-bookings.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/demo-data.js +176 -0
- package/dist/dashboard/(bookings)/bookings/_components/demo-data.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/index.js +9 -0
- package/dist/dashboard/(bookings)/bookings/_components/index.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/booking-card.js +126 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/booking-card.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/demo-data.js +142 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/demo-data.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/handover.js +128 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/handover.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/index.js +17 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/index.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/past-band.js +69 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/past-band.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/resource-board.js +111 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/resource-board.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/today-band.js +61 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/today-band.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/upcoming-band.js +113 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/upcoming-band.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/waiting-queue.js +62 -0
- package/dist/dashboard/(bookings)/bookings/_components/today/waiting-queue.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today-board.js +192 -0
- package/dist/dashboard/(bookings)/bookings/_components/today-board.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_components/today.js +1 -0
- package/dist/dashboard/(bookings)/bookings/_components.js +1 -0
- package/dist/dashboard/(bookings)/bookings/_hooks/index.js +5 -0
- package/dist/dashboard/(bookings)/bookings/_hooks/index.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_hooks/use-bookings-data.js +331 -0
- package/dist/dashboard/(bookings)/bookings/_hooks/use-bookings-data.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_hooks/use-today-data.js +309 -0
- package/dist/dashboard/(bookings)/bookings/_hooks/use-today-data.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/_hooks.js +1 -0
- package/dist/dashboard/(bookings)/bookings/_lib/booking-link.js +13 -0
- package/dist/dashboard/(bookings)/bookings/_lib/booking-link.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/attendees/_components/attendee-cards.js +60 -0
- package/dist/dashboard/(bookings)/bookings/attendees/_components/attendee-cards.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/attendees/_components/qr-scanner-modal.js +225 -0
- package/dist/dashboard/(bookings)/bookings/attendees/_components/qr-scanner-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/attendees/demo-data.js +195 -0
- package/dist/dashboard/(bookings)/bookings/attendees/demo-data.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/attendees/page.js +341 -0
- package/dist/dashboard/(bookings)/bookings/attendees/page.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/new/page.js +129 -0
- package/dist/dashboard/(bookings)/bookings/new/page.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/page.js +10 -0
- package/dist/dashboard/(bookings)/bookings/page.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/_components/save-buttons.js +36 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/_components/save-buttons.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/_components/session-creator.js +386 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/_components/session-creator.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/_lib/session-payload.js +62 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/_lib/session-payload.js.map +1 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/page.js +10 -0
- package/dist/dashboard/(bookings)/bookings/sessions/new/page.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/calendar-nav.js +84 -0
- package/dist/dashboard/(bookings)/calendar/_components/calendar-nav.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/calendar-range.js +84 -0
- package/dist/dashboard/(bookings)/calendar/_components/calendar-range.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/day-board-view.js +279 -0
- package/dist/dashboard/(bookings)/calendar/_components/day-board-view.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/event-detail-modal.js +113 -0
- package/dist/dashboard/(bookings)/calendar/_components/event-detail-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/format.js +22 -0
- package/dist/dashboard/(bookings)/calendar/_components/format.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/month-grid.js +109 -0
- package/dist/dashboard/(bookings)/calendar/_components/month-grid.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/resource-day-grid.js +325 -0
- package/dist/dashboard/(bookings)/calendar/_components/resource-day-grid.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/slot-action-sheet.js +209 -0
- package/dist/dashboard/(bookings)/calendar/_components/slot-action-sheet.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/use-block-drag.js +77 -0
- package/dist/dashboard/(bookings)/calendar/_components/use-block-drag.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/use-calendar-nav.js +69 -0
- package/dist/dashboard/(bookings)/calendar/_components/use-calendar-nav.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/week-grid.js +202 -0
- package/dist/dashboard/(bookings)/calendar/_components/week-grid.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/_components/year-grid.js +111 -0
- package/dist/dashboard/(bookings)/calendar/_components/year-grid.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar/page.js +8 -0
- package/dist/dashboard/(bookings)/calendar/page.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feed-modal.js +126 -0
- package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feed-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feeds-section.js +99 -0
- package/dist/dashboard/(bookings)/calendar-sync/_components/channel-feeds-section.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar-sync/demo-data.js +64 -0
- package/dist/dashboard/(bookings)/calendar-sync/demo-data.js.map +1 -0
- package/dist/dashboard/(bookings)/calendar-sync/page.js +15 -0
- package/dist/dashboard/(bookings)/calendar-sync/page.js.map +1 -0
- package/dist/dashboard/(bookings)/check-in/page.js +252 -0
- package/dist/dashboard/(bookings)/check-in/page.js.map +1 -0
- package/dist/dashboard/(bookings)/events/[eventId]/_components/event-attendees.js +108 -0
- package/dist/dashboard/(bookings)/events/[eventId]/_components/event-attendees.js.map +1 -0
- package/dist/dashboard/(bookings)/events/[eventId]/_components/event-share.js +73 -0
- package/dist/dashboard/(bookings)/events/[eventId]/_components/event-share.js.map +1 -0
- package/dist/dashboard/(bookings)/events/[eventId]/layout.js +10 -0
- package/dist/dashboard/(bookings)/events/[eventId]/layout.js.map +1 -0
- package/dist/dashboard/(bookings)/events/[eventId]/page.js +247 -0
- package/dist/dashboard/(bookings)/events/[eventId]/page.js.map +1 -0
- package/dist/dashboard/(bookings)/events/_components/event-grid.js +44 -0
- package/dist/dashboard/(bookings)/events/_components/event-grid.js.map +1 -0
- package/dist/dashboard/(bookings)/events/_components/event-poster.js +17 -0
- package/dist/dashboard/(bookings)/events/_components/event-poster.js.map +1 -0
- package/dist/dashboard/(bookings)/events/_hooks/use-events-data.js +55 -0
- package/dist/dashboard/(bookings)/events/_hooks/use-events-data.js.map +1 -0
- package/dist/dashboard/(bookings)/events/_lib/event-facts.js +68 -0
- package/dist/dashboard/(bookings)/events/_lib/event-facts.js.map +1 -0
- package/dist/dashboard/(bookings)/events/new/_components/event-composer.js +295 -0
- package/dist/dashboard/(bookings)/events/new/_components/event-composer.js.map +1 -0
- package/dist/dashboard/(bookings)/events/new/_components/event-poster.js +65 -0
- package/dist/dashboard/(bookings)/events/new/_components/event-poster.js.map +1 -0
- package/dist/dashboard/(bookings)/events/new/_components/ticket-tiers.js +75 -0
- package/dist/dashboard/(bookings)/events/new/_components/ticket-tiers.js.map +1 -0
- package/dist/dashboard/(bookings)/events/new/page.js +10 -0
- package/dist/dashboard/(bookings)/events/new/page.js.map +1 -0
- package/dist/dashboard/(bookings)/events/page.js +214 -0
- package/dist/dashboard/(bookings)/events/page.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/[resourceId]/layout.js +36 -0
- package/dist/dashboard/(bookings)/resources/[resourceId]/layout.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/[resourceId]/page.js +351 -0
- package/dist/dashboard/(bookings)/resources/[resourceId]/page.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/block-time-modal.js +130 -0
- package/dist/dashboard/(bookings)/resources/_components/block-time-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/category-card.js +74 -0
- package/dist/dashboard/(bookings)/resources/_components/category-card.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/category-form-dialog.js +197 -0
- package/dist/dashboard/(bookings)/resources/_components/category-form-dialog.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/day-editor.js +194 -0
- package/dist/dashboard/(bookings)/resources/_components/day-editor.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/group-dialog.js +170 -0
- package/dist/dashboard/(bookings)/resources/_components/group-dialog.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/group-header.js +90 -0
- package/dist/dashboard/(bookings)/resources/_components/group-header.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/index.js +22 -0
- package/dist/dashboard/(bookings)/resources/_components/index.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/mobile-category-form-sheet.js +256 -0
- package/dist/dashboard/(bookings)/resources/_components/mobile-category-form-sheet.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/resource-form.js +420 -0
- package/dist/dashboard/(bookings)/resources/_components/resource-form.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/resource-picker.js +144 -0
- package/dist/dashboard/(bookings)/resources/_components/resource-picker.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/resource-type-picker-empty.js +109 -0
- package/dist/dashboard/(bookings)/resources/_components/resource-type-picker-empty.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/roster-empty.js +103 -0
- package/dist/dashboard/(bookings)/resources/_components/roster-empty.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/roster-grid.js +160 -0
- package/dist/dashboard/(bookings)/resources/_components/roster-grid.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/schedule-editor.js +244 -0
- package/dist/dashboard/(bookings)/resources/_components/schedule-editor.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/schedule-timezone-field.js +25 -0
- package/dist/dashboard/(bookings)/resources/_components/schedule-timezone-field.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/solo-schedule-view.js +146 -0
- package/dist/dashboard/(bookings)/resources/_components/solo-schedule-view.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/team-onboarding-dialog.js +161 -0
- package/dist/dashboard/(bookings)/resources/_components/team-onboarding-dialog.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components/week-grid.js +175 -0
- package/dist/dashboard/(bookings)/resources/_components/week-grid.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_components.js +1 -0
- package/dist/dashboard/(bookings)/resources/_hooks/index.js +8 -0
- package/dist/dashboard/(bookings)/resources/_hooks/index.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_hooks/use-resource-categories-data.js +86 -0
- package/dist/dashboard/(bookings)/resources/_hooks/use-resource-categories-data.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_hooks/use-roster-page.js +138 -0
- package/dist/dashboard/(bookings)/resources/_hooks/use-roster-page.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_hooks/use-roster.js +182 -0
- package/dist/dashboard/(bookings)/resources/_hooks/use-roster.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_hooks.js +1 -0
- package/dist/dashboard/(bookings)/resources/_lib/presets.js +147 -0
- package/dist/dashboard/(bookings)/resources/_lib/presets.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_lib/schedule-timezone.js +17 -0
- package/dist/dashboard/(bookings)/resources/_lib/schedule-timezone.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_lib/shapes.js +105 -0
- package/dist/dashboard/(bookings)/resources/_lib/shapes.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/_lib/week.js +122 -0
- package/dist/dashboard/(bookings)/resources/_lib/week.js.map +1 -0
- package/dist/dashboard/(bookings)/resources/page.js +391 -0
- package/dist/dashboard/(bookings)/resources/page.js.map +1 -0
- package/dist/dashboard/(bookings)/schedule/page.js +8 -0
- package/dist/dashboard/(bookings)/schedule/page.js.map +1 -0
- package/dist/dashboard/(bookings)/today/page.js +14 -0
- package/dist/dashboard/(bookings)/today/page.js.map +1 -0
- package/dist/dashboard/(bookings)/waitlist/_components/demo-data.js +99 -0
- package/dist/dashboard/(bookings)/waitlist/_components/demo-data.js.map +1 -0
- package/dist/dashboard/(bookings)/waitlist/_components/offer-spot-modal.js +71 -0
- package/dist/dashboard/(bookings)/waitlist/_components/offer-spot-modal.js.map +1 -0
- package/dist/dashboard/(bookings)/waitlist/_components/waitlist-entry-editor.js +150 -0
- package/dist/dashboard/(bookings)/waitlist/_components/waitlist-entry-editor.js.map +1 -0
- package/dist/dashboard/(bookings)/waitlist/new/page.js +59 -0
- package/dist/dashboard/(bookings)/waitlist/new/page.js.map +1 -0
- package/dist/dashboard/(bookings)/waitlist/page.js +317 -0
- package/dist/dashboard/(bookings)/waitlist/page.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useItemLinks } from "@withpotter/lib/use-item-links";
|
|
4
|
+
import { FLAT_CONTROL, TOOLBAR_H } from "@withpotter/ui-kit/toolbar-parts";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { useRouter } from "next/navigation";
|
|
7
|
+
import { CalendarDays, LayoutGrid, List, Plus, Users } from "lucide-react";
|
|
8
|
+
import {
|
|
9
|
+
ListPage,
|
|
10
|
+
ListFrame,
|
|
11
|
+
ListStates,
|
|
12
|
+
TableShell,
|
|
13
|
+
Th,
|
|
14
|
+
TableRow,
|
|
15
|
+
TablePagination,
|
|
16
|
+
Select,
|
|
17
|
+
Button,
|
|
18
|
+
ViewSwitch,
|
|
19
|
+
OverflowMenu,
|
|
20
|
+
OverflowItem,
|
|
21
|
+
StateView
|
|
22
|
+
} from "@withpotter/ui-kit";
|
|
23
|
+
import { StatusBadge } from "@withpotter/components/shared/status-badge";
|
|
24
|
+
import { MobilePageHeader } from "@withpotter/components/mobile/mobile-page-header";
|
|
25
|
+
import { useRegisterRefresh } from "@withpotter/components/mobile/pull-to-refresh-context";
|
|
26
|
+
import { LIST_PAGE_SIZE } from "@withpotter/lib/list-page-size";
|
|
27
|
+
import { useEventsData } from "./_hooks/use-events-data";
|
|
28
|
+
import { EventGrid } from "./_components/event-grid";
|
|
29
|
+
import { EventThumb } from "./_components/event-poster";
|
|
30
|
+
import {
|
|
31
|
+
eventFacts,
|
|
32
|
+
eventPublicationStatus,
|
|
33
|
+
whenLabel
|
|
34
|
+
} from "./_lib/event-facts";
|
|
35
|
+
function EventsPage() {
|
|
36
|
+
const router = useRouter();
|
|
37
|
+
const links = useItemLinks();
|
|
38
|
+
const [view, setView] = useState("list");
|
|
39
|
+
const {
|
|
40
|
+
events,
|
|
41
|
+
total,
|
|
42
|
+
totalPages,
|
|
43
|
+
page,
|
|
44
|
+
setPage,
|
|
45
|
+
window,
|
|
46
|
+
setWindow,
|
|
47
|
+
loading,
|
|
48
|
+
error,
|
|
49
|
+
refetch
|
|
50
|
+
} = useEventsData();
|
|
51
|
+
useRegisterRefresh(refetch);
|
|
52
|
+
return /* @__PURE__ */ jsx(
|
|
53
|
+
ListPage,
|
|
54
|
+
{
|
|
55
|
+
largeTitle: true,
|
|
56
|
+
title: "Events",
|
|
57
|
+
mobileHeader: /* @__PURE__ */ jsx(
|
|
58
|
+
MobilePageHeader,
|
|
59
|
+
{
|
|
60
|
+
title: "Events",
|
|
61
|
+
action: {
|
|
62
|
+
label: "New event",
|
|
63
|
+
icon: Plus,
|
|
64
|
+
onClick: () => router.push("/dashboard/events/new?intent=event-tickets")
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
),
|
|
68
|
+
actions: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
69
|
+
/* @__PURE__ */ jsx(
|
|
70
|
+
Select,
|
|
71
|
+
{
|
|
72
|
+
size: "sm",
|
|
73
|
+
value: window,
|
|
74
|
+
onChange: (value) => setWindow(value),
|
|
75
|
+
ariaLabel: "Which events to show",
|
|
76
|
+
options: [
|
|
77
|
+
{ value: "all", label: "All events" },
|
|
78
|
+
{ value: "upcoming", label: "Upcoming" },
|
|
79
|
+
{ value: "past", label: "Past" }
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
),
|
|
83
|
+
/* @__PURE__ */ jsx(
|
|
84
|
+
ViewSwitch,
|
|
85
|
+
{
|
|
86
|
+
className: `${TOOLBAR_H} ${FLAT_CONTROL}`,
|
|
87
|
+
value: view,
|
|
88
|
+
onChange: setView,
|
|
89
|
+
"aria-label": "Show events as a list or a grid",
|
|
90
|
+
options: [
|
|
91
|
+
{ value: "list", label: "List", icon: List },
|
|
92
|
+
{ value: "grid", label: "Grid", icon: LayoutGrid }
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
),
|
|
96
|
+
/* @__PURE__ */ jsx(
|
|
97
|
+
Button,
|
|
98
|
+
{
|
|
99
|
+
className: `${TOOLBAR_H} ${FLAT_CONTROL}`,
|
|
100
|
+
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
101
|
+
onClick: () => router.push("/dashboard/events/new?intent=event-tickets"),
|
|
102
|
+
children: "New event"
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
] }),
|
|
106
|
+
children: /* @__PURE__ */ jsx(ListFrame, { children: /* @__PURE__ */ jsx(
|
|
107
|
+
ListStates,
|
|
108
|
+
{
|
|
109
|
+
framed: true,
|
|
110
|
+
loading: loading && events.length === 0,
|
|
111
|
+
isEmpty: events.length === 0,
|
|
112
|
+
error,
|
|
113
|
+
onRetry: () => refetch(),
|
|
114
|
+
empty: (
|
|
115
|
+
/* The first-run state carries the act that resolves it, even
|
|
116
|
+
though the header offers the same one: on an empty page the
|
|
117
|
+
header button is small and in the far corner and this is in the
|
|
118
|
+
middle of the screen, where the eye already is.
|
|
119
|
+
|
|
120
|
+
A NARROWED empty list says something else. Nobody arriving at
|
|
121
|
+
"no past events" wants to be sold a new one — they want the
|
|
122
|
+
window they came from. */
|
|
123
|
+
window === "all" ? /* @__PURE__ */ jsx(
|
|
124
|
+
StateView,
|
|
125
|
+
{
|
|
126
|
+
kind: "empty",
|
|
127
|
+
icon: CalendarDays,
|
|
128
|
+
title: "No events yet",
|
|
129
|
+
description: "Put on a night, sell the tickets, and see who is coming.",
|
|
130
|
+
action: {
|
|
131
|
+
label: "New event",
|
|
132
|
+
href: "/dashboard/events/new?intent=event-tickets"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
) : /* @__PURE__ */ jsx(
|
|
136
|
+
StateView,
|
|
137
|
+
{
|
|
138
|
+
kind: "empty",
|
|
139
|
+
icon: CalendarDays,
|
|
140
|
+
title: window === "upcoming" ? "Nothing coming up" : "Nothing has happened yet",
|
|
141
|
+
description: "Events with no date set are in All, which is where a half-written listing waits.",
|
|
142
|
+
action: {
|
|
143
|
+
label: "Show all events",
|
|
144
|
+
onClick: () => setWindow("all")
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
),
|
|
149
|
+
children: view === "grid" ? /* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsx(EventGrid, { events }) }) : /* @__PURE__ */ jsx(
|
|
150
|
+
TableShell,
|
|
151
|
+
{
|
|
152
|
+
bare: true,
|
|
153
|
+
minWidth: 760,
|
|
154
|
+
footer: /* @__PURE__ */ jsx(
|
|
155
|
+
TablePagination,
|
|
156
|
+
{
|
|
157
|
+
page,
|
|
158
|
+
totalPages,
|
|
159
|
+
pageSize: LIST_PAGE_SIZE,
|
|
160
|
+
totalItems: total,
|
|
161
|
+
entityName: "events",
|
|
162
|
+
onPageChange: setPage
|
|
163
|
+
}
|
|
164
|
+
),
|
|
165
|
+
head: /* @__PURE__ */ jsxs("tr", { className: "h-[44px]", children: [
|
|
166
|
+
/* @__PURE__ */ jsx(Th, { children: "Event" }),
|
|
167
|
+
/* @__PURE__ */ jsx(Th, { children: "When" }),
|
|
168
|
+
/* @__PURE__ */ jsx(Th, { children: "Tickets" }),
|
|
169
|
+
/* @__PURE__ */ jsx(Th, { children: "Status" }),
|
|
170
|
+
/* @__PURE__ */ jsx("th", { className: "w-12" })
|
|
171
|
+
] }),
|
|
172
|
+
children: events.map((event) => {
|
|
173
|
+
const facts = eventFacts(event);
|
|
174
|
+
return /* @__PURE__ */ jsxs(
|
|
175
|
+
TableRow,
|
|
176
|
+
{
|
|
177
|
+
onClick: () => router.push(links.detail(event.id)),
|
|
178
|
+
children: [
|
|
179
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
180
|
+
/* @__PURE__ */ jsx(EventThumb, { event }),
|
|
181
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
182
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-[var(--text-primary)]", children: event.title }),
|
|
183
|
+
facts.venue && /* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--text-tertiary)]", children: facts.venue })
|
|
184
|
+
] })
|
|
185
|
+
] }) }),
|
|
186
|
+
/* @__PURE__ */ jsx("td", { className: "text-sm text-[var(--text-secondary)]", children: whenLabel(facts) }),
|
|
187
|
+
/* @__PURE__ */ jsx("td", { className: "text-sm tabular-nums text-[var(--text-secondary)]", children: facts.capacity > 0 ? `${facts.sold} of ${facts.capacity}` : "\u2014" }),
|
|
188
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(StatusBadge, { status: eventPublicationStatus(event) }) }),
|
|
189
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(OverflowMenu, { children: /* @__PURE__ */ jsx(
|
|
190
|
+
OverflowItem,
|
|
191
|
+
{
|
|
192
|
+
icon: /* @__PURE__ */ jsx(Users, {}),
|
|
193
|
+
onClick: () => router.push(
|
|
194
|
+
`/dashboard/bookings/attendees?contentId=${event.id}`
|
|
195
|
+
),
|
|
196
|
+
children: "Who is coming"
|
|
197
|
+
}
|
|
198
|
+
) }) })
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
event.id
|
|
202
|
+
);
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
) })
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
export {
|
|
212
|
+
EventsPage as default
|
|
213
|
+
};
|
|
214
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/dashboard/%28bookings%29/events/page.tsx"],"sourcesContent":["'use client';\n\nimport { useItemLinks } from '@withpotter/lib/use-item-links';\nimport { FLAT_CONTROL, TOOLBAR_H } from '@withpotter/ui-kit/toolbar-parts';\nimport { useState } from 'react';\n\nimport { useRouter } from 'next/navigation';\nimport { CalendarDays, LayoutGrid, List, Plus, Users } from 'lucide-react';\nimport {\n ListPage,\n ListFrame,\n ListStates,\n TableShell,\n Th,\n TableRow,\n TablePagination,\n Select,\n Button,\n ViewSwitch,\n OverflowMenu,\n OverflowItem,\n StateView,\n} from '@withpotter/ui-kit';\nimport { StatusBadge } from '@withpotter/components/shared/status-badge';\nimport { MobilePageHeader } from '@withpotter/components/mobile/mobile-page-header';\nimport { useRegisterRefresh } from '@withpotter/components/mobile/pull-to-refresh-context';\nimport { LIST_PAGE_SIZE } from '@withpotter/lib/list-page-size';\nimport { useEventsData, type EventWindow } from './_hooks/use-events-data';\nimport { EventGrid } from './_components/event-grid';\nimport { EventThumb } from './_components/event-poster';\nimport {\n eventFacts,\n eventPublicationStatus,\n whenLabel,\n} from './_lib/event-facts';\n\n/**\n * EVERY EVENT THIS BUSINESS HAS PUT ON — John, 2026-09-03: *\"I need events I\n * have created, I need to be able to see all events I've created, so yes we\n * need a nav for that.\"*\n *\n * ── WHY THE CATALOGUE WAS NOT THIS ──\n *\n * An event IS a product with the `ticketed` behaviour, and the archetype's\n * catalogue row has always been called Event Listings, so on paper a ticket\n * business already had this page. Two things made it not one.\n *\n * The first is the axis. A shop reads its shelf by name and a venue reads its\n * diary by WHEN — what is on next, and what has been — and the catalogue could\n * not be asked either question: there was no event window in the API and no\n * sort by date on the screen. \"Show me past events\" meant scrolling the whole\n * catalogue.\n *\n * The second is the collapse. When a business runs tickets alongside anything\n * else, the sidebar folds the two catalogue rows into one — same destination,\n * so one row — and the merged row takes the generic noun. A shop that added\n * events got \"Products\", and its events stopped being nameable in the nav at\n * the moment it had two kinds of thing to tell apart. A separate destination\n * is what makes an Events row survive that, and the row is why this is a route\n * rather than a query parameter: `?intent=event-tickets` re-scopes the whole\n * shell, which is a different and much larger promise than \"show me my\n * events\".\n *\n * ── ATTENDEES ARE REACHED FROM AN EVENT ──\n *\n * Not from a global row of their own. An attendee is not a second kind of\n * person: it is a customer in relation to one night, and the identity belongs\n * in Customers where every other relationship this person has already lives.\n * What an operator needs on the door is the other thing entirely — this event's\n * 142, checked in or not — which is a view of an event and is where the row's\n * ⋯ sends you.\n */\nexport default function EventsPage() {\n const router = useRouter();\n const links = useItemLinks();\n /**\n * TABLE OR GRID — John, 2026-09-03: *\"the events page should have a grid\n * view not just list.\"*\n *\n * A shop's stock list is read by name and reads well as rows. An event is a\n * poster, and a promoter running six nights recognises theirs by the artwork\n * long before they finish reading a title — which is the same argument the\n * catalogue's own switch makes about products with photographs.\n *\n * `ViewSwitch`, because this is one set of records drawn two ways: the house\n * primitive for exactly that, and not `OptionButton`, which is for a choice\n * that narrows.\n */\n const [view, setView] = useState<'list' | 'grid'>('list');\n const {\n events,\n total,\n totalPages,\n page,\n setPage,\n window,\n setWindow,\n loading,\n error,\n refetch,\n } = useEventsData();\n\n useRegisterRefresh(refetch);\n\n return (\n <ListPage\n largeTitle\n title=\"Events\"\n mobileHeader={\n <MobilePageHeader\n title=\"Events\"\n action={{\n label: 'New event',\n icon: Plus,\n onClick: () =>\n router.push('/dashboard/events/new?intent=event-tickets'),\n }}\n />\n }\n actions={\n <>\n {/* The window narrows the list, so it sits with the controls that\n act on the list. Not a tab strip: the house rule is that a list\n narrows in its filters, and a page-scoped pill row under a title\n claims a line that belongs to the data. */}\n <Select\n size=\"sm\"\n value={window}\n onChange={(value) => setWindow(value as EventWindow)}\n ariaLabel=\"Which events to show\"\n options={[\n { value: 'all', label: 'All events' },\n { value: 'upcoming', label: 'Upcoming' },\n { value: 'past', label: 'Past' },\n ]}\n />\n {/* THE EDITOR, SCOPED TO EVENTS — not the plain product creator.\n John, 2026-09-03: *\"when I click on create it goes to create\n products.\"*\n\n `ProductEditorPage` decides what it is making from whichever\n archetype the workspace lists first, so a shop that later added\n events pressed New event and got a form headed Product — no date,\n no venue, no tiers. `?intent=event-tickets` is what\n `useIntentConfig` reads to narrow that, which is exactly the\n right promise on a create screen: this form is for one kind of\n thing, and you have just said which. */}\n <ViewSwitch\n className={`${TOOLBAR_H} ${FLAT_CONTROL}`}\n value={view}\n onChange={setView}\n aria-label=\"Show events as a list or a grid\"\n options={[\n { value: 'list', label: 'List', icon: List },\n { value: 'grid', label: 'Grid', icon: LayoutGrid },\n ]}\n />\n <Button\n className={`${TOOLBAR_H} ${FLAT_CONTROL}`}\n icon={<Plus />}\n onClick={() =>\n router.push('/dashboard/events/new?intent=event-tickets')\n }\n >\n New event\n </Button>\n </>\n }\n >\n <ListFrame>\n <ListStates\n framed\n loading={loading && events.length === 0}\n isEmpty={events.length === 0}\n error={error}\n onRetry={() => refetch()}\n empty={\n /* The first-run state carries the act that resolves it, even\n though the header offers the same one: on an empty page the\n header button is small and in the far corner and this is in the\n middle of the screen, where the eye already is.\n\n A NARROWED empty list says something else. Nobody arriving at\n \"no past events\" wants to be sold a new one — they want the\n window they came from. */\n window === 'all' ? (\n <StateView\n kind=\"empty\"\n icon={CalendarDays}\n title=\"No events yet\"\n description=\"Put on a night, sell the tickets, and see who is coming.\"\n action={{\n label: 'New event',\n href: '/dashboard/events/new?intent=event-tickets',\n }}\n />\n ) : (\n <StateView\n kind=\"empty\"\n icon={CalendarDays}\n title={\n window === 'upcoming'\n ? 'Nothing coming up'\n : 'Nothing has happened yet'\n }\n description=\"Events with no date set are in All, which is where a half-written listing waits.\"\n action={{\n label: 'Show all events',\n onClick: () => setWindow('all'),\n }}\n />\n )\n }\n >\n {view === 'grid' ? (\n <div className=\"p-3\">\n <EventGrid events={events} />\n </div>\n ) : (\n <TableShell\n bare\n minWidth={760}\n footer={\n <TablePagination\n page={page}\n totalPages={totalPages}\n pageSize={LIST_PAGE_SIZE}\n totalItems={total}\n entityName=\"events\"\n onPageChange={setPage}\n />\n }\n head={\n <tr className=\"h-[44px]\">\n <Th>Event</Th>\n <Th>When</Th>\n {/* Sold against what is on sale, which is the only number a\n venue is actually watching. A room's capacity is not it:\n seats held back were never for sale. */}\n <Th>Tickets</Th>\n <Th>Status</Th>\n <th className=\"w-12\" />\n </tr>\n }\n >\n {events.map((event) => {\n const facts = eventFacts(event);\n return (\n <TableRow\n key={event.id}\n onClick={() => router.push(links.detail(event.id))}\n >\n <td>\n <div className=\"flex items-center gap-3\">\n <EventThumb event={event} />\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium text-[var(--text-primary)]\">\n {event.title}\n </div>\n {facts.venue && (\n <div className=\"text-xs text-[var(--text-tertiary)]\">\n {facts.venue}\n </div>\n )}\n </div>\n </div>\n </td>\n <td className=\"text-sm text-[var(--text-secondary)]\">\n {whenLabel(facts)}\n </td>\n <td className=\"text-sm tabular-nums text-[var(--text-secondary)]\">\n {facts.capacity > 0\n ? `${facts.sold} of ${facts.capacity}`\n : '—'}\n </td>\n <td>\n <StatusBadge status={eventPublicationStatus(event)} />\n </td>\n <td>\n <OverflowMenu>\n <OverflowItem\n icon={<Users />}\n onClick={() =>\n router.push(\n `/dashboard/bookings/attendees?contentId=${event.id}`,\n )\n }\n >\n Who is coming\n </OverflowItem>\n </OverflowMenu>\n </td>\n </TableRow>\n );\n })}\n </TableShell>\n )}\n </ListStates>\n </ListFrame>\n </ListPage>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useParams } from "next/navigation";
|
|
4
|
+
import { useAuth } from "@withpotter/lib/auth-context";
|
|
5
|
+
import { useApiQuery } from "@withpotter/hooks/use-api-query";
|
|
6
|
+
import { resourcesApi } from "@withpotter/lib/api/resources";
|
|
7
|
+
import { IntentScope } from "@withpotter/lib/intents/intent-scope";
|
|
8
|
+
import { INTENTS } from "@withpotter/components/intents";
|
|
9
|
+
import { ownerIntentOfResource } from "@withpotter/components/intents/item-owner";
|
|
10
|
+
import { scopeLabelsFor } from "@withpotter/components/intents/scope-labels";
|
|
11
|
+
function ResourceLayout({ children }) {
|
|
12
|
+
const { resourceId } = useParams();
|
|
13
|
+
const { tenant } = useAuth();
|
|
14
|
+
const { data: type } = useApiQuery(
|
|
15
|
+
["resource", resourceId, "type"],
|
|
16
|
+
async (slug) => {
|
|
17
|
+
const res = await resourcesApi.get(slug, resourceId);
|
|
18
|
+
return res?.data?.type ?? res?.type ?? null;
|
|
19
|
+
},
|
|
20
|
+
{ enabled: Boolean(resourceId && tenant?.slug) }
|
|
21
|
+
);
|
|
22
|
+
const owner = ownerIntentOfResource(type, INTENTS);
|
|
23
|
+
if (!owner) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
24
|
+
return /* @__PURE__ */ jsx(
|
|
25
|
+
IntentScope,
|
|
26
|
+
{
|
|
27
|
+
intentKey: owner.key,
|
|
28
|
+
labels: scopeLabelsFor(owner, owner.nav.label),
|
|
29
|
+
children
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
ResourceLayout as default
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/dashboard/%28bookings%29/resources/%5BresourceId%5D/layout.tsx"],"sourcesContent":["'use client';\n\nimport { useParams } from 'next/navigation';\nimport type { ReactNode } from 'react';\nimport { useAuth } from '@withpotter/lib/auth-context';\nimport { useApiQuery } from '@withpotter/hooks/use-api-query';\nimport { resourcesApi } from '@withpotter/lib/api/resources';\nimport { IntentScope } from '@withpotter/lib/intents/intent-scope';\nimport { INTENTS } from '@withpotter/components/intents';\nimport { ownerIntentOfResource } from '@withpotter/components/intents/item-owner';\nimport { scopeLabelsFor } from '@withpotter/components/intents/scope-labels';\n\n/**\n * A resource's screen, spoken in the words of the intent that manages it: a\n * table is a restaurant's, a room a rental's, a staff member a booking\n * business's. Each intent declares the resource types it manages, and the\n * resource says which it is. It shares the page's own query key.\n */\nexport default function ResourceLayout({ children }: { children: ReactNode }) {\n const { resourceId } = useParams<{ resourceId: string }>();\n const { tenant } = useAuth();\n\n const { data: type } = useApiQuery<string | null>(\n ['resource', resourceId, 'type'],\n async (slug) => {\n const res = (await resourcesApi.get(slug, resourceId)) as unknown as {\n data?: { type?: string };\n type?: string;\n };\n return res?.data?.type ?? res?.type ?? null;\n },\n { enabled: Boolean(resourceId && tenant?.slug) },\n );\n\n const owner = ownerIntentOfResource(type, INTENTS);\n if (!owner) return <>{children}</>;\n\n return (\n <IntentScope\n intentKey={owner.key}\n labels={scopeLabelsFor(owner, owner.nav.label)}\n >\n {children}\n </IntentScope>\n );\n}\n"],"mappings":";AAmCqB;AAjCrB,SAAS,iBAAiB;AAE1B,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AACxB,SAAS,6BAA6B;AACtC,SAAS,sBAAsB;AAQhB,SAAR,eAAgC,EAAE,SAAS,GAA4B;AAC5E,QAAM,EAAE,WAAW,IAAI,UAAkC;AACzD,QAAM,EAAE,OAAO,IAAI,QAAQ;AAE3B,QAAM,EAAE,MAAM,KAAK,IAAI;AAAA,IACrB,CAAC,YAAY,YAAY,MAAM;AAAA,IAC/B,OAAO,SAAS;AACd,YAAM,MAAO,MAAM,aAAa,IAAI,MAAM,UAAU;AAIpD,aAAO,KAAK,MAAM,QAAQ,KAAK,QAAQ;AAAA,IACzC;AAAA,IACA,EAAE,SAAS,QAAQ,cAAc,QAAQ,IAAI,EAAE;AAAA,EACjD;AAEA,QAAM,QAAQ,sBAAsB,MAAM,OAAO;AACjD,MAAI,CAAC,MAAO,QAAO,gCAAG,UAAS;AAE/B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,MAAM;AAAA,MACjB,QAAQ,eAAe,OAAO,MAAM,IAAI,KAAK;AAAA,MAE5C;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useItemLinks } from "@withpotter/lib/use-item-links";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { useParams, useRouter } from "next/navigation";
|
|
6
|
+
import { Power, Trash2, Boxes } from "lucide-react";
|
|
7
|
+
import { useAuth } from "@withpotter/lib/auth-context";
|
|
8
|
+
import { useApiQuery } from "@withpotter/hooks/use-api-query";
|
|
9
|
+
import { useBusinessLocations } from "@withpotter/lib/use-business-locations";
|
|
10
|
+
import { useDetailHeader } from "@withpotter/hooks/use-detail-header";
|
|
11
|
+
import { useEntityLabel } from "@withpotter/lib/intents/use-entity-label";
|
|
12
|
+
import { useModuleLabel } from "@withpotter/lib/use-module-label";
|
|
13
|
+
import { resourceCategoriesApi } from "@withpotter/lib/api/resource-categories";
|
|
14
|
+
import { resourcesApi } from "@withpotter/lib/api/resources";
|
|
15
|
+
import { Button } from "@withpotter/ui-kit/button";
|
|
16
|
+
import { DetailPage } from "@withpotter/ui-kit/detail-page";
|
|
17
|
+
import { DetailStates } from "@withpotter/ui-kit/detail-states";
|
|
18
|
+
import { EditorSection } from "@withpotter/ui-kit/editor-section";
|
|
19
|
+
import { ErrorBanner } from "@withpotter/ui-kit/error-banner";
|
|
20
|
+
import { Field } from "@withpotter/ui-kit/field";
|
|
21
|
+
import { Input, NumberField, Select, Textarea } from "@withpotter/ui-kit";
|
|
22
|
+
import { GeneratedAvatar } from "@withpotter/ui-kit/generated-avatar";
|
|
23
|
+
import { OverflowMenu, OverflowItem } from "@withpotter/ui-kit/overflow-menu";
|
|
24
|
+
import { StatusBadge } from "@withpotter/components/shared/status-badge";
|
|
25
|
+
import { useConfirm } from "@withpotter/ui-kit/confirm-dialog";
|
|
26
|
+
import { ImageUpload } from "@withpotter/components/image-upload";
|
|
27
|
+
import { ScheduleEditor, getDefaultSchedule } from "../_components";
|
|
28
|
+
import { availabilityWords } from "../_lib/shapes";
|
|
29
|
+
function ResourceRecordPage() {
|
|
30
|
+
const params = useParams();
|
|
31
|
+
const router = useRouter();
|
|
32
|
+
const back = useItemLinks().resources;
|
|
33
|
+
const { tenant } = useAuth();
|
|
34
|
+
const confirm = useConfirm();
|
|
35
|
+
const resourceId = params.resourceId;
|
|
36
|
+
const slug = tenant?.slug ?? "";
|
|
37
|
+
const { locations, isMultiSite } = useBusinessLocations();
|
|
38
|
+
const resourceLabel = useEntityLabel("resource");
|
|
39
|
+
const listTitle = useModuleLabel("resources", resourceLabel.plural);
|
|
40
|
+
const {
|
|
41
|
+
data: resource,
|
|
42
|
+
isLoading,
|
|
43
|
+
error: loadError,
|
|
44
|
+
refetch
|
|
45
|
+
} = useApiQuery(["resource", resourceId], async (s) => {
|
|
46
|
+
const res = await resourcesApi.get(s, resourceId);
|
|
47
|
+
return res?.data ?? res ?? null;
|
|
48
|
+
});
|
|
49
|
+
const { data: categories } = useApiQuery(
|
|
50
|
+
["resource-categories"],
|
|
51
|
+
(s) => resourceCategoriesApi.list(s)
|
|
52
|
+
);
|
|
53
|
+
const [categoryId, setCategoryId] = useState("");
|
|
54
|
+
const [locationId, setLocationId] = useState("");
|
|
55
|
+
const [name, setName] = useState("");
|
|
56
|
+
const [description, setDescription] = useState("");
|
|
57
|
+
const [imageUrl, setImageUrl] = useState("");
|
|
58
|
+
const [skills, setSkills] = useState("");
|
|
59
|
+
const [schedule, setSchedule] = useState(getDefaultSchedule());
|
|
60
|
+
const [defaultDuration, setDefaultDuration] = useState(60);
|
|
61
|
+
const [bufferMinutes, setBufferMinutes] = useState(0);
|
|
62
|
+
const [advanceBookingDays, setAdvanceBookingDays] = useState(30);
|
|
63
|
+
const [maxBookingsPerSlot, setMaxBookingsPerSlot] = useState(1);
|
|
64
|
+
const [price, setPrice] = useState("");
|
|
65
|
+
const [saving, setSaving] = useState(false);
|
|
66
|
+
const [saved, setSaved] = useState(false);
|
|
67
|
+
const [error, setError] = useState(null);
|
|
68
|
+
const groups = Array.isArray(categories) ? categories : [];
|
|
69
|
+
const category = groups.find((c) => c.id === categoryId) ?? null;
|
|
70
|
+
const kind = category?.kind ?? "person";
|
|
71
|
+
const { byTheNight } = availabilityWords(kind);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (!resource) return;
|
|
74
|
+
setCategoryId(resource.categoryId ?? "");
|
|
75
|
+
setLocationId(resource.locationId ?? "");
|
|
76
|
+
setName(resource.name);
|
|
77
|
+
setDescription(resource.description || "");
|
|
78
|
+
setImageUrl(resource.imageUrl || "");
|
|
79
|
+
setSkills(resource.skills?.join(", ") || "");
|
|
80
|
+
setSchedule(resource.schedule || getDefaultSchedule());
|
|
81
|
+
setDefaultDuration(resource.defaultDurationMinutes || 60);
|
|
82
|
+
setBufferMinutes(resource.bufferMinutes || 0);
|
|
83
|
+
setAdvanceBookingDays(resource.advanceBookingDays || 30);
|
|
84
|
+
setMaxBookingsPerSlot(resource.maxBookingsPerSlot || 1);
|
|
85
|
+
setPrice(resource.price != null ? String(resource.price) : "");
|
|
86
|
+
}, [resource]);
|
|
87
|
+
useDetailHeader({
|
|
88
|
+
title: resource?.name || resourceLabel.singular,
|
|
89
|
+
onBack: () => router.push(back)
|
|
90
|
+
});
|
|
91
|
+
const handleSave = async () => {
|
|
92
|
+
if (!resource) return;
|
|
93
|
+
if (!name.trim()) {
|
|
94
|
+
setError("Give it a name.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
setSaving(true);
|
|
98
|
+
setError(null);
|
|
99
|
+
try {
|
|
100
|
+
await resourcesApi.update(slug, resource.id, {
|
|
101
|
+
...categoryId ? { categoryId } : {},
|
|
102
|
+
// Omitted rather than sent empty: the API reads absence as the main
|
|
103
|
+
// location, which is not the same instruction as an empty string.
|
|
104
|
+
...locationId ? { locationId } : {},
|
|
105
|
+
name: name.trim(),
|
|
106
|
+
description: description.trim() || void 0,
|
|
107
|
+
imageUrl: imageUrl.trim() || void 0,
|
|
108
|
+
skills: skills.split(",").map((s) => s.trim()).filter(Boolean),
|
|
109
|
+
schedule,
|
|
110
|
+
defaultDurationMinutes: defaultDuration,
|
|
111
|
+
bufferMinutes,
|
|
112
|
+
advanceBookingDays,
|
|
113
|
+
maxBookingsPerSlot,
|
|
114
|
+
price: price ? Number(price) : void 0
|
|
115
|
+
});
|
|
116
|
+
await refetch();
|
|
117
|
+
setSaved(true);
|
|
118
|
+
setTimeout(() => setSaved(false), 2e3);
|
|
119
|
+
} catch (err) {
|
|
120
|
+
setError(err instanceof Error ? err.message : "That did not save.");
|
|
121
|
+
} finally {
|
|
122
|
+
setSaving(false);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const handleToggleStatus = async () => {
|
|
126
|
+
if (!resource) return;
|
|
127
|
+
setError(null);
|
|
128
|
+
try {
|
|
129
|
+
if (resource.status === "active") {
|
|
130
|
+
await resourcesApi.deactivate(slug, resource.id);
|
|
131
|
+
} else {
|
|
132
|
+
await resourcesApi.activate(slug, resource.id);
|
|
133
|
+
}
|
|
134
|
+
await refetch();
|
|
135
|
+
} catch {
|
|
136
|
+
setError("Could not change whether it can be booked.");
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
const handleDelete = async () => {
|
|
140
|
+
if (!resource) return;
|
|
141
|
+
const ok = await confirm({
|
|
142
|
+
title: `Delete ${resource.name}?`,
|
|
143
|
+
description: "Bookings already taken keep their record. This cannot be undone.",
|
|
144
|
+
confirmLabel: "Delete",
|
|
145
|
+
tone: "danger"
|
|
146
|
+
});
|
|
147
|
+
if (!ok) return;
|
|
148
|
+
try {
|
|
149
|
+
await resourcesApi.delete(slug, resource.id);
|
|
150
|
+
router.push(back);
|
|
151
|
+
} catch {
|
|
152
|
+
setError("Could not delete it.");
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
if (isLoading || loadError || !resource) {
|
|
156
|
+
return /* @__PURE__ */ jsx(
|
|
157
|
+
DetailStates,
|
|
158
|
+
{
|
|
159
|
+
loading: isLoading,
|
|
160
|
+
error: loadError?.message,
|
|
161
|
+
notFoundLabel: `That ${resourceLabel.singular.toLowerCase()} is not here.`,
|
|
162
|
+
back: { href: back, label: listTitle },
|
|
163
|
+
onRetry: refetch,
|
|
164
|
+
maxWidth: "max-w-4xl"
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const inactive = resource.status !== "active";
|
|
169
|
+
return /* @__PURE__ */ jsx(
|
|
170
|
+
DetailPage,
|
|
171
|
+
{
|
|
172
|
+
maxWidth: "max-w-4xl",
|
|
173
|
+
breadcrumbs: [
|
|
174
|
+
{ label: listTitle, href: back, icon: /* @__PURE__ */ jsx(Boxes, {}) },
|
|
175
|
+
{ label: resource.name }
|
|
176
|
+
],
|
|
177
|
+
leading: resource.imageUrl ? (
|
|
178
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
179
|
+
/* @__PURE__ */ jsx(
|
|
180
|
+
"img",
|
|
181
|
+
{
|
|
182
|
+
src: resource.imageUrl,
|
|
183
|
+
alt: "",
|
|
184
|
+
className: "size-10 squircle object-cover"
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
) : /* @__PURE__ */ jsx(GeneratedAvatar, { name: resource.name, className: "size-10" }),
|
|
188
|
+
title: resource.name,
|
|
189
|
+
badges: /* @__PURE__ */ jsx(StatusBadge, { status: inactive ? "inactive" : "active" }),
|
|
190
|
+
actions: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
191
|
+
/* @__PURE__ */ jsxs(OverflowMenu, { children: [
|
|
192
|
+
/* @__PURE__ */ jsx(OverflowItem, { icon: /* @__PURE__ */ jsx(Power, {}), onClick: handleToggleStatus, children: inactive ? "Make bookable" : "Take off the board" }),
|
|
193
|
+
/* @__PURE__ */ jsx(OverflowItem, { destructive: true, icon: /* @__PURE__ */ jsx(Trash2, {}), onClick: handleDelete, children: "Delete" })
|
|
194
|
+
] }),
|
|
195
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleSave, loading: saving, children: saved ? "Saved" : "Save" })
|
|
196
|
+
] }),
|
|
197
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
198
|
+
/* @__PURE__ */ jsx(ErrorBanner, { children: error }),
|
|
199
|
+
/* @__PURE__ */ jsx(EditorSection, { title: "What a customer sees", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
|
|
200
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
|
|
201
|
+
kind === "person" && /* @__PURE__ */ jsx(
|
|
202
|
+
ImageUpload,
|
|
203
|
+
{
|
|
204
|
+
value: imageUrl || void 0,
|
|
205
|
+
onChange: (url) => setImageUrl(url ?? ""),
|
|
206
|
+
label: "Photo",
|
|
207
|
+
aspectRatio: "square",
|
|
208
|
+
size: "avatar"
|
|
209
|
+
}
|
|
210
|
+
),
|
|
211
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
|
|
212
|
+
Field,
|
|
213
|
+
{
|
|
214
|
+
label: kind === "person" ? "Full name" : "Name",
|
|
215
|
+
required: true,
|
|
216
|
+
children: /* @__PURE__ */ jsx(
|
|
217
|
+
Input,
|
|
218
|
+
{
|
|
219
|
+
value: name,
|
|
220
|
+
onChange: (e) => setName(e.target.value)
|
|
221
|
+
}
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
) })
|
|
225
|
+
] }),
|
|
226
|
+
groups.length > 0 && // Bottom-aligned with the name beside it: the photo makes that
|
|
227
|
+
// cell tall, and the name sits at its foot, so a top-aligned
|
|
228
|
+
// Group read a row higher than the field next to it.
|
|
229
|
+
/* @__PURE__ */ jsx("div", { className: kind === "person" ? "md:self-end" : void 0, children: /* @__PURE__ */ jsx(Field, { label: "Group", children: /* @__PURE__ */ jsx(
|
|
230
|
+
Select,
|
|
231
|
+
{
|
|
232
|
+
value: categoryId,
|
|
233
|
+
onChange: setCategoryId,
|
|
234
|
+
options: groups.map((g) => ({
|
|
235
|
+
value: g.id,
|
|
236
|
+
label: g.labelPlural
|
|
237
|
+
})),
|
|
238
|
+
placeholder: "In no group"
|
|
239
|
+
}
|
|
240
|
+
) }) }),
|
|
241
|
+
isMultiSite && /* @__PURE__ */ jsx(Field, { label: "Where", children: /* @__PURE__ */ jsx(
|
|
242
|
+
Select,
|
|
243
|
+
{
|
|
244
|
+
value: locationId,
|
|
245
|
+
onChange: setLocationId,
|
|
246
|
+
options: locations.map((l) => ({
|
|
247
|
+
value: l.id,
|
|
248
|
+
label: l.name
|
|
249
|
+
})),
|
|
250
|
+
placeholder: "Main location"
|
|
251
|
+
}
|
|
252
|
+
) }),
|
|
253
|
+
kind === "person" && /* @__PURE__ */ jsx(
|
|
254
|
+
Field,
|
|
255
|
+
{
|
|
256
|
+
label: "Skills",
|
|
257
|
+
hint: "Comma separated. A service can ask for one of these.",
|
|
258
|
+
children: /* @__PURE__ */ jsx(
|
|
259
|
+
Input,
|
|
260
|
+
{
|
|
261
|
+
value: skills,
|
|
262
|
+
onChange: (e) => setSkills(e.target.value),
|
|
263
|
+
placeholder: "e.g. Coloring, Braids, Styling"
|
|
264
|
+
}
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
),
|
|
268
|
+
/* @__PURE__ */ jsx("div", { className: "md:col-span-2", children: /* @__PURE__ */ jsx(Field, { label: "Description", children: /* @__PURE__ */ jsx(
|
|
269
|
+
Textarea,
|
|
270
|
+
{
|
|
271
|
+
value: description,
|
|
272
|
+
onChange: (e) => setDescription(e.target.value),
|
|
273
|
+
rows: 3,
|
|
274
|
+
className: "resize-none"
|
|
275
|
+
}
|
|
276
|
+
) }) }),
|
|
277
|
+
kind !== "person" && /* @__PURE__ */ jsx("div", { className: "md:col-span-2", children: /* @__PURE__ */ jsx(
|
|
278
|
+
ImageUpload,
|
|
279
|
+
{
|
|
280
|
+
value: imageUrl || void 0,
|
|
281
|
+
onChange: (url) => setImageUrl(url ?? ""),
|
|
282
|
+
label: "Image",
|
|
283
|
+
aspectRatio: "video"
|
|
284
|
+
}
|
|
285
|
+
) })
|
|
286
|
+
] }) }),
|
|
287
|
+
/* @__PURE__ */ jsx(EditorSection, { title: "How it is booked", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-4", children: [
|
|
288
|
+
!byTheNight && /* @__PURE__ */ jsx(Field, { label: "Duration", hint: "Minutes", children: /* @__PURE__ */ jsx(
|
|
289
|
+
NumberField,
|
|
290
|
+
{
|
|
291
|
+
min: 5,
|
|
292
|
+
decimal: false,
|
|
293
|
+
value: defaultDuration,
|
|
294
|
+
onChange: (v) => setDefaultDuration(v ?? 5)
|
|
295
|
+
}
|
|
296
|
+
) }),
|
|
297
|
+
!byTheNight && /* @__PURE__ */ jsx(Field, { label: "Gap after", hint: "Minutes", children: /* @__PURE__ */ jsx(
|
|
298
|
+
NumberField,
|
|
299
|
+
{
|
|
300
|
+
min: 0,
|
|
301
|
+
decimal: false,
|
|
302
|
+
value: bufferMinutes,
|
|
303
|
+
onChange: (v) => setBufferMinutes(v ?? 0)
|
|
304
|
+
}
|
|
305
|
+
) }),
|
|
306
|
+
/* @__PURE__ */ jsx(Field, { label: "Booked ahead", hint: "Days", children: /* @__PURE__ */ jsx(
|
|
307
|
+
NumberField,
|
|
308
|
+
{
|
|
309
|
+
min: 1,
|
|
310
|
+
decimal: false,
|
|
311
|
+
value: advanceBookingDays,
|
|
312
|
+
onChange: (v) => setAdvanceBookingDays(v ?? 1)
|
|
313
|
+
}
|
|
314
|
+
) }),
|
|
315
|
+
/* @__PURE__ */ jsx(Field, { label: byTheNight ? "Price a night" : "Price", children: /* @__PURE__ */ jsx(
|
|
316
|
+
Input,
|
|
317
|
+
{
|
|
318
|
+
type: "number",
|
|
319
|
+
min: 0,
|
|
320
|
+
step: "0.01",
|
|
321
|
+
value: price,
|
|
322
|
+
onChange: (e) => setPrice(e.target.value),
|
|
323
|
+
placeholder: "0.00"
|
|
324
|
+
}
|
|
325
|
+
) }),
|
|
326
|
+
(kind === "space" || kind === "equipment") && /* @__PURE__ */ jsx(Field, { label: "At once", hint: "How many can share it", children: /* @__PURE__ */ jsx(
|
|
327
|
+
NumberField,
|
|
328
|
+
{
|
|
329
|
+
min: 1,
|
|
330
|
+
decimal: false,
|
|
331
|
+
value: maxBookingsPerSlot,
|
|
332
|
+
onChange: (v) => setMaxBookingsPerSlot(v ?? 1)
|
|
333
|
+
}
|
|
334
|
+
) })
|
|
335
|
+
] }) }),
|
|
336
|
+
!byTheNight && /* @__PURE__ */ jsx(EditorSection, { title: "The week it works", children: /* @__PURE__ */ jsx(
|
|
337
|
+
ScheduleEditor,
|
|
338
|
+
{
|
|
339
|
+
title: null,
|
|
340
|
+
schedule,
|
|
341
|
+
onChange: setSchedule
|
|
342
|
+
}
|
|
343
|
+
) })
|
|
344
|
+
] })
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
export {
|
|
349
|
+
ResourceRecordPage as default
|
|
350
|
+
};
|
|
351
|
+
//# sourceMappingURL=page.js.map
|