@algenium/blocks 1.19.1 → 1.20.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/dist/index.cjs +669 -231
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +670 -232
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { Drawer as Drawer$1 } from 'vaul';
|
|
|
14
14
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
15
15
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
16
16
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
17
|
-
import { startOfMonth, endOfMonth, eachDayOfInterval, endOfWeek, startOfWeek, format, isSameDay, subMonths, addMonths } from 'date-fns';
|
|
17
|
+
import { startOfMonth, endOfMonth, eachDayOfInterval, endOfWeek, startOfWeek, format, isSameDay, startOfDay, subMonths, addMonths, addDays, addHours, setMinutes, setHours } from 'date-fns';
|
|
18
18
|
import { DayPicker } from 'react-day-picker';
|
|
19
19
|
import { Command as Command$1 } from 'cmdk';
|
|
20
20
|
import valid from 'card-validator';
|
|
@@ -6522,6 +6522,258 @@ function CalendarView({
|
|
|
6522
6522
|
] })
|
|
6523
6523
|
] });
|
|
6524
6524
|
}
|
|
6525
|
+
var TIME_SLOTS = Array.from({ length: 24 * 4 }, (_, i) => {
|
|
6526
|
+
const hours = Math.floor(i / 4);
|
|
6527
|
+
const minutes = i % 4 * 15;
|
|
6528
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
|
|
6529
|
+
});
|
|
6530
|
+
function formatTimeDisplay(value) {
|
|
6531
|
+
const parsed = parseTimeInput(value);
|
|
6532
|
+
if (!parsed) return value;
|
|
6533
|
+
const [h, m] = parsed.split(":").map(Number);
|
|
6534
|
+
const period = h >= 12 ? "pm" : "am";
|
|
6535
|
+
const hour12 = h % 12 === 0 ? 12 : h % 12;
|
|
6536
|
+
return `${hour12}:${String(m).padStart(2, "0")}${period}`;
|
|
6537
|
+
}
|
|
6538
|
+
function parseTimeInput(raw) {
|
|
6539
|
+
const cleaned = raw.trim().toLowerCase().replace(/\s+/g, "");
|
|
6540
|
+
if (!cleaned) return null;
|
|
6541
|
+
const ampmMatch = cleaned.match(/^(\d{1,2})(?::(\d{2}))?(am|pm)$/);
|
|
6542
|
+
if (ampmMatch) {
|
|
6543
|
+
let hours = Number(ampmMatch[1]);
|
|
6544
|
+
const minutes = Number(ampmMatch[2] ?? "0");
|
|
6545
|
+
const period = ampmMatch[3];
|
|
6546
|
+
if (hours < 1 || hours > 12 || minutes > 59) return null;
|
|
6547
|
+
if (period === "am") {
|
|
6548
|
+
if (hours === 12) hours = 0;
|
|
6549
|
+
} else if (hours !== 12) {
|
|
6550
|
+
hours += 12;
|
|
6551
|
+
}
|
|
6552
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
|
|
6553
|
+
}
|
|
6554
|
+
const colonMatch = cleaned.match(/^(\d{1,2}):(\d{2})$/);
|
|
6555
|
+
if (colonMatch) {
|
|
6556
|
+
const hours = Number(colonMatch[1]);
|
|
6557
|
+
const minutes = Number(colonMatch[2]);
|
|
6558
|
+
if (hours > 23 || minutes > 59) return null;
|
|
6559
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
|
|
6560
|
+
}
|
|
6561
|
+
const compactMatch = cleaned.match(/^(\d{1,2})(\d{2})$/);
|
|
6562
|
+
if (compactMatch) {
|
|
6563
|
+
const hours = Number(compactMatch[1]);
|
|
6564
|
+
const minutes = Number(compactMatch[2]);
|
|
6565
|
+
if (hours > 23 || minutes > 59) return null;
|
|
6566
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
|
|
6567
|
+
}
|
|
6568
|
+
const hourOnly = cleaned.match(/^(\d{1,2})$/);
|
|
6569
|
+
if (hourOnly) {
|
|
6570
|
+
const hours = Number(hourOnly[1]);
|
|
6571
|
+
if (hours > 23) return null;
|
|
6572
|
+
return `${String(hours).padStart(2, "0")}:00`;
|
|
6573
|
+
}
|
|
6574
|
+
return null;
|
|
6575
|
+
}
|
|
6576
|
+
function minutesFromMidnight(value) {
|
|
6577
|
+
const [h, m] = value.split(":").map(Number);
|
|
6578
|
+
return h * 60 + m;
|
|
6579
|
+
}
|
|
6580
|
+
function formatDurationHintClean(start, end) {
|
|
6581
|
+
let mins = minutesFromMidnight(end) - minutesFromMidnight(start);
|
|
6582
|
+
if (mins <= 0) mins += 24 * 60;
|
|
6583
|
+
if (mins < 60) return `${mins} mins`;
|
|
6584
|
+
const hours = Math.floor(mins / 60);
|
|
6585
|
+
const rem = mins % 60;
|
|
6586
|
+
if (rem === 0) return hours === 1 ? "1 hr" : `${hours} hrs`;
|
|
6587
|
+
if (rem === 30) return `${hours}.5 hrs`;
|
|
6588
|
+
return `${hours} hr ${rem} mins`;
|
|
6589
|
+
}
|
|
6590
|
+
function TimeCombobox({
|
|
6591
|
+
value,
|
|
6592
|
+
onChange,
|
|
6593
|
+
disabled,
|
|
6594
|
+
durationFrom,
|
|
6595
|
+
className,
|
|
6596
|
+
placeholder = "Time",
|
|
6597
|
+
"aria-label": ariaLabel
|
|
6598
|
+
}) {
|
|
6599
|
+
const [open, setOpen] = useState(false);
|
|
6600
|
+
const [draft, setDraft] = useState(formatTimeDisplay(value));
|
|
6601
|
+
const listRef = useRef(null);
|
|
6602
|
+
const selectedRef = useRef(null);
|
|
6603
|
+
useEffect(() => {
|
|
6604
|
+
if (!open) {
|
|
6605
|
+
setDraft(formatTimeDisplay(value));
|
|
6606
|
+
}
|
|
6607
|
+
}, [value, open]);
|
|
6608
|
+
useEffect(() => {
|
|
6609
|
+
if (open) {
|
|
6610
|
+
requestAnimationFrame(() => {
|
|
6611
|
+
selectedRef.current?.scrollIntoView({ block: "center" });
|
|
6612
|
+
});
|
|
6613
|
+
}
|
|
6614
|
+
}, [open]);
|
|
6615
|
+
const filtered = useMemo(() => {
|
|
6616
|
+
const q = draft.trim().toLowerCase().replace(/\s+/g, "");
|
|
6617
|
+
if (!q || parseTimeInput(draft) === value) return TIME_SLOTS;
|
|
6618
|
+
return TIME_SLOTS.filter((slot) => {
|
|
6619
|
+
const display = formatTimeDisplay(slot).toLowerCase();
|
|
6620
|
+
return display.includes(q) || slot.includes(q);
|
|
6621
|
+
});
|
|
6622
|
+
}, [draft, value]);
|
|
6623
|
+
const commitDraft = () => {
|
|
6624
|
+
const parsed = parseTimeInput(draft);
|
|
6625
|
+
if (parsed) {
|
|
6626
|
+
onChange(parsed);
|
|
6627
|
+
setDraft(formatTimeDisplay(parsed));
|
|
6628
|
+
} else {
|
|
6629
|
+
setDraft(formatTimeDisplay(value));
|
|
6630
|
+
}
|
|
6631
|
+
};
|
|
6632
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
6633
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
6634
|
+
"button",
|
|
6635
|
+
{
|
|
6636
|
+
type: "button",
|
|
6637
|
+
disabled,
|
|
6638
|
+
"aria-label": ariaLabel,
|
|
6639
|
+
className: cn(
|
|
6640
|
+
"inline-flex h-9 min-w-[5.5rem] items-center justify-center rounded-md border border-input bg-background px-2 text-sm tabular-nums ring-offset-background transition-colors",
|
|
6641
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
6642
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6643
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
6644
|
+
className
|
|
6645
|
+
),
|
|
6646
|
+
onClick: () => setOpen(true),
|
|
6647
|
+
children: formatTimeDisplay(value) || placeholder
|
|
6648
|
+
}
|
|
6649
|
+
) }),
|
|
6650
|
+
/* @__PURE__ */ jsxs(
|
|
6651
|
+
PopoverContent,
|
|
6652
|
+
{
|
|
6653
|
+
className: "z-[100] w-40 p-0",
|
|
6654
|
+
align: "start",
|
|
6655
|
+
onOpenAutoFocus: (e) => {
|
|
6656
|
+
e.preventDefault();
|
|
6657
|
+
const input = e.currentTarget?.querySelector(
|
|
6658
|
+
"input"
|
|
6659
|
+
);
|
|
6660
|
+
input?.focus();
|
|
6661
|
+
},
|
|
6662
|
+
children: [
|
|
6663
|
+
/* @__PURE__ */ jsx("div", { className: "border-b p-1.5", children: /* @__PURE__ */ jsx(
|
|
6664
|
+
"input",
|
|
6665
|
+
{
|
|
6666
|
+
value: draft,
|
|
6667
|
+
onChange: (e) => setDraft(e.target.value),
|
|
6668
|
+
onKeyDown: (e) => {
|
|
6669
|
+
if (e.key === "Enter") {
|
|
6670
|
+
e.preventDefault();
|
|
6671
|
+
commitDraft();
|
|
6672
|
+
setOpen(false);
|
|
6673
|
+
} else if (e.key === "Escape") {
|
|
6674
|
+
setDraft(formatTimeDisplay(value));
|
|
6675
|
+
setOpen(false);
|
|
6676
|
+
}
|
|
6677
|
+
},
|
|
6678
|
+
onBlur: commitDraft,
|
|
6679
|
+
placeholder,
|
|
6680
|
+
className: "w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm tabular-nums focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6681
|
+
"aria-label": ariaLabel
|
|
6682
|
+
}
|
|
6683
|
+
) }),
|
|
6684
|
+
/* @__PURE__ */ jsxs("div", { ref: listRef, className: "max-h-56 overflow-y-auto py-1", children: [
|
|
6685
|
+
filtered.map((slot) => {
|
|
6686
|
+
const selected = slot === value;
|
|
6687
|
+
const label = formatTimeDisplay(slot);
|
|
6688
|
+
const hint = durationFrom != null ? formatDurationHintClean(durationFrom, slot) : null;
|
|
6689
|
+
return /* @__PURE__ */ jsxs(
|
|
6690
|
+
"button",
|
|
6691
|
+
{
|
|
6692
|
+
ref: selected ? selectedRef : void 0,
|
|
6693
|
+
type: "button",
|
|
6694
|
+
className: cn(
|
|
6695
|
+
"flex w-full items-center justify-between px-3 py-1.5 text-left text-sm tabular-nums hover:bg-accent",
|
|
6696
|
+
selected && "bg-accent font-medium"
|
|
6697
|
+
),
|
|
6698
|
+
onMouseDown: (e) => {
|
|
6699
|
+
e.preventDefault();
|
|
6700
|
+
},
|
|
6701
|
+
onClick: () => {
|
|
6702
|
+
onChange(slot);
|
|
6703
|
+
setDraft(formatTimeDisplay(slot));
|
|
6704
|
+
setOpen(false);
|
|
6705
|
+
},
|
|
6706
|
+
children: [
|
|
6707
|
+
/* @__PURE__ */ jsx("span", { children: label }),
|
|
6708
|
+
hint && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: hint })
|
|
6709
|
+
]
|
|
6710
|
+
},
|
|
6711
|
+
slot
|
|
6712
|
+
);
|
|
6713
|
+
}),
|
|
6714
|
+
filtered.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No matching times" })
|
|
6715
|
+
] })
|
|
6716
|
+
]
|
|
6717
|
+
}
|
|
6718
|
+
)
|
|
6719
|
+
] });
|
|
6720
|
+
}
|
|
6721
|
+
function toTimeValue(date) {
|
|
6722
|
+
return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
6723
|
+
}
|
|
6724
|
+
function dateKey(date) {
|
|
6725
|
+
return format(date, "yyyy-MM-dd");
|
|
6726
|
+
}
|
|
6727
|
+
function combineDateAndTime(date, time) {
|
|
6728
|
+
const [h, m] = time.split(":").map(Number);
|
|
6729
|
+
return setMinutes(setHours(startOfDay(date), h), m);
|
|
6730
|
+
}
|
|
6731
|
+
function defaultTimes(from) {
|
|
6732
|
+
const base = /* @__PURE__ */ new Date();
|
|
6733
|
+
const nextHour = addHours(setMinutes(setHours(base, base.getHours()), 0), 1);
|
|
6734
|
+
const end = addHours(nextHour, 1);
|
|
6735
|
+
return {
|
|
6736
|
+
date: startOfDay(nextHour),
|
|
6737
|
+
startTime: toTimeValue(nextHour),
|
|
6738
|
+
endTime: toTimeValue(end)
|
|
6739
|
+
};
|
|
6740
|
+
}
|
|
6741
|
+
function splitEventTimes(event) {
|
|
6742
|
+
if (event?.dtstart) {
|
|
6743
|
+
const start = new Date(event.dtstart);
|
|
6744
|
+
const end = event.dtend ? new Date(event.dtend) : addHours(start, 1);
|
|
6745
|
+
return {
|
|
6746
|
+
date: startOfDay(start),
|
|
6747
|
+
startTime: toTimeValue(start),
|
|
6748
|
+
endTime: toTimeValue(end),
|
|
6749
|
+
allDay: event.allDay ?? false
|
|
6750
|
+
};
|
|
6751
|
+
}
|
|
6752
|
+
const defaults = defaultTimes();
|
|
6753
|
+
return { ...defaults, allDay: event?.allDay ?? false };
|
|
6754
|
+
}
|
|
6755
|
+
var dayPickerClassNames = {
|
|
6756
|
+
months: "flex flex-col",
|
|
6757
|
+
month: "space-y-2",
|
|
6758
|
+
month_caption: "flex justify-center relative items-center pt-1",
|
|
6759
|
+
caption_label: "text-sm font-medium",
|
|
6760
|
+
nav: "space-x-1 flex items-center",
|
|
6761
|
+
button_previous: "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1 top-1 inline-flex items-center justify-center rounded-md hover:bg-accent",
|
|
6762
|
+
button_next: "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute right-1 top-1 inline-flex items-center justify-center rounded-md hover:bg-accent",
|
|
6763
|
+
month_grid: "w-full border-collapse space-y-1",
|
|
6764
|
+
weekdays: "flex",
|
|
6765
|
+
weekday: "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
|
|
6766
|
+
week: "flex w-full mt-1",
|
|
6767
|
+
day: "relative p-0 text-center text-sm focus-within:relative focus-within:z-20",
|
|
6768
|
+
day_button: cn(
|
|
6769
|
+
"h-8 w-8 p-0 font-normal",
|
|
6770
|
+
"hover:bg-accent hover:text-accent-foreground rounded-md"
|
|
6771
|
+
),
|
|
6772
|
+
selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground rounded-md",
|
|
6773
|
+
today: "bg-accent text-accent-foreground rounded-md",
|
|
6774
|
+
outside: "text-muted-foreground opacity-50",
|
|
6775
|
+
disabled: "text-muted-foreground opacity-50"
|
|
6776
|
+
};
|
|
6525
6777
|
function EventDialog({
|
|
6526
6778
|
open,
|
|
6527
6779
|
onOpenChange,
|
|
@@ -6541,13 +6793,11 @@ function EventDialog({
|
|
|
6541
6793
|
const [summary, setSummary] = useState(event?.summary ?? "");
|
|
6542
6794
|
const [description, setDescription] = useState(event?.description ?? "");
|
|
6543
6795
|
const [location, setLocation] = useState(event?.location ?? "");
|
|
6544
|
-
const
|
|
6545
|
-
|
|
6546
|
-
);
|
|
6547
|
-
const [
|
|
6548
|
-
|
|
6549
|
-
);
|
|
6550
|
-
const [allDay, setAllDay] = useState(event?.allDay ?? false);
|
|
6796
|
+
const initialTimes = splitEventTimes(event);
|
|
6797
|
+
const [date, setDate] = useState(initialTimes.date);
|
|
6798
|
+
const [startTime, setStartTime] = useState(initialTimes.startTime);
|
|
6799
|
+
const [endTime, setEndTime] = useState(initialTimes.endTime);
|
|
6800
|
+
const [allDay, setAllDay] = useState(initialTimes.allDay);
|
|
6551
6801
|
const [categoryId, setCategoryId] = useState(event?.categoryId ?? "");
|
|
6552
6802
|
const [referenceType, setReferenceType] = useState(
|
|
6553
6803
|
event?.referenceType ?? ""
|
|
@@ -6558,20 +6808,47 @@ function EventDialog({
|
|
|
6558
6808
|
const [linkOptions, setLinkOptions] = useState([]);
|
|
6559
6809
|
const [saving, setSaving] = useState(false);
|
|
6560
6810
|
const [completing, setCompleting] = useState(false);
|
|
6811
|
+
const [datePickerOpen, setDatePickerOpen] = useState(false);
|
|
6812
|
+
const [confirmDiscard, setConfirmDiscard] = useState(false);
|
|
6813
|
+
const [discardIntent, setDiscardIntent] = useState(
|
|
6814
|
+
"close"
|
|
6815
|
+
);
|
|
6816
|
+
const snapshotRef = useRef(null);
|
|
6817
|
+
const allowCloseRef = useRef(false);
|
|
6561
6818
|
const linkTimer = useRef(null);
|
|
6819
|
+
const requestDiscard = (intent) => {
|
|
6820
|
+
setDiscardIntent(intent);
|
|
6821
|
+
setConfirmDiscard(true);
|
|
6822
|
+
};
|
|
6823
|
+
const revertToSnapshot = () => {
|
|
6824
|
+
const snap = snapshotRef.current;
|
|
6825
|
+
if (!snap) return;
|
|
6826
|
+
setSummary(snap.summary);
|
|
6827
|
+
setDescription(snap.description);
|
|
6828
|
+
setLocation(snap.location);
|
|
6829
|
+
setDate(startOfDay(/* @__PURE__ */ new Date(`${snap.dateKey}T00:00:00`)));
|
|
6830
|
+
setStartTime(snap.startTime);
|
|
6831
|
+
setEndTime(snap.endTime);
|
|
6832
|
+
setAllDay(snap.allDay);
|
|
6833
|
+
setCategoryId(snap.categoryId);
|
|
6834
|
+
setReferenceType(snap.referenceType);
|
|
6835
|
+
setReferenceId(snap.referenceId);
|
|
6836
|
+
};
|
|
6562
6837
|
useEffect(() => {
|
|
6563
|
-
if (!open)
|
|
6838
|
+
if (!open) {
|
|
6839
|
+
setConfirmDiscard(false);
|
|
6840
|
+
allowCloseRef.current = false;
|
|
6841
|
+
return;
|
|
6842
|
+
}
|
|
6564
6843
|
setMode(event?.id ? "preview" : "edit");
|
|
6565
6844
|
setSummary(event?.summary ?? "");
|
|
6566
6845
|
setDescription(event?.description ?? "");
|
|
6567
6846
|
setLocation(event?.location ?? "");
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
);
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
);
|
|
6574
|
-
setAllDay(event?.allDay ?? false);
|
|
6847
|
+
const times = splitEventTimes(event);
|
|
6848
|
+
setDate(times.date);
|
|
6849
|
+
setStartTime(times.startTime);
|
|
6850
|
+
setEndTime(times.endTime);
|
|
6851
|
+
setAllDay(times.allDay);
|
|
6575
6852
|
setCategoryId(event?.categoryId ?? "");
|
|
6576
6853
|
setReferenceType(event?.referenceType ?? "");
|
|
6577
6854
|
setReferenceId(event?.referenceId ?? "");
|
|
@@ -6580,6 +6857,21 @@ function EventDialog({
|
|
|
6580
6857
|
);
|
|
6581
6858
|
setLinkQuery("");
|
|
6582
6859
|
setLinkOptions([]);
|
|
6860
|
+
setConfirmDiscard(false);
|
|
6861
|
+
allowCloseRef.current = false;
|
|
6862
|
+
const snap = {
|
|
6863
|
+
summary: (event?.summary ?? "").trim(),
|
|
6864
|
+
description: (event?.description ?? "").trim(),
|
|
6865
|
+
location: (event?.location ?? "").trim(),
|
|
6866
|
+
dateKey: dateKey(times.date),
|
|
6867
|
+
startTime: times.startTime,
|
|
6868
|
+
endTime: times.endTime,
|
|
6869
|
+
allDay: times.allDay,
|
|
6870
|
+
categoryId: event?.categoryId ?? "",
|
|
6871
|
+
referenceType: event?.referenceType ?? "",
|
|
6872
|
+
referenceId: event?.referenceId ?? ""
|
|
6873
|
+
};
|
|
6874
|
+
snapshotRef.current = snap;
|
|
6583
6875
|
}, [open, event]);
|
|
6584
6876
|
useEffect(() => {
|
|
6585
6877
|
if (!linkSearch || !linkQuery.trim()) {
|
|
@@ -6599,25 +6891,67 @@ function EventDialog({
|
|
|
6599
6891
|
if (linkTimer.current) clearTimeout(linkTimer.current);
|
|
6600
6892
|
};
|
|
6601
6893
|
}, [linkQuery, linkSearch]);
|
|
6894
|
+
const isDirty = useMemo(() => {
|
|
6895
|
+
const snap = snapshotRef.current;
|
|
6896
|
+
if (!snap) return false;
|
|
6897
|
+
return summary.trim() !== snap.summary || description.trim() !== snap.description || location.trim() !== snap.location || dateKey(date) !== snap.dateKey || startTime !== snap.startTime || endTime !== snap.endTime || allDay !== snap.allDay || categoryId !== snap.categoryId || referenceType !== snap.referenceType || referenceId !== snap.referenceId;
|
|
6898
|
+
}, [
|
|
6899
|
+
summary,
|
|
6900
|
+
description,
|
|
6901
|
+
location,
|
|
6902
|
+
date,
|
|
6903
|
+
startTime,
|
|
6904
|
+
endTime,
|
|
6905
|
+
allDay,
|
|
6906
|
+
categoryId,
|
|
6907
|
+
referenceType,
|
|
6908
|
+
referenceId
|
|
6909
|
+
]);
|
|
6602
6910
|
const selectedCategory = categories.find((c) => c.id === categoryId) ?? event?.category ?? null;
|
|
6911
|
+
const handleOpenChange = (nextOpen) => {
|
|
6912
|
+
if (nextOpen) {
|
|
6913
|
+
onOpenChange(true);
|
|
6914
|
+
return;
|
|
6915
|
+
}
|
|
6916
|
+
if (allowCloseRef.current || saving) {
|
|
6917
|
+
allowCloseRef.current = false;
|
|
6918
|
+
onOpenChange(false);
|
|
6919
|
+
return;
|
|
6920
|
+
}
|
|
6921
|
+
if (mode === "edit" && isDirty) {
|
|
6922
|
+
requestDiscard("close");
|
|
6923
|
+
return;
|
|
6924
|
+
}
|
|
6925
|
+
onOpenChange(false);
|
|
6926
|
+
};
|
|
6927
|
+
const forceClose = () => {
|
|
6928
|
+
allowCloseRef.current = true;
|
|
6929
|
+
setConfirmDiscard(false);
|
|
6930
|
+
onOpenChange(false);
|
|
6931
|
+
};
|
|
6603
6932
|
const handleSave = async () => {
|
|
6604
|
-
if (!summary.trim() || !
|
|
6933
|
+
if (!summary.trim() || !date || !startTime || !endTime) return;
|
|
6605
6934
|
setSaving(true);
|
|
6606
6935
|
try {
|
|
6936
|
+
const start = allDay ? startOfDay(date) : combineDateAndTime(date, startTime);
|
|
6937
|
+
let end = allDay ? startOfDay(addDays(date, 1)) : combineDateAndTime(date, endTime);
|
|
6938
|
+
if (!allDay && end.getTime() <= start.getTime()) {
|
|
6939
|
+
end = addDays(end, 1);
|
|
6940
|
+
}
|
|
6607
6941
|
await onSave({
|
|
6608
6942
|
...event?.id ? { id: event.id } : {},
|
|
6609
6943
|
summary: summary.trim(),
|
|
6610
6944
|
description: description.trim() || null,
|
|
6611
6945
|
location: location.trim() || null,
|
|
6612
|
-
dtstart:
|
|
6613
|
-
dtend:
|
|
6946
|
+
dtstart: start.toISOString(),
|
|
6947
|
+
dtend: end.toISOString(),
|
|
6614
6948
|
allDay,
|
|
6615
6949
|
categoryId: categoryId || null,
|
|
6616
6950
|
category: selectedCategory,
|
|
6617
6951
|
referenceType: referenceType || null,
|
|
6618
6952
|
referenceId: referenceId || null
|
|
6619
6953
|
});
|
|
6620
|
-
|
|
6954
|
+
forceClose();
|
|
6621
6955
|
} catch (err) {
|
|
6622
6956
|
console.error("[EventDialog] Failed to save event:", err);
|
|
6623
6957
|
} finally {
|
|
@@ -6629,275 +6963,379 @@ function EventDialog({
|
|
|
6629
6963
|
setCompleting(true);
|
|
6630
6964
|
try {
|
|
6631
6965
|
await onComplete();
|
|
6632
|
-
|
|
6966
|
+
forceClose();
|
|
6633
6967
|
} finally {
|
|
6634
6968
|
setCompleting(false);
|
|
6635
6969
|
}
|
|
6636
6970
|
};
|
|
6971
|
+
const handleStartTimeChange = (value) => {
|
|
6972
|
+
setStartTime(value);
|
|
6973
|
+
const [sh, sm] = value.split(":").map(Number);
|
|
6974
|
+
const [eh, em] = endTime.split(":").map(Number);
|
|
6975
|
+
if (eh * 60 + em <= sh * 60 + sm) {
|
|
6976
|
+
const next = addHours(combineDateAndTime(date, value), 1);
|
|
6977
|
+
setEndTime(toTimeValue(next));
|
|
6978
|
+
}
|
|
6979
|
+
};
|
|
6637
6980
|
const CategoryIcon = getCategoryIcon(selectedCategory?.alias);
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
/* @__PURE__ */
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
/* @__PURE__ */ jsx(
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 text-sm text-muted-foreground", children: [
|
|
6650
|
-
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
6651
|
-
/* @__PURE__ */ jsx(Clock, { className: "h-3.5 w-3.5" }),
|
|
6652
|
-
event?.dtstart ? new Date(event.dtstart).toLocaleString() : "\u2014",
|
|
6653
|
-
event?.dtend ? ` \u2013 ${new Date(event.dtend).toLocaleString()}` : ""
|
|
6981
|
+
const dateLabel = format(date, "EEEE, d MMMM");
|
|
6982
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6983
|
+
/* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[520px]", children: [
|
|
6984
|
+
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: mode === "preview" ? labels.previewTitle ?? "Event details" : isExisting ? labels.editTitle ?? "Edit event" : labels.createTitle ?? "New event" }) }),
|
|
6985
|
+
mode === "preview" ? /* @__PURE__ */ jsxs("div", { className: "space-y-4 py-2", children: [
|
|
6986
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
6987
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: event?.summary }),
|
|
6988
|
+
isCompleted && /* @__PURE__ */ jsxs("p", { className: "mt-1 inline-flex items-center gap-1 text-sm text-emerald-600", children: [
|
|
6989
|
+
/* @__PURE__ */ jsx(CheckCircle2, { className: "h-3.5 w-3.5" }),
|
|
6990
|
+
labels.completed ?? "Completed"
|
|
6991
|
+
] })
|
|
6654
6992
|
] }),
|
|
6655
|
-
event?.
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
color: selectedCategory.iconColor
|
|
6667
|
-
},
|
|
6668
|
-
children: [
|
|
6669
|
-
/* @__PURE__ */ jsx(CategoryIcon, { className: "h-3.5 w-3.5" }),
|
|
6670
|
-
selectedCategory.name
|
|
6671
|
-
]
|
|
6672
|
-
}
|
|
6673
|
-
),
|
|
6674
|
-
(event?.referenceId || linkLabel) && /* @__PURE__ */ jsxs("p", { className: "inline-flex items-center gap-1.5 text-sm", children: [
|
|
6675
|
-
/* @__PURE__ */ jsx(Link2, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
6676
|
-
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
6677
|
-
linkSearch?.label ?? labels.link ?? "Linked case",
|
|
6678
|
-
":"
|
|
6993
|
+
event?.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground whitespace-pre-wrap", children: event.description }),
|
|
6994
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 text-sm text-muted-foreground", children: [
|
|
6995
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
6996
|
+
/* @__PURE__ */ jsx(Clock, { className: "h-3.5 w-3.5" }),
|
|
6997
|
+
event?.dtstart ? new Date(event.dtstart).toLocaleString() : "\u2014",
|
|
6998
|
+
event?.dtend ? ` \u2013 ${new Date(event.dtend).toLocaleString()}` : ""
|
|
6999
|
+
] }),
|
|
7000
|
+
event?.location && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
7001
|
+
/* @__PURE__ */ jsx(MapPin, { className: "h-3.5 w-3.5" }),
|
|
7002
|
+
event.location
|
|
7003
|
+
] })
|
|
6679
7004
|
] }),
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
/* @__PURE__ */ jsxs(DialogFooter, { className: "gap-2", children: [
|
|
6683
|
-
!isCompleted && onComplete && /* @__PURE__ */ jsxs(
|
|
6684
|
-
Button,
|
|
7005
|
+
selectedCategory && /* @__PURE__ */ jsxs(
|
|
7006
|
+
"span",
|
|
6685
7007
|
{
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
7008
|
+
className: "inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium",
|
|
7009
|
+
style: {
|
|
7010
|
+
backgroundColor: selectedCategory.bgColor,
|
|
7011
|
+
color: selectedCategory.iconColor
|
|
7012
|
+
},
|
|
6690
7013
|
children: [
|
|
6691
|
-
|
|
6692
|
-
|
|
7014
|
+
/* @__PURE__ */ jsx(CategoryIcon, { className: "h-3.5 w-3.5" }),
|
|
7015
|
+
selectedCategory.name
|
|
6693
7016
|
]
|
|
6694
7017
|
}
|
|
6695
7018
|
),
|
|
6696
|
-
/* @__PURE__ */
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
/* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium", children: labels.summary ?? "Summary" }),
|
|
6708
|
-
/* @__PURE__ */ jsx(
|
|
6709
|
-
"input",
|
|
7019
|
+
(event?.referenceId || linkLabel) && /* @__PURE__ */ jsxs("p", { className: "inline-flex items-center gap-1.5 text-sm", children: [
|
|
7020
|
+
/* @__PURE__ */ jsx(Link2, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
7021
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
7022
|
+
linkSearch?.label ?? labels.link ?? "Linked case",
|
|
7023
|
+
":"
|
|
7024
|
+
] }),
|
|
7025
|
+
linkLabel || event?.referenceId
|
|
7026
|
+
] }),
|
|
7027
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "gap-2", children: [
|
|
7028
|
+
!isCompleted && onComplete && /* @__PURE__ */ jsxs(
|
|
7029
|
+
Button,
|
|
6710
7030
|
{
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
7031
|
+
variant: "secondary",
|
|
7032
|
+
size: "sm",
|
|
7033
|
+
onClick: handleComplete,
|
|
7034
|
+
disabled: completing,
|
|
7035
|
+
children: [
|
|
7036
|
+
completing && /* @__PURE__ */ jsx(Loader2, { className: "mr-1 h-3.5 w-3.5 animate-spin" }),
|
|
7037
|
+
labels.markComplete ?? "Mark as completed"
|
|
7038
|
+
]
|
|
6716
7039
|
}
|
|
6717
|
-
)
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
/* @__PURE__ */ jsx(
|
|
6721
|
-
/* @__PURE__ */
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
7040
|
+
),
|
|
7041
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
7042
|
+
isExisting && onDelete && !isCompleted && /* @__PURE__ */ jsx(Button, { variant: "destructive", size: "sm", onClick: onDelete, children: labels.delete ?? "Delete" }),
|
|
7043
|
+
/* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", children: labels.cancel ?? "Close" }) }),
|
|
7044
|
+
!isCompleted && /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => setMode("edit"), children: [
|
|
7045
|
+
/* @__PURE__ */ jsx(Pencil, { className: "mr-1 h-3.5 w-3.5" }),
|
|
7046
|
+
labels.edit ?? "Edit"
|
|
7047
|
+
] })
|
|
7048
|
+
] })
|
|
7049
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7050
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4 py-2", children: [
|
|
7051
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
7052
|
+
/* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium", children: labels.summary ?? "Summary" }),
|
|
7053
|
+
/* @__PURE__ */ jsx(
|
|
7054
|
+
"input",
|
|
6726
7055
|
{
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
7056
|
+
value: summary,
|
|
7057
|
+
onChange: (e) => setSummary(e.target.value),
|
|
7058
|
+
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7059
|
+
placeholder: "Event name",
|
|
7060
|
+
disabled: isCompleted
|
|
7061
|
+
}
|
|
7062
|
+
)
|
|
7063
|
+
] }),
|
|
7064
|
+
categories.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
7065
|
+
/* @__PURE__ */ jsx("label", { className: "mb-1.5 block text-sm font-medium", children: labels.category ?? "Category" }),
|
|
7066
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: categories.map((cat) => {
|
|
7067
|
+
const Icon = getCategoryIcon(cat.alias);
|
|
7068
|
+
const selected = categoryId === cat.id;
|
|
7069
|
+
return /* @__PURE__ */ jsxs(
|
|
7070
|
+
"button",
|
|
7071
|
+
{
|
|
7072
|
+
type: "button",
|
|
7073
|
+
disabled: isCompleted,
|
|
7074
|
+
onClick: () => setCategoryId(selected ? "" : cat.id),
|
|
7075
|
+
className: cn(
|
|
7076
|
+
"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-medium transition-all",
|
|
7077
|
+
selected ? "ring-2 ring-offset-1 ring-primary" : "opacity-80 hover:opacity-100"
|
|
7078
|
+
),
|
|
7079
|
+
style: {
|
|
7080
|
+
backgroundColor: cat.bgColor,
|
|
7081
|
+
color: cat.iconColor,
|
|
7082
|
+
borderColor: cat.iconColor
|
|
7083
|
+
},
|
|
7084
|
+
children: [
|
|
7085
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }),
|
|
7086
|
+
cat.name
|
|
7087
|
+
]
|
|
6738
7088
|
},
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
},
|
|
6744
|
-
cat.id
|
|
6745
|
-
);
|
|
6746
|
-
}) })
|
|
6747
|
-
] }),
|
|
6748
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
7089
|
+
cat.id
|
|
7090
|
+
);
|
|
7091
|
+
}) })
|
|
7092
|
+
] }),
|
|
6749
7093
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
6750
|
-
/* @__PURE__ */ jsxs("label", { className: "mb-1 block text-sm font-medium", children: [
|
|
7094
|
+
/* @__PURE__ */ jsxs("label", { className: "mb-1.5 block text-sm font-medium", children: [
|
|
6751
7095
|
/* @__PURE__ */ jsx(Clock, { className: "mr-1 inline h-3.5 w-3.5" }),
|
|
6752
|
-
labels.startDate ?? "
|
|
7096
|
+
labels.date ?? labels.startDate ?? "Date & time"
|
|
6753
7097
|
] }),
|
|
7098
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
7099
|
+
/* @__PURE__ */ jsxs(
|
|
7100
|
+
Popover,
|
|
7101
|
+
{
|
|
7102
|
+
open: datePickerOpen,
|
|
7103
|
+
onOpenChange: setDatePickerOpen,
|
|
7104
|
+
children: [
|
|
7105
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
7106
|
+
"button",
|
|
7107
|
+
{
|
|
7108
|
+
type: "button",
|
|
7109
|
+
disabled: isCompleted,
|
|
7110
|
+
className: cn(
|
|
7111
|
+
"inline-flex h-9 items-center rounded-md border border-input bg-background px-3 text-sm",
|
|
7112
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
7113
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7114
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
7115
|
+
),
|
|
7116
|
+
children: dateLabel
|
|
7117
|
+
}
|
|
7118
|
+
) }),
|
|
7119
|
+
/* @__PURE__ */ jsx(
|
|
7120
|
+
PopoverContent,
|
|
7121
|
+
{
|
|
7122
|
+
className: "z-[100] w-auto p-2",
|
|
7123
|
+
align: "start",
|
|
7124
|
+
children: /* @__PURE__ */ jsx(
|
|
7125
|
+
DayPicker,
|
|
7126
|
+
{
|
|
7127
|
+
mode: "single",
|
|
7128
|
+
selected: date,
|
|
7129
|
+
onSelect: (d) => {
|
|
7130
|
+
if (d) {
|
|
7131
|
+
setDate(startOfDay(d));
|
|
7132
|
+
setDatePickerOpen(false);
|
|
7133
|
+
}
|
|
7134
|
+
},
|
|
7135
|
+
showOutsideDays: true,
|
|
7136
|
+
classNames: dayPickerClassNames
|
|
7137
|
+
}
|
|
7138
|
+
)
|
|
7139
|
+
}
|
|
7140
|
+
)
|
|
7141
|
+
]
|
|
7142
|
+
}
|
|
7143
|
+
),
|
|
7144
|
+
!allDay && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7145
|
+
/* @__PURE__ */ jsx(
|
|
7146
|
+
TimeCombobox,
|
|
7147
|
+
{
|
|
7148
|
+
value: startTime,
|
|
7149
|
+
onChange: handleStartTimeChange,
|
|
7150
|
+
disabled: isCompleted,
|
|
7151
|
+
"aria-label": labels.startTime ?? "Start time"
|
|
7152
|
+
}
|
|
7153
|
+
),
|
|
7154
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u2013" }),
|
|
7155
|
+
/* @__PURE__ */ jsx(
|
|
7156
|
+
TimeCombobox,
|
|
7157
|
+
{
|
|
7158
|
+
value: endTime,
|
|
7159
|
+
onChange: setEndTime,
|
|
7160
|
+
disabled: isCompleted,
|
|
7161
|
+
durationFrom: startTime,
|
|
7162
|
+
"aria-label": labels.endTime ?? "End time"
|
|
7163
|
+
}
|
|
7164
|
+
)
|
|
7165
|
+
] })
|
|
7166
|
+
] })
|
|
7167
|
+
] }),
|
|
7168
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
|
|
6754
7169
|
/* @__PURE__ */ jsx(
|
|
6755
7170
|
"input",
|
|
6756
7171
|
{
|
|
6757
|
-
type: "
|
|
6758
|
-
|
|
6759
|
-
onChange: (e) =>
|
|
7172
|
+
type: "checkbox",
|
|
7173
|
+
checked: allDay,
|
|
7174
|
+
onChange: (e) => setAllDay(e.target.checked),
|
|
6760
7175
|
disabled: isCompleted,
|
|
6761
|
-
className: "
|
|
7176
|
+
className: "rounded border-input"
|
|
6762
7177
|
}
|
|
6763
|
-
)
|
|
7178
|
+
),
|
|
7179
|
+
labels.allDay ?? "All day"
|
|
7180
|
+
] }),
|
|
7181
|
+
(linkSearch || referenceId) && !isExisting && /* @__PURE__ */ jsxs("div", { children: [
|
|
7182
|
+
/* @__PURE__ */ jsxs("label", { className: "mb-1 block text-sm font-medium", children: [
|
|
7183
|
+
/* @__PURE__ */ jsx(Link2, { className: "mr-1 inline h-3.5 w-3.5" }),
|
|
7184
|
+
linkSearch?.label ?? labels.link ?? "Link to case"
|
|
7185
|
+
] }),
|
|
7186
|
+
referenceId ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-md border px-3 py-2 text-sm", children: [
|
|
7187
|
+
/* @__PURE__ */ jsx("span", { children: linkLabel || referenceId }),
|
|
7188
|
+
linkSearch && /* @__PURE__ */ jsx(
|
|
7189
|
+
"button",
|
|
7190
|
+
{
|
|
7191
|
+
type: "button",
|
|
7192
|
+
className: "text-xs text-muted-foreground hover:text-foreground",
|
|
7193
|
+
onClick: () => {
|
|
7194
|
+
setReferenceId("");
|
|
7195
|
+
setReferenceType("");
|
|
7196
|
+
setLinkLabel("");
|
|
7197
|
+
},
|
|
7198
|
+
children: "Clear"
|
|
7199
|
+
}
|
|
7200
|
+
)
|
|
7201
|
+
] }) : linkSearch ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7202
|
+
/* @__PURE__ */ jsx(
|
|
7203
|
+
"input",
|
|
7204
|
+
{
|
|
7205
|
+
value: linkQuery,
|
|
7206
|
+
onChange: (e) => setLinkQuery(e.target.value),
|
|
7207
|
+
placeholder: labels.linkPlaceholder ?? "Search cases\u2026",
|
|
7208
|
+
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7209
|
+
}
|
|
7210
|
+
),
|
|
7211
|
+
linkOptions.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-1 max-h-40 overflow-auto rounded-md border bg-popover text-sm shadow-md", children: linkOptions.map((opt) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
7212
|
+
"button",
|
|
7213
|
+
{
|
|
7214
|
+
type: "button",
|
|
7215
|
+
className: "flex w-full flex-col px-3 py-2 text-left hover:bg-accent",
|
|
7216
|
+
onClick: () => {
|
|
7217
|
+
setReferenceId(opt.id);
|
|
7218
|
+
setReferenceType("cases-svc");
|
|
7219
|
+
setLinkLabel(opt.label);
|
|
7220
|
+
setLinkQuery("");
|
|
7221
|
+
setLinkOptions([]);
|
|
7222
|
+
},
|
|
7223
|
+
children: [
|
|
7224
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: opt.label }),
|
|
7225
|
+
opt.description && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: opt.description })
|
|
7226
|
+
]
|
|
7227
|
+
}
|
|
7228
|
+
) }, opt.id)) })
|
|
7229
|
+
] }) : null
|
|
6764
7230
|
] }),
|
|
6765
7231
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
6766
|
-
/* @__PURE__ */
|
|
7232
|
+
/* @__PURE__ */ jsxs("label", { className: "mb-1 block text-sm font-medium", children: [
|
|
7233
|
+
/* @__PURE__ */ jsx(MapPin, { className: "mr-1 inline h-3.5 w-3.5" }),
|
|
7234
|
+
labels.location ?? "Location"
|
|
7235
|
+
] }),
|
|
6767
7236
|
/* @__PURE__ */ jsx(
|
|
6768
7237
|
"input",
|
|
6769
7238
|
{
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
onChange: (e) => setDtend(e.target.value),
|
|
7239
|
+
value: location,
|
|
7240
|
+
onChange: (e) => setLocation(e.target.value),
|
|
6773
7241
|
disabled: isCompleted,
|
|
6774
|
-
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7242
|
+
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7243
|
+
placeholder: "Add location"
|
|
6775
7244
|
}
|
|
6776
7245
|
)
|
|
6777
|
-
] })
|
|
6778
|
-
] }),
|
|
6779
|
-
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
|
|
6780
|
-
/* @__PURE__ */ jsx(
|
|
6781
|
-
"input",
|
|
6782
|
-
{
|
|
6783
|
-
type: "checkbox",
|
|
6784
|
-
checked: allDay,
|
|
6785
|
-
onChange: (e) => setAllDay(e.target.checked),
|
|
6786
|
-
disabled: isCompleted,
|
|
6787
|
-
className: "rounded border-input"
|
|
6788
|
-
}
|
|
6789
|
-
),
|
|
6790
|
-
labels.allDay ?? "All day"
|
|
6791
|
-
] }),
|
|
6792
|
-
(linkSearch || referenceId) && !isExisting && /* @__PURE__ */ jsxs("div", { children: [
|
|
6793
|
-
/* @__PURE__ */ jsxs("label", { className: "mb-1 block text-sm font-medium", children: [
|
|
6794
|
-
/* @__PURE__ */ jsx(Link2, { className: "mr-1 inline h-3.5 w-3.5" }),
|
|
6795
|
-
linkSearch?.label ?? labels.link ?? "Link to case"
|
|
6796
7246
|
] }),
|
|
6797
|
-
|
|
6798
|
-
/* @__PURE__ */ jsx("
|
|
6799
|
-
linkSearch && /* @__PURE__ */ jsx(
|
|
6800
|
-
"button",
|
|
6801
|
-
{
|
|
6802
|
-
type: "button",
|
|
6803
|
-
className: "text-xs text-muted-foreground hover:text-foreground",
|
|
6804
|
-
onClick: () => {
|
|
6805
|
-
setReferenceId("");
|
|
6806
|
-
setReferenceType("");
|
|
6807
|
-
setLinkLabel("");
|
|
6808
|
-
},
|
|
6809
|
-
children: "Clear"
|
|
6810
|
-
}
|
|
6811
|
-
)
|
|
6812
|
-
] }) : linkSearch ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7247
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
7248
|
+
/* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium", children: labels.description ?? "Description" }),
|
|
6813
7249
|
/* @__PURE__ */ jsx(
|
|
6814
|
-
"
|
|
6815
|
-
{
|
|
6816
|
-
value: linkQuery,
|
|
6817
|
-
onChange: (e) => setLinkQuery(e.target.value),
|
|
6818
|
-
placeholder: labels.linkPlaceholder ?? "Search cases\u2026",
|
|
6819
|
-
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
6820
|
-
}
|
|
6821
|
-
),
|
|
6822
|
-
linkOptions.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-1 max-h-40 overflow-auto rounded-md border bg-popover text-sm shadow-md", children: linkOptions.map((opt) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
6823
|
-
"button",
|
|
7250
|
+
"textarea",
|
|
6824
7251
|
{
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
setLinkQuery("");
|
|
6832
|
-
setLinkOptions([]);
|
|
6833
|
-
},
|
|
6834
|
-
children: [
|
|
6835
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: opt.label }),
|
|
6836
|
-
opt.description && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: opt.description })
|
|
6837
|
-
]
|
|
7252
|
+
value: description,
|
|
7253
|
+
onChange: (e) => setDescription(e.target.value),
|
|
7254
|
+
disabled: isCompleted,
|
|
7255
|
+
rows: 3,
|
|
7256
|
+
className: "w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7257
|
+
placeholder: "Add description"
|
|
6838
7258
|
}
|
|
6839
|
-
)
|
|
6840
|
-
] })
|
|
7259
|
+
)
|
|
7260
|
+
] })
|
|
6841
7261
|
] }),
|
|
6842
|
-
/* @__PURE__ */ jsxs("
|
|
6843
|
-
/* @__PURE__ */
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
/* @__PURE__ */ jsx(
|
|
6848
|
-
"input",
|
|
7262
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "gap-2", children: [
|
|
7263
|
+
isExisting && onDelete && !isCompleted && /* @__PURE__ */ jsx(Button, { variant: "destructive", size: "sm", onClick: onDelete, children: labels.delete ?? "Delete" }),
|
|
7264
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
7265
|
+
isExisting && /* @__PURE__ */ jsx(
|
|
7266
|
+
Button,
|
|
6849
7267
|
{
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
7268
|
+
variant: "outline",
|
|
7269
|
+
size: "sm",
|
|
7270
|
+
onClick: () => {
|
|
7271
|
+
if (isDirty) {
|
|
7272
|
+
requestDiscard("preview");
|
|
7273
|
+
} else {
|
|
7274
|
+
setMode("preview");
|
|
7275
|
+
}
|
|
7276
|
+
},
|
|
7277
|
+
children: labels.cancel ?? "Cancel"
|
|
6855
7278
|
}
|
|
6856
|
-
)
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
/* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium", children: labels.description ?? "Description" }),
|
|
6860
|
-
/* @__PURE__ */ jsx(
|
|
6861
|
-
"textarea",
|
|
7279
|
+
),
|
|
7280
|
+
!isExisting && /* @__PURE__ */ jsx(
|
|
7281
|
+
Button,
|
|
6862
7282
|
{
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
7283
|
+
variant: "outline",
|
|
7284
|
+
size: "sm",
|
|
7285
|
+
onClick: () => handleOpenChange(false),
|
|
7286
|
+
children: labels.cancel ?? "Cancel"
|
|
7287
|
+
}
|
|
7288
|
+
),
|
|
7289
|
+
!isCompleted && /* @__PURE__ */ jsxs(
|
|
7290
|
+
Button,
|
|
7291
|
+
{
|
|
7292
|
+
size: "sm",
|
|
7293
|
+
onClick: handleSave,
|
|
7294
|
+
disabled: saving || !summary.trim() || !date || !startTime || !endTime,
|
|
7295
|
+
children: [
|
|
7296
|
+
saving && /* @__PURE__ */ jsx(Loader2, { className: "mr-1 h-3.5 w-3.5 animate-spin" }),
|
|
7297
|
+
labels.save ?? "Save"
|
|
7298
|
+
]
|
|
6869
7299
|
}
|
|
6870
7300
|
)
|
|
6871
7301
|
] })
|
|
7302
|
+
] })
|
|
7303
|
+
] }) }),
|
|
7304
|
+
/* @__PURE__ */ jsx(Dialog, { open: confirmDiscard, onOpenChange: setConfirmDiscard, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[400px]", showCloseButton: false, children: [
|
|
7305
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
7306
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: labels.discardTitle ?? "Discard changes?" }),
|
|
7307
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: labels.discardMessage ?? "You have unsaved changes. Are you sure you want to discard them?" })
|
|
6872
7308
|
] }),
|
|
6873
7309
|
/* @__PURE__ */ jsxs(DialogFooter, { className: "gap-2", children: [
|
|
6874
|
-
|
|
6875
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
6876
|
-
isExisting && /* @__PURE__ */ jsx(
|
|
7310
|
+
/* @__PURE__ */ jsx(
|
|
6877
7311
|
Button,
|
|
6878
7312
|
{
|
|
6879
7313
|
variant: "outline",
|
|
6880
7314
|
size: "sm",
|
|
6881
|
-
onClick: () =>
|
|
6882
|
-
children: labels.
|
|
7315
|
+
onClick: () => setConfirmDiscard(false),
|
|
7316
|
+
children: labels.discardCancel ?? "Keep editing"
|
|
6883
7317
|
}
|
|
6884
7318
|
),
|
|
6885
|
-
|
|
6886
|
-
!isCompleted && /* @__PURE__ */ jsxs(
|
|
7319
|
+
/* @__PURE__ */ jsx(
|
|
6887
7320
|
Button,
|
|
6888
7321
|
{
|
|
7322
|
+
variant: "destructive",
|
|
6889
7323
|
size: "sm",
|
|
6890
|
-
onClick:
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
7324
|
+
onClick: () => {
|
|
7325
|
+
if (discardIntent === "preview") {
|
|
7326
|
+
revertToSnapshot();
|
|
7327
|
+
setConfirmDiscard(false);
|
|
7328
|
+
setMode("preview");
|
|
7329
|
+
} else {
|
|
7330
|
+
forceClose();
|
|
7331
|
+
}
|
|
7332
|
+
},
|
|
7333
|
+
children: labels.discardConfirm ?? "Discard"
|
|
6896
7334
|
}
|
|
6897
7335
|
)
|
|
6898
7336
|
] })
|
|
6899
|
-
] })
|
|
6900
|
-
] })
|
|
7337
|
+
] }) })
|
|
7338
|
+
] });
|
|
6901
7339
|
}
|
|
6902
7340
|
function MiniCalendar({
|
|
6903
7341
|
selected,
|