"use client"; import AddEvent from "@/components/Event/AddEvent"; import EditEvent, { EventSubmitData } from "@/components/Event/EditEvent"; import LocalDate from "@/components/LocalDate"; import { apiCall, getTasks } from "@/lib"; import { EventData } from "@/Zustand"; import { Add, AddLarge, Copy, Edit, NotAvailable, Renew, TrashCan, } from "@carbon/icons-react"; import { Button, ButtonGroup, Chip, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow, Tooltip, } from "@heroui/react"; import { useAsyncList } from "@react-stately/data"; import React, { Key, useState } from "react"; type EventWithAvailabilities = EventData & { availabilities: string[] }; function availability2Tailwind(availability?: Availability) { switch (availability) { case "yes": return ""; default: return "italic"; } } function availability2Color(availability?: Availability) { switch (availability) { case "yes": return "default"; case "maybe": return "warning"; default: return "danger"; } } export default function AdminPanel() { const [showAddEvent, setShowAddEvent] = useState(false); const [editEvent, setEditEvent] = useState(); const [deleteEvent, setDeleteEvent] = useState(); // get the available tasks and craft them into the headers const headers = useAsyncList({ async load() { const tasks = await getTasks(); return { items: [ { key: "date", label: "Date" }, { key: "description", label: "Description" }, ...Object.values(tasks) .filter((task) => !task.disabled) .map((task) => ({ label: task.text, key: task.text })), { key: "actions", label: "Action" }, ], }; }, }); // get the individual events const events = useAsyncList({ async load() { const result = await apiCall( "GET", "events/availabilities", ); if (result.ok) { return { items: await result.json() }; } else { return { items: [] }; } }, async sort({ items, sortDescriptor }) { return { items: items.sort((a, b) => { let cmp = 0; // if it is the date-column, convert to a date if (sortDescriptor.column === "date") { const first = a[sortDescriptor.column]; const second = b[sortDescriptor.column]; cmp = first < second ? -1 : 1; } if (sortDescriptor.direction === "descending") { cmp *= -1; } return cmp; }), }; }, }); // send a delete request to the backend and close the popup on success async function sendDeleteEvent() { if (deleteEvent !== undefined) { const result = await apiCall("DELETE", "event", { id: deleteEvent.id }); if (result.ok) { // store the received events events.reload(); } } } function getKeyValue( event: EventWithAvailabilities, key: Key, ): React.ReactNode { switch (key) { case "date": return ( {event[key]} ); case "description": return (
{event[key]}
); case "actions": return (
); default: // only show the selector, if the task is needed for the event if (Object.keys(event.tasks).includes(key as string)) { return ( {!!event.tasks[key as string] ? ( alert("implement")}> {event.tasks[key as string]} ) : ( )} {Object.entries(event.availabilities).map( ([volunteer, availability]) => ( {volunteer} ({availability}) ), )} ); } else { return ; } } } async function updateEvent(data: EventSubmitData) { const result = await apiCall("PATCH", "events", undefined, data); if (result.ok) { // clear the selected-event to hide the modal setEditEvent(undefined); events.reload(); } } const topContent = (
); return (

Event Managment

tr]:first:!shadow-border", }} className="w-fit max-w-full" > {(task) => ( {task.label} )} {(event) => ( {(columnKey) => ( {getKeyValue(event, columnKey)} )} )}
events.reload()} /> (!isOpen ? setEditEvent(undefined) : null)} onSubmit={updateEvent} initialState={editEvent} footer={ } > Edit Event (!isOpen ? setDeleteEvent(undefined) : null)} shadow={"none" as "sm"} backdrop="blur" className="bg-accent-5" >

Confirm event deletion

The event{" "} {deleteEvent?.date} {" "} will be deleted.
); }