First version

This commit is contained in:
Sebastien Castiel
2023-12-05 17:39:05 -05:00
parent 1fd6e48807
commit ed55c696cd
41 changed files with 8305 additions and 468 deletions

View File

@@ -0,0 +1,186 @@
'use client'
import { Button } from '@/components/ui/button'
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card'
import { Checkbox } from '@/components/ui/checkbox'
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { getExpense, getGroup } from '@/lib/api'
import { ExpenseFormValues, expenseFormSchema } from '@/lib/schemas'
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
export type Props = {
group: NonNullable<Awaited<ReturnType<typeof getGroup>>>
expense?: NonNullable<Awaited<ReturnType<typeof getExpense>>>
onSubmit: (values: ExpenseFormValues) => void
}
export function ExpenseForm({ group, expense, onSubmit }: Props) {
const form = useForm<ExpenseFormValues>({
resolver: zodResolver(expenseFormSchema),
defaultValues: expense
? {
title: expense.title,
amount: expense.amount,
paidBy: expense.paidById,
paidFor: expense.paidFor.map(({ participantId }) => participantId),
}
: { title: '', amount: 0, paidFor: [] },
})
return (
<Form {...form}>
<form onSubmit={form.handleSubmit((values) => onSubmit(values))}>
<Card>
<CardHeader>
<CardTitle>Expense information</CardTitle>
</CardHeader>
<CardContent className="grid grid-cols-2 gap-6">
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>Expense title</FormLabel>
<FormControl>
<Input placeholder="Monday evening restaurant" {...field} />
</FormControl>
<FormDescription>
Enter a description for the expense.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="paidBy"
render={({ field }) => (
<FormItem>
<FormLabel>Paid by</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value}
>
<SelectTrigger>
<SelectValue placeholder="Select a participant" />
</SelectTrigger>
<SelectContent>
{group.participants.map(({ id, name }) => (
<SelectItem key={id} value={id}>
{name}
</SelectItem>
))}
</SelectContent>
</Select>
<FormDescription>
Select the participant who paid the expense.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="amount"
render={({ field }) => (
<FormItem>
<FormLabel>Amount</FormLabel>
<FormControl>
<Input
type="number"
min={0.01}
step={0.01}
placeholder="0.00"
{...field}
/>
</FormControl>
<FormDescription>Enter the expense amount.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="paidFor"
render={() => (
<FormItem>
<div className="mb-4">
<FormLabel>Paid for</FormLabel>
<FormDescription>
Select who the expense was paid for.
</FormDescription>
</div>
{group.participants.map(({ id, name }) => (
<FormField
key={id}
control={form.control}
name="paidFor"
render={({ field }) => {
return (
<FormItem
key={id}
className="flex flex-row items-start space-x-3 space-y-0"
>
<FormControl>
<Checkbox
checked={field.value?.includes(id)}
onCheckedChange={(checked) => {
return checked
? field.onChange([...field.value, id])
: field.onChange(
field.value?.filter(
(value) => value !== id,
),
)
}}
/>
</FormControl>
<FormLabel className="text-sm font-normal">
{name}
</FormLabel>
</FormItem>
)
}}
/>
))}
<FormMessage />
</FormItem>
)}
/>
</CardContent>
<CardFooter>
<Button variant="secondary" type="submit">
Submit
</Button>
</CardFooter>
</Card>
</form>
</Form>
)
}