diff --git a/ToDo.md b/ToDo.md new file mode 100644 index 0000000..9f4daca --- /dev/null +++ b/ToDo.md @@ -0,0 +1,126 @@ +# ToDo List + +## ✅ Commission System TODO + +### 🎨 Commission Request Form +- [x] Commission order form UI +- [ ] Form submission logic +- [ ] File upload with storage (e.g. MinIO) +- [ ] Store form data in Prisma +- [ ] Confirmation / success page after submission +- [ ] Add optional fields (contact method, payment method, deadline, etc.) +- [ ] Add streaming/video preferences +- [ ] Add privacy & crediting preferences +- [ ] Admin-configurable field visibility / requirements (future) + +### 📄 Pages +- [x] Terms of Service page +- [ ] Public commission info / landing page +- [ ] Commission type list with filters +- [ ] Single commission type preview (with examples) +- [ ] Commission request success page +- [ ] FAQ or Help page +- [ ] Page for **custom offers / YCHs** + - [ ] YCH listing grid + - [ ] YCH details page (slots, price, preview image) + - [ ] YCH claim form + - [ ] Status display (e.g. "slot taken", "open", "closed") + +### 🔐 Admin Panel +- [x] Commission type create/edit form +- [ ] Commission option/extra CRUD UI +- [ ] View list of commission requests +- [ ] View single request details +- [ ] Update request status (pending, accepted, rejected, etc.) +- [ ] Filter and sort commission requests +- [ ] View submitted files / references +- [ ] Tag, flag, or star requests for tracking +- [ ] Delete / archive requests + +### 📦 Backend & Actions +- [ ] Submit commission request server action +- [ ] Upload reference image(s) action +- [ ] Create YCH offer action +- [ ] Claim YCH slot action +- [ ] Send confirmation email (optional) +- [ ] Notify artist via email or admin panel +- [ ] Export commission request to JSON or PDF (optional) + +### 🧩 Extras (Later) +- [ ] Kanban-style board for request tracking +- [ ] Queue page (public or admin) +- [ ] Markdown/WYSIWYG editor for ToS and descriptions +- [ ] Analytics for commission activity +- [ ] iCal or Notion export +- [ ] Stripe or Ko-fi payment integration + + +## Customer Commission Ordering Form + +### ✅ Essential Fields +- [x] Commission type +- [x] Base option (e.g. headshot, fullbody) +- [x] Selected extras +- [x] Customer name +- [x] Customer email +- [x] Commission description / idea +- [x] Reference image upload +- [x] Confirm Terms of Service + +### 🧠 Project Details +- [ ] Character description / bio +- [ ] Pose or mood suggestions +- [ ] Background description +- [ ] Scene / environment ideas +- [ ] Color palette preferences +- [ ] Inspiration images or links +- [ ] “I’m unsure, open to ideas” checkbox + +### 📅 Timeline & Budget +- [ ] Preferred deadline / latest delivery date +- [ ] “Flexible deadline” checkbox +- [ ] Budget or max amount willing to pay +- [ ] “Urgent / rush commission” checkbox + +### 💬 Contact Preferences +- [ ] Preferred contact method + - [ ] Email + - [ ] Telegram + - [ ] Twitter + - [ ] Discord + - [ ] Other (input) +- [ ] Contact handle / username +- [ ] Timezone or active hours (optional) + +### 💸 Payment Preferences +- [ ] Preferred payment method + - [ ] PayPal + - [ ] Ko-fi + - [ ] Stripe + - [ ] Bank transfer + - [ ] Crypto + - [ ] Other (input) +- [ ] Payment notes (optional) +- [ ] Invoice required? +- [ ] “I want to pay upfront” checkbox + +### 📽 Streaming / Video +- [ ] I’d like to watch on stream +- [ ] Please record a speedpaint / timelapse +- [ ] OK to share the stream publicly +- [ ] OK to post timelapse/video publicly + +### 🌐 Visibility & Rights +- [ ] NSFW content +- [ ] Gore / heavy themes +- [ ] “Please keep this private” checkbox +- [ ] “OK to share on social media / portfolio” +- [ ] Credit preference + - [ ] Use my name + - [ ] Use my alias + - [ ] Stay anonymous +- [ ] Commercial use intended + +### 🗂 Optional / Admin Fields +- [ ] Commission title / project name +- [ ] Additional notes / anything else to mention diff --git a/package-lock.json b/package-lock.json index 3f940fa..6b8ff2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "react-dom": "^19.0.0", "react-hook-form": "^7.60.0", "react-markdown": "^10.1.0", + "remark-gfm": "^4.0.1", "sonner": "^2.0.6", "tailwind-merge": "^3.3.1", "zod": "^3.25.74" @@ -5899,6 +5900,16 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -5909,6 +5920,34 @@ "node": ">= 0.4" } }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mdast-util-from-markdown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", @@ -5933,6 +5972,107 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-mdx-expression": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", @@ -6141,6 +6281,127 @@ "micromark-util-types": "^2.0.0" } }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-factory-destination": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", @@ -7360,6 +7621,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -7393,6 +7672,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", diff --git a/package.json b/package.json index 2615b5b..38c32df 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "react-dom": "^19.0.0", "react-hook-form": "^7.60.0", "react-markdown": "^10.1.0", + "remark-gfm": "^4.0.1", "sonner": "^2.0.6", "tailwind-merge": "^3.3.1", "zod": "^3.25.74" diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f376ca0..13a5c6a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -24,8 +24,9 @@ model CommissionType { description String? - options CommissionTypeOption[] - extras CommissionTypeExtra[] + options CommissionTypeOption[] + extras CommissionTypeExtra[] + customInputs CommissionTypeCustomInput[] } model CommissionOption { @@ -54,6 +55,18 @@ model CommissionExtra { types CommissionTypeExtra[] } +model CommissionCustomInput { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + name String @unique + fieldId String + + types CommissionTypeCustomInput[] +} + model CommissionTypeOption { id String @id @default(cuid()) createdAt DateTime @default(now()) @@ -92,6 +105,25 @@ model CommissionTypeExtra { @@unique([typeId, extraId]) } +model CommissionTypeCustomInput { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + sortIndex Int @default(0) + + typeId String + customInputId String + + inputType String + label String + required Boolean @default(false) + + type CommissionType @relation(fields: [typeId], references: [id]) + customInput CommissionCustomInput @relation(fields: [customInputId], references: [id]) + + @@unique([typeId, customInputId]) +} + model TermsOfService { id String @id @default(cuid()) createdAt DateTime @default(now()) diff --git a/src/app/commissions/page.tsx b/src/app/commissions/page.tsx index 643e335..4b1873f 100644 --- a/src/app/commissions/page.tsx +++ b/src/app/commissions/page.tsx @@ -7,6 +7,7 @@ export default async function CommissionsPage() { include: { options: { include: { option: true }, orderBy: { sortIndex: "asc" } }, extras: { include: { extra: true }, orderBy: { sortIndex: "asc" } }, + customInputs: { include: { customInput: true }, orderBy: { sortIndex: "asc" } }, }, orderBy: [{ sortIndex: "asc" }, { name: "asc" }], }) diff --git a/src/app/globals.css b/src/app/globals.css index 1f64edf..b89bf78 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -160,6 +160,17 @@ @apply underline text-primary hover:text-primary/80; } +.markdown li:has(input[type="checkbox"]) { + @apply list-none pl-0 items-start gap-2 mb-2; +} + +.markdown input[type="checkbox"] { + @apply mt-1 h-4 w-4 shrink-0 rounded border border-border bg-background text-primary accent-primary cursor-default; +} + +.markdown input[type="checkbox"]:checked + * { + @apply line-through text-muted-foreground; +} @layer base { * { diff --git a/src/app/todo/page.tsx b/src/app/todo/page.tsx new file mode 100644 index 0000000..5d995af --- /dev/null +++ b/src/app/todo/page.tsx @@ -0,0 +1,19 @@ +import fs from "fs/promises"; +import path from "path"; +import ReactMarkdown from "react-markdown"; +import remarkGfm from "remark-gfm"; + +export default async function TodoPage() { + const filePath = path.join(process.cwd(), "ToDo.md") + const content = await fs.readFile(filePath, "utf-8") + + return ( +
+ + {content} + +
+ ); +} \ No newline at end of file diff --git a/src/components/commissions/CommissionOrderForm.tsx b/src/components/commissions/CommissionOrderForm.tsx index 26301f4..51cc74a 100644 --- a/src/components/commissions/CommissionOrderForm.tsx +++ b/src/components/commissions/CommissionOrderForm.tsx @@ -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) { - 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) { )} + +
+ {selectedType && selectedType.customInputs.length > 0 && ( +
+ {selectedType.customInputs.map((input) => { + const name = `customFields.${input.customInput.name}` + return ( + ( + + {input.label} + + {input.inputType === "textarea" ? ( +