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)} />
 | 
			
		||||
        </div>
 | 
			
		||||
          <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 (
 | 
			
		||||
    <input
 | 
			
		||||
      type="file"
 | 
			
		||||
      multiple
 | 
			
		||||
      onChange={handleChange}
 | 
			
		||||
      className="border p-2 rounded-md"
 | 
			
		||||
    />
 | 
			
		||||
    <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="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