added basic data for event list, md editor and viewer
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
} from '../../../../_components/PaginatedTable';
|
||||
import { Select } from '../../../../_components/ui/Select';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { MarkdownEditor } from '../../../../_components/ui/MDEditor';
|
||||
|
||||
export const Form = ({
|
||||
event,
|
||||
@@ -107,12 +108,7 @@ export const Form = ({
|
||||
<FileText className="w-5 h-5" /> Allgemeines
|
||||
</h2>
|
||||
<Input form={form} label="Name" name="name" className="input-sm" />
|
||||
<Input
|
||||
form={form}
|
||||
label="Beschreibung"
|
||||
name="description"
|
||||
className="input-sm"
|
||||
/>
|
||||
<MarkdownEditor form={form} name="description" />
|
||||
<Input
|
||||
form={form}
|
||||
label="Maximale Teilnehmer (Nur für live Events)"
|
||||
@@ -174,12 +170,14 @@ export const Form = ({
|
||||
<h2 className="card-title">
|
||||
<Calendar className="w-5 h-5" /> Termine
|
||||
</h2>
|
||||
{event && (
|
||||
<button
|
||||
className="btn btn-primary btn-outline"
|
||||
onClick={() => addParticipantModal.current?.showModal()}
|
||||
>
|
||||
Hinzufügen
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<PaginatedTable
|
||||
@@ -233,6 +231,7 @@ export const Form = ({
|
||||
type="button"
|
||||
onClick={() => {
|
||||
console.log(row.original);
|
||||
// TODO: open modal to edit appointment
|
||||
}}
|
||||
className="btn btn-sm btn-outline"
|
||||
>
|
||||
|
||||
@@ -1,28 +1,15 @@
|
||||
"use client";
|
||||
import { DrawingPinFilledIcon, EnterIcon } from "@radix-ui/react-icons";
|
||||
import { User } from "@repo/db";
|
||||
import ModalBtn from "./modalBtn";
|
||||
'use client';
|
||||
import { DrawingPinFilledIcon, EnterIcon } from '@radix-ui/react-icons';
|
||||
import { Event, User } from '@repo/db';
|
||||
import ModalBtn from './modalBtn';
|
||||
import MDEditor from '@uiw/react-md-editor';
|
||||
|
||||
export const KursItem = ({
|
||||
user,
|
||||
title,
|
||||
type,
|
||||
beschreibung,
|
||||
badge,
|
||||
moodleReq,
|
||||
}: {
|
||||
user: User;
|
||||
title: string;
|
||||
type: string;
|
||||
beschreibung: string;
|
||||
badge: string;
|
||||
moodleReq: boolean;
|
||||
}) => {
|
||||
export const KursItem = ({ user, event }: { user: User; event: Event }) => {
|
||||
return (
|
||||
<div className="col-span-full">
|
||||
<div className="card bg-base-200 shadow-xl mb-4">
|
||||
<div className="card-body">
|
||||
<h2 className="card-title">{title}</h2>
|
||||
<h2 className="card-title">{event.name}</h2>
|
||||
<div className="absolute top-0 right-0 m-4">
|
||||
<span className="badge badge-info badge-outline">
|
||||
Zusatzqualifikation
|
||||
@@ -30,21 +17,48 @@ export const KursItem = ({
|
||||
</div>
|
||||
<div className="grid grid-cols-6 gap-4">
|
||||
<div className="col-span-4">
|
||||
<p className="text-left text-balance">{beschreibung}</p>
|
||||
<div className="text-left text-balance">
|
||||
<MDEditor.Markdown
|
||||
source={event.description}
|
||||
className="whitespace-pre-wrap"
|
||||
style={{
|
||||
backgroundColor: 'transparent',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2">{badge}</div>
|
||||
</div>
|
||||
<div className="col-span-2">{event.finishedBadges}</div>
|
||||
</div>
|
||||
<div className="card-actions flex justify-between items-center mt-5">
|
||||
<div>
|
||||
<p className="text-gray-600 text-left flex items-center gap-2">
|
||||
<DrawingPinFilledIcon /> <b>Teilnahmevoraussetzungen:</b>
|
||||
<DrawingPinFilledIcon /> <b>Teilnahmevoraussetzungen: </b>
|
||||
{(!event.starterMoodleCourseId ||
|
||||
!event.requiredBadges.length) &&
|
||||
'Keine'}
|
||||
{event.starterMoodleCourseId && (
|
||||
<a className="link link-info" href="">
|
||||
Moodle Kurs /MOODLEKURSTITLE\
|
||||
Moodle Kurs {event.starterMoodleCourseId}
|
||||
</a>
|
||||
)}
|
||||
</p>
|
||||
{!!event.requiredBadges.length && (
|
||||
<div className="flex ml-6">
|
||||
<b className="text-gray-600 text-left">Abzeichen:</b>
|
||||
<div className="flex gap-2">
|
||||
{event.requiredBadges.map((badge) => (
|
||||
<div className="badge badge-secondary badge-outline">
|
||||
{badge}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ModalBtn
|
||||
title={title}
|
||||
dates={["Dienstag, 25 Februar 2025", "Mittwoch, 26 Februar 2025"]}
|
||||
modalId={title + "_modal" + Math.random()}
|
||||
title={event.name}
|
||||
dates={['Dienstag, 25 Februar 2025', 'Mittwoch, 26 Februar 2025']}
|
||||
modalId={`${event.name}_modal.${event.id}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
import { getServerSession } from "../../api/auth/[...nextauth]/auth";
|
||||
import { PrismaClient } from "@repo/db";
|
||||
import { PilotKurs, KursItem } from "./_components/item";
|
||||
import {
|
||||
RocketIcon,
|
||||
DrawingPinFilledIcon,
|
||||
EnterIcon,
|
||||
} from "@radix-ui/react-icons";
|
||||
import { getServerSession } from '../../api/auth/[...nextauth]/auth';
|
||||
import { PrismaClient } from '@repo/db';
|
||||
import { PilotKurs, KursItem } from './_components/item';
|
||||
import { RocketIcon } from '@radix-ui/react-icons';
|
||||
|
||||
export default async () => {
|
||||
const prisma = new PrismaClient();
|
||||
const session = await getServerSession();
|
||||
if (!session) return null;
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
id: session.user.id,
|
||||
},
|
||||
});
|
||||
const user = session.user;
|
||||
const events = await prisma.event.findMany();
|
||||
if (!user) return null;
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-6 gap-4">
|
||||
<div className="col-span-full">
|
||||
@@ -25,21 +19,9 @@ export default async () => {
|
||||
</p>
|
||||
</div>
|
||||
<PilotKurs user={user} />
|
||||
<KursItem
|
||||
user={user}
|
||||
title="Einsteigerkurs für Disponenten"
|
||||
type="1"
|
||||
beschreibung="In diesem Kurs lernen Teilnehmer die Aufgaben eines
|
||||
Disponenten in der Rettungsfliegerei kennen. Dazu gehören die
|
||||
Koordination von Notfalleinsätzen, die effiziente Planung von
|
||||
Ressourcen und die Kommunikation mit Piloten sowie
|
||||
Rettungsdiensten. Der Kurs vermittelt praxisnahe Kenntnisse
|
||||
für die schnelle und präzise Entscheidungsfindung unter
|
||||
Zeitdruck, um eine reibungslose Abwicklung von
|
||||
Rettungseinsätzen zu gewährleisten."
|
||||
badge="Badge"
|
||||
moodleReq={true}
|
||||
/>
|
||||
{events.map((event) => (
|
||||
<KursItem user={user} event={event} key={event.id} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -90,9 +90,9 @@ export function PaginatedTable<TData>({
|
||||
|
||||
return (
|
||||
<div className="space-y-4 m-4">
|
||||
{searchFields.length > 0 && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1">{leftOfSearch}</div>
|
||||
{searchFields.length > 0 && (
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Suchen..."
|
||||
@@ -103,9 +103,9 @@ export function PaginatedTable<TData>({
|
||||
}}
|
||||
className="input input-bordered w-full max-w-xs justify-end"
|
||||
/>
|
||||
)}
|
||||
<div className="flex justify-center">{rightOfSearch}</div>
|
||||
</div>
|
||||
)}
|
||||
<SortableTable
|
||||
data={data}
|
||||
prismaModel={prismaModel}
|
||||
|
||||
46
apps/hub/app/_components/ui/MDEditor.tsx
Normal file
46
apps/hub/app/_components/ui/MDEditor.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
'use client';
|
||||
import MDEditor from '@uiw/react-md-editor';
|
||||
import {
|
||||
FieldValues,
|
||||
Path,
|
||||
RegisterOptions,
|
||||
UseFormReturn,
|
||||
} from 'react-hook-form';
|
||||
import { cn } from '../../../helper/cn';
|
||||
|
||||
interface MarkdownEditorProps<T extends FieldValues> {
|
||||
name: Path<T>;
|
||||
form: UseFormReturn<T>;
|
||||
formOptions?: RegisterOptions<T>;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const MarkdownEditor = <T extends FieldValues>({
|
||||
name,
|
||||
label = name,
|
||||
placeholder = label,
|
||||
form,
|
||||
className,
|
||||
}: MarkdownEditorProps<T>) => {
|
||||
return (
|
||||
<label className="floating-label w-full mt-5">
|
||||
<span className="text-lg flex items-center gap-2">{label}</span>
|
||||
<div className={cn('border rounded-lg p-2 w-full', className)}>
|
||||
<MDEditor
|
||||
value={form.watch(name)}
|
||||
onChange={(value) =>
|
||||
form.setValue(name, value as any, { shouldValidate: true })
|
||||
}
|
||||
textareaProps={{ placeholder }}
|
||||
/>
|
||||
</div>
|
||||
{form.formState.errors[name] && (
|
||||
<p className="text-error">
|
||||
{form.formState.errors[name].message as string}
|
||||
</p>
|
||||
)}
|
||||
</label>
|
||||
);
|
||||
};
|
||||
@@ -23,9 +23,11 @@ export const Switch = <T extends FieldValues>({
|
||||
...inputProps
|
||||
}: InputProps<T>) => {
|
||||
return (
|
||||
<div className="form-control">
|
||||
<label className="label cursor-pointer">
|
||||
<span className={cn('label-text', className)}>{label}</span>
|
||||
<div className="form-control ">
|
||||
<label className="label cursor-pointer w-full">
|
||||
<span className={cn('label-text text-left w-full', className)}>
|
||||
{label}
|
||||
</span>
|
||||
<input type="checkbox" className="toggle" {...form.register(name)} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
const removeImports = require('next-remove-imports')();
|
||||
const nextConfig = removeImports({});
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
@@ -14,14 +14,18 @@
|
||||
"@repo/db": "*",
|
||||
"@repo/ui": "*",
|
||||
"@tanstack/react-table": "^8.20.6",
|
||||
"@uiw/react-md-editor": "^4.0.5",
|
||||
"axios": "^1.7.9",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"clsx": "^2.1.1",
|
||||
"i": "^0.3.7",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.474.0",
|
||||
"next": "15.1.4",
|
||||
"next-auth": "^4.24.11",
|
||||
"next-remove-imports": "^1.0.12",
|
||||
"npm": "^11.1.0",
|
||||
"react": "^19.0.0",
|
||||
"react-day-picker": "^9.5.1",
|
||||
"react-dom": "^19.0.0",
|
||||
|
||||
5687
package-lock.json
generated
5687
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user