feat: enhance event modal for desktop and mobile views

This commit is contained in:
Linus Rath
2026-03-11 20:35:25 +01:00
parent e5c1cd45c5
commit d3a5b4189e
2 changed files with 33 additions and 13 deletions
+21 -1
View File
@@ -683,6 +683,25 @@ export default function CalendarPage() {
{renderView()}
{/* Desktop event panel */}
{!isMobile && showEventModal && (
<div className="w-[400px] border-l border-border flex-shrink-0 overflow-hidden">
<EventModal
event={editEvent}
calendars={calendars}
defaultDate={defaultModalDate}
defaultEndDate={defaultModalEndDate}
onSave={handleSaveEvent}
onDelete={handleDeleteEvent}
onDuplicate={handleDuplicateEvent}
onRsvp={handleRsvp}
onClose={() => { setShowEventModal(false); setEditEvent(null); }}
currentUserEmails={currentUserEmails}
isMobile={false}
/>
</div>
)}
{/* Floating Create Event Button (mobile) */}
{isMobile && (
<Button
@@ -718,7 +737,7 @@ export default function CalendarPage() {
/>
)}
{showEventModal && (
{showEventModal && isMobile && (
<EventModal
event={editEvent}
calendars={calendars}
@@ -730,6 +749,7 @@ export default function CalendarPage() {
onRsvp={handleRsvp}
onClose={() => { setShowEventModal(false); setEditEvent(null); }}
currentUserEmails={currentUserEmails}
isMobile={true}
/>
)}
+12 -12
View File
@@ -29,6 +29,7 @@ interface EventModalProps {
onRsvp?: (eventId: string, participantId: string, status: CalendarParticipant['participationStatus']) => void;
onClose: () => void;
currentUserEmails?: string[];
isMobile?: boolean;
}
function formatDateInput(d: Date): string {
@@ -68,6 +69,7 @@ export function EventModal({
onRsvp,
onClose,
currentUserEmails = [],
isMobile = false,
}: EventModalProps) {
const t = useTranslations("calendar");
const isEdit = !!event;
@@ -374,16 +376,15 @@ export function EventModal({
const participants = getParticipantList(event);
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className="absolute inset-0 bg-black/50 backdrop-blur-[1px]" onClick={onClose} aria-hidden="true" />
<div ref={modalRef} role="dialog" aria-modal="true" aria-label={event.title || t("events.no_title")} className="relative bg-background border border-border rounded-lg shadow-xl w-full max-w-lg mx-4 max-h-[90vh] overflow-y-auto animate-in zoom-in-95 duration-200">
<div className="flex items-center justify-between px-6 py-4 border-b border-border">
<div ref={modalRef} role="dialog" aria-modal={isMobile || undefined} aria-label={event.title || t("events.no_title")} className={isMobile ? "fixed inset-0 z-50 flex flex-col bg-background" : "flex flex-col h-full bg-background"}>
<div className="flex items-center justify-between px-6 py-4 border-b border-border flex-shrink-0">
<h2 className="text-lg font-semibold truncate">{event.title || t("events.no_title")}</h2>
<button onClick={onClose} className="p-1.5 rounded-md hover:bg-muted transition-colors duration-150 text-muted-foreground hover:text-foreground" aria-label={t("form.cancel")}>
<X className="w-5 h-5" />
</button>
</div>
<div className="flex-1 overflow-y-auto">
<div className="px-6 py-4 space-y-3">
<div className="flex items-start gap-3 rounded-lg border border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-950/50 px-4 py-3">
<CalendarDays className="w-5 h-5 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0" />
@@ -431,8 +432,9 @@ export function EventModal({
</div>
)}
</div>
</div>
<div className="px-6 py-4 border-t border-border">
<div className="px-6 py-4 border-t border-border flex-shrink-0">
<div className="flex items-center justify-between">
<span className="text-sm font-medium">{t("participants.rsvp_label")}</span>
<div className="flex gap-2">
@@ -472,16 +474,13 @@ export function EventModal({
</div>
</div>
</div>
</div>
</div>
);
}
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className="absolute inset-0 bg-black/50 backdrop-blur-[1px]" onClick={onClose} aria-hidden="true" />
<div ref={modalRef} role="dialog" aria-modal="true" aria-label={isEdit ? t("events.edit") : t("events.create")} className="relative bg-background border border-border rounded-lg shadow-xl w-full max-w-lg mx-4 max-h-[90vh] overflow-y-auto animate-in zoom-in-95 duration-200">
<div className="flex items-center justify-between px-6 py-4 border-b border-border">
<div ref={modalRef} role="dialog" aria-modal={isMobile || undefined} aria-label={isEdit ? t("events.edit") : t("events.create")} className={isMobile ? "fixed inset-0 z-50 flex flex-col bg-background" : "flex flex-col h-full bg-background"}>
<div className="flex items-center justify-between px-6 py-4 border-b border-border flex-shrink-0">
<h2 className="text-lg font-semibold">
{isEdit ? t("events.edit") : t("events.create")}
</h2>
@@ -490,6 +489,7 @@ export function EventModal({
</button>
</div>
<div className="flex-1 overflow-y-auto">
<div className="px-6 py-4 space-y-4">
<div>
<label className="text-sm font-medium mb-1 block">{t("form.title")}</label>
@@ -665,8 +665,9 @@ export function EventModal({
</div>
)}
</div>
</div>
<div className="flex items-center justify-between px-6 py-4 border-t border-border">
<div className="flex items-center justify-between px-6 py-4 border-t border-border flex-shrink-0">
<div className="flex items-center gap-1">
{isEdit && onDelete && (
showDeleteConfirm ? (
@@ -727,7 +728,6 @@ export function EventModal({
</Button>
</div>
</div>
</div>
</div>
);
}