Now that we have created a custom hook to write data to Firestore, we need to build a form to create a new task
.
The example below is straightforward:
- We have a form with two input fields
- When the form is submitted, we read the data using
FormData
- Finally, we add the document using the callback returned by the hook
useCreateTask
components/tasks/CreateTaskForm.tsx
'use client';
import type { FormEventHandler } from 'react';
import { useCallback } from 'react';
import { useRouter } from 'next/navigation';
import toaster from 'react-hot-toast';
import TextField from '~/core/ui/TextField';
import Button from '~/core/ui/Button';
import If from '~/core/ui/If';
import useCreateTaskMutation from '~/lib/tasks/hooks/use-create-task';
import useCurrentOrganization from '~/lib/organizations/hooks/use-current-organization';
const CreateTaskForm = () => {
const { trigger, isMutating } = useCreateTaskMutation();
const router = useRouter();
const organization = useCurrentOrganization();
const organizationId = organization?.id as number;
const onCreateTask: FormEventHandler<HTMLFormElement> = useCallback(
async (event) => {
event.preventDefault();
const target = event.currentTarget;
const data = new FormData(target);
const name = data.get('name') as string;
const dueDate = (data.get('dueDate') as string) || getDefaultDueDate();
if (name.trim().length < 3) {
toaster.error('Task name must be at least 3 characters long');
return;
}
const task = {
organizationId,
name,
dueDate,
done: false,
};
// create task
await trigger(task);
// redirect to /tasks
return router.push(`/tasks`);
},
[router, trigger, organizationId]
);
return (
<form onSubmit={onCreateTask}>
<div className={'flex flex-col space-y-2'}>
<TextField.Label>
Name
<TextField.Input
required
name={'name'}
placeholder={'ex. Launch on IndieHackers'}
/>
<TextField.Hint>Hint: whatever you do, ship!</TextField.Hint>
</TextField.Label>
<TextField.Label>
Due date
<TextField.Input name={'dueDate'} type={'date'} />
</TextField.Label>
<div
className={
'flex flex-col space-y-2 md:flex-row md:space-y-0 md:space-x-2'
}
>
<Button loading={isMutating}>
<If
condition={isMutating}
fallback={<>Create Task</>}
>
Creating Task...
</If>
</Button>
<Button color={'transparent'} href={'/tasks'}>
Go back
</Button>
</div>
</div>
</form>
);
};
function getDefaultDueDate() {
const date = new Date();
date.setDate(date.getDate() + 1);
date.setHours(23, 59, 59);
return date.toDateString();
}
export default CreateTaskForm;