Fixed type errors in nextJS apps, added Docker files
Co-authored-by: Nicolas <nocnico@users.noreply.github.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { prisma } from "@repo/db";
|
||||
import { Form } from "../_components/Form";
|
||||
|
||||
export default async ({ params }: { params: Promise<{ id: string }> }) => {
|
||||
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await params;
|
||||
const event = await prisma.event.findUnique({
|
||||
where: {
|
||||
@@ -10,4 +10,4 @@ export default async ({ params }: { params: Promise<{ id: string }> }) => {
|
||||
});
|
||||
if (!event) return <div>Event not found</div>;
|
||||
return <Form event={event} />;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,34 +1,21 @@
|
||||
import { DateInput } from "../../../../_components/ui/DateInput";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Event, Participant, Prisma } from "@repo/db";
|
||||
import {
|
||||
EventAppointmentOptionalDefaults,
|
||||
EventAppointmentOptionalDefaultsSchema,
|
||||
ParticipantOptionalDefaultsSchema,
|
||||
} from "@repo/db/zod";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { Controller, useForm, UseFormReturn } from "react-hook-form";
|
||||
import { deleteAppoinement, upsertAppointment } from "../action";
|
||||
import { Button } from "../../../../_components/ui/Button";
|
||||
import {
|
||||
PaginatedTable,
|
||||
PaginatedTableRef,
|
||||
} from "../../../../_components/PaginatedTable";
|
||||
import { Ref, RefObject, useRef } from "react";
|
||||
import { Event, Participant } from "@repo/db";
|
||||
import { EventAppointmentOptionalDefaults } from "@repo/db/zod";
|
||||
import { CellContext } 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 { Switch } from "../../../../_components/ui/Switch";
|
||||
import { deleteAppoinement, upsertAppointment } from "../action";
|
||||
|
||||
interface AppointmentModalProps {
|
||||
event?: Event;
|
||||
ref: RefObject<HTMLDialogElement | null>;
|
||||
participantModal: RefObject<HTMLDialogElement | null>;
|
||||
appointmentsTableRef: React.RefObject<PaginatedTableRef>;
|
||||
appointmentForm: UseFormReturn<
|
||||
EventAppointmentOptionalDefaults,
|
||||
any,
|
||||
undefined
|
||||
>;
|
||||
appointmentsTableRef: React.RefObject<PaginatedTableRef | null>;
|
||||
appointmentForm: UseFormReturn<EventAppointmentOptionalDefaults, any, undefined>;
|
||||
participantForm: UseFormReturn<Participant, any, undefined>;
|
||||
}
|
||||
|
||||
@@ -56,9 +43,7 @@ export const AppointmentModal = ({
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
<h3 className="font-bold text-lg">
|
||||
Termin {appointmentForm.watch("id")}
|
||||
</h3>
|
||||
<h3 className="font-bold text-lg">Termin {appointmentForm.watch("id")}</h3>
|
||||
<form
|
||||
onSubmit={appointmentForm.handleSubmit(async (values) => {
|
||||
if (!event) return;
|
||||
@@ -101,13 +86,7 @@ export const AppointmentModal = ({
|
||||
accessorKey: "enscriptionDate",
|
||||
header: "Einschreibedatum",
|
||||
cell: ({ row }: CellContext<Participant, any>) => {
|
||||
return (
|
||||
<span>
|
||||
{new Date(
|
||||
row.original.enscriptionDate,
|
||||
).toLocaleString()}
|
||||
</span>
|
||||
);
|
||||
return <span>{new Date(row.original.enscriptionDate).toLocaleString()}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -116,11 +95,7 @@ export const AppointmentModal = ({
|
||||
if (row.original.attended) {
|
||||
return <span className="text-green-500">Ja</span>;
|
||||
} else if (row.original.appointmentCancelled) {
|
||||
return (
|
||||
<span className="text-red-500">
|
||||
Nein (Termin abgesagt)
|
||||
</span>
|
||||
);
|
||||
return <span className="text-red-500">Nein (Termin abgesagt)</span>;
|
||||
} else {
|
||||
return <span>?</span>;
|
||||
}
|
||||
@@ -159,33 +134,32 @@ export const AppointmentModal = ({
|
||||
Anwesend
|
||||
</button>
|
||||
)}
|
||||
{!row.original.appointmentCancelled &&
|
||||
event?.hasPresenceEvents && (
|
||||
<button
|
||||
type="button"
|
||||
onSubmit={() => {}}
|
||||
onClick={async () => {
|
||||
await upsertParticipant({
|
||||
eventId: event!.id,
|
||||
userId: row.original.userId,
|
||||
attended: false,
|
||||
appointmentCancelled: true,
|
||||
statusLog: [
|
||||
...(row.original.statusLog as any),
|
||||
{
|
||||
event: "Gefehlt an Event",
|
||||
timestamp: new Date().toISOString(),
|
||||
user: `${session?.user?.firstname} ${session?.user?.lastname} - ${session?.user?.publicId}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
participantTableRef.current?.refresh();
|
||||
}}
|
||||
className="btn btn-outline btn-error btn-sm"
|
||||
>
|
||||
abwesend
|
||||
</button>
|
||||
)}
|
||||
{!row.original.appointmentCancelled && event?.hasPresenceEvents && (
|
||||
<button
|
||||
type="button"
|
||||
onSubmit={() => {}}
|
||||
onClick={async () => {
|
||||
await upsertParticipant({
|
||||
eventId: event!.id,
|
||||
userId: row.original.userId,
|
||||
attended: false,
|
||||
appointmentCancelled: true,
|
||||
statusLog: [
|
||||
...(row.original.statusLog as any),
|
||||
{
|
||||
event: "Gefehlt an Event",
|
||||
timestamp: new Date().toISOString(),
|
||||
user: `${session?.user?.firstname} ${session?.user?.lastname} - ${session?.user?.publicId}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
participantTableRef.current?.refresh();
|
||||
}}
|
||||
className="btn btn-outline btn-error btn-sm"
|
||||
>
|
||||
abwesend
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,51 +1,42 @@
|
||||
"use client";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { BADGES, Event, EVENT_TYPE, Participant, PERMISSION, User } from "@repo/db";
|
||||
import {
|
||||
EventAppointmentOptionalDefaults,
|
||||
EventAppointmentOptionalDefaultsSchema,
|
||||
EventOptionalDefaults,
|
||||
EventOptionalDefaultsSchema,
|
||||
ParticipantOptionalDefaultsSchema,
|
||||
ParticipantSchema,
|
||||
} from "@repo/db/zod";
|
||||
import { Controller, set, useForm } from "react-hook-form";
|
||||
import {
|
||||
BADGES,
|
||||
Event,
|
||||
EVENT_TYPE,
|
||||
Participant,
|
||||
PERMISSION,
|
||||
prisma,
|
||||
Prisma,
|
||||
} from "@repo/db";
|
||||
import { Bot, Calendar, FileText, User, UserIcon } from "lucide-react";
|
||||
import { Input } from "../../../../_components/ui/Input";
|
||||
import { useRef, useState } from "react";
|
||||
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,
|
||||
} from "../../../../_components/PaginatedTable";
|
||||
import { Select } from "../../../../_components/ui/Select";
|
||||
import { Bot, Calendar, FileText, UserIcon } from "lucide-react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { redirect } from "next/navigation";
|
||||
import { useRef, useState } 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";
|
||||
|
||||
export const Form = ({ event }: { event?: Event }) => {
|
||||
const { data: session } = useSession();
|
||||
const form = useForm({
|
||||
const form = useForm<EventOptionalDefaults>({
|
||||
resolver: zodResolver(EventOptionalDefaultsSchema),
|
||||
defaultValues: event,
|
||||
defaultValues: event
|
||||
? {
|
||||
...event,
|
||||
discordRoleId: event.discordRoleId ?? undefined,
|
||||
maxParticipants: event.maxParticipants ?? undefined,
|
||||
finisherMoodleCourseId: event.finisherMoodleCourseId ?? undefined,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
const appointmentForm = useForm<EventAppointmentOptionalDefaults>({
|
||||
resolver: zodResolver(EventAppointmentOptionalDefaultsSchema),
|
||||
@@ -55,7 +46,7 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
},
|
||||
});
|
||||
const participantForm = useForm<Participant>({
|
||||
resolver: zodResolver(ParticipantOptionalDefaultsSchema),
|
||||
resolver: zodResolver(ParticipantSchema),
|
||||
});
|
||||
const appointmentsTableRef = useRef<PaginatedTableRef>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -73,10 +64,7 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
appointmentsTableRef={appointmentsTableRef}
|
||||
event={event}
|
||||
/>
|
||||
<ParticipantModal
|
||||
participantForm={participantForm}
|
||||
ref={participantModal}
|
||||
/>
|
||||
<ParticipantModal participantForm={participantForm} ref={participantModal} />
|
||||
<form
|
||||
onSubmit={form.handleSubmit(async (values) => {
|
||||
setLoading(true);
|
||||
@@ -155,11 +143,7 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
value: key,
|
||||
}))}
|
||||
/>
|
||||
<Switch
|
||||
form={form}
|
||||
name="hasPresenceEvents"
|
||||
label="Hat Live Event"
|
||||
/>
|
||||
<Switch form={form} name="hasPresenceEvents" label="Hat Live Event" />
|
||||
</div>
|
||||
</div>
|
||||
{form.watch("hasPresenceEvents") ? (
|
||||
@@ -196,58 +180,61 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
Presenter: true,
|
||||
Participants: true,
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
header: "Datum",
|
||||
accessorKey: "appointmentDate",
|
||||
accessorFn: (date) =>
|
||||
new Date(date.appointmentDate).toLocaleString(),
|
||||
},
|
||||
{
|
||||
header: "Presenter",
|
||||
accessorKey: "presenter",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center">
|
||||
<span className="ml-2">
|
||||
{(row.original as any).Presenter.firstname}{" "}
|
||||
{(row.original as any).Presenter.lastname}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: "Teilnehmer",
|
||||
accessorKey: "Participants",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center">
|
||||
<UserIcon className="w-5 h-5" />
|
||||
<span className="ml-2">
|
||||
{row.original.Participants.length}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: "Aktionen",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onSubmit={() => false}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
appointmentForm.reset(row.original);
|
||||
appointmentModal.current?.showModal();
|
||||
}}
|
||||
className="btn btn-sm btn-outline"
|
||||
>
|
||||
Bearbeiten
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
columns={
|
||||
[
|
||||
{
|
||||
header: "Datum",
|
||||
accessorKey: "appointmentDate",
|
||||
accessorFn: (date) => new Date(date.appointmentDate).toLocaleString(),
|
||||
},
|
||||
},
|
||||
]}
|
||||
{
|
||||
header: "Presenter",
|
||||
accessorKey: "presenter",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center">
|
||||
<span className="ml-2">
|
||||
{row.original.Presenter.firstname} {row.original.Presenter.lastname}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: "Teilnehmer",
|
||||
accessorKey: "Participants",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center">
|
||||
<UserIcon className="w-5 h-5" />
|
||||
<span className="ml-2">{row.original.Participants.length}</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: "Aktionen",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onSubmit={() => false}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
appointmentForm.reset(row.original);
|
||||
appointmentModal.current?.showModal();
|
||||
}}
|
||||
className="btn btn-sm btn-outline"
|
||||
>
|
||||
Bearbeiten
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
] as ColumnDef<
|
||||
EventAppointmentOptionalDefaults & {
|
||||
Presenter: User;
|
||||
Participants: Participant[];
|
||||
}
|
||||
>[]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -311,11 +298,7 @@ export const Form = ({ event }: { event?: Event }) => {
|
||||
<div className="card bg-base-200 shadow-xl col-span-6">
|
||||
<div className="card-body ">
|
||||
<div className="flex w-full gap-4">
|
||||
<Button
|
||||
isLoading={loading}
|
||||
type="submit"
|
||||
className="btn btn-primary flex-1"
|
||||
>
|
||||
<Button isLoading={loading} type="submit" className="btn btn-primary flex-1">
|
||||
Speichern
|
||||
</Button>
|
||||
{event && (
|
||||
|
||||
Reference in New Issue
Block a user