CHanged Event admin layout
This commit is contained in:
@@ -22,33 +22,37 @@ import { Switch } from "../../../../_components/ui/Switch";
|
||||
interface AppointmentModalProps {
|
||||
event?: Event;
|
||||
ref: RefObject<HTMLDialogElement | null>;
|
||||
participantModal: RefObject<HTMLDialogElement | null>;
|
||||
appointmentsTableRef: React.RefObject<PaginatedTableRef>;
|
||||
appointmentForm: UseFormReturn<
|
||||
EventAppointmentOptionalDefaults,
|
||||
any,
|
||||
undefined
|
||||
>;
|
||||
participantForm: UseFormReturn<Participant, any, undefined>;
|
||||
}
|
||||
|
||||
export const AppointmentModal = ({
|
||||
event,
|
||||
ref,
|
||||
participantModal,
|
||||
appointmentsTableRef,
|
||||
appointmentForm,
|
||||
participantForm,
|
||||
}: AppointmentModalProps) => {
|
||||
const { data: session } = useSession();
|
||||
|
||||
const participantTableRef = useRef<PaginatedTableRef>(null);
|
||||
const participantForm = useForm<Participant>({
|
||||
resolver: zodResolver(ParticipantOptionalDefaultsSchema),
|
||||
});
|
||||
|
||||
return (
|
||||
<dialog ref={ref} className="modal">
|
||||
<div className="modal-box">
|
||||
<form method="dialog">
|
||||
{/* if there is a button in form, it will close the modal */}
|
||||
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">
|
||||
<button
|
||||
className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
onClick={() => ref.current?.close()}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
@@ -57,6 +61,7 @@ export const AppointmentModal = ({
|
||||
</h3>
|
||||
<form
|
||||
onSubmit={appointmentForm.handleSubmit(async (values) => {
|
||||
console.log(values);
|
||||
if (!event) return;
|
||||
const createdAppointment = await upsertAppointment(values);
|
||||
ref.current?.close();
|
||||
@@ -75,131 +80,83 @@ export const AppointmentModal = ({
|
||||
}}
|
||||
/> */}
|
||||
<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 (
|
||||
<>
|
||||
<PaginatedTable
|
||||
hide={appointmentForm.watch("id") === undefined}
|
||||
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);
|
||||
participantModal.current?.showModal();
|
||||
}}
|
||||
className="btn btn-outline btn-sm"
|
||||
>
|
||||
anzeigen
|
||||
</button>
|
||||
{!row.original.attended && event?.hasPresenceEvents && (
|
||||
<button
|
||||
onClick={() => {
|
||||
participantForm.reset(row.original);
|
||||
type="button"
|
||||
onSubmit={() => {}}
|
||||
onClick={async () => {
|
||||
await upsertParticipant({
|
||||
eventId: event!.id,
|
||||
userId: participantForm.watch("userId"),
|
||||
attended: true,
|
||||
});
|
||||
participantTableRef.current?.refresh();
|
||||
}}
|
||||
className="btn btn-outline btn-sm"
|
||||
className="btn btn-outline btn-info btn-sm"
|
||||
>
|
||||
anzeigen
|
||||
Anwesend
|
||||
</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="flex gap-2">
|
||||
<Button type="submit" className="btn btn-primary">
|
||||
Speichern
|
||||
},
|
||||
]}
|
||||
prismaModel={"participant"}
|
||||
filter={{
|
||||
eventAppointmentId: appointmentForm.watch("id"),
|
||||
}}
|
||||
include={{ User: true }}
|
||||
leftOfPagination={
|
||||
<div className="flex gap-2">
|
||||
<Button type="submit" className="btn btn-primary">
|
||||
Speichern
|
||||
</Button>
|
||||
{appointmentForm.watch("id") && (
|
||||
<Button
|
||||
type="button"
|
||||
onSubmit={() => {}}
|
||||
onClick={async () => {
|
||||
await deleteAppoinement(appointmentForm.watch("id")!);
|
||||
ref.current?.close();
|
||||
appointmentsTableRef.current?.refresh();
|
||||
}}
|
||||
className="btn btn-error btn-outline"
|
||||
>
|
||||
Löschen
|
||||
</Button>
|
||||
{appointmentForm.watch("id") && (
|
||||
<Button
|
||||
type="button"
|
||||
onSubmit={() => {}}
|
||||
onClick={async () => {
|
||||
await deleteAppoinement(appointmentForm.watch("id")!);
|
||||
ref.current?.close();
|
||||
appointmentsTableRef.current?.refresh();
|
||||
}}
|
||||
className="btn btn-error btn-outline"
|
||||
>
|
||||
Löschen
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
)}
|
||||
</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"
|
||||
key={(s as any).timestamp}
|
||||
>
|
||||
<p>{(s as any).event}</p>
|
||||
<p>{new Date((s as any).timestamp).toLocaleString()}</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Button>Speichern</Button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</dialog>
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
prisma,
|
||||
Prisma,
|
||||
} from "@repo/db";
|
||||
import { Bot, Calendar, FileText, UserIcon } from "lucide-react";
|
||||
import { Bot, Calendar, FileText, User, UserIcon } from "lucide-react";
|
||||
import { Input } from "../../../../_components/ui/Input";
|
||||
import { useRef, useState } from "react";
|
||||
import {
|
||||
@@ -39,6 +39,7 @@ import { Select } from "../../../../_components/ui/Select";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { MarkdownEditor } from "../../../../_components/ui/MDEditor";
|
||||
import { AppointmentModal } from "./AppointmentModal";
|
||||
import { ParticipantModal } from "./ParticipantModal";
|
||||
|
||||
export const Form = ({ event }: { event?: Event }) => {
|
||||
const { data: session } = useSession();
|
||||
@@ -53,17 +54,28 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
presenterId: session?.user?.id,
|
||||
},
|
||||
});
|
||||
const participantForm = useForm<Participant>({
|
||||
resolver: zodResolver(ParticipantOptionalDefaultsSchema),
|
||||
});
|
||||
const appointmentsTableRef = useRef<PaginatedTableRef>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [deleteLoading, setDeleteLoading] = useState(false);
|
||||
const appointmentModal = useRef<HTMLDialogElement>(null);
|
||||
const participantModal = useRef<HTMLDialogElement>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppointmentModal
|
||||
participantModal={participantModal}
|
||||
participantForm={participantForm}
|
||||
appointmentForm={appointmentForm}
|
||||
ref={appointmentModal}
|
||||
appointmentsTableRef={appointmentsTableRef}
|
||||
event={event}
|
||||
/>
|
||||
<ParticipantModal
|
||||
participantForm={participantForm}
|
||||
ref={participantModal}
|
||||
/>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(async (values) => {
|
||||
@@ -164,6 +176,8 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
appointmentModal.current?.showModal();
|
||||
appointmentForm.reset({
|
||||
id: undefined,
|
||||
eventId: event.id,
|
||||
presenterId: session?.user?.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -238,6 +252,62 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{!form.watch("hasPresenceEvents") ? (
|
||||
<div className="card bg-base-200 shadow-xl col-span-6">
|
||||
<div className="card-body">
|
||||
<PaginatedTable
|
||||
leftOfSearch={
|
||||
<h2 className="card-title">
|
||||
<Calendar className="w-5 h-5" /> Teilnehmer
|
||||
</h2>
|
||||
}
|
||||
searchFields={["User.firstname", "User.lastname"]}
|
||||
ref={appointmentsTableRef}
|
||||
prismaModel={"participant"}
|
||||
filter={{
|
||||
eventId: event?.id,
|
||||
}}
|
||||
include={{
|
||||
User: true,
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
header: "Vorname",
|
||||
accessorKey: "User.firstname",
|
||||
},
|
||||
{
|
||||
header: "Nachname",
|
||||
accessorKey: "User.lastname",
|
||||
},
|
||||
{
|
||||
header: "Moodle Kurs abgeschlossen",
|
||||
accessorKey: "finisherMoodleCurseCompleted",
|
||||
},
|
||||
{
|
||||
header: "Aktionen",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onSubmit={() => false}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
participantForm.reset(row.original);
|
||||
participantModal.current?.showModal();
|
||||
}}
|
||||
className="btn btn-sm btn-outline"
|
||||
>
|
||||
Bearbeiten
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="card bg-base-200 shadow-xl col-span-6">
|
||||
<div className="card-body ">
|
||||
<div className="flex w-full gap-4">
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Switch } from "../../../../_components/ui/Switch";
|
||||
import { Button } from "../../../../_components/ui/Button";
|
||||
import { Participant, Prisma } from "@repo/db";
|
||||
import { UseFormReturn } from "react-hook-form";
|
||||
import { upsertParticipant } from "../../../events/actions";
|
||||
import { RefObject } from "react";
|
||||
|
||||
interface ParticipantModalProps {
|
||||
participantForm: UseFormReturn<Participant>;
|
||||
ref: RefObject<HTMLDialogElement | null>;
|
||||
}
|
||||
|
||||
export const ParticipantModal = ({
|
||||
participantForm,
|
||||
ref,
|
||||
}: ParticipantModalProps) => {
|
||||
return (
|
||||
<dialog className="modal" ref={ref}>
|
||||
<div className="modal-box">
|
||||
<form method="dialog">
|
||||
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
<h1 className="text-2xl">Teilnehmer bearbeiten</h1>
|
||||
<form
|
||||
onSubmit={participantForm.handleSubmit(async (data) => {
|
||||
await upsertParticipant({
|
||||
...data,
|
||||
statusLog: data.statusLog as Prisma.InputJsonValue[],
|
||||
});
|
||||
participantForm.reset();
|
||||
ref.current?.close();
|
||||
})}
|
||||
className="space-y-1"
|
||||
>
|
||||
<Switch
|
||||
form={participantForm}
|
||||
name="appointmentCancelled"
|
||||
label="Termin abgesagt"
|
||||
/>
|
||||
<Switch
|
||||
form={participantForm}
|
||||
name="finisherMoodleCurseCompleted"
|
||||
label="Abschluss-Moodle-Kurs abgeschlossen"
|
||||
/>
|
||||
<Switch
|
||||
form={participantForm}
|
||||
name="completetionWorkflowFinished"
|
||||
label="Abgeschlossen (E-Mail-Benachrichtigung senden)"
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<h3 className="text-xl">Verlauf</h3>
|
||||
{participantForm.watch("statusLog")?.map((s) => (
|
||||
<div className="flex justify-between" key={(s as any).timestamp}>
|
||||
<p>{(s as any).event}</p>
|
||||
<p>{new Date((s as any).timestamp).toLocaleString()}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button type="submit">Speichern</Button>
|
||||
</form>
|
||||
</div>
|
||||
</dialog>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user