@wealthx/shadcn 1.5.22 → 1.5.23
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/.turbo/turbo-build.log +78 -78
- package/CHANGELOG.md +6 -0
- package/dist/{chunk-NEMWMXGL.mjs → chunk-3HFOSFOM.mjs} +76 -48
- package/dist/{chunk-F3MIRXRF.mjs → chunk-ONYADWSO.mjs} +7 -1
- package/dist/{chunk-SET6GFGL.mjs → chunk-ZSMQZ3VN.mjs} +96 -73
- package/dist/components/ui/appointment-action-dialogs.js +96 -73
- package/dist/components/ui/appointment-action-dialogs.mjs +1 -1
- package/dist/components/ui/appointment-book-dialog.js +76 -48
- package/dist/components/ui/appointment-book-dialog.mjs +1 -1
- package/dist/components/ui/appointment-detail-sheet.js +102 -73
- package/dist/components/ui/appointment-detail-sheet.mjs +2 -2
- package/dist/index.js +180 -123
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
- package/src/components/ui/appointment-action-dialogs.tsx +67 -21
- package/src/components/ui/appointment-book-dialog.tsx +150 -53
- package/src/components/ui/appointment-detail-sheet.tsx +18 -0
package/dist/index.js
CHANGED
|
@@ -8384,6 +8384,15 @@ function AppointmentConfirmDialog({
|
|
|
8384
8384
|
] })
|
|
8385
8385
|
] }) });
|
|
8386
8386
|
}
|
|
8387
|
+
var DAY_MAP = {
|
|
8388
|
+
Sun: 0,
|
|
8389
|
+
Mon: 1,
|
|
8390
|
+
Tue: 2,
|
|
8391
|
+
Wed: 3,
|
|
8392
|
+
Thu: 4,
|
|
8393
|
+
Fri: 5,
|
|
8394
|
+
Sat: 6
|
|
8395
|
+
};
|
|
8387
8396
|
function AppointmentRescheduleDialog({
|
|
8388
8397
|
open,
|
|
8389
8398
|
onOpenChange,
|
|
@@ -8392,11 +8401,19 @@ function AppointmentRescheduleDialog({
|
|
|
8392
8401
|
currentDate,
|
|
8393
8402
|
currentTimeStart,
|
|
8394
8403
|
currentTimeEnd,
|
|
8404
|
+
onDateChange,
|
|
8405
|
+
schedule,
|
|
8406
|
+
isLoadingSlots,
|
|
8395
8407
|
onReschedule
|
|
8396
8408
|
}) {
|
|
8397
8409
|
const [date, setDate] = import_react13.default.useState(/* @__PURE__ */ new Date());
|
|
8398
8410
|
const [slot, setSlot] = import_react13.default.useState();
|
|
8399
8411
|
const [note, setNote] = import_react13.default.useState("");
|
|
8412
|
+
const today = import_react13.default.useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
8413
|
+
const disabledDayOfWeek = import_react13.default.useMemo(
|
|
8414
|
+
() => schedule == null ? void 0 : schedule.filter((d) => !d.enabled).map((d) => DAY_MAP[d.day]).filter((n) => n !== void 0),
|
|
8415
|
+
[schedule]
|
|
8416
|
+
);
|
|
8400
8417
|
const handleOpenChange = (next) => {
|
|
8401
8418
|
if (!next) {
|
|
8402
8419
|
setDate(/* @__PURE__ */ new Date());
|
|
@@ -8414,87 +8431,93 @@ function AppointmentRescheduleDialog({
|
|
|
8414
8431
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(DialogDescription, { children: "Select a new date and time slot. The client will be notified by email." })
|
|
8415
8432
|
] }),
|
|
8416
8433
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Separator, {}),
|
|
8417
|
-
|
|
8418
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.
|
|
8426
|
-
|
|
8427
|
-
|
|
8434
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-4 overflow-y-auto max-h-[calc(90vh-200px)]", children: [
|
|
8435
|
+
(currentDate || currentTimeStart) && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
8436
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Current booking" }),
|
|
8437
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-4 border border-border bg-muted/30 px-3 py-2.5 text-sm text-muted-foreground", children: [
|
|
8438
|
+
currentDate && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "flex items-center gap-1.5", children: [
|
|
8439
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react23.Calendar, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
8440
|
+
currentDate
|
|
8441
|
+
] }),
|
|
8442
|
+
currentTimeStart && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "flex items-center gap-1.5", children: [
|
|
8443
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react23.Clock, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
8444
|
+
currentTimeStart,
|
|
8445
|
+
currentTimeEnd ? ` \u2013 ${currentTimeEnd}` : ""
|
|
8446
|
+
] })
|
|
8428
8447
|
] })
|
|
8429
|
-
] })
|
|
8430
|
-
] }),
|
|
8431
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "grid grid-cols-[auto_1fr] items-start gap-5", children: [
|
|
8432
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
8433
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Label, { children: "New date" }),
|
|
8434
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
8435
|
-
Calendar3,
|
|
8436
|
-
{
|
|
8437
|
-
mode: "single",
|
|
8438
|
-
selected: date,
|
|
8439
|
-
onSelect: (d) => {
|
|
8440
|
-
setDate(d);
|
|
8441
|
-
setSlot(void 0);
|
|
8442
|
-
},
|
|
8443
|
-
captionLayout: "label",
|
|
8444
|
-
fromDate: /* @__PURE__ */ new Date(),
|
|
8445
|
-
disabled: { before: /* @__PURE__ */ new Date() },
|
|
8446
|
-
className: "border border-border"
|
|
8447
|
-
}
|
|
8448
|
-
)
|
|
8449
8448
|
] }),
|
|
8450
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.
|
|
8451
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex
|
|
8449
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "grid grid-cols-[auto_1fr] items-start gap-5", children: [
|
|
8450
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
8451
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Label, { children: "New date" }),
|
|
8452
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
8453
|
+
Calendar3,
|
|
8454
|
+
{
|
|
8455
|
+
mode: "single",
|
|
8456
|
+
selected: date,
|
|
8457
|
+
onSelect: (d) => {
|
|
8458
|
+
setDate(d);
|
|
8459
|
+
setSlot(void 0);
|
|
8460
|
+
if (d) onDateChange == null ? void 0 : onDateChange(d);
|
|
8461
|
+
},
|
|
8462
|
+
captionLayout: "label",
|
|
8463
|
+
fromDate: today,
|
|
8464
|
+
disabled: disabledDayOfWeek && disabledDayOfWeek.length > 0 ? [{ before: today }, { dayOfWeek: disabledDayOfWeek }] : { before: today },
|
|
8465
|
+
className: "border border-border"
|
|
8466
|
+
}
|
|
8467
|
+
)
|
|
8468
|
+
] }),
|
|
8469
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex flex-col gap-5", children: date ? isLoadingSlots ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-2 py-8 text-center", children: [
|
|
8470
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm font-semibold", children: "Loading slots\u2026" }),
|
|
8471
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", children: "Fetching available times for the selected date." })
|
|
8472
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
8473
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
8474
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm font-semibold", children: "Select a time slot" }),
|
|
8475
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
|
|
8476
|
+
totalAvailable,
|
|
8477
|
+
" available"
|
|
8478
|
+
] })
|
|
8479
|
+
] }),
|
|
8480
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
8481
|
+
AppointmentSlotSection,
|
|
8482
|
+
{
|
|
8483
|
+
label: "Morning",
|
|
8484
|
+
slots: amSlots,
|
|
8485
|
+
selectedSlotId: slot == null ? void 0 : slot.id,
|
|
8486
|
+
onSelect: setSlot
|
|
8487
|
+
}
|
|
8488
|
+
),
|
|
8489
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
8490
|
+
AppointmentSlotSection,
|
|
8491
|
+
{
|
|
8492
|
+
label: "Afternoon",
|
|
8493
|
+
slots: pmSlots,
|
|
8494
|
+
selectedSlotId: slot == null ? void 0 : slot.id,
|
|
8495
|
+
onSelect: setSlot
|
|
8496
|
+
}
|
|
8497
|
+
)
|
|
8498
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-2 py-8 text-center", children: [
|
|
8452
8499
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm font-semibold", children: "Select a time slot" }),
|
|
8453
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8500
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", children: "Pick a date on the left to see available slots." })
|
|
8501
|
+
] }) })
|
|
8502
|
+
] }),
|
|
8503
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
8504
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(Label, { htmlFor: "reschedule-note", children: [
|
|
8505
|
+
"Note",
|
|
8506
|
+
" ",
|
|
8507
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
|
|
8457
8508
|
] }),
|
|
8458
8509
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
8459
|
-
|
|
8460
|
-
{
|
|
8461
|
-
label: "Morning",
|
|
8462
|
-
slots: amSlots,
|
|
8463
|
-
selectedSlotId: slot == null ? void 0 : slot.id,
|
|
8464
|
-
onSelect: setSlot
|
|
8465
|
-
}
|
|
8466
|
-
),
|
|
8467
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
8468
|
-
AppointmentSlotSection,
|
|
8510
|
+
Textarea,
|
|
8469
8511
|
{
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8512
|
+
id: "reschedule-note",
|
|
8513
|
+
placeholder: "e.g. Rescheduling due to an internal conflict \u2014 apologies for the inconvenience\u2026",
|
|
8514
|
+
value: note,
|
|
8515
|
+
onChange: (e) => setNote(e.target.value),
|
|
8516
|
+
className: "w-full resize-none",
|
|
8517
|
+
rows: 2
|
|
8474
8518
|
}
|
|
8475
8519
|
)
|
|
8476
|
-
] })
|
|
8477
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm font-semibold", children: "Select a time slot" }),
|
|
8478
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", children: "Pick a date on the left to see available slots." })
|
|
8479
|
-
] }) })
|
|
8480
|
-
] }),
|
|
8481
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
8482
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(Label, { htmlFor: "reschedule-note", children: [
|
|
8483
|
-
"Note",
|
|
8484
|
-
" ",
|
|
8485
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
|
|
8486
|
-
] }),
|
|
8487
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
8488
|
-
Textarea,
|
|
8489
|
-
{
|
|
8490
|
-
id: "reschedule-note",
|
|
8491
|
-
placeholder: "e.g. Rescheduling due to an internal conflict \u2014 apologies for the inconvenience\u2026",
|
|
8492
|
-
value: note,
|
|
8493
|
-
onChange: (e) => setNote(e.target.value),
|
|
8494
|
-
className: "w-full resize-none",
|
|
8495
|
-
rows: 2
|
|
8496
|
-
}
|
|
8497
|
-
)
|
|
8520
|
+
] })
|
|
8498
8521
|
] }),
|
|
8499
8522
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(DialogFooter, { children: [
|
|
8500
8523
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(DialogClose, { render: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Button, { variant: "outline" }), children: "Cancel" }),
|
|
@@ -9058,12 +9081,17 @@ var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
|
9058
9081
|
function ClientSearch({
|
|
9059
9082
|
clients,
|
|
9060
9083
|
value,
|
|
9061
|
-
onValueChange
|
|
9084
|
+
onValueChange,
|
|
9085
|
+
onSearch,
|
|
9086
|
+
isSearching,
|
|
9087
|
+
hasMore,
|
|
9088
|
+
onLoadMore,
|
|
9089
|
+
isLoadingMore
|
|
9062
9090
|
}) {
|
|
9063
9091
|
const [query, setQuery] = import_react14.default.useState("");
|
|
9064
9092
|
const [open, setOpen] = import_react14.default.useState(false);
|
|
9065
9093
|
const selected = clients.find((c) => c.id === value);
|
|
9066
|
-
const filtered = clients.filter((c) => {
|
|
9094
|
+
const filtered = onSearch ? clients : clients.filter((c) => {
|
|
9067
9095
|
const q = query.toLowerCase();
|
|
9068
9096
|
return c.name.toLowerCase().includes(q) || c.email.toLowerCase().includes(q);
|
|
9069
9097
|
});
|
|
@@ -9073,67 +9101,79 @@ function ClientSearch({
|
|
|
9073
9101
|
{
|
|
9074
9102
|
value: selected ? selected.name : query,
|
|
9075
9103
|
onChange: (e) => {
|
|
9076
|
-
|
|
9104
|
+
const v = e.target.value;
|
|
9105
|
+
setQuery(v);
|
|
9077
9106
|
if (selected) onValueChange(void 0);
|
|
9078
|
-
setOpen(
|
|
9107
|
+
setOpen(v.length > 0);
|
|
9108
|
+
onSearch == null ? void 0 : onSearch(v);
|
|
9079
9109
|
},
|
|
9080
9110
|
onBlur: () => setTimeout(() => setOpen(false), 150),
|
|
9081
9111
|
placeholder: "Search by name or email\u2026",
|
|
9082
9112
|
autoComplete: "off"
|
|
9083
9113
|
}
|
|
9084
9114
|
),
|
|
9085
|
-
open && (filtered.length > 0 || query.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "absolute z-50 mt-1 w-full border border-border bg-popover shadow-md", children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: "No clients found." }) :
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9115
|
+
open && (filtered.length > 0 || query.length > 0 || isSearching) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "absolute z-50 mt-1 max-h-64 w-full overflow-y-auto border border-border bg-popover shadow-md", children: isSearching ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: "Searching..." }) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: "No clients found." }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
|
|
9116
|
+
filtered.map((c) => /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
9117
|
+
Button,
|
|
9118
|
+
{
|
|
9119
|
+
type: "button",
|
|
9120
|
+
variant: "ghost",
|
|
9121
|
+
className: "h-auto w-full flex-col items-start gap-0.5 px-3 py-2 text-left hover:bg-primary/5",
|
|
9122
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
9123
|
+
onClick: () => {
|
|
9124
|
+
onValueChange(c.id);
|
|
9125
|
+
setQuery("");
|
|
9126
|
+
setOpen(false);
|
|
9127
|
+
},
|
|
9128
|
+
children: [
|
|
9129
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "text-sm font-medium", children: c.name }),
|
|
9130
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "text-xs text-muted-foreground", children: c.email })
|
|
9131
|
+
]
|
|
9096
9132
|
},
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9133
|
+
c.id
|
|
9134
|
+
)),
|
|
9135
|
+
hasMore && onLoadMore && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
9136
|
+
Button,
|
|
9137
|
+
{
|
|
9138
|
+
type: "button",
|
|
9139
|
+
variant: "ghost",
|
|
9140
|
+
size: "sm",
|
|
9141
|
+
className: "w-full text-sm text-primary",
|
|
9142
|
+
disabled: isLoadingMore,
|
|
9143
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
9144
|
+
onClick: onLoadMore,
|
|
9145
|
+
children: isLoadingMore ? "Loading..." : "Load more"
|
|
9146
|
+
}
|
|
9147
|
+
)
|
|
9148
|
+
] }) })
|
|
9104
9149
|
] });
|
|
9105
9150
|
}
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9151
|
+
function getFormatOptions(platform) {
|
|
9152
|
+
const call = {
|
|
9153
|
+
value: "call",
|
|
9154
|
+
label: "Call",
|
|
9155
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react26.Phone, { className: "h-4 w-4" })
|
|
9156
|
+
};
|
|
9157
|
+
const googleMeet = {
|
|
9109
9158
|
value: "google-meet",
|
|
9110
9159
|
label: "Google Meet",
|
|
9111
9160
|
icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react26.Video, { className: "h-4 w-4" })
|
|
9112
|
-
}
|
|
9113
|
-
{
|
|
9161
|
+
};
|
|
9162
|
+
const msTeams = {
|
|
9114
9163
|
value: "microsoft-teams",
|
|
9115
9164
|
label: "MS Teams",
|
|
9116
9165
|
icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react26.Users, { className: "h-4 w-4" })
|
|
9117
|
-
}
|
|
9118
|
-
{
|
|
9119
|
-
value: "offline",
|
|
9120
|
-
label: "Offline",
|
|
9121
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react26.MapPin, { className: "h-4 w-4" })
|
|
9122
|
-
}
|
|
9123
|
-
];
|
|
9124
|
-
var CLIENT_FORMAT_OPTIONS = [
|
|
9125
|
-
{ value: "call", label: "Call", icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react26.Phone, { className: "h-4 w-4" }) },
|
|
9126
|
-
{
|
|
9127
|
-
value: "online",
|
|
9128
|
-
label: "Online Meeting",
|
|
9129
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react26.Video, { className: "h-4 w-4" })
|
|
9130
|
-
},
|
|
9131
|
-
{
|
|
9166
|
+
};
|
|
9167
|
+
const offline = {
|
|
9132
9168
|
value: "offline",
|
|
9133
9169
|
label: "Offline Meeting",
|
|
9134
9170
|
icon: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react26.MapPin, { className: "h-4 w-4" })
|
|
9135
|
-
}
|
|
9136
|
-
];
|
|
9171
|
+
};
|
|
9172
|
+
if (platform === "google-meet") return [call, googleMeet, offline];
|
|
9173
|
+
if (platform === "microsoft-teams") return [call, msTeams, offline];
|
|
9174
|
+
if (platform === "any") return [call, googleMeet, msTeams, offline];
|
|
9175
|
+
return [call, offline];
|
|
9176
|
+
}
|
|
9137
9177
|
function MeetingFormatSection({
|
|
9138
9178
|
format: format5,
|
|
9139
9179
|
onFormatChange,
|
|
@@ -9250,7 +9290,7 @@ function BookingConfirmationScreen({
|
|
|
9250
9290
|
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Button, { className: "w-full", onClick: onDone, children: "Done" })
|
|
9251
9291
|
] });
|
|
9252
9292
|
}
|
|
9253
|
-
var
|
|
9293
|
+
var DAY_MAP2 = {
|
|
9254
9294
|
Sun: 0,
|
|
9255
9295
|
Mon: 1,
|
|
9256
9296
|
Tue: 2,
|
|
@@ -9263,6 +9303,11 @@ function AppointmentBookDialog({
|
|
|
9263
9303
|
open,
|
|
9264
9304
|
onOpenChange,
|
|
9265
9305
|
clients = [],
|
|
9306
|
+
onSearchClients,
|
|
9307
|
+
isSearchingClients,
|
|
9308
|
+
hasMoreClients,
|
|
9309
|
+
onLoadMoreClients,
|
|
9310
|
+
isLoadingMoreClients,
|
|
9266
9311
|
meetingTypes = [],
|
|
9267
9312
|
amSlots,
|
|
9268
9313
|
pmSlots,
|
|
@@ -9273,14 +9318,15 @@ function AppointmentBookDialog({
|
|
|
9273
9318
|
advisorInfo,
|
|
9274
9319
|
initialClientId,
|
|
9275
9320
|
defaultMeetingFormat,
|
|
9321
|
+
onlinePlatform,
|
|
9276
9322
|
guestInfo,
|
|
9277
9323
|
onBook
|
|
9278
9324
|
}) {
|
|
9279
9325
|
var _a, _b, _c;
|
|
9280
|
-
const isClientMode = clients.length === 0;
|
|
9326
|
+
const isClientMode = clients.length === 0 && !onSearchClients;
|
|
9281
9327
|
const showGuestForm = isClientMode && !((guestInfo == null ? void 0 : guestInfo.name) && (guestInfo == null ? void 0 : guestInfo.email));
|
|
9282
9328
|
const disabledDayOfWeek = import_react14.default.useMemo(
|
|
9283
|
-
() => schedule == null ? void 0 : schedule.filter((d) => !d.enabled).map((d) =>
|
|
9329
|
+
() => schedule == null ? void 0 : schedule.filter((d) => !d.enabled).map((d) => DAY_MAP2[d.day]).filter((n) => n !== void 0),
|
|
9284
9330
|
[schedule]
|
|
9285
9331
|
);
|
|
9286
9332
|
const today = import_react14.default.useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
@@ -9369,7 +9415,12 @@ function AppointmentBookDialog({
|
|
|
9369
9415
|
{
|
|
9370
9416
|
clients,
|
|
9371
9417
|
value: clientId,
|
|
9372
|
-
onValueChange: setClientId
|
|
9418
|
+
onValueChange: setClientId,
|
|
9419
|
+
onSearch: onSearchClients,
|
|
9420
|
+
isSearching: isSearchingClients,
|
|
9421
|
+
hasMore: hasMoreClients,
|
|
9422
|
+
onLoadMore: onLoadMoreClients,
|
|
9423
|
+
isLoadingMore: isLoadingMoreClients
|
|
9373
9424
|
}
|
|
9374
9425
|
)
|
|
9375
9426
|
] }),
|
|
@@ -9427,7 +9478,7 @@ function AppointmentBookDialog({
|
|
|
9427
9478
|
)
|
|
9428
9479
|
] })
|
|
9429
9480
|
] }),
|
|
9430
|
-
|
|
9481
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
9431
9482
|
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Label, { children: "Meeting format" }),
|
|
9432
9483
|
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
9433
9484
|
MeetingFormatSection,
|
|
@@ -9441,7 +9492,7 @@ function AppointmentBookDialog({
|
|
|
9441
9492
|
advisorOfficeAddress,
|
|
9442
9493
|
clientHomeAddress,
|
|
9443
9494
|
isClientMode,
|
|
9444
|
-
formatOptions:
|
|
9495
|
+
formatOptions: getFormatOptions(onlinePlatform)
|
|
9445
9496
|
}
|
|
9446
9497
|
)
|
|
9447
9498
|
] }),
|
|
@@ -10041,6 +10092,9 @@ function AppointmentDetailSheet({
|
|
|
10041
10092
|
clientProfile,
|
|
10042
10093
|
amSlots,
|
|
10043
10094
|
pmSlots,
|
|
10095
|
+
onDateChange,
|
|
10096
|
+
schedule,
|
|
10097
|
+
isLoadingSlots,
|
|
10044
10098
|
onAccept,
|
|
10045
10099
|
onDecline,
|
|
10046
10100
|
onReschedule,
|
|
@@ -10241,6 +10295,9 @@ function AppointmentDetailSheet({
|
|
|
10241
10295
|
currentDate: appointment.date,
|
|
10242
10296
|
currentTimeStart: appointment.timeStart,
|
|
10243
10297
|
currentTimeEnd: appointment.timeEnd,
|
|
10298
|
+
onDateChange,
|
|
10299
|
+
schedule,
|
|
10300
|
+
isLoadingSlots,
|
|
10244
10301
|
onReschedule: (date, slot, note) => {
|
|
10245
10302
|
onReschedule == null ? void 0 : onReschedule(appointment.id, date, slot, note);
|
|
10246
10303
|
setRescheduleOpen(false);
|
package/dist/index.mjs
CHANGED
|
@@ -364,7 +364,7 @@ import {
|
|
|
364
364
|
} from "./chunk-R2ON6CAN.mjs";
|
|
365
365
|
import {
|
|
366
366
|
AppointmentBookDialog
|
|
367
|
-
} from "./chunk-
|
|
367
|
+
} from "./chunk-3HFOSFOM.mjs";
|
|
368
368
|
import {
|
|
369
369
|
RadioGroup,
|
|
370
370
|
RadioGroupCard,
|
|
@@ -384,7 +384,7 @@ import {
|
|
|
384
384
|
} from "./chunk-V23CBULF.mjs";
|
|
385
385
|
import {
|
|
386
386
|
AppointmentDetailSheet
|
|
387
|
-
} from "./chunk-
|
|
387
|
+
} from "./chunk-ONYADWSO.mjs";
|
|
388
388
|
import {
|
|
389
389
|
AppointmentGmailConnect
|
|
390
390
|
} from "./chunk-7TMPOZDE.mjs";
|
|
@@ -408,7 +408,7 @@ import {
|
|
|
408
408
|
import {
|
|
409
409
|
AppointmentConfirmDialog,
|
|
410
410
|
AppointmentRescheduleDialog
|
|
411
|
-
} from "./chunk-
|
|
411
|
+
} from "./chunk-ZSMQZ3VN.mjs";
|
|
412
412
|
import {
|
|
413
413
|
AppointmentSlotSection,
|
|
414
414
|
AppointmentTimeSlotPicker
|
package/package.json
CHANGED
|
@@ -138,9 +138,25 @@ export interface AppointmentRescheduleDialogProps {
|
|
|
138
138
|
currentDate?: string;
|
|
139
139
|
currentTimeStart?: string;
|
|
140
140
|
currentTimeEnd?: string;
|
|
141
|
+
/**
|
|
142
|
+
* Fired when the user selects a different date in the calendar.
|
|
143
|
+
* Use this to fetch fresh `amSlots`/`pmSlots` for the new date.
|
|
144
|
+
*/
|
|
145
|
+
onDateChange?: (date: Date) => void;
|
|
146
|
+
/**
|
|
147
|
+
* Advisor's weekly availability schedule. Days with `enabled: false` are
|
|
148
|
+
* disabled in the date picker so the user cannot select them.
|
|
149
|
+
*/
|
|
150
|
+
schedule?: { day: string; enabled: boolean }[];
|
|
151
|
+
/** True while slots are being fetched for the selected date. */
|
|
152
|
+
isLoadingSlots?: boolean;
|
|
141
153
|
onReschedule: (date: Date, slot: AppointmentTimeSlot, note: string) => void;
|
|
142
154
|
}
|
|
143
155
|
|
|
156
|
+
const DAY_MAP: Record<string, number> = {
|
|
157
|
+
Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6,
|
|
158
|
+
};
|
|
159
|
+
|
|
144
160
|
export function AppointmentRescheduleDialog({
|
|
145
161
|
open,
|
|
146
162
|
onOpenChange,
|
|
@@ -149,12 +165,26 @@ export function AppointmentRescheduleDialog({
|
|
|
149
165
|
currentDate,
|
|
150
166
|
currentTimeStart,
|
|
151
167
|
currentTimeEnd,
|
|
168
|
+
onDateChange,
|
|
169
|
+
schedule,
|
|
170
|
+
isLoadingSlots,
|
|
152
171
|
onReschedule,
|
|
153
172
|
}: AppointmentRescheduleDialogProps) {
|
|
154
173
|
const [date, setDate] = React.useState<Date | undefined>(new Date());
|
|
155
174
|
const [slot, setSlot] = React.useState<AppointmentTimeSlot | undefined>();
|
|
156
175
|
const [note, setNote] = React.useState("");
|
|
157
176
|
|
|
177
|
+
const today = React.useMemo(() => new Date(), []);
|
|
178
|
+
|
|
179
|
+
const disabledDayOfWeek = React.useMemo(
|
|
180
|
+
() =>
|
|
181
|
+
schedule
|
|
182
|
+
?.filter((d) => !d.enabled)
|
|
183
|
+
.map((d) => DAY_MAP[d.day])
|
|
184
|
+
.filter((n): n is number => n !== undefined),
|
|
185
|
+
[schedule],
|
|
186
|
+
);
|
|
187
|
+
|
|
158
188
|
const handleOpenChange = (next: boolean) => {
|
|
159
189
|
if (!next) {
|
|
160
190
|
setDate(new Date());
|
|
@@ -181,6 +211,7 @@ export function AppointmentRescheduleDialog({
|
|
|
181
211
|
|
|
182
212
|
<Separator />
|
|
183
213
|
|
|
214
|
+
<div className="flex flex-col gap-4 overflow-y-auto max-h-[calc(90vh-200px)]">
|
|
184
215
|
{/* Current booking */}
|
|
185
216
|
{(currentDate || currentTimeStart) && (
|
|
186
217
|
<div className="flex flex-col gap-1.5">
|
|
@@ -215,10 +246,15 @@ export function AppointmentRescheduleDialog({
|
|
|
215
246
|
onSelect={(d) => {
|
|
216
247
|
setDate(d);
|
|
217
248
|
setSlot(undefined);
|
|
249
|
+
if (d) onDateChange?.(d);
|
|
218
250
|
}}
|
|
219
251
|
captionLayout="label"
|
|
220
|
-
fromDate={
|
|
221
|
-
disabled={
|
|
252
|
+
fromDate={today}
|
|
253
|
+
disabled={
|
|
254
|
+
disabledDayOfWeek && disabledDayOfWeek.length > 0
|
|
255
|
+
? [{ before: today }, { dayOfWeek: disabledDayOfWeek }]
|
|
256
|
+
: { before: today }
|
|
257
|
+
}
|
|
222
258
|
className="border border-border"
|
|
223
259
|
/>
|
|
224
260
|
</div>
|
|
@@ -226,26 +262,35 @@ export function AppointmentRescheduleDialog({
|
|
|
226
262
|
{/* Time slots */}
|
|
227
263
|
<div className="flex flex-col gap-5">
|
|
228
264
|
{date ? (
|
|
229
|
-
|
|
230
|
-
<div className="flex items-center justify-
|
|
231
|
-
<p className="text-sm font-semibold">
|
|
232
|
-
<
|
|
233
|
-
|
|
234
|
-
</
|
|
265
|
+
isLoadingSlots ? (
|
|
266
|
+
<div className="flex h-full flex-col items-center justify-center gap-2 py-8 text-center">
|
|
267
|
+
<p className="text-sm font-semibold">Loading slots…</p>
|
|
268
|
+
<p className="text-xs text-muted-foreground">
|
|
269
|
+
Fetching available times for the selected date.
|
|
270
|
+
</p>
|
|
235
271
|
</div>
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
272
|
+
) : (
|
|
273
|
+
<>
|
|
274
|
+
<div className="flex items-center justify-between">
|
|
275
|
+
<p className="text-sm font-semibold">Select a time slot</p>
|
|
276
|
+
<span className="text-xs text-muted-foreground">
|
|
277
|
+
{totalAvailable} available
|
|
278
|
+
</span>
|
|
279
|
+
</div>
|
|
280
|
+
<AppointmentSlotSection
|
|
281
|
+
label="Morning"
|
|
282
|
+
slots={amSlots}
|
|
283
|
+
selectedSlotId={slot?.id}
|
|
284
|
+
onSelect={setSlot}
|
|
285
|
+
/>
|
|
286
|
+
<AppointmentSlotSection
|
|
287
|
+
label="Afternoon"
|
|
288
|
+
slots={pmSlots}
|
|
289
|
+
selectedSlotId={slot?.id}
|
|
290
|
+
onSelect={setSlot}
|
|
291
|
+
/>
|
|
292
|
+
</>
|
|
293
|
+
)
|
|
249
294
|
) : (
|
|
250
295
|
<div className="flex h-full flex-col items-center justify-center gap-2 py-8 text-center">
|
|
251
296
|
<p className="text-sm font-semibold">Select a time slot</p>
|
|
@@ -274,6 +319,7 @@ export function AppointmentRescheduleDialog({
|
|
|
274
319
|
rows={2}
|
|
275
320
|
/>
|
|
276
321
|
</div>
|
|
322
|
+
</div>
|
|
277
323
|
|
|
278
324
|
<DialogFooter>
|
|
279
325
|
<DialogClose render={<Button variant="outline" />}>
|