feat: create db-entry on event-form-submit

This commit is contained in:
micha 2025-06-14 15:54:06 +02:00
parent 411386b51e
commit 5f1a32cac9
2 changed files with 138 additions and 26 deletions

View file

@ -1,22 +1,85 @@
'use client';
import React from 'react';
import LabeledInput from '@/components/labeled-input';
import { Button } from '@/components/custom-ui/button';
import Logo from '../logo';
import TimePicker from '../time-picker';
import { Label } from '../ui/label';
import {
useGetApiUserMe,
usePostApiEvent,
} from '@/generated/api/default/default';
type eventFormProps = {
type?: 'create' | 'edit';
};
export default function EventForm({ type = 'edit' }: eventFormProps) {
const { mutate: createEvent, status, isSuccess, error } = usePostApiEvent();
const { data, isLoading } = useGetApiUserMe();
const [startDate, setStartDate] = React.useState<Date | undefined>();
const [startTime, setStartTime] = React.useState<string>('12:00');
const [endDate, setEndDate] = React.useState<Date | undefined>();
const [endTime, setEndTime] = React.useState<string>('13:00');
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const formData = new FormData(e.currentTarget);
function combine(date?: Date, time?: string) {
if (!date || !time) return undefined;
const [hours, minutes] = time.split(':');
const d = new Date(date);
d.setHours(Number(hours), Number(minutes), 0, 0);
return d;
}
const start = combine(startDate, startTime);
const end = combine(endDate, endTime);
//validate form data
if (!formData.get('eventName')) {
alert('Event name is required.');
return;
}
if (!start || !end) {
alert('Please provide both start and end date/time.');
return;
} else if (start >= end) {
alert('End time must be after start time.');
return;
}
const data = {
title: formData.get('eventName') as string,
description: formData.get('eventDescription') as string,
start_time: start.toISOString(),
end_time: end.toISOString(),
location: formData.get('eventLocation') as string,
created_at: formData.get('createdAt') as string,
updated_at: formData.get('updatedAt') as string,
organiser: formData.get('organiser') as string,
};
console.log('Submitting event data:', data);
createEvent({ data });
}
// Calculate values for organiser, created, and updated
const organiserValue = isLoading
? 'Loading...'
: data?.data.user?.name || 'Unknown User';
const createdAtValue = new Date().toISOString();
const updatedAtValue = new Date().toISOString();
// Format date for display
const createdAtDisplay = new Date(createdAtValue).toLocaleDateString();
const updatedAtDisplay = new Date(updatedAtValue).toLocaleDateString();
return (
<form
className='flex flex-col gap-5 w-full'
action={async (formData) => {
'use server';
console.log('Form submitted with data:', formData);
}}
>
<form className='flex flex-col gap-5 w-full' onSubmit={handleSubmit}>
<div className='grid grid-row-start:auto gap-8'>
<div className='h-full mt-0 ml-2 mb-16 flex items-center justify-between max-sm:flex-col max-sm:mb-6 max-sm:mt-10'>
<div className='w-[50px]'>
@ -35,10 +98,24 @@ export default function EventForm({ type = 'edit' }: eventFormProps) {
</div>
<div className='grid grid-cols-4 gap-4 h-full w-full max-lg:grid-cols-2 max-sm:grid-cols-1'>
<div>
<TimePicker dateLabel='start Time' timeLabel='&nbsp;' />
<TimePicker
dateLabel='start Time'
timeLabel='&nbsp;'
date={startDate}
setDate={setStartDate}
time={startTime}
setTime={setStartTime}
/>
</div>
<div>
<TimePicker dateLabel='end Time' timeLabel='&nbsp;' />
<TimePicker
dateLabel='end Time'
timeLabel='&nbsp;'
date={endDate}
setDate={setEndDate}
time={endTime}
setTime={setEndTime}
/>
</div>
<div className='w-54'>
<LabeledInput
@ -50,14 +127,16 @@ export default function EventForm({ type = 'edit' }: eventFormProps) {
</div>
<div className='flex flex-col gap-4'>
<div className='flex flex-row gap-2'>
<Label>created:</Label>
<Label className='w-[70px]'>created:</Label>
<Label className='text-[var(--color-neutral-300)]'>
2023-10-01
{createdAtDisplay}
</Label>
</div>
<div className='flex flex-row gap-2'>
<Label>updated:</Label>
<p className='text-[var(--color-neutral-300)]'>2023-10-01</p>
<Label className='w-[70px]'>updated:</Label>
<p className='text-[var(--color-neutral-300)]'>
{updatedAtDisplay}
</p>
</div>
</div>
</div>
@ -67,7 +146,7 @@ export default function EventForm({ type = 'edit' }: eventFormProps) {
<div className='flex flex-row gap-2'>
<Label>Organiser:</Label>
<Label className='text-[var(--color-neutral-300)]'>
[Username here]
{organiserValue}
</Label>
</div>
</div>
@ -82,7 +161,8 @@ export default function EventForm({ type = 'edit' }: eventFormProps) {
</div>
</div>
<div className='h-full w-full'>
<Label>Participants here</Label>
<Label>Participants here</Label>{' '}
{/* TODO: add participants input */}
</div>
</div>
@ -91,15 +171,43 @@ export default function EventForm({ type = 'edit' }: eventFormProps) {
<Button type='button' variant='secondary'>
cancel
</Button>
{/* TODO: add onClick handler to cancel cancel */}
</div>
<div className='w-[20%] grid max-sm:w-[40%]'>
<Button type='submit' variant='primary'>
save event
<Button
type='submit'
variant='primary'
disabled={status === 'pending'}
>
{status === 'pending' ? 'Saving...' : 'save event'}
</Button>
</div>
</div>
{isSuccess && <p>Event created!</p>}
{error && <p className='text-red-500'>Error: {error.message}</p>}
</div>
{/* Hidden inputs for formData */}
<input
type='hidden'
name='startTime'
value={
startDate && startTime
? `${startDate.toISOString().split('T')[0]}T${startTime}`
: ''
}
/>
<input
type='hidden'
name='endTime'
value={
endDate && endTime
? `${endDate.toISOString().split('T')[0]}T${endTime}`
: ''
}
/>
<input type='hidden' name='organiser' value={organiserValue} />
<input type='hidden' name='createdAt' value={createdAtValue} />
<input type='hidden' name='updatedAt' value={updatedAtValue} />
</form>
);
}

View file

@ -16,12 +16,19 @@ import {
export default function TimePicker({
dateLabel = 'Date',
timeLabel = 'Time',
date,
setDate,
time,
setTime,
}: {
dateLabel?: string;
timeLabel?: string;
date?: Date;
setDate?: (date: Date | undefined) => void;
time?: string;
setTime?: (time: string) => void;
}) {
const [open, setOpen] = React.useState(false);
const [date, setDate] = React.useState<Date | undefined>(undefined);
return (
<div className='flex gap-4'>
@ -45,8 +52,8 @@ export default function TimePicker({
mode='single'
selected={date}
captionLayout='dropdown'
onSelect={(date) => {
setDate(date);
onSelect={(d) => {
setDate?.(d);
setOpen(false);
}}
modifiers={{
@ -71,11 +78,8 @@ export default function TimePicker({
type='time'
id='time'
step='60'
defaultValue={new Date().toLocaleTimeString('en-GB', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
})}
value={time}
onChange={(e) => setTime?.(e.target.value)}
className='bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
/>
</div>