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