From 76b72f64d87994aa958c7df81e0bb4e9f9ad3202 Mon Sep 17 00:00:00 2001 From: Malte Delfs Date: Fri, 18 Jun 2021 21:58:42 +0200 Subject: [PATCH] event type custom input WIP --- lib/EventTypeInput.ts | 14 ++ pages/api/availability/eventtype.ts | 23 ++- pages/availability/event/[type].tsx | 136 +++++++++++++++++- .../migration.sql | 13 ++ 4 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 lib/EventTypeInput.ts create mode 100644 prisma/migrations/20210618140954_added_event_type_custom/migration.sql diff --git a/lib/EventTypeInput.ts b/lib/EventTypeInput.ts new file mode 100644 index 00000000..ac0799d3 --- /dev/null +++ b/lib/EventTypeInput.ts @@ -0,0 +1,14 @@ + +export enum EventTypeCustomInputType { + Text = 'text', + TextLong = 'textLong', + Number = 'number', +} + +export interface EventTypeCustomInput { + id?: number; + type: EventTypeCustomInputType; + label: string; + required: boolean; +} + diff --git a/pages/api/availability/eventtype.ts b/pages/api/availability/eventtype.ts index 8f03e3e9..885c117c 100644 --- a/pages/api/availability/eventtype.ts +++ b/pages/api/availability/eventtype.ts @@ -18,6 +18,27 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) length: parseInt(req.body.length), hidden: req.body.hidden, locations: req.body.locations, + customInputs: !req.body.customInputs + ? undefined + : { + createMany: { + data: req.body.customInputs.filter(input => !input.id).map(input => ({ + type: input.type, + label: input.label, + required: input.required + })) + }, + update: req.body.customInputs.filter(input => !!input.id).map(input => ({ + data: { + type: input.type, + label: input.label, + required: input.required + }, + where: { + id: input.id + } + })) + }, }; if (req.method == "POST") { @@ -50,4 +71,4 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) res.status(200).json({message: 'Event deleted successfully'}); } -} \ No newline at end of file +} diff --git a/pages/availability/event/[type].tsx b/pages/availability/event/[type].tsx index ed575f25..54ff28b3 100644 --- a/pages/availability/event/[type].tsx +++ b/pages/availability/event/[type].tsx @@ -13,14 +13,25 @@ import { XIcon, PhoneIcon, } from '@heroicons/react/outline'; +import {EventTypeCustomInput, EventTypeCustomInputType} from "../../../lib/EventTypeInput"; +import {PlusIcon} from "@heroicons/react/solid"; export default function EventType(props) { const router = useRouter(); + const inputOptions: OptionBase[] = [ + { value: EventTypeCustomInputType.Text, label: 'Text' }, + { value: EventTypeCustomInputType.TextLong, label: 'Multiline Text' }, + { value: EventTypeCustomInputType.Number, label: 'Number', }, + ] + const [ session, loading ] = useSession(); const [ showLocationModal, setShowLocationModal ] = useState(false); + const [ showAddCustomModal, setShowAddCustomModal ] = useState(false); const [ selectedLocation, setSelectedLocation ] = useState(undefined); + const [ selectedInputOption, setSelectedInputOption ] = useState(inputOptions[0]); const [ locations, setLocations ] = useState(props.eventType.locations || []); + const [customInputs, setCustomInputs] = useState(props.eventType.customInputs.sort((a, b) => a.id - b.id) || []); const titleRef = useRef(); const slugRef = useRef(); @@ -44,7 +55,7 @@ export default function EventType(props) { const response = await fetch('/api/availability/eventtype', { method: 'PATCH', - body: JSON.stringify({id: props.eventType.id, title: enteredTitle, slug: enteredSlug, description: enteredDescription, length: enteredLength, hidden: enteredIsHidden, locations }), + body: JSON.stringify({id: props.eventType.id, title: enteredTitle, slug: enteredSlug, description: enteredDescription, length: enteredLength, hidden: enteredIsHidden, locations, customInputs }), headers: { 'Content-Type': 'application/json' } @@ -83,6 +94,11 @@ export default function EventType(props) { setShowLocationModal(false); }; + const closeAddCustomModal = () => { + setSelectedInputOption(inputOptions[0]); + setShowAddCustomModal(false); + }; + const LocationOptions = () => { if (!selectedLocation) { return null; @@ -133,7 +149,22 @@ export default function EventType(props) { setLocations(locations.filter( (location) => location.type !== selectedLocation.type )); }; - return ( + const updateCustom = (e) => { + e.preventDefault(); + + const customInput: EventTypeCustomInput = { + label: e.target.label.value, + required: e.target.required.checked, + type: e.target.type.value + }; + + setCustomInputs(customInputs.concat(customInput)); + + console.log(customInput) + setShowAddCustomModal(false); + }; + + return (
{props.eventType.title} | Event Type | Calendso @@ -232,6 +263,44 @@ export default function EventType(props) {
+
+ +
    + {customInputs.map( (customInput) => ( +
  • +
    +
    +
    + Label: {customInput.label} +
    +
    + Type: {customInput.type} +
    +
    + {customInput.required ? "Required" : "Optional"} +
    +
    +
    + + +
    +
    +
  • + ))} +
  • + +
  • +
+
@@ -317,6 +386,66 @@ export default function EventType(props) {
} + {showAddCustomModal && +
+
+ +
+
+ }
); @@ -348,6 +477,7 @@ export async function getServerSideProps(context) { length: true, hidden: true, locations: true, + customInputs: true } }); @@ -357,4 +487,4 @@ export async function getServerSideProps(context) { eventType }, } -} \ No newline at end of file +} diff --git a/prisma/migrations/20210618140954_added_event_type_custom/migration.sql b/prisma/migrations/20210618140954_added_event_type_custom/migration.sql new file mode 100644 index 00000000..5d038f2b --- /dev/null +++ b/prisma/migrations/20210618140954_added_event_type_custom/migration.sql @@ -0,0 +1,13 @@ +-- CreateTable +CREATE TABLE "EventTypeCustomInput" ( + "id" SERIAL NOT NULL, + "eventTypeId" INTEGER NOT NULL, + "label" TEXT NOT NULL, + "type" TEXT NOT NULL, + "required" BOOLEAN NOT NULL, + + PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "EventTypeCustomInput" ADD FOREIGN KEY ("eventTypeId") REFERENCES "EventType"("id") ON DELETE CASCADE ON UPDATE CASCADE;