modify commission ordering form
This commit is contained in:
@ -34,7 +34,7 @@ model CommissionOption {
|
||||
updatedAt DateTime @updatedAt
|
||||
sortIndex Int @default(0)
|
||||
|
||||
name String @unique
|
||||
name String
|
||||
|
||||
description String?
|
||||
|
||||
@ -47,7 +47,7 @@ model CommissionExtra {
|
||||
updatedAt DateTime @updatedAt
|
||||
sortIndex Int @default(0)
|
||||
|
||||
name String @unique
|
||||
name String
|
||||
|
||||
description String?
|
||||
|
||||
@ -91,84 +91,3 @@ model CommissionTypeExtra {
|
||||
|
||||
@@unique([typeId, extraId])
|
||||
}
|
||||
|
||||
// model User {
|
||||
// id String @id @default(cuid())
|
||||
// email String @unique
|
||||
// name String?
|
||||
// role Role @default(ADMIN)
|
||||
// createdAt DateTime @default(now())
|
||||
// }
|
||||
|
||||
// enum Role {
|
||||
// ADMIN
|
||||
// ARTIST
|
||||
// }
|
||||
|
||||
// model CommissionType {
|
||||
// id String @id @default(cuid())
|
||||
// title String
|
||||
// description String?
|
||||
// basePrice Float
|
||||
// deliveryEst String? // e.g. "2 weeks"
|
||||
// tags String[] // e.g. shaded, sketch, full-body
|
||||
// active Boolean @default(true)
|
||||
// createdAt DateTime @default(now())
|
||||
// CommissionRequest CommissionRequest[]
|
||||
// }
|
||||
|
||||
// model CommissionRequest {
|
||||
// id String @id @default(cuid())
|
||||
// name String
|
||||
// email String
|
||||
// message String
|
||||
// typeId String
|
||||
// status RequestStatus @default(PENDING)
|
||||
// createdAt DateTime @default(now())
|
||||
|
||||
// type CommissionType @relation(fields: [typeId], references: [id])
|
||||
// }
|
||||
|
||||
// enum RequestStatus {
|
||||
// PENDING
|
||||
// ACCEPTED
|
||||
// IN_PROGRESS
|
||||
// DONE
|
||||
// REJECTED
|
||||
// }
|
||||
|
||||
// model Artwork {
|
||||
// id String @id @default(cuid())
|
||||
// title String
|
||||
// imageUrl String
|
||||
// description String?
|
||||
// tags String[]
|
||||
// formats String[]
|
||||
// isPublic Boolean @default(true)
|
||||
// groupId String?
|
||||
// createdAt DateTime @default(now())
|
||||
|
||||
// group PresentationGroup? @relation(fields: [groupId], references: [id])
|
||||
// }
|
||||
|
||||
// model PresentationGroup {
|
||||
// id String @id @default(cuid())
|
||||
// name String
|
||||
// description String?
|
||||
// createdAt DateTime @default(now())
|
||||
// Artwork Artwork[]
|
||||
// }
|
||||
|
||||
// model Preferences {
|
||||
// id String @id @default(cuid())
|
||||
// commissionOpen Boolean @default(true)
|
||||
// defaultDelivery String? // e.g. "7 days"
|
||||
// autoReplyMessage String?
|
||||
// notifyByEmail Boolean @default(true)
|
||||
// }
|
||||
|
||||
// model TOS {
|
||||
// id String @id @default(cuid())
|
||||
// content String // Markdown or rich text
|
||||
// createdAt DateTime @default(now())
|
||||
// }
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { CommissionExtra, CommissionOption, CommissionType, CommissionTypeExtra, CommissionTypeOption } from "@/generated/prisma"
|
||||
// import { useState } from "react"
|
||||
import { Badge } from "../ui/badge"
|
||||
// import { Badge } from "../ui/badge"
|
||||
|
||||
type CommissionTypeWithItems = CommissionType & {
|
||||
options: (CommissionTypeOption & {
|
||||
@ -85,13 +85,13 @@ export function CommissionCard({ commission }: { commission: CommissionTypeWithI
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{/* <div className="flex flex-wrap gap-2">
|
||||
{commission.extras.map((extra) => (
|
||||
<Badge variant="outline" key={extra.id}>
|
||||
{extra.extra?.name}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</div> */}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
@ -77,7 +77,6 @@ export function CommissionOrderForm({ types }: Props) {
|
||||
|
||||
async function onSubmit(values: z.infer<typeof commissionOrderSchema>) {
|
||||
console.log("Submit:", { ...values, files })
|
||||
// TODO: send to server
|
||||
}
|
||||
|
||||
return (
|
||||
@ -220,12 +219,23 @@ export function CommissionOrderForm({ types }: Props) {
|
||||
)}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<FormItem>
|
||||
<FormLabel>Reference Images</FormLabel>
|
||||
<FileDropzone onFilesSelected={(f: File[]) => setFiles(f)} />
|
||||
<FormControl>
|
||||
<div className="space-y-2">
|
||||
<FileDropzone onFilesSelected={setFiles} />
|
||||
{files.length > 0 && (
|
||||
<ul className="list-disc pl-4 text-sm text-muted-foreground">
|
||||
{files.map((file, i) => (
|
||||
<li key={i}>{file.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
|
||||
<div className="text-xl font-semibold">
|
||||
<div className="text-lg font-semibold">
|
||||
Estimated Price: €{price.toFixed(2)}
|
||||
</div>
|
||||
|
||||
|
@ -1,24 +1,65 @@
|
||||
// components/form/FileDropzone.tsx
|
||||
"use client"
|
||||
import { useCallback } from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useCallback, useRef, useState } from "react"
|
||||
|
||||
export function FileDropzone({
|
||||
onFilesSelected,
|
||||
}: {
|
||||
onFilesSelected: (files: File[]) => void
|
||||
}) {
|
||||
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files) {
|
||||
onFilesSelected(Array.from(e.target.files))
|
||||
const [isDragging, setIsDragging] = useState(false)
|
||||
const inputRef = useRef<HTMLInputElement | null>(null)
|
||||
|
||||
const handleFiles = (files: FileList | null) => {
|
||||
if (files) {
|
||||
onFilesSelected(Array.from(files))
|
||||
}
|
||||
}, [onFilesSelected])
|
||||
}
|
||||
|
||||
const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault()
|
||||
setIsDragging(false)
|
||||
handleFiles(e.dataTransfer.files)
|
||||
}
|
||||
|
||||
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault()
|
||||
setIsDragging(true)
|
||||
}
|
||||
|
||||
const handleDragLeave = () => {
|
||||
setIsDragging(false)
|
||||
}
|
||||
|
||||
const handleChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
handleFiles(e.target.files)
|
||||
},
|
||||
[onFilesSelected]
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => inputRef.current?.click()}
|
||||
onDrop={handleDrop}
|
||||
onDragOver={handleDragOver}
|
||||
onDragLeave={handleDragLeave}
|
||||
className={cn(
|
||||
"w-full border-2 border-dashed rounded-md p-6 text-center cursor-pointer transition-colors",
|
||||
isDragging ? "border-primary bg-muted" : "border-muted-foreground/30"
|
||||
)}
|
||||
>
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="file"
|
||||
multiple
|
||||
onChange={handleChange}
|
||||
className="border p-2 rounded-md"
|
||||
className="hidden"
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Drag & drop images here or click to upload
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user