fix: show end date in event popover for multi-day events #318
This commit is contained in:
@@ -8,11 +8,11 @@ import {
|
|||||||
X, Clock, MapPin, Video, Users, Repeat, Bell, AlignLeft,
|
X, Clock, MapPin, Video, Users, Repeat, Bell, AlignLeft,
|
||||||
Pencil, Trash2, Copy, Send, Check,
|
Pencil, Trash2, Copy, Send, Check,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { format, parseISO } from "date-fns";
|
import { format, isSameDay, parseISO } from "date-fns";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import type { CalendarEvent, Calendar, CalendarParticipant } from "@/lib/jmap/types";
|
import type { CalendarEvent, Calendar, CalendarParticipant } from "@/lib/jmap/types";
|
||||||
import { parseDuration, getEventColor } from "./event-card";
|
import { parseDuration, getEventColor } from "./event-card";
|
||||||
import { getEventEndDate, getEventStartDate } from "@/lib/calendar-utils";
|
import { getEventDisplayEndDate, getEventEndDate, getEventStartDate } from "@/lib/calendar-utils";
|
||||||
import {
|
import {
|
||||||
isOrganizer,
|
isOrganizer,
|
||||||
getUserParticipantId,
|
getUserParticipantId,
|
||||||
@@ -143,6 +143,8 @@ export function EventDetailPopover({
|
|||||||
const startDate = getEventStartDate(event);
|
const startDate = getEventStartDate(event);
|
||||||
const durationMinutes = parseDuration(event.duration);
|
const durationMinutes = parseDuration(event.duration);
|
||||||
const endDate = getEventEndDate(event);
|
const endDate = getEventEndDate(event);
|
||||||
|
const displayEndDate = getEventDisplayEndDate(event);
|
||||||
|
const isMultiDay = !isSameDay(startDate, displayEndDate);
|
||||||
|
|
||||||
const locationName = useMemo(() => {
|
const locationName = useMemo(() => {
|
||||||
if (!event.locations) return null;
|
if (!event.locations) return null;
|
||||||
@@ -331,16 +333,50 @@ export function EventDetailPopover({
|
|||||||
<div className="flex items-start gap-2.5">
|
<div className="flex items-start gap-2.5">
|
||||||
<Clock className="w-4 h-4 text-muted-foreground mt-0.5 flex-shrink-0" />
|
<Clock className="w-4 h-4 text-muted-foreground mt-0.5 flex-shrink-0" />
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<span className="font-medium text-foreground">
|
{isMultiDay ? (
|
||||||
{formatEventDate(startDate)}
|
event.showWithoutTime ? (
|
||||||
</span>
|
<>
|
||||||
{event.showWithoutTime ? (
|
<div className="font-medium text-foreground">
|
||||||
<span className="text-muted-foreground ml-1.5">{t("events.all_day")}</span>
|
{formatEventDate(startDate)} –
|
||||||
|
</div>
|
||||||
|
<div className="font-medium text-foreground">
|
||||||
|
{formatEventDate(displayEndDate)}
|
||||||
|
</div>
|
||||||
|
<div className="text-muted-foreground">{t("events.all_day")}</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="font-medium text-foreground">
|
||||||
|
{formatEventDate(startDate)}
|
||||||
|
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||||
|
{formatTime(startDate)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="font-medium text-foreground">
|
||||||
|
{formatEventDate(endDate)}
|
||||||
|
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||||
|
{formatTime(endDate)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-muted-foreground text-xs">
|
||||||
|
({formatDurationDisplay(durationMinutes)})
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<div className="text-muted-foreground">
|
<>
|
||||||
{formatTime(startDate)} – {formatTime(endDate)}
|
<span className="font-medium text-foreground">
|
||||||
<span className="ml-1.5 text-xs">({formatDurationDisplay(durationMinutes)})</span>
|
{formatEventDate(startDate)}
|
||||||
</div>
|
</span>
|
||||||
|
{event.showWithoutTime ? (
|
||||||
|
<span className="text-muted-foreground ml-1.5">{t("events.all_day")}</span>
|
||||||
|
) : (
|
||||||
|
<div className="text-muted-foreground">
|
||||||
|
{formatTime(startDate)} – {formatTime(endDate)}
|
||||||
|
<span className="ml-1.5 text-xs">({formatDurationDisplay(durationMinutes)})</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useTranslations } from "next-intl";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { X, Trash2, Check, Users, CalendarDays, Copy, Pencil, Clock, MapPin, Video, Repeat, Bell, AlignLeft, Plus } from "lucide-react";
|
import { X, Trash2, Check, Users, CalendarDays, Copy, Pencil, Clock, MapPin, Video, Repeat, Bell, AlignLeft, Plus } from "lucide-react";
|
||||||
import { format, parseISO, addHours, addDays } from "date-fns";
|
import { format, parseISO, addHours, addDays, isSameDay } from "date-fns";
|
||||||
import type { CalendarEvent, Calendar, CalendarParticipant, CalendarEventAlert } from "@/lib/jmap/types";
|
import type { CalendarEvent, Calendar, CalendarParticipant, CalendarEventAlert } from "@/lib/jmap/types";
|
||||||
import { parseDuration, getEventColor } from "./event-card";
|
import { parseDuration, getEventColor } from "./event-card";
|
||||||
import { buildAllDayDuration, getEventDisplayEndDate, getEventEndDate, getEventStartDate, getPrimaryCalendarId } from "@/lib/calendar-utils";
|
import { buildAllDayDuration, getEventDisplayEndDate, getEventEndDate, getEventStartDate, getPrimaryCalendarId } from "@/lib/calendar-utils";
|
||||||
@@ -621,14 +621,42 @@ export function EventModal({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-sm">
|
{(() => {
|
||||||
<span className="font-medium">{formatEventDate(startD)}</span>
|
const displayEnd = getEventDisplayEndDate(event);
|
||||||
{!event.showWithoutTime && (
|
const multiDay = !isSameDay(startD, displayEnd);
|
||||||
<span className="text-muted-foreground ml-2">
|
if (multiDay && event.showWithoutTime) {
|
||||||
{format(startD, timeDisplayFmt)} – {format(endD, timeDisplayFmt)}
|
return (
|
||||||
</span>
|
<div className="text-sm">
|
||||||
)}
|
<div className="font-medium">{formatEventDate(startD)} –</div>
|
||||||
</div>
|
<div className="font-medium">{formatEventDate(displayEnd)}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (multiDay) {
|
||||||
|
return (
|
||||||
|
<div className="text-sm">
|
||||||
|
<div>
|
||||||
|
<span className="font-medium">{formatEventDate(startD)}</span>
|
||||||
|
<span className="text-muted-foreground ml-2">{format(startD, timeDisplayFmt)}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="font-medium">{formatEventDate(endD)}</span>
|
||||||
|
<span className="text-muted-foreground ml-2">{format(endD, timeDisplayFmt)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="text-sm">
|
||||||
|
<span className="font-medium">{formatEventDate(startD)}</span>
|
||||||
|
{!event.showWithoutTime && (
|
||||||
|
<span className="text-muted-foreground ml-2">
|
||||||
|
{format(startD, timeDisplayFmt)} – {format(endD, timeDisplayFmt)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
|
||||||
{event.description && (
|
{event.description && (
|
||||||
<p className="text-sm text-muted-foreground">{event.description}</p>
|
<p className="text-sm text-muted-foreground">{event.description}</p>
|
||||||
@@ -742,17 +770,55 @@ export function EventModal({
|
|||||||
<div className="flex items-start gap-2.5">
|
<div className="flex items-start gap-2.5">
|
||||||
<Clock className="w-4 h-4 text-muted-foreground mt-0.5 flex-shrink-0" />
|
<Clock className="w-4 h-4 text-muted-foreground mt-0.5 flex-shrink-0" />
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<span className="font-medium text-foreground">
|
{(() => {
|
||||||
{formatEventDate(startD)}
|
const displayEnd = getEventDisplayEndDate(event);
|
||||||
</span>
|
const multiDay = !isSameDay(startD, displayEnd);
|
||||||
{event.showWithoutTime ? (
|
if (multiDay && event.showWithoutTime) {
|
||||||
<span className="text-muted-foreground ml-1.5">{t("events.all_day")}</span>
|
return (
|
||||||
) : (
|
<>
|
||||||
<div className="text-muted-foreground">
|
<div className="font-medium text-foreground">{formatEventDate(startD)} –</div>
|
||||||
{format(startD, timeDisplayFmt)} – {format(endD, timeDisplayFmt)}
|
<div className="font-medium text-foreground">{formatEventDate(displayEnd)}</div>
|
||||||
<span className="ml-1.5 text-xs">({formatDurationDisplay(durMin)})</span>
|
<div className="text-muted-foreground">{t("events.all_day")}</div>
|
||||||
</div>
|
</>
|
||||||
)}
|
);
|
||||||
|
}
|
||||||
|
if (multiDay) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="font-medium text-foreground">
|
||||||
|
{formatEventDate(startD)}
|
||||||
|
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||||
|
{format(startD, timeDisplayFmt)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="font-medium text-foreground">
|
||||||
|
{formatEventDate(endD)}
|
||||||
|
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||||
|
{format(endD, timeDisplayFmt)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-muted-foreground text-xs">
|
||||||
|
({formatDurationDisplay(durMin)})
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span className="font-medium text-foreground">
|
||||||
|
{formatEventDate(startD)}
|
||||||
|
</span>
|
||||||
|
{event.showWithoutTime ? (
|
||||||
|
<span className="text-muted-foreground ml-1.5">{t("events.all_day")}</span>
|
||||||
|
) : (
|
||||||
|
<div className="text-muted-foreground">
|
||||||
|
{format(startD, timeDisplayFmt)} – {format(endD, timeDisplayFmt)}
|
||||||
|
<span className="ml-1.5 text-xs">({formatDurationDisplay(durMin)})</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user