completed Implementation of User Event page

This commit is contained in:
PxlLoewe
2025-03-01 00:31:03 +01:00
parent 488c50e2e0
commit daf3238bee
6 changed files with 146 additions and 113 deletions

View File

@@ -7,9 +7,21 @@ import {
} from "@radix-ui/react-icons";
import { Event, EventAppointment, Participant, User } from "@repo/db";
import { cn } from "../../../../helper/cn";
import { addParticipant, inscribeToMoodleCourse } from "../actions";
import { inscribeToMoodleCourse, upsertParticipant } from "../actions";
import { useSession } from "next-auth/react";
import { Cross } from "lucide-react";
import { Clock10Icon, Cross } from "lucide-react";
import { useForm } from "react-hook-form";
import {
EventAppointmentOptionalDefaults,
EventAppointmentSchema,
ParticipantOptionalDefaults,
ParticipantOptionalDefaultsSchema,
ParticipantSchema,
} from "@repo/db/zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Select } from "../../../_components/ui/Select";
import toast from "react-hot-toast";
import { useRouter } from "next/navigation";
interface ModalBtnProps {
title: string;
@@ -45,6 +57,7 @@ const ModalBtn = ({
modal?.removeEventListener("close", handleClose);
};
}, [modalId]);
const router = useRouter();
const canSelectDate =
event.hasPresenceEvents &&
@@ -62,7 +75,15 @@ const ModalBtn = ({
document.body.classList.remove("modal-open");
modal?.close();
};
const selectAppointmentForm = useForm<ParticipantOptionalDefaults>({
resolver: zodResolver(ParticipantOptionalDefaultsSchema),
defaultValues: {
eventId: event.id,
userId: user.id,
...participant,
},
});
const selectedAppointment = selectedAppointments[0];
return (
<>
<button
@@ -83,14 +104,16 @@ const ModalBtn = ({
<div className="flex items-center gap-2 justify-center">
<CalendarIcon />
{!!dates.length && (
<select className="select w-full max-w-xs" defaultValue={0}>
<option disabled>Bitte wähle einen Termin aus</option>
{dates.map((date, index) => (
<option key={index}>
{date.appointmentDate.toLocaleString()}
</option>
))}
</select>
<Select
form={selectAppointmentForm as any}
options={dates.map((date) => ({
label: new Date(date.appointmentDate).toLocaleString(),
value: date.id,
}))}
name="eventAppointmentId"
label={""}
className="min-w-[200px]"
/>
)}
{!dates.length && (
<p className="text-center text-info">
@@ -99,6 +122,31 @@ const ModalBtn = ({
)}
</div>
)}
{selectedAppointment && !participant?.appointmentCancelled && (
<div className="flex items-center gap-2 justify-center">
<p>Dein Ausgewähler Termin</p>
<p>
{new Date(
selectedAppointment.appointmentDate,
).toLocaleString()}
</p>
<button
onClick={async () => {
await upsertParticipant({
eventId: event.id,
userId: user.id,
appointmentCancelled: true,
});
toast.success("Termin abgesagt");
router.refresh();
}}
className="btn btn-error btn-outline btn-sm"
>
absagen
</button>
</div>
)}
{!!dates.length && (
<p className="mt-3 text-center">
Bitte finde dich an diesem Termin in unserem Discord ein.
@@ -111,7 +159,7 @@ const ModalBtn = ({
participant={participant}
user={user}
moodleCourseId={event.finisherMoodleCourseId}
completed={participant?.finisherMoodleCurseCompleted}
completed={participant?.finisherMoodleCurseCompleted || false}
event={event}
/>
)}
@@ -119,8 +167,27 @@ const ModalBtn = ({
<button className="btn" onClick={closeModal}>
Abbrechen
</button>
{!!(event.hasPresenceEvents && dates.length) && (
<button className="btn btn-info btn-outline btn-wide">
{!!canSelectDate && (
<button
className={cn(
"btn btn-info btn-outline btn-wide",
event.type === "OBLIGATED_COURSE" && "btn-secondary",
)}
onClick={async () => {
console.log("submit", selectAppointmentForm.formState.errors);
const data = selectAppointmentForm.getValues();
if (!data.eventAppointmentId) return;
console.log("submit", data);
await upsertParticipant({
...data,
statusLog: data.statusLog?.filter((log) => log !== null),
appointmentCancelled: false,
});
router.refresh();
closeModal();
}}
>
<EnterIcon /> Anmelden
</button>
)}
@@ -150,6 +217,13 @@ const MoodleCourseIndicator = ({
event: Event;
}) => {
const courseUrl = `${process.env.NEXT_PUBLIC_MOODLE_URL}/course/view.php?id=${moodleCourseId}`;
if (!participant || (event.hasPresenceEvents && !participant?.attended))
return (
<p className="py-4 flex items-center gap-2 justify-center">
<Clock10Icon className="text-error" />
Abschlusstest erst nach Teilnahme verfügbar
</p>
);
if (completed)
return (
<p className="py-4 flex items-center gap-2 justify-center">
@@ -157,20 +231,17 @@ const MoodleCourseIndicator = ({
Moodle Kurs abgeschlossen
</p>
);
if (!participant || (event.hasPresenceEvents && !participant?.attended))
return (
<p className="py-4 flex items-center gap-2 justify-center">
<Cross className="text-error" />
Teilnahme an Event erforderlich
</p>
);
return (
<p className="py-4 flex items-center gap-2 justify-center">
Moodle-Kurs Benötigt
<button
className="btn btn-xs btn-info ml-2"
onClick={async () => {
await addParticipant(event.id, user.id);
await upsertParticipant({
eventId: event.id,
userId: user.id,
finisherMoodleCurseCompleted: false,
});
if (user.moodleId) {
await inscribeToMoodleCourse(moodleCourseId, user.moodleId);