import { useSignal } from '@preact/signals'; import { Calendar } from '/lib/models/calendar.ts'; import { CALENDAR_COLOR_OPTIONS, getColorAsHex } from '/lib/utils/calendar.ts'; import { RequestBody as AddRequestBody, ResponseBody as AddResponseBody } from '/routes/api/calendar/add.tsx'; import { RequestBody as UpdateRequestBody, ResponseBody as UpdateResponseBody } from '/routes/api/calendar/update.tsx'; import { RequestBody as DeleteRequestBody, ResponseBody as DeleteResponseBody } from '/routes/api/calendar/delete.tsx'; interface CalendarsProps { initialCalendars: Calendar[]; } export default function Calendars({ initialCalendars }: CalendarsProps) { const isAdding = useSignal(false); const isDeleting = useSignal(false); const isSaving = useSignal(false); const calendars = useSignal(initialCalendars); const openCalendar = useSignal(null); async function onClickAddCalendar() { if (isAdding.value) { return; } const name = (prompt(`What's the **name** for the new calendar?`) || '').trim(); if (!name) { alert('A name is required for a new calendar!'); return; } isAdding.value = true; try { const requestBody: AddRequestBody = { name }; const response = await fetch(`/api/calendar/add`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as AddResponseBody; if (!result.success) { throw new Error('Failed to add calendar!'); } calendars.value = [...result.newCalendars]; } catch (error) { console.error(error); } isAdding.value = false; } async function onClickDeleteCalendar(calendarId: string) { if (confirm('Are you sure you want to delete this calendar and all its events?')) { if (isDeleting.value) { return; } isDeleting.value = true; try { const requestBody: DeleteRequestBody = { calendarId }; const response = await fetch(`/api/calendar/delete`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as DeleteResponseBody; if (!result.success) { throw new Error('Failed to delete calendar!'); } calendars.value = [...result.newCalendars]; } catch (error) { console.error(error); } isDeleting.value = false; } } async function onClickSaveOpenCalendar() { if (isSaving.value) { return; } if (!openCalendar.value?.uid) { alert('A calendar is required to update one!'); return; } if (!openCalendar.value?.displayName) { alert('A name is required to update the calendar!'); return; } if (!openCalendar.value?.calendarColor) { alert('A color is required to update the calendar!'); return; } isSaving.value = true; try { const requestBody: UpdateRequestBody = { id: openCalendar.value.uid!, name: openCalendar.value.displayName!, color: openCalendar.value.calendarColor!, isVisible: openCalendar.value.isVisible!, }; const response = await fetch(`/api/calendar/update`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as UpdateResponseBody; if (!result.success) { throw new Error('Failed to update calendar!'); } calendars.value = [...result.newCalendars]; } catch (error) { console.error(error); } isSaving.value = false; openCalendar.value = null; } return ( <>
View calendar
{calendars.value.map((calendar) => ( ))} {calendars.value.length === 0 ? ( ) : null}
Name Color Visible?
{calendar.displayName} openCalendar.value = { ...calendar }} > {calendar.isVisible ? 'Yes' : 'No'}
No calendars to show
{isDeleting.value ? ( <> Deleting... ) : null} {isSaving.value ? ( <> Saving... ) : null} {!isDeleting.value && !isSaving.value ? <>  : null}

Edit Calendar

openCalendar.value = { ...openCalendar.value!, displayName: event.currentTarget.value }} placeholder='Personal' />
openCalendar.value = { ...openCalendar.value!, isVisible: event.currentTarget.checked }} />
); }