diff --git a/package-lock.json b/package-lock.json index 18cf248..f5d2395 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "dependencies": { "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@hookform/resolvers": "^5.1.1", "@prisma/client": "^6.11.1", @@ -17,12 +19,15 @@ "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-navigation-menu": "^1.2.13", + "@radix-ui/react-popover": "^1.1.14", "@radix-ui/react-progress": "^1.1.7", "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-slider": "^1.3.5", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cmdk": "^1.1.1", "lucide-react": "^0.525.0", "next": "15.3.5", "next-auth": "^5.0.0-beta.29", @@ -30,6 +35,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-hook-form": "^7.59.0", + "sonner": "^2.0.6", "tailwind-merge": "^3.3.1", "zod": "^3.25.73" }, @@ -132,6 +138,34 @@ "react-dom": ">=16.8.0" } }, + "node_modules/@dnd-kit/modifiers": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz", + "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", + "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, "node_modules/@dnd-kit/utilities": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", @@ -1589,6 +1623,43 @@ } } }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz", + "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", @@ -1790,6 +1861,39 @@ } } }, + "node_modules/@radix-ui/react-slider": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.5.tgz", + "integrity": "sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", @@ -3405,6 +3509,22 @@ "node": ">=6" } }, + "node_modules/cmdk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", + "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-id": "^1.1.0", + "@radix-ui/react-primitive": "^2.0.2" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -6876,6 +6996,16 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/sonner": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.6.tgz", + "integrity": "sha512-yHFhk8T/DK3YxjFQXIrcHT1rGEeTLliVzWbO0xN8GberVun2RiBnxAjXAYpZrqwEVHBG9asI/Li8TAAhN9m59Q==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/package.json b/package.json index a57486b..278a414 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ }, "dependencies": { "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@hookform/resolvers": "^5.1.1", "@prisma/client": "^6.11.1", @@ -18,12 +20,15 @@ "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-navigation-menu": "^1.2.13", + "@radix-ui/react-popover": "^1.1.14", "@radix-ui/react-progress": "^1.1.7", "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-slider": "^1.3.5", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cmdk": "^1.1.1", "lucide-react": "^0.525.0", "next": "15.3.5", "next-auth": "^5.0.0-beta.29", @@ -31,6 +36,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-hook-form": "^7.59.0", + "sonner": "^2.0.6", "tailwind-merge": "^3.3.1", "zod": "^3.25.73" }, diff --git a/prisma/migrations/20250705193450_commision_types/migration.sql b/prisma/migrations/20250705193450_commision_types/migration.sql new file mode 100644 index 0000000..633aeb0 --- /dev/null +++ b/prisma/migrations/20250705193450_commision_types/migration.sql @@ -0,0 +1,127 @@ +/* + Warnings: + + - You are about to drop the column `active` on the `CommissionType` table. All the data in the column will be lost. + - You are about to drop the column `basePrice` on the `CommissionType` table. All the data in the column will be lost. + - You are about to drop the column `deliveryEst` on the `CommissionType` table. All the data in the column will be lost. + - You are about to drop the column `tags` on the `CommissionType` table. All the data in the column will be lost. + - You are about to drop the column `title` on the `CommissionType` table. All the data in the column will be lost. + - You are about to drop the `Artwork` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `CommissionRequest` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Preferences` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `PresentationGroup` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `TOS` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `User` table. If the table is not empty, all the data it contains will be lost. + - Added the required column `name` to the `CommissionType` table without a default value. This is not possible if the table is not empty. + - Added the required column `updatedAt` to the `CommissionType` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "Artwork" DROP CONSTRAINT "Artwork_groupId_fkey"; + +-- DropForeignKey +ALTER TABLE "CommissionRequest" DROP CONSTRAINT "CommissionRequest_typeId_fkey"; + +-- AlterTable +ALTER TABLE "CommissionType" DROP COLUMN "active", +DROP COLUMN "basePrice", +DROP COLUMN "deliveryEst", +DROP COLUMN "tags", +DROP COLUMN "title", +ADD COLUMN "name" TEXT NOT NULL, +ADD COLUMN "sortIndex" INTEGER NOT NULL DEFAULT 0, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL; + +-- DropTable +DROP TABLE "Artwork"; + +-- DropTable +DROP TABLE "CommissionRequest"; + +-- DropTable +DROP TABLE "Preferences"; + +-- DropTable +DROP TABLE "PresentationGroup"; + +-- DropTable +DROP TABLE "TOS"; + +-- DropTable +DROP TABLE "User"; + +-- DropEnum +DROP TYPE "RequestStatus"; + +-- DropEnum +DROP TYPE "Role"; + +-- CreateTable +CREATE TABLE "CommissionOption" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "sortIndex" INTEGER NOT NULL DEFAULT 0, + "name" TEXT NOT NULL, + "description" TEXT, + + CONSTRAINT "CommissionOption_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "CommissionExtra" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "sortIndex" INTEGER NOT NULL DEFAULT 0, + "name" TEXT NOT NULL, + "description" TEXT, + + CONSTRAINT "CommissionExtra_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "CommissionTypeOption" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "typeId" TEXT NOT NULL, + "optionId" TEXT NOT NULL, + "priceRange" TEXT, + "pricePercent" DOUBLE PRECISION, + "price" DOUBLE PRECISION, + + CONSTRAINT "CommissionTypeOption_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "CommissionExtraOption" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "typeId" TEXT NOT NULL, + "extraId" TEXT NOT NULL, + "priceRange" TEXT, + "pricePercent" DOUBLE PRECISION, + "price" DOUBLE PRECISION, + + CONSTRAINT "CommissionExtraOption_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "CommissionTypeOption_typeId_optionId_key" ON "CommissionTypeOption"("typeId", "optionId"); + +-- CreateIndex +CREATE UNIQUE INDEX "CommissionExtraOption_typeId_extraId_key" ON "CommissionExtraOption"("typeId", "extraId"); + +-- AddForeignKey +ALTER TABLE "CommissionTypeOption" ADD CONSTRAINT "CommissionTypeOption_typeId_fkey" FOREIGN KEY ("typeId") REFERENCES "CommissionType"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "CommissionTypeOption" ADD CONSTRAINT "CommissionTypeOption_optionId_fkey" FOREIGN KEY ("optionId") REFERENCES "CommissionOption"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "CommissionExtraOption" ADD CONSTRAINT "CommissionExtraOption_typeId_fkey" FOREIGN KEY ("typeId") REFERENCES "CommissionType"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "CommissionExtraOption" ADD CONSTRAINT "CommissionExtraOption_extraId_fkey" FOREIGN KEY ("extraId") REFERENCES "CommissionExtra"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20250705194630_commision_types/migration.sql b/prisma/migrations/20250705194630_commision_types/migration.sql new file mode 100644 index 0000000..97f2094 --- /dev/null +++ b/prisma/migrations/20250705194630_commision_types/migration.sql @@ -0,0 +1,37 @@ +/* + Warnings: + + - You are about to drop the `CommissionExtraOption` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "CommissionExtraOption" DROP CONSTRAINT "CommissionExtraOption_extraId_fkey"; + +-- DropForeignKey +ALTER TABLE "CommissionExtraOption" DROP CONSTRAINT "CommissionExtraOption_typeId_fkey"; + +-- DropTable +DROP TABLE "CommissionExtraOption"; + +-- CreateTable +CREATE TABLE "CommissionTypeExtra" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "typeId" TEXT NOT NULL, + "extraId" TEXT NOT NULL, + "priceRange" TEXT, + "pricePercent" DOUBLE PRECISION, + "price" DOUBLE PRECISION, + + CONSTRAINT "CommissionTypeExtra_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "CommissionTypeExtra_typeId_extraId_key" ON "CommissionTypeExtra"("typeId", "extraId"); + +-- AddForeignKey +ALTER TABLE "CommissionTypeExtra" ADD CONSTRAINT "CommissionTypeExtra_typeId_fkey" FOREIGN KEY ("typeId") REFERENCES "CommissionType"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "CommissionTypeExtra" ADD CONSTRAINT "CommissionTypeExtra_extraId_fkey" FOREIGN KEY ("extraId") REFERENCES "CommissionExtra"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20250705212806_commision_types/migration.sql b/prisma/migrations/20250705212806_commision_types/migration.sql new file mode 100644 index 0000000..1a8eb31 --- /dev/null +++ b/prisma/migrations/20250705212806_commision_types/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "CommissionTypeExtra" ADD COLUMN "sortIndex" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "CommissionTypeOption" ADD COLUMN "sortIndex" INTEGER NOT NULL DEFAULT 0; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6c1e4e1..3c35534 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,83 +14,161 @@ datasource db { url = env("DATABASE_URL") } -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()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + name String + + description String? + + options CommissionTypeOption[] + extras CommissionTypeExtra[] } + +model CommissionOption { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + name String + + description String? + + types CommissionTypeOption[] +} + +model CommissionExtra { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + name String + + description String? + + types CommissionTypeExtra[] +} + +model CommissionTypeOption { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + typeId String + optionId String + + priceRange String? + pricePercent Float? + price Float? + + type CommissionType @relation(fields: [typeId], references: [id]) + option CommissionOption @relation(fields: [optionId], references: [id]) + + @@unique([typeId, optionId]) +} + +model CommissionTypeExtra { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + typeId String + extraId String + + priceRange String? + pricePercent Float? + price Float? + + type CommissionType @relation(fields: [typeId], references: [id]) + extra CommissionExtra @relation(fields: [extraId], references: [id]) + + @@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()) +// } diff --git a/src/actions/items/commissions/types/newType.ts b/src/actions/items/commissions/types/newType.ts new file mode 100644 index 0000000..5a399a7 --- /dev/null +++ b/src/actions/items/commissions/types/newType.ts @@ -0,0 +1,58 @@ +"use server" + +import prisma from "@/lib/prisma" +import { commissionTypeSchema } from "@/schemas/commissionType" + +export async function createCommissionOption(data: { name: string }) { + return await prisma.commissionOption.create({ + data: { + name: data.name, + description: "", + }, + }) +} + +export async function createCommissionExtra(data: { name: string }) { + return await prisma.commissionExtra.create({ + data: { + name: data.name, + description: "", + }, + }) +} + +export async function createCommissionType(formData: commissionTypeSchema) { + const parsed = commissionTypeSchema.safeParse(formData) + + if (!parsed.success) { + console.error("Validation failed", parsed.error) + throw new Error("Invalid input") + } + + const data = parsed.data + + const created = await prisma.commissionType.create({ + data: { + name: data.name, + description: data.description, + options: { + create: data.options?.map((opt) => ({ + option: { connect: { id: opt.optionId } }, + price: opt.price, + pricePercent: opt.pricePercent, + priceRange: opt.priceRange, + })) || [], + }, + extras: { + create: data.extras?.map((ext) => ({ + extra: { connect: { id: ext.extraId } }, + price: ext.price, + pricePercent: ext.pricePercent, + priceRange: ext.priceRange, + })) || [], + }, + }, + }) + + return created +} \ No newline at end of file diff --git a/src/app/items/commissions/types/new/page.tsx b/src/app/items/commissions/types/new/page.tsx new file mode 100644 index 0000000..9c50035 --- /dev/null +++ b/src/app/items/commissions/types/new/page.tsx @@ -0,0 +1,21 @@ +import NewTypeForm from "@/components/items/commissions/types/NewTypeForm"; +import prisma from "@/lib/prisma"; + +export default async function CommissionTypesNewPage() { + const options = await prisma.commissionOption.findMany({ + orderBy: [{ sortIndex: "asc" }, { name: "asc" }], + }); + const extras = await prisma.commissionExtra.findMany({ + orderBy: [{ sortIndex: "asc" }, { name: "asc" }], + }) + + + return ( +
No types found.
} +