implemented assigning users to events
This commit is contained in:
@@ -10,8 +10,12 @@ export default function MyEvents() {
|
||||
const result = await apiCall<EventData[]>("GET", "events/user/assigned");
|
||||
|
||||
if (result.ok) {
|
||||
const data = await result.json();
|
||||
|
||||
console.debug(data);
|
||||
|
||||
return {
|
||||
items: await result.json(),
|
||||
items: data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import AddEvent from "@/components/Event/AddEvent";
|
||||
import EditEvent from "@/components/Event/EditEvent";
|
||||
import LocalDate from "@/components/LocalDate";
|
||||
import { apiCall, getTasks } from "@/lib";
|
||||
import { apiCall, getAvailabilities, getTasks } from "@/lib";
|
||||
import { EventData } from "@/Zustand";
|
||||
import {
|
||||
Add,
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
DropdownMenu,
|
||||
DropdownSection,
|
||||
DropdownTrigger,
|
||||
Modal,
|
||||
ModalBody,
|
||||
@@ -37,14 +38,21 @@ import {
|
||||
Tooltip,
|
||||
} from "@heroui/react";
|
||||
import { useAsyncList } from "@react-stately/data";
|
||||
import React, { Key, useState } from "react";
|
||||
import React, { Key, ReactElement, useEffect, useState } from "react";
|
||||
import { Availability } from "../admin/(availabilities)/AvailabilityEditor";
|
||||
import AvailabilityChip from "@/components/AvailabilityChip";
|
||||
|
||||
type EventWithAvailabilities = EventData & { availabilities: string[] };
|
||||
type EventWithAvailabilities = EventData & {
|
||||
availabilities: Record<string, string[]>;
|
||||
};
|
||||
|
||||
export default function AdminPanel() {
|
||||
const [showAddEvent, setShowAddEvent] = useState(false);
|
||||
const [editEvent, setEditEvent] = useState<EventData | undefined>();
|
||||
const [deleteEvent, setDeleteEvent] = useState<EventData | undefined>();
|
||||
const [availabilityMap, setAvailabilityMap] = useState<
|
||||
Record<number, Availability>
|
||||
>({});
|
||||
|
||||
// get the available tasks and craft them into the headers
|
||||
const headers = useAsyncList<{
|
||||
@@ -113,6 +121,51 @@ export default function AdminPanel() {
|
||||
},
|
||||
});
|
||||
|
||||
// retrieve the availabilites and store them in a map
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setAvailabilityMap(
|
||||
Object.fromEntries(
|
||||
(await getAvailabilities()).map((a) => [a.availabilityID, a]),
|
||||
),
|
||||
);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
function getAvailabilityById(availabilityID: number): Availability {
|
||||
return availabilityMap[availabilityID];
|
||||
}
|
||||
|
||||
// send a command to the backend to assign a volunteer to a task
|
||||
async function sendVolunteerAssignment(
|
||||
eventID: number,
|
||||
taskID: number,
|
||||
userName: string,
|
||||
) {
|
||||
const result = await apiCall(
|
||||
"PUT",
|
||||
"events/assignments",
|
||||
{ eventID, taskID },
|
||||
userName,
|
||||
);
|
||||
|
||||
if (result.ok) {
|
||||
events.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// sends a command to the backend to remove an volunteer-assignment
|
||||
async function removeVolunteerAssignment(eventID: number, taskID: number) {
|
||||
const result = await apiCall("DELETE", "events/assignments", {
|
||||
eventID,
|
||||
taskID,
|
||||
});
|
||||
|
||||
if (result.ok) {
|
||||
events.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// send a delete request to the backend and close the popup on success
|
||||
async function sendDeleteEvent() {
|
||||
if (deleteEvent !== undefined) {
|
||||
@@ -123,6 +176,9 @@ export default function AdminPanel() {
|
||||
if (result.ok) {
|
||||
// store the received events
|
||||
events.reload();
|
||||
|
||||
// close the delete-confirmaton
|
||||
setDeleteEvent(undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,9 +240,13 @@ export default function AdminPanel() {
|
||||
return (
|
||||
<Dropdown>
|
||||
<DropdownTrigger>
|
||||
{!!event.tasks.find((t) => t.taskID === key)?.userName ? (
|
||||
<Chip onClose={() => alert("implement")}>
|
||||
{event.tasks.find((t) => t.taskID === key)?.taskName}
|
||||
{!!event.tasks.find((t) => t.taskID == key)?.userName ? (
|
||||
<Chip
|
||||
onClose={() =>
|
||||
removeVolunteerAssignment(event.eventID, key as number)
|
||||
}
|
||||
>
|
||||
{event.tasks.find((t) => t.taskID == key)?.userName}
|
||||
</Chip>
|
||||
) : (
|
||||
<Button isIconOnly size="sm" radius="md" variant="flat">
|
||||
@@ -194,19 +254,50 @@ export default function AdminPanel() {
|
||||
</Button>
|
||||
)}
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu>
|
||||
<DropdownMenu
|
||||
onAction={(a) =>
|
||||
sendVolunteerAssignment(
|
||||
event.eventID,
|
||||
key as number,
|
||||
a as string,
|
||||
)
|
||||
}
|
||||
>
|
||||
{Object.entries(event.availabilities).map(
|
||||
([volunteer, availability]) => (
|
||||
<DropdownItem
|
||||
key={volunteer}
|
||||
// color={availability2Color(availability)}
|
||||
className={[
|
||||
// "text-" + availability2Color(availability),
|
||||
// availability2Tailwind(availability),
|
||||
].join(" ")}
|
||||
(
|
||||
[availabilityId, volunteers],
|
||||
iAvailability,
|
||||
aAvailabilities,
|
||||
) => (
|
||||
<DropdownSection
|
||||
key={availabilityId}
|
||||
showDivider={iAvailability < aAvailabilities.length - 1}
|
||||
classNames={{
|
||||
base: "flex flex-col justify-start",
|
||||
heading: "mx-auto",
|
||||
}}
|
||||
className="justi"
|
||||
title={
|
||||
(
|
||||
<AvailabilityChip
|
||||
availability={getAvailabilityById(
|
||||
parseInt(availabilityId),
|
||||
)}
|
||||
/>
|
||||
) as ReactElement & string
|
||||
}
|
||||
>
|
||||
{volunteer} ({availability})
|
||||
</DropdownItem>
|
||||
{volunteers.map((v) => (
|
||||
<DropdownItem
|
||||
key={v}
|
||||
classNames={{
|
||||
base: "", // this empty class is needed, else some styles are applied
|
||||
}}
|
||||
>
|
||||
{v}
|
||||
</DropdownItem>
|
||||
))}
|
||||
</DropdownSection>
|
||||
),
|
||||
)}
|
||||
</DropdownMenu>
|
||||
|
||||
@@ -6,11 +6,11 @@ export default function AvailabilityChip({
|
||||
availability,
|
||||
className,
|
||||
}: {
|
||||
availability: Availability;
|
||||
availability?: Availability;
|
||||
className?: string;
|
||||
classNames?: ChipProps["classNames"];
|
||||
}) {
|
||||
return (
|
||||
return !!availability ? (
|
||||
<Chip
|
||||
classNames={{
|
||||
base: `bg-${color2Tailwind(availability.color)}`,
|
||||
@@ -19,5 +19,5 @@ export default function AvailabilityChip({
|
||||
>
|
||||
{availability.availabilityName}
|
||||
</Chip>
|
||||
);
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ export async function apiCall<K>(
|
||||
},
|
||||
credentials: "include",
|
||||
method,
|
||||
body: body !== undefined ? JSON.stringify(body) : undefined,
|
||||
body: prepareBody(body),
|
||||
});
|
||||
|
||||
return response;
|
||||
@@ -79,6 +79,19 @@ function getContentType(type: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
function prepareBody(
|
||||
body: object | number | string | boolean | undefined,
|
||||
): BodyInit | undefined {
|
||||
switch (typeof body) {
|
||||
case "object":
|
||||
return JSON.stringify(body);
|
||||
case "undefined":
|
||||
return undefined;
|
||||
default:
|
||||
return body.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export function classNames(classNames: Record<string, boolean>): string {
|
||||
return Object.entries(classNames)
|
||||
.map(([classString, value]) => {
|
||||
@@ -157,11 +170,11 @@ export async function getAvailabilities(): Promise<Availability[]> {
|
||||
const result = await apiCall<Availability[]>("GET", "availabilities");
|
||||
|
||||
if (result.ok) {
|
||||
const tasks = await result.json();
|
||||
const availabilities = await result.json();
|
||||
|
||||
state.patch({ availabilities: tasks });
|
||||
state.patch({ availabilities: availabilities });
|
||||
|
||||
return tasks;
|
||||
return availabilities;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user