diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx index a3edbbb..cfef63e 100644 --- a/src/components/Calendar/Calendar.tsx +++ b/src/components/Calendar/Calendar.tsx @@ -14,6 +14,7 @@ import { CalendarEvent } from "../../features/Events/EventsTypes"; import CalendarSelection from "./CalendarSelection"; import { getCalendarDetailAsync, + getCalendarsListAsync, getEventAsync, putEventAsync, updateEventLocal, @@ -92,13 +93,15 @@ export default function CalendarApp() { let filteredEvents: CalendarEvent[] = []; selectedCalendars.forEach((id) => { - filteredEvents = filteredEvents - .concat( - Object.keys(calendars[id].events).map( - (eventid) => calendars[id].events[eventid] + if (calendars[id].events) { + filteredEvents = filteredEvents + .concat( + Object.keys(calendars[id].events).map( + (eventid) => calendars[id].events[eventid] + ) ) - ) - .filter((event) => !(event.status === "CANCELLED")); + .filter((event) => !(event.status === "CANCELLED")); + } }); useEffect(() => { @@ -125,7 +128,6 @@ export default function CalendarApp() { const [openEventDisplay, setOpenEventDisplay] = useState(false); const [eventDisplayedId, setEventDisplayedId] = useState(""); const [eventDisplayedCalId, setEventDisplayedCalId] = useState(""); - const [anchorElCal, setAnchorElCal] = useState(null); const [selectedRange, setSelectedRange] = useState( null ); @@ -248,7 +250,6 @@ export default function CalendarApp() { selectedCalendars={selectedCalendars} setSelectedCalendars={setSelectedCalendars} /> -
@@ -270,7 +271,8 @@ export default function CalendarApp() { customButtons={{ refresh: { text: "↻", - click: () => { + click: async () => { + await dispatch(getCalendarsListAsync()); selectedCalendars.forEach((id) => { if (!pending && rangeKey) { dispatch( @@ -521,11 +523,6 @@ export default function CalendarApp() { setSelectedRange={setSelectedRange} calendarRef={calendarRef} /> - setAnchorElCal(null)} - /> {openEventDisplay && eventDisplayedId && eventDisplayedCalId && ( {}, [calendars]); + const [anchorElCal, setAnchorElCal] = useState(null); + return ( -
- -

Personnal Calendars

-
- {personnalCalendars.map((id) => { - return ( -
- -
- ); - })} - {delegatedCalendars.length > 0 && ( - <> - -

Delegated Calendars

-
- {delegatedCalendars.map((id) => ( + <> +
+
+

Personnal Calendars

+ +
+ {personnalCalendars.map((id) => { + return (
- ))} - - )} - {sharedCalendars.length > 0 && ( - <> - -

Shared Calendars

-
- {sharedCalendars.map((id) => ( -
- -
- ))} - - )} -
+ ); + })} + {delegatedCalendars.length > 0 && ( + <> + +

Delegated Calendars

+
+ {delegatedCalendars.map((id) => ( +
+ +
+ ))} + + )} + {sharedCalendars.length > 0 && ( + <> + +

Shared Calendars

+
+ {sharedCalendars.map((id) => ( +
+ +
+ ))} + + )} +
+ setAnchorElCal(null)} + /> + ); } diff --git a/src/features/Calendars/CalendarApi.ts b/src/features/Calendars/CalendarApi.ts index 9439be6..9cf8035 100644 --- a/src/features/Calendars/CalendarApi.ts +++ b/src/features/Calendars/CalendarApi.ts @@ -30,3 +30,24 @@ export async function getCalendar( const calendar = await response.json(); return calendar; } + +export async function postCalendar( + userId: string, + calId: string, + color: string, + name: string, + desc: string +) { + const response = await api.post(`dav/calendars/${userId}.json`, { + headers: { + Accept: "application/json, text/plain, */*", + }, + body: JSON.stringify({ + id: calId, + "dav:name": name, + "apple:color": color, + "caldav:description": desc, + }), + }); + return response; +} diff --git a/src/features/Calendars/CalendarModal.tsx b/src/features/Calendars/CalendarModal.tsx index 10c7360..a196993 100644 --- a/src/features/Calendars/CalendarModal.tsx +++ b/src/features/Calendars/CalendarModal.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; -import { createCalendar } from "./CalendarSlice"; -import { useAppDispatch } from "../../app/hooks"; +import { createCalendar, createCalendarAsync } from "./CalendarSlice"; +import { useAppDispatch, useAppSelector } from "../../app/hooks"; import { Popover, TextField, @@ -21,14 +21,18 @@ function CalendarPopover({ onClose: (Calendar: {}, reason: "backdropClick" | "escapeKeyDown") => void; }) { const dispatch = useAppDispatch(); - + const userId = + useAppSelector((state) => state.user.userData.openpaasId) ?? ""; const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [color, setColor] = useState(""); const [timeZone, setTimeZone] = useState(""); const timezones = Intl.supportedValuesOf?.("timeZone") ?? []; const handleSave = () => { - dispatch(createCalendar({ name, description, color })); + const calId = crypto.randomUUID(); + dispatch( + createCalendarAsync({ name, desc: description, color, userId, calId }) + ); onClose({}, "backdropClick"); // Reset @@ -68,7 +72,7 @@ function CalendarPopover({ gutterBottom style={{ backgroundColor: color }} > - Create a Calendar + Calendar configuration ("calendars/createCalendar", async ({ userId, calId, color, name, desc }) => { + const response = await postCalendar(userId, calId, color, name, desc); + return { userId, calId, color, name, desc }; +}); + const CalendarSlice = createSlice({ name: "calendars", initialState: { list: {} as Record, pending: false }, @@ -206,9 +214,7 @@ const CalendarSlice = createSlice({ getCalendarsListAsync.fulfilled, (state, action: PayloadAction>) => { state.pending = false; - Object.keys(action.payload).forEach((id) => { - state.list[id] = action.payload[id]; - }); + state.list = action.payload; } ) .addCase( @@ -324,6 +330,15 @@ const CalendarSlice = createSlice({ ]; } }) + .addCase(createCalendarAsync.fulfilled, (state, action) => { + state.pending = false; + state.list[`${action.payload.userId}/${action.payload.calId}`] = { + color: action.payload.color, + id: `${action.payload.userId}/${action.payload.calId}`, + description: action.payload.desc, + name: action.payload.name, + } as unknown as Calendars; + }) .addCase(getCalendarDetailAsync.pending, (state) => { state.pending = true; }) @@ -341,6 +356,9 @@ const CalendarSlice = createSlice({ }) .addCase(deleteEventAsync.pending, (state) => { state.pending = true; + }) + .addCase(createCalendarAsync.pending, (state) => { + state.pending = true; }); }, }); diff --git a/src/features/Events/ImportAlert.tsx b/src/features/Events/ImportAlert.tsx index 995f7fc..70a32d6 100644 --- a/src/features/Events/ImportAlert.tsx +++ b/src/features/Events/ImportAlert.tsx @@ -18,28 +18,30 @@ export default function ImportAlert() { return ( <> {Object.keys(calendars).map((calendarId) => - 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 + calendars[calendarId]?.events + ? 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(calendars[calendarId].events[id].uid) - } - > - {calendars[calendarId].events[id].error} - - - ); - }) + return ( + + + toggleEventAlert(calendars[calendarId].events[id].uid) + } + > + {calendars[calendarId].events[id].error} + + + ); + }) + : [] )} );