310 lines
9.5 KiB
TypeScript
310 lines
9.5 KiB
TypeScript
'use client';
|
|
|
|
import { useRouter } from 'next/navigation';
|
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { useAction } from 'next-safe-action/hooks';
|
|
import { useForm } from 'react-hook-form';
|
|
|
|
import { Button } from '@kit/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card';
|
|
import {
|
|
Form,
|
|
FormControl,
|
|
FormField,
|
|
FormItem,
|
|
FormLabel,
|
|
FormMessage,
|
|
} from '@kit/ui/form';
|
|
import { Input } from '@kit/ui/input';
|
|
import { toast } from '@kit/ui/sonner';
|
|
|
|
import { CreateCourseSchema } from '../schema/course.schema';
|
|
import { createCourse } from '../server/actions/course-actions';
|
|
|
|
interface Props {
|
|
accountId: string;
|
|
account: string;
|
|
}
|
|
|
|
export function CreateCourseForm({ accountId, account }: Props) {
|
|
const router = useRouter();
|
|
const form = useForm({
|
|
resolver: zodResolver(CreateCourseSchema),
|
|
defaultValues: {
|
|
accountId,
|
|
courseNumber: '',
|
|
name: '',
|
|
description: '',
|
|
startDate: '',
|
|
endDate: '',
|
|
fee: 0,
|
|
reducedFee: 0,
|
|
capacity: 20,
|
|
minParticipants: 5,
|
|
status: 'planned' as const,
|
|
registrationDeadline: '',
|
|
notes: '',
|
|
},
|
|
});
|
|
|
|
const { execute, isPending } = useAction(createCourse, {
|
|
onSuccess: ({ data }) => {
|
|
if (data?.success) {
|
|
toast.success('Kurs erfolgreich erstellt');
|
|
router.push(`/home/${account}/courses`);
|
|
}
|
|
},
|
|
onError: ({ error }) => {
|
|
toast.error(error.serverError ?? 'Fehler beim Erstellen des Kurses');
|
|
},
|
|
});
|
|
|
|
return (
|
|
<Form {...form}>
|
|
<form
|
|
onSubmit={form.handleSubmit((data) => execute(data))}
|
|
className="space-y-6"
|
|
>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Grunddaten</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
<FormField
|
|
control={form.control}
|
|
name="courseNumber"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Kursnummer</FormLabel>
|
|
<FormControl>
|
|
<Input {...field} />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<FormField
|
|
control={form.control}
|
|
name="name"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Kursname *</FormLabel>
|
|
<FormControl>
|
|
<Input {...field} />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<div className="sm:col-span-2">
|
|
<FormField
|
|
control={form.control}
|
|
name="description"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Beschreibung</FormLabel>
|
|
<FormControl>
|
|
<textarea
|
|
{...field}
|
|
className="border-input bg-background flex min-h-[80px] w-full rounded-md border px-3 py-2 text-sm"
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Zeitplan</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
|
<FormField
|
|
control={form.control}
|
|
name="startDate"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Startdatum</FormLabel>
|
|
<FormControl>
|
|
<Input type="date" {...field} />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<FormField
|
|
control={form.control}
|
|
name="endDate"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Enddatum</FormLabel>
|
|
<FormControl>
|
|
<Input type="date" {...field} />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<FormField
|
|
control={form.control}
|
|
name="registrationDeadline"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Anmeldeschluss</FormLabel>
|
|
<FormControl>
|
|
<Input type="date" {...field} />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Kapazität</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
<FormField
|
|
control={form.control}
|
|
name="capacity"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Max. Teilnehmer</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
type="number"
|
|
min={1}
|
|
{...field}
|
|
onChange={(e) => field.onChange(Number(e.target.value))}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<FormField
|
|
control={form.control}
|
|
name="minParticipants"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Min. Teilnehmer</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
type="number"
|
|
min={0}
|
|
{...field}
|
|
onChange={(e) => field.onChange(Number(e.target.value))}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<FormField
|
|
control={form.control}
|
|
name="fee"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Gebühr (€)</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
type="number"
|
|
min={0}
|
|
step="0.01"
|
|
{...field}
|
|
onChange={(e) => field.onChange(Number(e.target.value))}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<FormField
|
|
control={form.control}
|
|
name="reducedFee"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Ermäßigte Gebühr (€)</FormLabel>
|
|
<FormControl>
|
|
<Input
|
|
type="number"
|
|
min={0}
|
|
step="0.01"
|
|
{...field}
|
|
onChange={(e) => field.onChange(Number(e.target.value))}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Status</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
<FormField
|
|
control={form.control}
|
|
name="status"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Kursstatus</FormLabel>
|
|
<FormControl>
|
|
<select
|
|
{...field}
|
|
className="border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm"
|
|
>
|
|
<option value="planned">Geplant</option>
|
|
<option value="open">Offen</option>
|
|
<option value="running">Laufend</option>
|
|
<option value="completed">Abgeschlossen</option>
|
|
<option value="cancelled">Abgesagt</option>
|
|
</select>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<div className="sm:col-span-1">
|
|
<FormField
|
|
control={form.control}
|
|
name="notes"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Notizen</FormLabel>
|
|
<FormControl>
|
|
<textarea
|
|
{...field}
|
|
className="border-input bg-background flex min-h-[80px] w-full rounded-md border px-3 py-2 text-sm"
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<div className="flex justify-end gap-2">
|
|
<Button type="button" variant="outline" onClick={() => router.back()}>
|
|
Abbrechen
|
|
</Button>
|
|
<Button type="submit" disabled={isPending}>
|
|
{isPending ? 'Wird erstellt...' : 'Kurs erstellen'}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</Form>
|
|
);
|
|
}
|