changed names of database columns

This commit is contained in:
z1glr
2025-01-23 10:12:12 +00:00
parent 7265a4e36a
commit c752bc6c14
36 changed files with 604 additions and 605 deletions

View File

@@ -30,10 +30,7 @@ export default function Header({ sites }: { sites: SiteLink[] }) {
useEffect(() => {
(async () => {
const result = await apiCall<{ pendingEvents: number }>(
"GET",
"events/user/pending",
);
const result = await apiCall<number>("GET", "events/user/pending/count");
if (result.ok) {
setPendingEvents(await result.json());

View File

@@ -0,0 +1,29 @@
"use client";
import { apiCall } from "@/lib";
import { EventData } from "@/Zustand";
import { useAsyncList } from "@react-stately/data";
export default function MyEvents() {
const events = useAsyncList({
async load() {
const result = await apiCall<EventData[]>("GET", "events/user/assigned");
if (result.ok) {
return {
items: await result.json(),
};
} else {
return {
items: [],
};
}
},
});
return (
<div>
<h2>{events.items.map((e) => e.date)}</h2>
</div>
);
}

View File

@@ -1,33 +1,17 @@
"use client";
import { Add } from "@carbon/icons-react";
import { useState } from "react";
import AddEvent from "../components/Event/AddEvent";
import { Button } from "@heroui/react";
export default function EventVolunteer() {
const [showAddItemDialogue, setShowAddItemDialogue] = useState(false);
import MyEvents from "./MyEvents";
import PengingEvents from "./PendingEvents";
export default function Overview() {
return (
<div className="relative flex-1">
<h2 className="mb-4 text-center text-4xl">Overview</h2>
<div className="flex flex-wrap justify-center gap-4"></div>
<Button
color="primary"
isIconOnly
radius="full"
className="absolute bottom-0 right-0"
onPress={() => setShowAddItemDialogue(true)}
>
<Add size={32} />
</Button>
<AddEvent
className="border-2 border-accent-3"
isOpen={showAddItemDialogue}
onOpenChange={setShowAddItemDialogue}
/>
<h1 className="mb-4 text-center text-4xl">My Events</h1>
<MyEvents />
<h1 className="mb-4 text-center text-4xl">
events that I don't have entered an availability yet
</h1>
<PengingEvents />
</div>
);
}

View File

@@ -0,0 +1,77 @@
"use client";
import AvailabilityChip from "@/components/AvailabilityChip";
import Event from "@/components/Event/Event";
import { apiCall, getAvailabilities } from "@/lib";
import { BaseEvent } from "@/Zustand";
import { Select, SelectItem } from "@heroui/react";
import { useAsyncList } from "@react-stately/data";
type EventAvailability = BaseEvent & {
availability: number;
};
export default function PengingEvents() {
// get the events the user hasn't yet inserted his availability for
const events = useAsyncList({
async load() {
const result = await apiCall<EventAvailability[]>(
"GET",
"events/user/pending",
);
if (result.ok) {
return {
items: await result.json(),
};
} else {
return {
items: [],
};
}
},
});
// the individual, selectable availabilities
const availabilities = useAsyncList({
async load() {
return {
items: (await getAvailabilities()).filter((a) => a.enabled),
};
},
});
return (
<div className="flex justify-center gap-4">
{events.items.map((e) => (
<Event key={e.eventID} event={e}>
<Select
items={availabilities.items}
label="Availability"
variant="bordered"
className="mt-auto"
isMultiline
renderValue={(availability) => (
<div>
{availability.map((a) =>
!!a.data ? (
<AvailabilityChip key={a.key} availability={a.data} />
) : null,
)}
</div>
)}
>
{(availability) => (
<SelectItem
key={availability.availabilityID}
textValue={availability.availabilityName}
>
<AvailabilityChip availability={availability} />
</SelectItem>
)}
</Select>
</Event>
))}
</div>
);
}

View File

@@ -40,7 +40,7 @@ export default function Availabilities() {
switch (sortDescriptor.column) {
case "text":
cmp = a.name.localeCompare(b.name);
cmp = a.availabilityName.localeCompare(b.availabilityName);
break;
case "enabled":
if (a.enabled && !b.enabled) {
@@ -78,9 +78,11 @@ export default function Availabilities() {
availabilities.reload();
}
async function sendDeleteAvailability(id: number | undefined) {
if (id !== undefined) {
const result = await apiCall("DELETE", "availabilities", { id });
async function sendDeleteAvailability(availabilityID: number | undefined) {
if (availabilityID !== undefined) {
const result = await apiCall("DELETE", "availabilities", {
availabilityID,
});
if (result.ok) {
reload();
@@ -133,7 +135,7 @@ export default function Availabilities() {
</TableHeader>
<TableBody items={availabilities.items}>
{(availability) => (
<TableRow key={availability.name}>
<TableRow key={availability.availabilityName}>
<TableCell>
<AvailabilityChip availability={availability} />
</TableCell>
@@ -190,7 +192,9 @@ export default function Availabilities() {
!isOpen ? setDeleteAvailability(undefined) : null
}
itemName="Availability"
onDelete={() => sendDeleteAvailability(deleteAvailability?.id)}
onDelete={() =>
sendDeleteAvailability(deleteAvailability?.availabilityID)
}
>
{!!deleteAvailability ? (
<>

View File

@@ -1,4 +1,5 @@
import ColorSelector from "@/components/Colorselector";
import { AllString } from "@/lib";
import {
Checkbox,
Form,
@@ -12,9 +13,9 @@ import {
import React, { FormEvent, useEffect, useState } from "react";
export interface Availability {
name: string;
availabilityName: string;
color: string;
id: number | undefined;
availabilityID: number | undefined;
enabled: boolean;
}
@@ -26,7 +27,7 @@ export default function AvailabilityEditor(props: {
onOpenChange?: (isOpen: boolean) => void;
onSubmit?: (e: Availability) => void;
}) {
const [name, setName] = useState(props.value?.name ?? "");
const [name, setName] = useState(props.value?.availabilityName ?? "");
const [color, setColor] = useState(props.value?.color ?? "Red");
const [enabled, setEnabled] = useState(props.value?.enabled ?? true);
@@ -40,15 +41,13 @@ export default function AvailabilityEditor(props: {
}, [props.isOpen]);
function submit(e: FormEvent<HTMLFormElement>) {
const formData = Object.fromEntries(new FormData(e.currentTarget)) as {
name: string;
color: string;
enabled: string;
};
const formData = Object.fromEntries(
new FormData(e.currentTarget),
) as AllString<Exclude<Availability, "availabilityID">>;
props.onSubmit?.({
...formData,
id: props.value?.id,
availabilityID: props.value?.availabilityID,
enabled: formData.enabled == "true",
});
}
@@ -77,7 +76,7 @@ export default function AvailabilityEditor(props: {
<Input
value={name}
onValueChange={setName}
name="name"
name="availabilityName"
label="Name"
isRequired
variant="bordered"

View File

@@ -21,7 +21,7 @@ export default function EditAvailability(props: {
return (
<AvailabilityEditor
key={props.value?.id}
key={props.value?.availabilityID}
header={
<>
Edit Availability{" "}

View File

@@ -20,12 +20,12 @@ export default function EditTask(props: {
return (
<TaskEditor
key={props.value?.name}
key={props.value?.taskName}
header={
<>
Edit Task{" "}
<span className="font-numbers font-normal italic">
&quot;{props.value?.name}&quot;
&quot;{props.value?.taskName}&quot;
</span>
</>
}

View File

@@ -1,4 +1,4 @@
import { Task } from "@/lib";
import { AllString, Task } from "@/lib";
import {
Checkbox,
Form,
@@ -19,7 +19,7 @@ export default function TaskEditor(props: {
onOpenChange?: (isOpen: boolean) => void;
onSubmit?: (e: Task) => void;
}) {
const [name, setName] = useState(props.value?.name ?? "");
const [name, setName] = useState(props.value?.taskName ?? "");
const [enabled, setEnabled] = useState(props.value?.enabled ?? true);
// clear the inputs on closing
@@ -31,14 +31,13 @@ export default function TaskEditor(props: {
}, [props.isOpen]);
function submit(e: FormEvent<HTMLFormElement>) {
const formData = Object.fromEntries(new FormData(e.currentTarget)) as {
name: string;
enabled: string;
};
const formData = Object.fromEntries(
new FormData(e.currentTarget),
) as AllString<Exclude<Task, "taskID">>;
props.onSubmit?.({
...formData,
id: props.value?.id,
taskID: props.value?.taskID,
enabled: formData.enabled == "true",
});
}
@@ -68,7 +67,7 @@ export default function TaskEditor(props: {
<Input
value={name}
onValueChange={setName}
name="name"
name="taskName"
label="Name"
isRequired
variant="bordered"

View File

@@ -47,7 +47,7 @@ export default function Tasks() {
switch (sortDescriptor.column) {
case "text":
cmp = a.name.localeCompare(b.name);
cmp = a.taskName.localeCompare(b.taskName);
break;
case "enabled":
if (a.enabled && !b.enabled) {
@@ -76,9 +76,9 @@ export default function Tasks() {
tasks.reload();
}
async function sendDeleteTask(id: number | undefined) {
if (id !== undefined) {
const result = await apiCall("DELETE", "tasks", { id });
async function sendDeleteTask(taskID: number | undefined) {
if (taskID !== undefined) {
const result = await apiCall("DELETE", "tasks", { taskID });
if (result.ok) {
tasks.reload();
@@ -130,8 +130,8 @@ export default function Tasks() {
</TableHeader>
<TableBody items={tasks.items}>
{(task) => (
<TableRow key={task.id}>
<TableCell>{task.name}</TableCell>
<TableRow key={task.taskID}>
<TableCell>{task.taskName}</TableCell>
<TableCell>
<Checkbox isSelected={task.enabled} />
</TableCell>
@@ -181,13 +181,13 @@ export default function Tasks() {
isOpen={!!deleteTask}
onOpenChange={(isOpen) => (!isOpen ? setDeleteTask(undefined) : null)}
itemName="Task"
onDelete={() => sendDeleteTask(deleteTask?.id)}
onDelete={() => sendDeleteTask(deleteTask?.taskID)}
>
{!!deleteTask ? (
<>
The task{" "}
<span className="font-numbers text-accent-1">
{deleteTask.name}
{deleteTask.taskName}
</span>{" "}
will be deleted.
</>

View File

@@ -1,4 +1,8 @@
import { classNames, validatePassword as validatePassword } from "@/lib";
import {
AllString,
classNames,
validatePassword as validatePassword,
} from "@/lib";
import zustand, { User, UserAddModify } from "@/Zustand";
import {
Checkbox,
@@ -29,11 +33,9 @@ export default function UserEditor(props: {
// update the user in the backend
async function submit(e: FormEvent<HTMLFormElement>) {
const formData = Object.fromEntries(new FormData(e.currentTarget)) as {
userName: string;
password: string;
admin: string;
};
const formData = Object.fromEntries(
new FormData(e.currentTarget),
) as AllString<UserAddModify>;
const data = {
...formData,

View File

@@ -62,8 +62,8 @@ export default function AdminPanel() {
...tasks
.filter((task) => task.enabled)
.map((task) => ({
label: task.name,
key: task.id ?? -1,
label: task.taskName,
key: task.taskID ?? -1,
align: "center",
})),
{ key: "actions", label: "Action", align: "center" },
@@ -116,7 +116,9 @@ export default function AdminPanel() {
// 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 });
const result = await apiCall("DELETE", "event", {
eventID: deleteEvent.eventID,
});
if (result.ok) {
// store the received events
@@ -262,7 +264,7 @@ export default function AdminPanel() {
</TableHeader>
<TableBody items={events.items} emptyContent={"No events scheduled"}>
{(event) => (
<TableRow key={event.id}>
<TableRow key={event.eventID}>
{(columnKey) => (
<TableCell>{getKeyValue(event, columnKey)}</TableCell>
)}

View File

@@ -15,13 +15,11 @@ export default function Events() {
const events = useAsyncList<EventData>({
async load() {
const result = await apiCall("GET", "events/assignments");
const result = await apiCall<EventData[]>("GET", "events/assignments");
if (result.ok) {
const data = await result.json();
console.debug(data);
return {
items: data,
};
@@ -62,6 +60,7 @@ export default function Events() {
className="border-2 border-accent-3"
isOpen={showAddItemDialogue}
onOpenChange={setShowAddItemDialogue}
onSuccess={events.reload}
/>
</>
) : null}

View File

@@ -1,5 +1,5 @@
import EventVolunteer from "./Overview";
import Overview from "./Overview";
export default function Home() {
return <EventVolunteer />;
return <Overview />;
}