diff --git a/src/App.css b/src/App.css index 0c38016..beadb97 100644 --- a/src/App.css +++ b/src/App.css @@ -19,12 +19,3 @@ .App-link { color: #61dafb; } - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx index 720cef0..d5f3b53 100644 --- a/src/components/Calendar/Calendar.tsx +++ b/src/components/Calendar/Calendar.tsx @@ -41,7 +41,9 @@ export default function CalendarApp() { Object.keys(userPersonnalCalendars).forEach((value, id) => { if (userPersonnalCalendars[id].events) { personnalEvents = personnalEvents.concat( - userPersonnalCalendars[id].events + Object.keys(userPersonnalCalendars[id].events).map( + (eventid) => userPersonnalCalendars[id].events[eventid] + ) ); } }); @@ -50,20 +52,27 @@ export default function CalendarApp() { ); const fetchedIdsRef = useRef>(new Set()); + const calendarRange = getCalendarRange(selectedDate); + + // Create a stable string key for the range + const rangeKey = `${formatDateToYYYYMMDDTHHMMSS( + calendarRange.start + )}_${formatDateToYYYYMMDDTHHMMSS(calendarRange.end)}`; + let filteredEvents: CalendarEvent[] = []; selectedCalendars.forEach((id) => { - filteredEvents = filteredEvents.concat(calendars[id].events); + filteredEvents = filteredEvents + .concat( + Object.keys(calendars[id].events).map( + (eventid) => calendars[id].events[eventid] + ) + ) + .filter((event) => !(event.status === "CANCELLED")); }); useEffect(() => { selectedCalendars.forEach((id) => { - const events = calendars[id]?.events ?? []; - - const isEmpty = events.length === 0; - const notFetched = !fetchedIdsRef.current.has(id); - const calendarRange = getCalendarRange(selectedDate); - - if (isEmpty && notFetched && !pending) { + if (!pending && rangeKey) { dispatch( getCalendarDetailAsync({ access_token: tokens.access_token, @@ -74,10 +83,9 @@ export default function CalendarApp() { }, }) ); - fetchedIdsRef.current.add(id); } }); - }, [selectedCalendars, calendars, pending, tokens.access_token, dispatch]); + }, [rangeKey, selectedCalendars]); const [anchorEl, setAnchorEl] = useState(null); const [anchorElCal, setAnchorElCal] = useState(null); @@ -156,7 +164,6 @@ export default function CalendarApp() { eventDate.getDate() === date.getDate() ); }); - console.log(date, hasEvents); return hasEvents ?
: null; }} /> @@ -191,7 +198,7 @@ export default function CalendarApp() { weekNumberFormat={{ week: "long" }} slotDuration={"00:30:00"} slotLabelInterval={"00:30:00"} - scrollTime={"07:00:00"} + scrollTime={"09:00:00"} allDayText="" slotLabelFormat={{ hour: "2-digit", diff --git a/src/components/Menubar/Menubar.css b/src/components/Menubar/Menubar.css index 7d87ae3..eb6d19f 100644 --- a/src/components/Menubar/Menubar.css +++ b/src/components/Menubar/Menubar.css @@ -79,7 +79,3 @@ left: 1511px; gap: 24px; } - -/* Responsive for mobile */ -@media (max-width: 768px) { -} diff --git a/src/features/Calendars/CalendarApi.ts b/src/features/Calendars/CalendarApi.ts index 881c0b5..6809101 100644 --- a/src/features/Calendars/CalendarApi.ts +++ b/src/features/Calendars/CalendarApi.ts @@ -19,7 +19,6 @@ export async function getCalendar( opaque_token: string, match: { start: string; end: string } ) { - console.log(match) const response = await fetch( `${(window as any).CALENDAR_BASE_URL}/dav/calendars/${id}.json`, { diff --git a/src/features/Calendars/CalendarSlice.ts b/src/features/Calendars/CalendarSlice.ts index 21ed44f..245dcfb 100644 --- a/src/features/Calendars/CalendarSlice.ts +++ b/src/features/Calendars/CalendarSlice.ts @@ -24,7 +24,7 @@ export const getCalendarsListAsync = createAsyncThunk< : cal._links.self.href.replace("/calendars/", "").replace(".json", ""); const color = cal["apple:color"]; - importedCalendars[id] = { id, name, description, color, events: [] }; + importedCalendars[id] = { id, name, description, color, events: {} }; } return importedCalendars; @@ -36,10 +36,12 @@ export const getCalendarDetailAsync = createAsyncThunk< >("calendars/getCalendarDetails", async ({ access_token, calId, match }) => { const calendar = await getCalendar(calId, access_token, match); const color = calendar["apple:color"]; - const events: CalendarEvent[] = calendar._embedded["dav:item"].map( + const events: CalendarEvent[] = calendar._embedded["dav:item"].flatMap( (eventdata: any) => { - const datas = eventdata.data[2][0][1]; - return parseCalendarEvent(datas, color, calId); + const vevents = eventdata.data[2] as any[][]; // array of ['vevent', RawEntry[], []] + return vevents.map((vevent: any[]) => { + return parseCalendarEvent(vevent[1], color, calId); + }); } ); @@ -56,28 +58,25 @@ const CalendarSlice = createSlice({ state.list[id].name = action.payload.name; state.list[id].color = action.payload.color; state.list[id].description = action.payload.description; - state.list[id].events = []; + state.list[id].events = {}; }, addEvent: ( state, action: PayloadAction<{ calendarUid: string; event: CalendarEvent }> ) => { if (!state.list[action.payload.calendarUid].events) { - state.list[action.payload.calendarUid].events = []; + state.list[action.payload.calendarUid].events = {}; } - state.list[action.payload.calendarUid].events.push(action.payload.event); + state.list[action.payload.calendarUid].events[action.payload.event.uid] = + action.payload.event; }, removeEvent: ( state, action: PayloadAction<{ calendarUid: string; eventUid: string }> ) => { - state.list[action.payload.calendarUid as string].events = state.list[ - action.payload.calendarUid - ].events.filter((event) => { - if (event.uid !== action.payload.calendarUid) { - return event; - } - }); + delete state.list[action.payload.calendarUid].events[ + action.payload.eventUid + ]; }, }, extraReducers: (builder) => { @@ -101,14 +100,15 @@ const CalendarSlice = createSlice({ if (!state.list[action.payload.calId]) { state.list[action.payload.calId] = { id: action.payload.calId, - events: [] as CalendarEvent[], + events: {}, } as Calendars; } action.payload.events.forEach((event) => { - state.list[action.payload.calId].events.push(event); + state.list[action.payload.calId].events[event.uid] = event; }); - state.list[action.payload.calId].events.forEach((event) => { - event.color = state.list[action.payload.calId].color; + Object.keys(state.list[action.payload.calId].events).forEach((id) => { + state.list[action.payload.calId].events[id].color = + state.list[action.payload.calId].color; }); } ) diff --git a/src/features/Calendars/CalendarTypes.ts b/src/features/Calendars/CalendarTypes.ts index 25fed48..1bb5aff 100644 --- a/src/features/Calendars/CalendarTypes.ts +++ b/src/features/Calendars/CalendarTypes.ts @@ -8,5 +8,5 @@ export interface Calendars { description?: string; calscale?: string; version?: string; - events: CalendarEvent[]; + events: Record; } diff --git a/src/features/Events/EventsTypes.ts b/src/features/Events/EventsTypes.ts index c27d337..e33237d 100644 --- a/src/features/Events/EventsTypes.ts +++ b/src/features/Events/EventsTypes.ts @@ -17,4 +17,5 @@ export interface CalendarEvent { color?: string; allday?: Boolean; error?: string; + status?: string; } diff --git a/src/features/Events/ImportAlert.tsx b/src/features/Events/ImportAlert.tsx index 0f3a292..995f7fc 100644 --- a/src/features/Events/ImportAlert.tsx +++ b/src/features/Events/ImportAlert.tsx @@ -18,18 +18,24 @@ export default function ImportAlert() { return ( <> {Object.keys(calendars).map((calendarId) => - calendars[calendarId].events - .filter((event) => event.error) - .map((event) => { - const isVisible = visibleAlerts[event.uid] ?? true; // default to visible + Object.keys(calendars[calendarId].events) + .filter((id) => calendars[calendarId].events[id].error) + .map((id) => { + const isVisible = + visibleAlerts[calendars[calendarId].events[id].uid] ?? true; // default to visible return ( - + toggleEventAlert(event.uid)} + onClose={() => + toggleEventAlert(calendars[calendarId].events[id].uid) + } > - {event.error} + {calendars[calendarId].events[id].error} ); diff --git a/src/features/Events/eventUtils.ts b/src/features/Events/eventUtils.ts index 6d238ea..ccee1a6 100644 --- a/src/features/Events/eventUtils.ts +++ b/src/features/Events/eventUtils.ts @@ -9,6 +9,7 @@ export function parseCalendarEvent( calendarid: string ): CalendarEvent { const event: Partial = { color, attendee: [] }; + let recurrenceId; for (const [key, params, type, value] of data) { switch (key.toLowerCase()) { @@ -61,8 +62,16 @@ export function parseCalendarEvent( case "sequence": event.sequence = Number(value); break; + case "recurrence-id": + recurrenceId = value; + break; + case "status": + event.status = String(value); } } + if (recurrenceId && event.uid) { + event.uid = `${event.uid}/${recurrenceId}`; + } if (!event.uid || !event.start) { console.error( diff --git a/src/index.tsx b/src/index.tsx index 3961865..6e618bf 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,7 +4,6 @@ import { Provider } from "react-redux"; import App from "./App"; import { store } from "./app/store"; -import reportWebVitals from "./reportWebVitals"; const container = document.getElementById("root")!; const root = createRoot(container); @@ -15,5 +14,3 @@ root.render( ); - -reportWebVitals();