Add custom inputs to commission types
This commit is contained in:
@ -11,9 +11,9 @@ import {
|
||||
} from "@/components/ui/form"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import { CommissionExtra, CommissionOption, CommissionType, CommissionTypeExtra, CommissionTypeOption } from "@/generated/prisma"
|
||||
import { CommissionCustomInput, CommissionExtra, CommissionOption, CommissionType, CommissionTypeCustomInput, CommissionTypeExtra, CommissionTypeOption } from "@/generated/prisma"
|
||||
import { commissionOrderSchema } from "@/schemas/commissionOrder"
|
||||
import { calculatePrice } from "@/utils/calculatePrice"
|
||||
import { calculatePriceRange } from "@/utils/calculatePrice"
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import Link from "next/link"
|
||||
import { useMemo, useState } from "react"
|
||||
@ -24,6 +24,7 @@ import { FileDropzone } from "./FileDropzone"
|
||||
type CommissionTypeWithRelations = CommissionType & {
|
||||
options: (CommissionTypeOption & { option: CommissionOption })[]
|
||||
extras: (CommissionTypeExtra & { extra: CommissionExtra })[]
|
||||
customInputs: (CommissionTypeCustomInput & { customInput: CommissionCustomInput })[]
|
||||
}
|
||||
|
||||
type Props = {
|
||||
@ -64,20 +65,13 @@ export function CommissionOrderForm({ types }: Props) {
|
||||
[selectedType, extraIds]
|
||||
)
|
||||
|
||||
const price = useMemo(() => {
|
||||
if (!selectedOption) return 0
|
||||
|
||||
const base = calculatePrice(selectedOption, 0)
|
||||
const extrasSum = selectedExtras.reduce(
|
||||
(sum, ext) => sum + calculatePrice(ext, base),
|
||||
0
|
||||
)
|
||||
|
||||
return base + extrasSum
|
||||
const [minPrice, maxPrice] = useMemo(() => {
|
||||
return calculatePriceRange(selectedOption, selectedExtras)
|
||||
}, [selectedOption, selectedExtras])
|
||||
|
||||
async function onSubmit(values: z.infer<typeof commissionOrderSchema>) {
|
||||
console.log("Submit:", { ...values, files })
|
||||
const { customFields, ...rest } = values
|
||||
console.log("Submit:", { ...rest, customFields, files })
|
||||
}
|
||||
|
||||
return (
|
||||
@ -173,6 +167,8 @@ export function CommissionOrderForm({ types }: Props) {
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
@ -220,6 +216,54 @@ export function CommissionOrderForm({ types }: Props) {
|
||||
)}
|
||||
/>
|
||||
|
||||
{selectedType && selectedType.customInputs.length > 0 && (
|
||||
<div className="space-y-4">
|
||||
{selectedType.customInputs.map((input) => {
|
||||
const name = `customFields.${input.customInput.name}`
|
||||
return (
|
||||
<FormField
|
||||
key={input.id}
|
||||
control={form.control}
|
||||
name={name as `customFields.${string}`}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{input.label}</FormLabel>
|
||||
<FormControl>
|
||||
{input.inputType === "textarea" ? (
|
||||
<Textarea {...field} rows={3} />
|
||||
) : input.inputType === "number" ? (
|
||||
<Input type="number" {...field} />
|
||||
) : input.inputType === "checkbox" ? (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={field.value ?? false}
|
||||
onChange={(e) => field.onChange(e.target.checked)}
|
||||
/>
|
||||
) : input.inputType === "date" ? (
|
||||
<Input type="date" {...field} />
|
||||
) : input.inputType === "select" ? (
|
||||
// Placeholder select – populate with options if needed
|
||||
<select
|
||||
{...field}
|
||||
className="border rounded px-2 py-1 w-full"
|
||||
>
|
||||
<option value="">Please select</option>
|
||||
<option value="example1">Example 1</option>
|
||||
<option value="example2">Example 2</option>
|
||||
</select>
|
||||
) : (
|
||||
<Input {...field} />
|
||||
)}
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<FormItem>
|
||||
<FormLabel>Reference Images</FormLabel>
|
||||
<FormControl>
|
||||
@ -237,7 +281,10 @@ export function CommissionOrderForm({ types }: Props) {
|
||||
</FormItem>
|
||||
|
||||
<div className="text-lg font-semibold">
|
||||
Estimated Price: €{price.toFixed(2)}
|
||||
Estimated Price:{" "}
|
||||
{minPrice === maxPrice
|
||||
? `€${minPrice.toFixed(2)}`
|
||||
: `€${minPrice.toFixed(2)} – €${maxPrice.toFixed(2)}`}
|
||||
</div>
|
||||
|
||||
<div className="text-muted-foreground">
|
||||
|
||||
@ -22,6 +22,11 @@ export default function TopNav() {
|
||||
<Link href="/tos">Terms of Service</Link>
|
||||
</NavigationMenuLink>
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem>
|
||||
<NavigationMenuLink asChild className={navigationMenuTriggerStyle()}>
|
||||
<Link href="/todo">todo (temp)</Link>
|
||||
</NavigationMenuLink>
|
||||
</NavigationMenuItem>
|
||||
</NavigationMenuList>
|
||||
</NavigationMenu>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user