1 import type { CSSProperties, KeyboardEvent, Ref } from 'react';
2 import { useMemo } from 'react';
4 import { useUser } from '@proton/account/user/hooks';
5 import { CalendarEventDateHeader, Icon } from '@proton/components';
6 import clsx from '@proton/utils/clsx';
8 import type { CalendarViewEvent, CalendarViewEventTemporaryEvent } from '../../containers/calendar/interface';
9 import { getEventStyle } from '../../helpers/color';
10 import { getEventStatusTraits } from '../../helpers/event';
11 import { getEventErrorMessage, getEventLoadingMessage } from './error';
12 import getEventInformation from './getEventInformation';
13 import useReadEvent from './useReadEvent';
17 formatTime: (date: Date) => string;
19 event: CalendarViewEvent | CalendarViewEventTemporaryEvent;
22 isOutsideStart: boolean;
23 isOutsideEnd: boolean;
25 eventRef?: Ref<HTMLDivElement>;
28 const FullDayEvent = ({
31 className = 'calendar-dayeventcell h-custom w-custom top-custom left-custom absolute text-left',
41 const [{ hasPaidMail }] = useUser();
42 const { start, end, data: targetEventData, isAllDay, isAllPartDay } = event;
44 const model = useReadEvent(targetEventData, tzid);
45 const { isEventReadLoading, color, eventReadError, eventTitleSafe } = getEventInformation(
51 const { isUnanswered, isCancelled } = getEventStatusTraits(model);
53 const eventStyle = useMemo(() => {
54 return getEventStyle(color);
57 const startTimeString = useMemo(() => {
58 if (start && (!isAllDay || isAllPartDay)) {
59 return formatTime(start);
61 }, [start, isAllPartDay, isAllDay, formatTime]);
63 const titleString = (() => {
67 if (isEventReadLoading) {
70 return eventTitleSafe;
73 const expandableTitleString = (() => {
75 return getEventErrorMessage(eventReadError);
77 if (isEventReadLoading) {
78 return getEventLoadingMessage();
80 return eventTitleSafe;
83 const handleKeyDown = (e: KeyboardEvent) => {
84 // The shortest way we found to open the event popover using keyboard
85 // is to click on the event.
86 // We need to trigger a mousedown to launch the logic to open an event,
87 // but since mousedown event is allowing to drag the event on the grid,
88 // we need to trigger a mouseup event right after so that we only open the popover.
89 if (e.key === 'Enter' || e.key === ' ') {
95 <div className="flex flex-nowrap flex-1 items-center">
97 <Icon className="mr-2 shrink-0 calendar-dayeventcell-circle" size={4} name="circle-filled" />
100 {isOutsideStart ? <Icon name="chevron-left" size={3} className="shrink-0" /> : null}
102 {eventReadError ? <Icon name="lock-filled" className="calendar-dayeventcell-lock-icon" /> : null}
104 <span data-testid="calendar-view:all-day-event" className="flex-1 text-ellipsis">
105 {startTimeString && <span className="calendar-dayeventcell-time">{startTimeString}</span>}
106 <span className="calendar-dayeventcell-title">{titleString}</span>
107 <div className="sr-only">
108 <CalendarEventDateHeader
112 formatTime={formatTime}
114 hasModifiedAllDayEndDate
119 {isOutsideEnd ? <Icon name="chevron-right" size={3} className="shrink-0" /> : null}
126 className={clsx([className, isOutsideStart && 'isOutsideStart', isOutsideEnd && 'isOutsideEnd'])}
127 data-ignore-create="1"
129 {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/prefer-tag-over-role */}
132 onKeyDown={handleKeyDown}
133 title={expandableTitleString}
137 'calendar-dayeventcell-inner text-left flex',
138 !isAllDay && 'isNotAllDay',
139 !isEventReadLoading && 'isLoaded',
140 isBeforeNow && 'isPast',
141 isSelected && 'isSelected',
142 isUnanswered && 'isUnanswered',
143 isCancelled && 'isCancelled',
154 export default FullDayEvent;