Update all non-major dependencies
[ProtonMail-WebClient.git] / applications / calendar / src / app / components / events / FullDayEvent.tsx
blob36f48f745333965bfe99259febb251f5f89bc3af
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';
15 interface Props {
16     style: CSSProperties;
17     formatTime: (date: Date) => string;
18     className?: string;
19     event: CalendarViewEvent | CalendarViewEventTemporaryEvent;
20     isSelected: boolean;
21     isBeforeNow: boolean;
22     isOutsideStart: boolean;
23     isOutsideEnd: boolean;
24     onClick?: () => void;
25     eventRef?: Ref<HTMLDivElement>;
26     tzid: string;
28 const FullDayEvent = ({
29     style,
30     formatTime,
31     className = 'calendar-dayeventcell h-custom w-custom top-custom left-custom absolute text-left',
32     event,
33     isSelected,
34     isBeforeNow,
35     isOutsideStart,
36     isOutsideEnd,
37     eventRef,
38     onClick,
39     tzid,
40 }: Props) => {
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(
46         event,
47         model,
48         hasPaidMail
49     );
51     const { isUnanswered, isCancelled } = getEventStatusTraits(model);
53     const eventStyle = useMemo(() => {
54         return getEventStyle(color);
55     }, [color]);
57     const startTimeString = useMemo(() => {
58         if (start && (!isAllDay || isAllPartDay)) {
59             return formatTime(start);
60         }
61     }, [start, isAllPartDay, isAllDay, formatTime]);
63     const titleString = (() => {
64         if (eventReadError) {
65             return '';
66         }
67         if (isEventReadLoading) {
68             return '…';
69         }
70         return eventTitleSafe;
71     })();
73     const expandableTitleString = (() => {
74         if (eventReadError) {
75             return getEventErrorMessage(eventReadError);
76         }
77         if (isEventReadLoading) {
78             return getEventLoadingMessage();
79         }
80         return eventTitleSafe;
81     })();
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 === ' ') {
90             onClick?.();
91         }
92     };
94     const content = (
95         <div className="flex flex-nowrap flex-1 items-center">
96             {!isAllDay ? (
97                 <Icon className="mr-2 shrink-0 calendar-dayeventcell-circle" size={4} name="circle-filled" />
98             ) : null}
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
109                         startDate={start}
110                         endDate={end}
111                         isAllDay={true}
112                         formatTime={formatTime}
113                         hasFakeUtcDates
114                         hasModifiedAllDayEndDate
115                     />
116                 </div>
117             </span>
119             {isOutsideEnd ? <Icon name="chevron-right" size={3} className="shrink-0" /> : null}
120         </div>
121     );
123     return (
124         <li
125             style={style}
126             className={clsx([className, isOutsideStart && 'isOutsideStart', isOutsideEnd && 'isOutsideEnd'])}
127             data-ignore-create="1"
128         >
129             {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/prefer-tag-over-role */}
130             <div
131                 onClick={onClick}
132                 onKeyDown={handleKeyDown}
133                 title={expandableTitleString}
134                 role="button"
135                 tabIndex={0}
136                 className={clsx([
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',
144                 ])}
145                 style={eventStyle}
146                 ref={eventRef}
147             >
148                 {content}
149             </div>
150         </li>
151     );
154 export default FullDayEvent;