@hanzo/booker 0.1.0
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/README.md +78 -0
- package/dist/cjs/Booker.cjs +153 -0
- package/dist/cjs/Booker.native.js +158 -0
- package/dist/cjs/Booker.native.js.map +1 -0
- package/dist/cjs/BookingForm.cjs +197 -0
- package/dist/cjs/BookingForm.native.js +203 -0
- package/dist/cjs/BookingForm.native.js.map +1 -0
- package/dist/cjs/CalendarEmbed.cjs +121 -0
- package/dist/cjs/CalendarEmbed.native.js +125 -0
- package/dist/cjs/CalendarEmbed.native.js.map +1 -0
- package/dist/cjs/Confirmation.cjs +177 -0
- package/dist/cjs/Confirmation.native.js +185 -0
- package/dist/cjs/Confirmation.native.js.map +1 -0
- package/dist/cjs/EventHeader.cjs +112 -0
- package/dist/cjs/EventHeader.native.js +118 -0
- package/dist/cjs/EventHeader.native.js.map +1 -0
- package/dist/cjs/MonthCalendar.cjs +177 -0
- package/dist/cjs/MonthCalendar.native.js +191 -0
- package/dist/cjs/MonthCalendar.native.js.map +1 -0
- package/dist/cjs/TimeSlots.cjs +119 -0
- package/dist/cjs/TimeSlots.native.js +126 -0
- package/dist/cjs/TimeSlots.native.js.map +1 -0
- package/dist/cjs/client.cjs +136 -0
- package/dist/cjs/client.native.js +267 -0
- package/dist/cjs/client.native.js.map +1 -0
- package/dist/cjs/hooks.cjs +193 -0
- package/dist/cjs/hooks.native.js +221 -0
- package/dist/cjs/hooks.native.js.map +1 -0
- package/dist/cjs/index.cjs +71 -0
- package/dist/cjs/index.native.js +74 -0
- package/dist/cjs/index.native.js.map +1 -0
- package/dist/cjs/time.cjs +145 -0
- package/dist/cjs/time.native.js +150 -0
- package/dist/cjs/time.native.js.map +1 -0
- package/dist/cjs/useBooker.cjs +151 -0
- package/dist/cjs/useBooker.native.js +173 -0
- package/dist/cjs/useBooker.native.js.map +1 -0
- package/dist/esm/Booker.mjs +128 -0
- package/dist/esm/Booker.mjs.map +1 -0
- package/dist/esm/Booker.native.js +130 -0
- package/dist/esm/Booker.native.js.map +1 -0
- package/dist/esm/BookingForm.mjs +172 -0
- package/dist/esm/BookingForm.mjs.map +1 -0
- package/dist/esm/BookingForm.native.js +175 -0
- package/dist/esm/BookingForm.native.js.map +1 -0
- package/dist/esm/CalendarEmbed.mjs +96 -0
- package/dist/esm/CalendarEmbed.mjs.map +1 -0
- package/dist/esm/CalendarEmbed.native.js +97 -0
- package/dist/esm/CalendarEmbed.native.js.map +1 -0
- package/dist/esm/Confirmation.mjs +152 -0
- package/dist/esm/Confirmation.mjs.map +1 -0
- package/dist/esm/Confirmation.native.js +157 -0
- package/dist/esm/Confirmation.native.js.map +1 -0
- package/dist/esm/EventHeader.mjs +87 -0
- package/dist/esm/EventHeader.mjs.map +1 -0
- package/dist/esm/EventHeader.native.js +90 -0
- package/dist/esm/EventHeader.native.js.map +1 -0
- package/dist/esm/MonthCalendar.mjs +152 -0
- package/dist/esm/MonthCalendar.mjs.map +1 -0
- package/dist/esm/MonthCalendar.native.js +163 -0
- package/dist/esm/MonthCalendar.native.js.map +1 -0
- package/dist/esm/TimeSlots.mjs +94 -0
- package/dist/esm/TimeSlots.mjs.map +1 -0
- package/dist/esm/TimeSlots.native.js +98 -0
- package/dist/esm/TimeSlots.native.js.map +1 -0
- package/dist/esm/client.mjs +104 -0
- package/dist/esm/client.mjs.map +1 -0
- package/dist/esm/client.native.js +232 -0
- package/dist/esm/client.native.js.map +1 -0
- package/dist/esm/hooks.mjs +165 -0
- package/dist/esm/hooks.mjs.map +1 -0
- package/dist/esm/hooks.native.js +190 -0
- package/dist/esm/hooks.native.js.map +1 -0
- package/dist/esm/index.js +13 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/index.mjs +13 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/index.native.js +13 -0
- package/dist/esm/index.native.js.map +1 -0
- package/dist/esm/time.mjs +107 -0
- package/dist/esm/time.mjs.map +1 -0
- package/dist/esm/time.native.js +109 -0
- package/dist/esm/time.native.js.map +1 -0
- package/dist/esm/useBooker.mjs +126 -0
- package/dist/esm/useBooker.mjs.map +1 -0
- package/dist/esm/useBooker.native.js +145 -0
- package/dist/esm/useBooker.native.js.map +1 -0
- package/package.json +61 -0
- package/src/Booker.tsx +152 -0
- package/src/BookingForm.tsx +180 -0
- package/src/CalendarEmbed.tsx +111 -0
- package/src/Confirmation.tsx +145 -0
- package/src/EventHeader.tsx +85 -0
- package/src/MonthCalendar.tsx +179 -0
- package/src/TimeSlots.tsx +102 -0
- package/src/client.ts +218 -0
- package/src/hooks.ts +180 -0
- package/src/index.ts +72 -0
- package/src/time.ts +131 -0
- package/src/useBooker.ts +187 -0
- package/types/Booker.d.ts +16 -0
- package/types/Booker.d.ts.map +1 -0
- package/types/BookingForm.d.ts +13 -0
- package/types/BookingForm.d.ts.map +1 -0
- package/types/CalendarEmbed.d.ts +15 -0
- package/types/CalendarEmbed.d.ts.map +1 -0
- package/types/Confirmation.d.ts +12 -0
- package/types/Confirmation.d.ts.map +1 -0
- package/types/EventHeader.d.ts +10 -0
- package/types/EventHeader.d.ts.map +1 -0
- package/types/MonthCalendar.d.ts +14 -0
- package/types/MonthCalendar.d.ts.map +1 -0
- package/types/TimeSlots.d.ts +15 -0
- package/types/TimeSlots.d.ts.map +1 -0
- package/types/client.d.ts +77 -0
- package/types/client.d.ts.map +1 -0
- package/types/hooks.d.ts +43 -0
- package/types/hooks.d.ts.map +1 -0
- package/types/index.d.ts +12 -0
- package/types/index.d.ts.map +1 -0
- package/types/time.d.ts +38 -0
- package/types/time.d.ts.map +1 -0
- package/types/useBooker.d.ts +41 -0
- package/types/useBooker.d.ts.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# @hanzo/calendar
|
|
2
|
+
|
|
3
|
+
Universal (web + native) scheduling UI for the [Hanzo Calendar](https://api.hanzo.ai/v1/calendar), built with [hanzogui](https://github.com/hanzoai/gui) primitives.
|
|
4
|
+
|
|
5
|
+
One booking flow — event header → month grid → time slots → details → confirmation — that runs unchanged on the web (DOM) and React Native (iOS / Android). No raw HTML, no ad-hoc CSS: every surface is a hanzogui/Tamagui component styled with theme tokens, so it inherits the host app's theme, dark mode, and design system.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
bun add @hanzo/calendar
|
|
11
|
+
# peer deps: hanzogui, react (and react-native for native targets)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Render inside a `GuiProvider` (from `hanzogui`) so tokens and themes resolve.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { GuiProvider } from 'hanzogui'
|
|
20
|
+
import { Booker } from '@hanzo/calendar'
|
|
21
|
+
import config from './gui.config' // your createGui(...) config
|
|
22
|
+
|
|
23
|
+
export function BookMeeting() {
|
|
24
|
+
return (
|
|
25
|
+
<GuiProvider config={config} defaultTheme="light">
|
|
26
|
+
<Booker
|
|
27
|
+
host="hanzo"
|
|
28
|
+
eventSlug="intro"
|
|
29
|
+
onBooked={(booking) => console.log('booked', booking.uid)}
|
|
30
|
+
/>
|
|
31
|
+
</GuiProvider>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
That's the whole integration. `Booker` fetches the public event type, renders a navigable month calendar, loads availability for the visible range, converts UTC slots into the visitor's time zone (`Intl.DateTimeFormat().resolvedOptions().timeZone`), collects attendee details, and posts the booking — with loading, error, empty, and "slot just taken" (HTTP 409) states handled throughout.
|
|
37
|
+
|
|
38
|
+
## Components
|
|
39
|
+
|
|
40
|
+
| Component | Purpose |
|
|
41
|
+
| ---------------- | ----------------------------------------------------------------------- |
|
|
42
|
+
| `Booker` | Full scheduling flow: event → month → times → details → confirmation. |
|
|
43
|
+
| `CalendarEmbed` | Compact card for a marketing hero — soonest availability inline. |
|
|
44
|
+
| `Confirmation` | Booking confirmation card; pass a `booking` or a `uid` to fetch one. |
|
|
45
|
+
| `EventHeader`, `MonthCalendar`, `TimeSlots`, `BookingForm` | Composable sub-views for a custom flow. |
|
|
46
|
+
|
|
47
|
+
### Props
|
|
48
|
+
|
|
49
|
+
`Booker` and `CalendarEmbed`:
|
|
50
|
+
|
|
51
|
+
- `host` — calendar owner's username, e.g. `"hanzo"`.
|
|
52
|
+
- `eventSlug` — event-type slug, e.g. `"intro"`.
|
|
53
|
+
- `apiUrl?` — API base; defaults to `https://api.hanzo.ai/v1/calendar`.
|
|
54
|
+
- `timeZone?` — visitor IANA zone; defaults to the browser/device zone.
|
|
55
|
+
- `weekStartsOn?` — `0` (Sunday, default) or `1` (Monday).
|
|
56
|
+
- `onBooked?(booking)` — called with the created booking.
|
|
57
|
+
|
|
58
|
+
`Confirmation`:
|
|
59
|
+
|
|
60
|
+
- `booking?` — a booking object, or
|
|
61
|
+
- `uid?` — a booking id to fetch (with `apiUrl?`, `timeZone?`, `onDone?`).
|
|
62
|
+
|
|
63
|
+
## Data & time helpers
|
|
64
|
+
|
|
65
|
+
The pure, framework-free data plane (`fetchEventType`, `fetchSlots`, `createBooking`, `fetchBooking`, `cancelBooking`) and time plane (`visitorTimeZone`, `formatSlotTime`, `monthMatrix`, …) are exported for building a bespoke flow or a headless integration. The `useBooker` hook exposes the entire state machine.
|
|
66
|
+
|
|
67
|
+
## Backend
|
|
68
|
+
|
|
69
|
+
Speaks the Hanzo Calendar API (Cal API-v2 shapes):
|
|
70
|
+
|
|
71
|
+
- `GET /atoms/event-types/{slug}/public?username={host}`
|
|
72
|
+
- `GET /slots/available?eventTypeSlug=&usernameList=&startTime=&endTime=&timeZone=`
|
|
73
|
+
- `POST /bookings` (`cal-api-version: 2024-08-13`)
|
|
74
|
+
- `GET /bookings/{uid}` · `POST /bookings/{uid}/cancel`
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
BSD-3-Clause © Hanzo AI
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all) __defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
21
|
+
value: true
|
|
22
|
+
}), mod);
|
|
23
|
+
var Booker_exports = {};
|
|
24
|
+
__export(Booker_exports, {
|
|
25
|
+
Booker: () => Booker
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(Booker_exports);
|
|
28
|
+
var import_hanzogui = require("hanzogui");
|
|
29
|
+
var import_BookingForm = require("./BookingForm.cjs");
|
|
30
|
+
var import_Confirmation = require("./Confirmation.cjs");
|
|
31
|
+
var import_EventHeader = require("./EventHeader.cjs");
|
|
32
|
+
var import_MonthCalendar = require("./MonthCalendar.cjs");
|
|
33
|
+
var import_TimeSlots = require("./TimeSlots.cjs");
|
|
34
|
+
var import_useBooker = require("./useBooker.cjs");
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
function Booker(props) {
|
|
37
|
+
const m = (0, import_useBooker.useBooker)(props);
|
|
38
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
39
|
+
backgroundColor: "$background",
|
|
40
|
+
borderColor: "$borderColor",
|
|
41
|
+
borderWidth: 1,
|
|
42
|
+
borderRadius: "$6",
|
|
43
|
+
padding: "$4",
|
|
44
|
+
gap: "$4",
|
|
45
|
+
width: "100%",
|
|
46
|
+
maxWidth: 860,
|
|
47
|
+
alignSelf: "center",
|
|
48
|
+
children: m.event.loading ? /* @__PURE__ */(0, import_jsx_runtime.jsxs)(StatePanel, {
|
|
49
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.Spinner, {
|
|
50
|
+
size: "large",
|
|
51
|
+
color: "$color9"
|
|
52
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
53
|
+
size: "$3",
|
|
54
|
+
color: "$color10",
|
|
55
|
+
children: "Loading\u2026"
|
|
56
|
+
})]
|
|
57
|
+
}) : m.event.error || !m.event.data ? /* @__PURE__ */(0, import_jsx_runtime.jsxs)(StatePanel, {
|
|
58
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
59
|
+
size: "$5",
|
|
60
|
+
fontWeight: "600",
|
|
61
|
+
color: "$color12",
|
|
62
|
+
children: "Couldn't load this event"
|
|
63
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
64
|
+
size: "$3",
|
|
65
|
+
color: "$color10",
|
|
66
|
+
textAlign: "center",
|
|
67
|
+
children: m.event.error ?? "The event type was not found."
|
|
68
|
+
})]
|
|
69
|
+
}) : m.phase === "done" && m.booking ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_Confirmation.Confirmation, {
|
|
70
|
+
booking: m.booking,
|
|
71
|
+
timeZone: m.timeZone,
|
|
72
|
+
onDone: m.reset
|
|
73
|
+
}) : /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.YStack, {
|
|
74
|
+
gap: "$4",
|
|
75
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_EventHeader.EventHeader, {
|
|
76
|
+
event: m.event.data,
|
|
77
|
+
host: props.host,
|
|
78
|
+
timeZone: m.timeZone,
|
|
79
|
+
compact: m.phase === "form"
|
|
80
|
+
}), m.phase === "form" && m.selectedSlot ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_BookingForm.BookingForm, {
|
|
81
|
+
slotIso: m.selectedSlot,
|
|
82
|
+
timeZone: m.timeZone,
|
|
83
|
+
eventLength: m.event.data.length,
|
|
84
|
+
submitting: m.submitting,
|
|
85
|
+
error: m.error,
|
|
86
|
+
onSubmit: m.submit,
|
|
87
|
+
onBack: m.back
|
|
88
|
+
}) : /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
|
|
89
|
+
children: [m.conflict ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(JustTakenBanner, {}) : null, m.slots.error ? /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.SizableText, {
|
|
90
|
+
size: "$2",
|
|
91
|
+
color: "$red10",
|
|
92
|
+
children: ["Couldn't load availability: ", m.slots.error]
|
|
93
|
+
}) : null, /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.XStack, {
|
|
94
|
+
gap: "$5",
|
|
95
|
+
flexDirection: "column",
|
|
96
|
+
$sm: {
|
|
97
|
+
flexDirection: "row"
|
|
98
|
+
},
|
|
99
|
+
alignItems: "flex-start",
|
|
100
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_MonthCalendar.MonthCalendar, {
|
|
101
|
+
viewDate: m.viewDate,
|
|
102
|
+
availableKeys: m.availableKeys,
|
|
103
|
+
selectedDay: m.selectedDay,
|
|
104
|
+
onSelectDay: m.selectDay,
|
|
105
|
+
onPrev: m.goPrevMonth,
|
|
106
|
+
onNext: m.goNextMonth,
|
|
107
|
+
atFirstMonth: m.atFirstMonth,
|
|
108
|
+
weekStartsOn: m.weekStartsOn,
|
|
109
|
+
loading: m.slots.loading
|
|
110
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_TimeSlots.TimeSlots, {
|
|
111
|
+
dayKey: m.selectedDay,
|
|
112
|
+
slots: m.daySlots,
|
|
113
|
+
timeZone: m.timeZone,
|
|
114
|
+
onPick: m.selectSlot,
|
|
115
|
+
selectedIso: m.selectedSlot,
|
|
116
|
+
loading: m.slots.loading && !m.selectedDay
|
|
117
|
+
})]
|
|
118
|
+
}), m.availableKeys.size === 0 && !m.slots.loading && !m.slots.error ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
119
|
+
size: "$3",
|
|
120
|
+
color: "$color10",
|
|
121
|
+
textAlign: "center",
|
|
122
|
+
children: "No availability this month \u2014 try the next month."
|
|
123
|
+
}) : null]
|
|
124
|
+
})]
|
|
125
|
+
})
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function StatePanel({
|
|
129
|
+
children
|
|
130
|
+
}) {
|
|
131
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
132
|
+
alignItems: "center",
|
|
133
|
+
justifyContent: "center",
|
|
134
|
+
gap: "$3",
|
|
135
|
+
padding: "$8",
|
|
136
|
+
minHeight: 220,
|
|
137
|
+
children
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function JustTakenBanner() {
|
|
141
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
142
|
+
backgroundColor: "$yellow3",
|
|
143
|
+
borderColor: "$yellow6",
|
|
144
|
+
borderWidth: 1,
|
|
145
|
+
borderRadius: "$4",
|
|
146
|
+
padding: "$2.5",
|
|
147
|
+
children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
148
|
+
size: "$2",
|
|
149
|
+
color: "$yellow11",
|
|
150
|
+
children: "That time was just taken. We refreshed the calendar \u2014 please pick another."
|
|
151
|
+
})
|
|
152
|
+
});
|
|
153
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: () => from[key],
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
}), mod);
|
|
25
|
+
var Booker_exports = {};
|
|
26
|
+
__export(Booker_exports, {
|
|
27
|
+
Booker: () => Booker
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(Booker_exports);
|
|
30
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
31
|
+
var import_hanzogui = require("hanzogui");
|
|
32
|
+
var import_BookingForm = require("./BookingForm.native.js");
|
|
33
|
+
var import_Confirmation = require("./Confirmation.native.js");
|
|
34
|
+
var import_EventHeader = require("./EventHeader.native.js");
|
|
35
|
+
var import_MonthCalendar = require("./MonthCalendar.native.js");
|
|
36
|
+
var import_TimeSlots = require("./TimeSlots.native.js");
|
|
37
|
+
var import_useBooker = require("./useBooker.native.js");
|
|
38
|
+
function Booker(props) {
|
|
39
|
+
var m = (0, import_useBooker.useBooker)(props);
|
|
40
|
+
var _m_event_error;
|
|
41
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
42
|
+
backgroundColor: "$background",
|
|
43
|
+
borderColor: "$borderColor",
|
|
44
|
+
borderWidth: 1,
|
|
45
|
+
borderRadius: "$6",
|
|
46
|
+
padding: "$4",
|
|
47
|
+
gap: "$4",
|
|
48
|
+
width: "100%",
|
|
49
|
+
maxWidth: 860,
|
|
50
|
+
alignSelf: "center",
|
|
51
|
+
children: m.event.loading ? /* @__PURE__ */(0, import_jsx_runtime.jsxs)(StatePanel, {
|
|
52
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.Spinner, {
|
|
53
|
+
size: "large",
|
|
54
|
+
color: "$color9"
|
|
55
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
56
|
+
size: "$3",
|
|
57
|
+
color: "$color10",
|
|
58
|
+
children: "Loading\u2026"
|
|
59
|
+
})]
|
|
60
|
+
}) : m.event.error || !m.event.data ? /* @__PURE__ */(0, import_jsx_runtime.jsxs)(StatePanel, {
|
|
61
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
62
|
+
size: "$5",
|
|
63
|
+
fontWeight: "600",
|
|
64
|
+
color: "$color12",
|
|
65
|
+
children: "Couldn't load this event"
|
|
66
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
67
|
+
size: "$3",
|
|
68
|
+
color: "$color10",
|
|
69
|
+
textAlign: "center",
|
|
70
|
+
children: (_m_event_error = m.event.error) !== null && _m_event_error !== void 0 ? _m_event_error : "The event type was not found."
|
|
71
|
+
})]
|
|
72
|
+
}) : m.phase === "done" && m.booking ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_Confirmation.Confirmation, {
|
|
73
|
+
booking: m.booking,
|
|
74
|
+
timeZone: m.timeZone,
|
|
75
|
+
onDone: m.reset
|
|
76
|
+
}) : /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.YStack, {
|
|
77
|
+
gap: "$4",
|
|
78
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_EventHeader.EventHeader, {
|
|
79
|
+
event: m.event.data,
|
|
80
|
+
host: props.host,
|
|
81
|
+
timeZone: m.timeZone,
|
|
82
|
+
compact: m.phase === "form"
|
|
83
|
+
}), m.phase === "form" && m.selectedSlot ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_BookingForm.BookingForm, {
|
|
84
|
+
slotIso: m.selectedSlot,
|
|
85
|
+
timeZone: m.timeZone,
|
|
86
|
+
eventLength: m.event.data.length,
|
|
87
|
+
submitting: m.submitting,
|
|
88
|
+
error: m.error,
|
|
89
|
+
onSubmit: m.submit,
|
|
90
|
+
onBack: m.back
|
|
91
|
+
}) : /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
|
|
92
|
+
children: [m.conflict ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(JustTakenBanner, {}) : null, m.slots.error ? /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.SizableText, {
|
|
93
|
+
size: "$2",
|
|
94
|
+
color: "$red10",
|
|
95
|
+
children: ["Couldn't load availability: ", m.slots.error]
|
|
96
|
+
}) : null, /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.XStack, {
|
|
97
|
+
gap: "$5",
|
|
98
|
+
flexDirection: "column",
|
|
99
|
+
$sm: {
|
|
100
|
+
flexDirection: "row"
|
|
101
|
+
},
|
|
102
|
+
alignItems: "flex-start",
|
|
103
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_MonthCalendar.MonthCalendar, {
|
|
104
|
+
viewDate: m.viewDate,
|
|
105
|
+
availableKeys: m.availableKeys,
|
|
106
|
+
selectedDay: m.selectedDay,
|
|
107
|
+
onSelectDay: m.selectDay,
|
|
108
|
+
onPrev: m.goPrevMonth,
|
|
109
|
+
onNext: m.goNextMonth,
|
|
110
|
+
atFirstMonth: m.atFirstMonth,
|
|
111
|
+
weekStartsOn: m.weekStartsOn,
|
|
112
|
+
loading: m.slots.loading
|
|
113
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_TimeSlots.TimeSlots, {
|
|
114
|
+
dayKey: m.selectedDay,
|
|
115
|
+
slots: m.daySlots,
|
|
116
|
+
timeZone: m.timeZone,
|
|
117
|
+
onPick: m.selectSlot,
|
|
118
|
+
selectedIso: m.selectedSlot,
|
|
119
|
+
loading: m.slots.loading && !m.selectedDay
|
|
120
|
+
})]
|
|
121
|
+
}), m.availableKeys.size === 0 && !m.slots.loading && !m.slots.error ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
122
|
+
size: "$3",
|
|
123
|
+
color: "$color10",
|
|
124
|
+
textAlign: "center",
|
|
125
|
+
children: "No availability this month \u2014 try the next month."
|
|
126
|
+
}) : null]
|
|
127
|
+
})]
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function StatePanel(param) {
|
|
132
|
+
var {
|
|
133
|
+
children
|
|
134
|
+
} = param;
|
|
135
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
136
|
+
alignItems: "center",
|
|
137
|
+
justifyContent: "center",
|
|
138
|
+
gap: "$3",
|
|
139
|
+
padding: "$8",
|
|
140
|
+
minHeight: 220,
|
|
141
|
+
children
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function JustTakenBanner() {
|
|
145
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
146
|
+
backgroundColor: "$yellow3",
|
|
147
|
+
borderColor: "$yellow6",
|
|
148
|
+
borderWidth: 1,
|
|
149
|
+
borderRadius: "$4",
|
|
150
|
+
padding: "$2.5",
|
|
151
|
+
children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
152
|
+
size: "$2",
|
|
153
|
+
color: "$yellow11",
|
|
154
|
+
children: "That time was just taken. We refreshed the calendar \u2014 please pick another."
|
|
155
|
+
})
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=Booker.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","Booker_exports","__export","Booker","module","exports","import_jsx_runtime","require","import_hanzogui","import_BookingForm","import_Confirmation","import_EventHeader","import_MonthCalendar","import_TimeSlots","import_useBooker","props","m","useBooker","_m_event_error","jsx","YStack","backgroundColor","borderColor","borderWidth","borderRadius","padding","gap","width","maxWidth","alignSelf","children","event","loading","jsxs","StatePanel","Spinner","size","color","SizableText","error","data","fontWeight","textAlign","phase","booking","Confirmation","timeZone","onDone","reset","EventHeader","host","compact","selectedSlot","BookingForm","slotIso","eventLength","length","submitting","onSubmit","submit","onBack","back","Fragment","conflict","JustTakenBanner","slots","XStack","flexDirection","$sm","alignItems","MonthCalendar","viewDate","availableKeys","selectedDay","onSelectDay","selectDay","onPrev","goPrevMonth","onNext","goNextMonth","atFirstMonth","weekStartsOn","TimeSlots","dayKey","daySlots","onPick","selectSlot","selectedIso","param"],"sources":["../../src/Booker.tsx"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all) __defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
21
|
+
value: true
|
|
22
|
+
}), mod);
|
|
23
|
+
var BookingForm_exports = {};
|
|
24
|
+
__export(BookingForm_exports, {
|
|
25
|
+
BookingForm: () => BookingForm
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(BookingForm_exports);
|
|
28
|
+
var import_react = require("react");
|
|
29
|
+
var import_hanzogui = require("hanzogui");
|
|
30
|
+
var import_time = require("./time.cjs");
|
|
31
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
32
|
+
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
33
|
+
function BookingForm({
|
|
34
|
+
slotIso,
|
|
35
|
+
timeZone,
|
|
36
|
+
eventLength,
|
|
37
|
+
submitting,
|
|
38
|
+
error,
|
|
39
|
+
onSubmit,
|
|
40
|
+
onBack
|
|
41
|
+
}) {
|
|
42
|
+
const [name, setName] = (0, import_react.useState)("");
|
|
43
|
+
const [email, setEmail] = (0, import_react.useState)("");
|
|
44
|
+
const [notes, setNotes] = (0, import_react.useState)("");
|
|
45
|
+
const [touched, setTouched] = (0, import_react.useState)(false);
|
|
46
|
+
const nameValid = name.trim().length > 0;
|
|
47
|
+
const emailValid = EMAIL_RE.test(email.trim());
|
|
48
|
+
const valid = nameValid && emailValid;
|
|
49
|
+
const submit = () => {
|
|
50
|
+
setTouched(true);
|
|
51
|
+
if (!valid || submitting) return;
|
|
52
|
+
onSubmit({
|
|
53
|
+
name: name.trim(),
|
|
54
|
+
email: email.trim(),
|
|
55
|
+
notes: notes.trim() || void 0
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.YStack, {
|
|
59
|
+
gap: "$3",
|
|
60
|
+
flex: 1,
|
|
61
|
+
minWidth: 240,
|
|
62
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.YStack, {
|
|
63
|
+
gap: "$1",
|
|
64
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.XStack, {
|
|
65
|
+
alignItems: "center",
|
|
66
|
+
gap: "$2",
|
|
67
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(BackLink, {
|
|
68
|
+
onPress: onBack
|
|
69
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
70
|
+
size: "$5",
|
|
71
|
+
fontWeight: "700",
|
|
72
|
+
color: "$color12",
|
|
73
|
+
children: "Enter details"
|
|
74
|
+
})]
|
|
75
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.SizableText, {
|
|
76
|
+
size: "$3",
|
|
77
|
+
color: "$color11",
|
|
78
|
+
children: [(0, import_time.formatBookingWhen)(slotIso, timeZone), " \xB7 ", eventLength, " min"]
|
|
79
|
+
})]
|
|
80
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(Field, {
|
|
81
|
+
label: "Name",
|
|
82
|
+
required: true,
|
|
83
|
+
invalid: touched && !nameValid,
|
|
84
|
+
hint: "Please enter your name",
|
|
85
|
+
children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.Input, {
|
|
86
|
+
value: name,
|
|
87
|
+
onChangeText: setName,
|
|
88
|
+
placeholder: "Ada Lovelace",
|
|
89
|
+
autoComplete: "name",
|
|
90
|
+
size: "$4"
|
|
91
|
+
})
|
|
92
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(Field, {
|
|
93
|
+
label: "Email",
|
|
94
|
+
required: true,
|
|
95
|
+
invalid: touched && !emailValid,
|
|
96
|
+
hint: "Please enter a valid email",
|
|
97
|
+
children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.Input, {
|
|
98
|
+
value: email,
|
|
99
|
+
onChangeText: setEmail,
|
|
100
|
+
placeholder: "ada@example.com",
|
|
101
|
+
keyboardType: "email-address",
|
|
102
|
+
autoCapitalize: "none",
|
|
103
|
+
autoComplete: "email",
|
|
104
|
+
size: "$4"
|
|
105
|
+
})
|
|
106
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(Field, {
|
|
107
|
+
label: "Notes",
|
|
108
|
+
hint: "Optional",
|
|
109
|
+
children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.TextArea, {
|
|
110
|
+
value: notes,
|
|
111
|
+
onChangeText: setNotes,
|
|
112
|
+
placeholder: "Anything that would help prepare?",
|
|
113
|
+
numberOfLines: 3,
|
|
114
|
+
size: "$4"
|
|
115
|
+
})
|
|
116
|
+
}), error ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
117
|
+
backgroundColor: "$red3",
|
|
118
|
+
borderColor: "$red6",
|
|
119
|
+
borderWidth: 1,
|
|
120
|
+
borderRadius: "$4",
|
|
121
|
+
padding: "$2.5",
|
|
122
|
+
children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
123
|
+
size: "$2",
|
|
124
|
+
color: "$red11",
|
|
125
|
+
children: error
|
|
126
|
+
})
|
|
127
|
+
}) : null, /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.XStack, {
|
|
128
|
+
gap: "$2",
|
|
129
|
+
justifyContent: "flex-end",
|
|
130
|
+
marginTop: "$1",
|
|
131
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.Button, {
|
|
132
|
+
size: "$4",
|
|
133
|
+
chromeless: true,
|
|
134
|
+
onPress: onBack,
|
|
135
|
+
disabled: submitting,
|
|
136
|
+
children: "Back"
|
|
137
|
+
}), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.Button, {
|
|
138
|
+
size: "$4",
|
|
139
|
+
theme: "blue",
|
|
140
|
+
onPress: submit,
|
|
141
|
+
disabled: submitting || touched && !valid,
|
|
142
|
+
opacity: submitting ? 0.7 : 1,
|
|
143
|
+
children: submitting ? "Booking\u2026" : "Confirm booking"
|
|
144
|
+
})]
|
|
145
|
+
})]
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function Field({
|
|
149
|
+
label,
|
|
150
|
+
required,
|
|
151
|
+
invalid,
|
|
152
|
+
hint,
|
|
153
|
+
children
|
|
154
|
+
}) {
|
|
155
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.YStack, {
|
|
156
|
+
gap: "$1.5",
|
|
157
|
+
children: [/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_hanzogui.SizableText, {
|
|
158
|
+
size: "$2",
|
|
159
|
+
color: "$color11",
|
|
160
|
+
fontWeight: "600",
|
|
161
|
+
children: [label, required ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
162
|
+
color: "$red10",
|
|
163
|
+
children: " *"
|
|
164
|
+
}) : null]
|
|
165
|
+
}), children, invalid && hint ? /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
166
|
+
size: "$1",
|
|
167
|
+
color: "$red10",
|
|
168
|
+
children: hint
|
|
169
|
+
}) : null]
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function BackLink({
|
|
173
|
+
onPress
|
|
174
|
+
}) {
|
|
175
|
+
return /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.YStack, {
|
|
176
|
+
width: 30,
|
|
177
|
+
height: 30,
|
|
178
|
+
alignItems: "center",
|
|
179
|
+
justifyContent: "center",
|
|
180
|
+
borderRadius: "$4",
|
|
181
|
+
cursor: "pointer",
|
|
182
|
+
hoverStyle: {
|
|
183
|
+
backgroundColor: "$color4"
|
|
184
|
+
},
|
|
185
|
+
pressStyle: {
|
|
186
|
+
backgroundColor: "$color6"
|
|
187
|
+
},
|
|
188
|
+
onPress,
|
|
189
|
+
"aria-label": "Back",
|
|
190
|
+
role: "button",
|
|
191
|
+
children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_hanzogui.SizableText, {
|
|
192
|
+
size: "$6",
|
|
193
|
+
color: "$color11",
|
|
194
|
+
children: "\u2039"
|
|
195
|
+
})
|
|
196
|
+
});
|
|
197
|
+
}
|