diff --git a/apps/core-server/routes/helper.ts b/apps/core-server/routes/helper.ts index d712ee86..8ab02909 100644 --- a/apps/core-server/routes/helper.ts +++ b/apps/core-server/routes/helper.ts @@ -7,7 +7,6 @@ const router: Router = Router(); export const eventCompleted = (event: Event, participant?: Participant) => { if (!participant) return false; if (event.finisherMoodleCourseId && !participant.finisherMoodleCurseCompleted) return false; - if (event.hasPresenceEvents && !participant.attended) return false; return true; }; diff --git a/apps/hub/app/(app)/_components/FeaturedEvents.tsx b/apps/hub/app/(app)/_components/FeaturedEvents.tsx index b3233bd5..0aa5782f 100644 --- a/apps/hub/app/(app)/_components/FeaturedEvents.tsx +++ b/apps/hub/app/(app)/_components/FeaturedEvents.tsx @@ -23,15 +23,6 @@ const page = async () => { userId: user.id, }, }, - Appointments: { - include: { - Participants: { - where: { - appointmentCancelled: false, - }, - }, - }, - }, }, }); @@ -47,23 +38,13 @@ const page = async () => { return (
-

- Laufende Events & Kurse +

+ Laufende Events & Kurse

{filteredEvents.map((event) => { - return ( - - a.Participants.find((p) => p.userId == user.id), - )} - user={user} - event={event} - key={event.id} - /> - ); + return ; })}
diff --git a/apps/hub/app/(app)/_components/FirstPath.tsx b/apps/hub/app/(app)/_components/FirstPath.tsx index b12301c5..3bda43c3 100644 --- a/apps/hub/app/(app)/_components/FirstPath.tsx +++ b/apps/hub/app/(app)/_components/FirstPath.tsx @@ -20,18 +20,18 @@ const PathsOptions = ({
{/* Disponent Card */}
setSelected("disponent")} role="button" tabIndex={0} aria-pressed={selected === "disponent"} > -

+

Disponent

-
+
Denkt sich realistische Einsatzszenarien aus, koordiniert deren Ablauf und ist die zentrale Schnittstelle zwischen Piloten und bodengebundenen Rettungsmitteln. Er trägt die Verantwortung für einen reibungslosen Ablauf und der erfolgreichen Durchführung der @@ -43,18 +43,18 @@ const PathsOptions = ({
{/* Pilot Card */}
setSelected("pilot")} role="button" tabIndex={0} aria-pressed={selected === "pilot"} > -

+

Pilot

-
+
Fliegt die vom Disponenten erstellten Einsätze und transportiert die Med-Crew sicher zum Einsatzort. Er übernimmt die navigatorische Vorbereitung, achtet auf Wetterentwicklungen und sorgt für die Sicherheit seiner Crew im Flug. @@ -76,17 +76,7 @@ const EventSelect = ({ pathSelected }: { pathSelected: "disponent" | "pilot" }) const user = useSession().data?.user; if (!user) return null; return events?.map((event) => { - return ( - - a.Participants.find((p) => p.userId == user.id), - )} - user={user} - event={event} - key={event.id} - /> - ); + return ; }); }; @@ -107,14 +97,14 @@ export const FirstPath = () => { return (
-

+

{session?.user.migratedFromV1 ? "Hallo, hier hat sich einiges geändert!" : "Wähle deinen Einstieg!"}

-

Willkommen bei Virtual Air Rescue!

+

Willkommen bei Virtual Air Rescue!

{session?.user.migratedFromV1 ? ( -

+

Dein Account wurde erfolgreich auf das neue System migriert. Herzlich Willkommen im neuen HUB! Um die Erfahrung für alle Nutzer zu steigern haben wir uns dazu entschlossen, dass alle Nutzer einen Test absolvieren müssen:{" "} @@ -129,12 +119,12 @@ export const FirstPath = () => { ausprobieren, wenn du möchtest.

)} -
+
{page === "path" && } {page === "event-select" && ( -
+
-

Wähle dein Einführungs-Event aus:

+

Wähle dein Einführungs-Event aus:

diff --git a/apps/hub/app/(app)/_components/Footer.tsx b/apps/hub/app/(app)/_components/Footer.tsx index 344d1e36..1ef446a9 100644 --- a/apps/hub/app/(app)/_components/Footer.tsx +++ b/apps/hub/app/(app)/_components/Footer.tsx @@ -2,23 +2,17 @@ import Image from "next/image"; import { DiscordLogoIcon, InstagramLogoIcon, ReaderIcon } from "@radix-ui/react-icons"; import YoutubeSvg from "./youtube_wider.svg"; import FacebookSvg from "./facebook.svg"; -import { ChangelogModalBtn } from "@repo/shared-components"; -import { getServerSession } from "api/auth/[...nextauth]/auth"; -import { updateUser } from "(app)/settings/actions"; -import toast from "react-hot-toast"; + import { ChangelogWrapper } from "(app)/_components/ChangelogWrapper"; import { prisma } from "@repo/db"; export const Footer = async () => { - const session = await getServerSession(); const latestChangelog = await prisma.changelog.findFirst({ orderBy: { createdAt: "desc", }, }); - const autoOpen = !session?.user.changelogAck && !!latestChangelog; - return (
{/* Left: Impressum & Datenschutz */} diff --git a/apps/hub/app/(app)/admin/event/[id]/participant/[participantId]/page.tsx b/apps/hub/app/(app)/admin/event/[id]/participant/[participantId]/page.tsx new file mode 100644 index 00000000..0fadd17e --- /dev/null +++ b/apps/hub/app/(app)/admin/event/[id]/participant/[participantId]/page.tsx @@ -0,0 +1,55 @@ +import { prisma } from "@repo/db"; +import { ParticipantForm } from "../../../_components/ParticipantForm"; +import { Error } from "_components/Error"; +import Link from "next/link"; +import { PersonIcon } from "@radix-ui/react-icons"; +import { ArrowLeft } from "lucide-react"; + +export default async function Page({ + params, +}: { + params: Promise<{ id: string; participantId: string }>; +}) { + const { id: eventId, participantId } = await params; + console.log(eventId, participantId); + + const event = await prisma.event.findUnique({ + where: { id: parseInt(eventId) }, + }); + + const participant = await prisma.participant.findUnique({ + where: { id: parseInt(participantId) }, + }); + + if (!participant) { + return ; + } + + const user = await prisma.user.findUnique({ + where: { id: participant?.userId }, + }); + + if (!event) return ; + + if (!participant || !user) { + return ; + } + + return ( +
+
+
+ + + Zurück zum Event + +
+

+ Event-Übersicht für{" "} + {`${user.firstname} ${user.lastname} #${user.publicId}`} +

+
+ +
+ ); +} diff --git a/apps/hub/app/(app)/admin/event/_components/AppointmentModal.tsx b/apps/hub/app/(app)/admin/event/_components/AppointmentModal.tsx deleted file mode 100644 index f2e69dcf..00000000 --- a/apps/hub/app/(app)/admin/event/_components/AppointmentModal.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import { Event, Participant, Prisma } from "@repo/db"; -import { EventAppointmentOptionalDefaults, InputJsonValueType } from "@repo/db/zod"; -import { ColumnDef } from "@tanstack/react-table"; -import { useSession } from "next-auth/react"; -import { RefObject, useRef } from "react"; -import { UseFormReturn } from "react-hook-form"; -import { PaginatedTable, PaginatedTableRef } from "../../../../_components/PaginatedTable"; -import { Button } from "../../../../_components/ui/Button"; -import { DateInput } from "../../../../_components/ui/DateInput"; -import { upsertParticipant } from "../../../events/actions"; -import { deleteAppoinement, upsertAppointment } from "../action"; -import { handleParticipantFinished } from "../../../../../helper/events"; -import toast from "react-hot-toast"; - -interface AppointmentModalProps { - event?: Event; - ref: RefObject; - participantModal: RefObject; - appointmentsTableRef: React.RefObject; - appointmentForm: UseFormReturn; - participantForm: UseFormReturn; -} - -export const AppointmentModal = ({ - event, - ref, - participantModal, - appointmentsTableRef, - appointmentForm, - participantForm, -}: AppointmentModalProps) => { - const { data: session } = useSession(); - - const participantTableRef = useRef(null); - - return ( - -
-
- {/* if there is a button in form, it will close the modal */} - -
- -
{ - if (!event) return; - await upsertAppointment(values); - ref.current?.close(); - appointmentsTableRef.current?.refresh(); - })} - className="flex flex-col" - > -
-

Termin {appointmentForm.watch("id")}

- appointmentForm.setValue("appointmentDate", date)} - /> -
-
- { - return {new Date(row.original.enscriptionDate).toLocaleString()}; - }, - }, - { - header: "Anwesend", - cell: ({ row }) => { - if (row.original.attended) { - return Ja; - } else if (row.original.appointmentCancelled) { - return Nein (Termin abgesagt); - } else { - return ?; - } - }, - }, - { - header: "Aktion", - - cell: ({ row }) => { - return ( -
- - {!row.original.attended && event?.hasPresenceEvents && ( - - )} - {!row.original.appointmentCancelled && event?.hasPresenceEvents && ( - - )} -
- ); - }, - }, - ] as ColumnDef[] - } - prismaModel={"participant"} - getFilter={() => - ({ - eventAppointmentId: appointmentForm.watch("id")!, - }) as Prisma.ParticipantWhereInput - } - include={{ User: true }} - leftOfPagination={ -
- - {appointmentForm.watch("id") && ( - - )} -
- } - /> -
-
-
-
- ); -}; diff --git a/apps/hub/app/(app)/admin/event/_components/Form.tsx b/apps/hub/app/(app)/admin/event/_components/Form.tsx index f2726311..55a43f34 100644 --- a/apps/hub/app/(app)/admin/event/_components/Form.tsx +++ b/apps/hub/app/(app)/admin/event/_components/Form.tsx @@ -1,70 +1,37 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; -import { BADGES, Event, EVENT_TYPE, Participant, PERMISSION, Prisma, User } from "@repo/db"; -import { - EventAppointmentOptionalDefaults, - EventAppointmentOptionalDefaultsSchema, - EventOptionalDefaults, - EventOptionalDefaultsSchema, - ParticipantSchema, -} from "@repo/db/zod"; -import { Bot, Calendar, FileText, UserIcon } from "lucide-react"; -import { useSession } from "next-auth/react"; +import { BADGES, Event, EVENT_TYPE, Participant, PERMISSION, Prisma } from "@repo/db"; +import { EventOptionalDefaults, EventOptionalDefaultsSchema } from "@repo/db/zod"; +import { Bot, FileText, UserIcon } from "lucide-react"; import { redirect } from "next/navigation"; -import { useRef } from "react"; import "react-datepicker/dist/react-datepicker.css"; import { useForm } from "react-hook-form"; -import { PaginatedTable, PaginatedTableRef } from "../../../../_components/PaginatedTable"; import { Button } from "../../../../_components/ui/Button"; import { Input } from "../../../../_components/ui/Input"; import { MarkdownEditor } from "../../../../_components/ui/MDEditor"; import { Select } from "../../../../_components/ui/Select"; import { Switch } from "../../../../_components/ui/Switch"; import { deleteEvent, upsertEvent } from "../action"; -import { AppointmentModal } from "./AppointmentModal"; -import { ParticipantModal } from "./ParticipantModal"; -import { ColumnDef } from "@tanstack/react-table"; import toast from "react-hot-toast"; +import { PaginatedTable } from "_components/PaginatedTable"; import Link from "next/link"; +import { ColumnDef } from "@tanstack/react-table"; +import { User } from "next-auth"; export const Form = ({ event }: { event?: Event }) => { - const { data: session } = useSession(); const form = useForm({ resolver: zodResolver(EventOptionalDefaultsSchema), defaultValues: event ? { ...event, discordRoleId: event.discordRoleId ?? undefined, - maxParticipants: event.maxParticipants ?? undefined, finisherMoodleCourseId: event.finisherMoodleCourseId ?? undefined, } : undefined, }); - const appointmentForm = useForm({ - resolver: zodResolver(EventAppointmentOptionalDefaultsSchema), - defaultValues: { - eventId: event?.id, - presenterId: session?.user?.id, - }, - }); - const participantForm = useForm({ - resolver: zodResolver(ParticipantSchema), - }); - const appointmentsTableRef = useRef(null); - const appointmentModal = useRef(null); - const participantModal = useRef(null); return ( <> - -
{ await upsertEvent(values, event?.id); @@ -139,224 +106,115 @@ export const Form = ({ event }: { event?: Event }) => { label="Discord Rolle für eingeschriebene Teilnehmer" className="input-sm" /> - -
- {form.watch("hasPresenceEvents") ? ( -
-
+
+
+ { - ({ - eventId: event?.id, - }) as Prisma.EventAppointmentWhereInput - } - include={{ - Presenter: true, - Participants: true, - }} leftOfSearch={

- Termine + Teilnehmer

} - rightOfSearch={ - event && ( - - ) + prismaModel={"participant"} + showSearch + getFilter={(searchTerm) => + ({ + AND: [{ eventId: event?.id }], + OR: [ + { + User: { + OR: [ + { firstname: { contains: searchTerm, mode: "insensitive" } }, + { lastname: { contains: searchTerm, mode: "insensitive" } }, + { publicId: { contains: searchTerm, mode: "insensitive" } }, + ], + }, + }, + ], + }) as Prisma.ParticipantWhereInput } + include={{ + User: true, + }} + supressQuery={!event} columns={ [ { - header: "Datum", - accessorKey: "appointmentDate", - accessorFn: (date) => new Date(date.appointmentDate).toLocaleString(), + header: "Vorname", + accessorKey: "User.firstname", + cell: ({ row }) => { + return ( + + {row.original.User.firstname} + + ); + }, }, { - header: "Presenter", - accessorKey: "presenter", - cell: ({ row }) => ( -
- - {row.original.Presenter.firstname} {row.original.Presenter.lastname} - -
- ), + header: "Nachname", + accessorKey: "User.lastname", + cell: ({ row }) => { + return ( + + {row.original.User.lastname} + + ); + }, }, { - header: "Teilnehmer", - accessorKey: "Participants", - cell: ({ row }) => ( -
- - {row.original.Participants.length} -
- ), + header: "VAR-Nummer", + accessorKey: "User.publicId", + cell: ({ row }) => { + return ( + + {row.original.User.publicId} + + ); + }, + }, + { + header: "Moodle Kurs abgeschlossen", + accessorKey: "finisherMoodleCurseCompleted", }, { header: "Aktionen", cell: ({ row }) => { return ( -
+ -
+ ); }, }, - ] as ColumnDef< - EventAppointmentOptionalDefaults & { - Presenter: User; - Participants: Participant[]; - } - >[] + ] as ColumnDef[] } /> -
+ }
- ) : null} - {!form.watch("hasPresenceEvents") ? ( -
-
- { - - Teilnehmer - - } - ref={appointmentsTableRef} - prismaModel={"participant"} - showSearch - getFilter={(searchTerm) => - ({ - AND: [{ eventId: event?.id }], - OR: [ - { - User: { - OR: [ - { firstname: { contains: searchTerm, mode: "insensitive" } }, - { lastname: { contains: searchTerm, mode: "insensitive" } }, - { publicId: { contains: searchTerm, mode: "insensitive" } }, - ], - }, - }, - ], - }) as Prisma.ParticipantWhereInput - } - include={{ - User: true, - }} - supressQuery={!event} - columns={ - [ - { - header: "Vorname", - accessorKey: "User.firstname", - cell: ({ row }) => { - return ( - - {row.original.User.firstname} - - ); - }, - }, - { - header: "Nachname", - accessorKey: "User.lastname", - cell: ({ row }) => { - return ( - - {row.original.User.lastname} - - ); - }, - }, - { - header: "VAR-Nummer", - accessorKey: "User.publicId", - cell: ({ row }) => { - return ( - - {row.original.User.publicId} - - ); - }, - }, - { - header: "Moodle Kurs abgeschlossen", - accessorKey: "finisherMoodleCurseCompleted", - }, - { - header: "Aktionen", - cell: ({ row }) => { - return ( -
- -
- ); - }, - }, - ] as ColumnDef[] - } - /> - } -
-
- ) : null} +
diff --git a/apps/hub/app/(app)/admin/event/_components/ParticipantForm.tsx b/apps/hub/app/(app)/admin/event/_components/ParticipantForm.tsx new file mode 100644 index 00000000..0b69f86e --- /dev/null +++ b/apps/hub/app/(app)/admin/event/_components/ParticipantForm.tsx @@ -0,0 +1,213 @@ +"use client"; +import { Participant, Event, ParticipantLog, Prisma } from "@repo/db"; +import { Users, Activity, Bug } from "lucide-react"; +import toast from "react-hot-toast"; +import { InputJsonValueType, ParticipantOptionalDefaultsSchema } from "@repo/db/zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { Switch } from "_components/ui/Switch"; +import { useState } from "react"; +import { Button } from "_components/ui/Button"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { upsertParticipant } from "(app)/events/actions"; +import { deleteParticipant } from "../action"; +import { redirect } from "next/navigation"; + +interface ParticipantFormProps { + event: Event; + participant: Participant; +} + +const checkEventCompleted = (participant: Participant, event: Event): boolean => { + return event.finisherMoodleCourseId ? participant.finisherMoodleCurseCompleted : false; +}; + +export const ParticipantForm = ({ event, participant }: ParticipantFormProps) => { + const [isLoading, setIsLoading] = useState(false); + const queryClient = useQueryClient(); + + const upsertParticipantMutation = useMutation({ + mutationKey: ["upsertParticipant"], + mutationFn: async (newData: Prisma.ParticipantUncheckedCreateInput) => { + const data = await upsertParticipant(newData); + await queryClient.invalidateQueries({ queryKey: ["participants", event.id] }); + return data; + }, + }); + + const deleteParticipantMutation = useMutation({ + mutationKey: ["deleteParticipant"], + mutationFn: async (participantId: number) => { + await deleteParticipant(participantId); + await queryClient.invalidateQueries({ queryKey: ["participants", event.id] }); + }, + }); + + const eventCompleted = checkEventCompleted(participant, event); + + const form = useForm({ + resolver: zodResolver(ParticipantOptionalDefaultsSchema), + defaultValues: participant, + }); + + const handleEventFinished = async () => { + setIsLoading(true); + try { + await upsertParticipantMutation.mutateAsync({ + eventId: event.id, + userId: participant.userId, + }); + toast.success("Event als beendet markiert"); + } finally { + setIsLoading(false); + } + }; + + const handleCheckMoodle = async () => { + setIsLoading(true); + try { + toast.success("Moodle-Check durchgeführt"); + } finally { + setIsLoading(false); + } + }; + + return ( + { + const data = await upsertParticipantMutation.mutateAsync({ + ...formData, + statusLog: participant.statusLog as unknown as Prisma.ParticipantCreatestatusLogInput, + eventId: event.id, + userId: participant.userId, + }); + form.reset(data); + toast.success("Teilnehmer aktualisiert"); + })} + className="bg-base-100 flex flex-wrap gap-6 p-6" + > + {/* Status Section */} +
+
+

+ + Debug +

+ + + +
+
+
+ {/* Info Card */} +
+
+

+ Informationen +

+
+
+

Kurs-status

+

{eventCompleted ? "Abgeschlossen" : "In Bearbeitung"}

+

Einschreibedatum

+

+ {participant?.enscriptionDate + ? new Date(participant.enscriptionDate).toLocaleDateString() + : "-"} +

+
+ +
+ +
+ + +
+
+
+ + {/* Activity Log */} +
+
+

+ Aktivitätslog +

+ +
+ + + + + + + + + + {participant?.statusLog && + Array.isArray(participant.statusLog) && + (participant.statusLog as InputJsonValueType[]) + .slice() + .reverse() + .map((log: InputJsonValueType, index: number) => { + const logEntry = log as unknown as ParticipantLog; + return ( + + + + + + ); + })} + +
DatumEventUser
+ {logEntry.timestamp + ? new Date(logEntry.timestamp).toLocaleDateString() + : "-"} + {logEntry.event || "-"}{logEntry.user || "-"}
+
+
+
+
+
+
+ + {event && ( + + )} +
+
+
+ + ); +}; diff --git a/apps/hub/app/(app)/admin/event/action.ts b/apps/hub/app/(app)/admin/event/action.ts index 0a3c6a3e..438135ce 100644 --- a/apps/hub/app/(app)/admin/event/action.ts +++ b/apps/hub/app/(app)/admin/event/action.ts @@ -2,6 +2,7 @@ import { prisma, Prisma, Event, Participant } from "@repo/db"; +//############# Event //############# export const upsertEvent = async (event: Prisma.EventCreateInput, id?: Event["id"]) => { const newEvent = id ? await prisma.event.update({ @@ -11,34 +12,22 @@ export const upsertEvent = async (event: Prisma.EventCreateInput, id?: Event["id : await prisma.event.create({ data: event }); return newEvent; }; - export const deleteEvent = async (id: Event["id"]) => { await prisma.event.delete({ where: { id: id } }); }; -export const upsertAppointment = async ( - eventAppointment: Prisma.EventAppointmentUncheckedCreateInput, -) => { - const newEventAppointment = eventAppointment.id - ? await prisma.eventAppointment.update({ - where: { id: eventAppointment.id }, - data: eventAppointment, +//############# Participant //############# + +export const upsertParticipant = async (participant: Prisma.ParticipantUncheckedCreateInput) => { + const newParticipant = participant.id + ? await prisma.participant.update({ + where: { id: participant.id }, + data: participant, }) - : await prisma.eventAppointment.create({ data: eventAppointment }); - return newEventAppointment; + : await prisma.participant.create({ data: participant }); + return newParticipant; }; -export const deleteAppoinement = async (id: Event["id"]) => { - await prisma.eventAppointment.delete({ where: { id: id } }); - prisma.eventAppointment.findMany({ - where: { - eventId: id, - }, - orderBy: { - // TODO: add order by in relation to table selected column - }, - }); -}; export const deleteParticipant = async (id: Participant["id"]) => { await prisma.participant.delete({ where: { id: id } }); }; diff --git a/apps/hub/app/(app)/events/_components/EventCard.tsx b/apps/hub/app/(app)/events/_components/EventCard.tsx index 0f66e28f..a64465c2 100644 --- a/apps/hub/app/(app)/events/_components/EventCard.tsx +++ b/apps/hub/app/(app)/events/_components/EventCard.tsx @@ -1,6 +1,6 @@ "use client"; import { DrawingPinFilledIcon } from "@radix-ui/react-icons"; -import { Event, Participant, EventAppointment, User } from "@repo/db"; +import { Event, Participant, User } from "@repo/db"; import ModalBtn from "./Modal"; import MDEditor from "@uiw/react-md-editor"; import { Badge } from "@repo/shared-components"; @@ -8,25 +8,18 @@ import { Badge } from "@repo/shared-components"; export const EventCard = ({ user, event, - selectedAppointments, - appointments, }: { user: User; event: Event & { - Appointments: EventAppointment[]; Participants: Participant[]; }; - selectedAppointments: EventAppointment[]; - appointments: (EventAppointment & { - Participants: { userId: string }[]; - })[]; }) => { return (
-
+

{event.name}

-
+
{event.type === "COURSE" && ( Zusatzqualifikation )} @@ -36,7 +29,7 @@ export const EventCard = ({
-
+
-
+
{event.finishedBadges.map((b) => { return ; })}
-
+
-

+

Teilnahmevoraussetzungen: {!event.requiredBadges.length && "Keine"}

{!!event.requiredBadges.length && ( -
- Abzeichen: +
+ Abzeichen:
{event.requiredBadges.map((badge) => (
@@ -71,11 +64,9 @@ export const EventCard = ({ )}
diff --git a/apps/hub/app/(app)/events/_components/Modal.tsx b/apps/hub/app/(app)/events/_components/Modal.tsx index bcf0e910..74b45364 100644 --- a/apps/hub/app/(app)/events/_components/Modal.tsx +++ b/apps/hub/app/(app)/events/_components/Modal.tsx @@ -1,56 +1,30 @@ "use client"; import { useEffect } from "react"; import { CheckCircledIcon, EnterIcon, DrawingPinFilledIcon } from "@radix-ui/react-icons"; -import { Event, EventAppointment, Participant, User } from "@repo/db"; +import { Event, Participant, User } from "@repo/db"; import { cn } from "@repo/shared-components"; import { inscribeToMoodleCourse, upsertParticipant } from "../actions"; import { BookCheck, - Calendar, Check, CirclePlay, - Clock10Icon, ExternalLink, EyeIcon, Info, TriangleAlert, } from "lucide-react"; -import { useForm } from "react-hook-form"; -import { - InputJsonValueType, - ParticipantOptionalDefaults, - ParticipantOptionalDefaultsSchema, -} from "@repo/db/zod"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { Select } from "../../../_components/ui/Select"; -import { useRouter } from "next/navigation"; -import { handleParticipantEnrolled } from "../../../../helper/events"; import { eventCompleted } from "@repo/shared-components"; import MDEditor from "@uiw/react-md-editor"; -import toast from "react-hot-toast"; -import { formatDate } from "date-fns"; interface ModalBtnProps { title: string; event: Event; - dates: (EventAppointment & { - Participants: { userId: string }[]; - })[]; - selectedAppointments: EventAppointment[]; participant?: Participant; user: User; modalId: string; } -const ModalBtn = ({ - title, - dates, - modalId, - participant, - selectedAppointments, - event, - user, -}: ModalBtnProps) => { +const ModalBtn = ({ title, modalId, participant, event, user }: ModalBtnProps) => { useEffect(() => { const modal = document.getElementById(modalId) as HTMLDialogElement; const handleOpen = () => { @@ -66,12 +40,6 @@ const ModalBtn = ({ modal?.removeEventListener("close", handleClose); }; }, [modalId]); - const router = useRouter(); - - const canSelectDate = - event.hasPresenceEvents && - !participant?.attended && - (selectedAppointments.length === 0 || participant?.appointmentCancelled); const openModal = () => { const modal = document.getElementById(modalId) as HTMLDialogElement; @@ -82,29 +50,6 @@ const ModalBtn = ({ const modal = document.getElementById(modalId) as HTMLDialogElement; modal?.close(); }; - const selectAppointmentForm = useForm({ - resolver: zodResolver(ParticipantOptionalDefaultsSchema), - defaultValues: { - eventId: event.id, - userId: user.id, - ...participant, - }, - }); - const selectedAppointment = selectedAppointments[0]; - const selectedDate = dates.find( - (date) => - date.id === selectAppointmentForm.watch("eventAppointmentId") || selectedAppointment?.id, - ); - const ownIndexInParticipantList = selectedDate?.Participants?.findIndex( - (p) => p.userId === user.id, - ); - - const ownPlaceInParticipantList = - typeof ownIndexInParticipantList === "number" - ? ownIndexInParticipantList === -1 - ? (selectedDate?.Participants?.length ?? 0) + 1 - : ownIndexInParticipantList + 1 - : undefined; const missingRequirements = event.requiredBadges?.length > 0 && @@ -163,79 +108,6 @@ const ModalBtn = ({ />
- {event.hasPresenceEvents && ( -
-

- Termine -

-
- {!!dates.length && !selectedDate && ( - <> -

Melde dich zu einem Termin an

-