added participant overview, (admin), Date input

This commit is contained in:
PxlLoewe
2025-03-01 17:09:09 +01:00
parent 4824ade795
commit e964c7d175
10 changed files with 385 additions and 161 deletions

View File

@@ -7,15 +7,30 @@ import {
EventOptionalDefaultsSchema,
ParticipantOptionalDefaultsSchema,
} from "@repo/db/zod";
import { set, useForm } from "react-hook-form";
import { BADGES, Event, EVENT_TYPE, PERMISSION } from "@repo/db";
import { Controller, set, useForm } from "react-hook-form";
import {
BADGES,
Event,
EVENT_TYPE,
Participant,
PERMISSION,
prisma,
Prisma,
} from "@repo/db";
import { Bot, Calendar, FileText, UserIcon } from "lucide-react";
import { Input } from "../../../../_components/ui/Input";
import { useRef, useState } from "react";
import { deleteEvent, upsertAppointment, upsertEvent } from "../action";
import {
deleteAppoinement,
deleteEvent,
upsertAppointment,
upsertEvent,
} from "../action";
import { Button } from "../../../../_components/ui/Button";
import { redirect, useRouter } from "next/navigation";
import { Switch } from "../../../../_components/ui/Switch";
import DatePicker, { registerLocale } from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import {
PaginatedTable,
PaginatedTableRef,
@@ -23,6 +38,10 @@ import {
import { Select } from "../../../../_components/ui/Select";
import { useSession } from "next-auth/react";
import { MarkdownEditor } from "../../../../_components/ui/MDEditor";
import { CellContext } from "@tanstack/react-table";
import { upsertParticipant } from "../../../events/actions";
import { de } from "date-fns/locale";
registerLocale("de", de);
export const Form = ({ event }: { event?: Event }) => {
const { data: session } = useSession();
@@ -38,12 +57,16 @@ export const Form = ({ event }: { event?: Event }) => {
},
});
const appointmentsTableRef = useRef<PaginatedTableRef>(null);
const participantTableRef = useRef<PaginatedTableRef>(null);
const [loading, setLoading] = useState(false);
const [deleteLoading, setDeleteLoading] = useState(false);
const addParticipantModal = useRef<HTMLDialogElement>(null);
const appointmentModal = useRef<HTMLDialogElement>(null);
const participantForm = useForm<Participant>({
resolver: zodResolver(ParticipantOptionalDefaultsSchema),
});
return (
<>
<dialog ref={addParticipantModal} className="modal">
<dialog ref={appointmentModal} className="modal">
<div className="modal-box">
<form method="dialog">
{/* if there is a button in form, it will close the modal */}
@@ -51,32 +74,167 @@ export const Form = ({ event }: { event?: Event }) => {
</button>
</form>
<h3 className="font-bold text-lg">Termin hinzufügen</h3>
<h3 className="font-bold text-lg">
Termin {appointmentForm.watch("id")}
</h3>
<form
onSubmit={appointmentForm.handleSubmit(async (values) => {
if (!event) return;
const createdAppointment = await upsertAppointment({
appointmentDate: values.appointmentDate,
eventId: event?.id,
presenterId: values.presenterId,
});
addParticipantModal.current?.close();
const createdAppointment = await upsertAppointment(values);
appointmentModal.current?.close();
appointmentsTableRef.current?.refresh();
})}
className="flex flex-col"
>
<Input
<Controller
control={appointmentForm.control}
name="appointmentDate"
render={({ field }) => (
<DatePicker
locale={"de"}
showTimeCaption
showTimeInput
showTimeSelect
placeholderText="Select date"
onChange={(date) => field.onChange(date)}
selected={field.value}
/>
)}
/>
{/* <Input
form={appointmentForm}
type="datetime-local"
label="Datum"
name="appointmentDate"
type="date"
/>
<div className="modal-action">
<Button type="submit" className="btn btn-primary">
Hinzufügen
</Button>
formOptions={{
valueAsDate: true,
}}
/> */}
<div>
{appointmentForm.watch("id") && (
<PaginatedTable
ref={participantTableRef}
columns={[
{
accessorKey: "User.firstname",
header: "Vorname",
},
{
accessorKey: "User.lastname",
header: "Nachname",
},
{
header: "Aktion",
cell: ({ row }: CellContext<Participant, any>) => {
return (
<>
<button
onClick={() => {
participantForm.reset(row.original);
}}
className="btn btn-outline btn-sm"
>
anzeigen
</button>
{!row.original.attended &&
event?.hasPresenceEvents && (
<button
type="button"
onSubmit={() => {}}
onClick={async () => {
await upsertParticipant({
eventId: event!.id,
userId: participantForm.watch("userId"),
attended: true,
});
participantTableRef.current?.refresh();
}}
className="btn btn-outline btn-info btn-sm"
>
Anwesend
</button>
)}
</>
);
},
},
]}
prismaModel={"participant"}
filter={{
eventAppointmentId: appointmentForm.watch("id"),
}}
include={{ User: true }}
leftOfPagination={
<div className="space-x-1">
<Button type="submit" className="btn btn-primary">
Speichern
</Button>
{appointmentForm.watch("id") && (
<Button
type="button"
onSubmit={() => {}}
onClick={async () => {
await deleteAppoinement(
appointmentForm.watch("id")!,
);
appointmentModal.current?.close();
appointmentsTableRef.current?.refresh();
}}
className="btn btn-error btn-outline"
>
Löschen
</Button>
)}
</div>
}
/>
)}
</div>
<div className="modal-action"></div>
</form>
{participantForm.watch("id") && (
<form
onSubmit={participantForm.handleSubmit(async (data) => {
await upsertParticipant({
...data,
statusLog: data.statusLog as Prisma.InputJsonValue[],
});
participantTableRef.current?.refresh();
})}
className="space-y-1"
>
<h1 className="text-2xl">Teilnehmer bearbeiten</h1>
<Switch
form={participantForm}
name="appointmentCancelled"
label="Termin abgesagt"
/>
<Switch
form={participantForm}
name="finisherMoodleCurseCompleted"
label="Abschluss-Moodle kurs abgeschlossen"
/>
{event?.hasPresenceEvents && (
<Switch
form={participantForm}
name="attended"
label="An Presenstermin teilgenommen"
/>
)}
<div className="flex flex-col">
<h3 className="text-xl">Verlauf</h3>
{participantForm.watch("statusLog").map((s) => {
return (
<div className="flex justify-between">
<p>{(s as any).event}</p>
<p>{new Date((s as any).timestamp).toLocaleString()}</p>
</div>
);
})}
</div>
<Button>Speichern</Button>
</form>
)}
</div>
</dialog>
<form
@@ -173,7 +331,12 @@ export const Form = ({ event }: { event?: Event }) => {
{event && (
<button
className="btn btn-primary btn-outline"
onClick={() => addParticipantModal.current?.showModal()}
onClick={() => {
appointmentModal.current?.showModal();
appointmentForm.reset({
id: undefined,
});
}}
>
Hinzufügen
</button>
@@ -230,8 +393,8 @@ export const Form = ({ event }: { event?: Event }) => {
onSubmit={() => false}
type="button"
onClick={() => {
console.log(row.original);
// TODO: open modal to edit appointment
appointmentForm.reset(row.original);
appointmentModal.current?.showModal();
}}
className="btn btn-sm btn-outline"
>