From e61b3a346335f3b2f3690e2a3e00c4eb1f8c2cc4 Mon Sep 17 00:00:00 2001 From: BK2004 Date: Thu, 18 Apr 2024 10:01:58 -0500 Subject: [PATCH 1/4] Create event API route and create event form schema --- package-lock.json | 270 +++---- .../manage/[clubId]/create/CreateDropdown.tsx | 19 + .../[clubId]/create/CreateEventForm.tsx | 36 + src/app/manage/[clubId]/create/page.tsx | 33 + src/server/api/routers/event.ts | 24 +- .../db/migrations/0007_cool_stature.sql | 8 + .../db/migrations/meta/0007_snapshot.json | 764 ++++++++++++++++++ src/server/db/migrations/meta/_journal.json | 7 + src/utils/formSchemas.ts | 9 + 9 files changed, 1019 insertions(+), 151 deletions(-) create mode 100644 src/app/manage/[clubId]/create/CreateDropdown.tsx create mode 100644 src/app/manage/[clubId]/create/CreateEventForm.tsx create mode 100644 src/app/manage/[clubId]/create/page.tsx create mode 100644 src/server/db/migrations/0007_cool_stature.sql create mode 100644 src/server/db/migrations/meta/0007_snapshot.json diff --git a/package-lock.json b/package-lock.json index 487c2f52..93e2cc93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1109,22 +1109,6 @@ "get-tsconfig": "^4.7.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1790,126 +1774,6 @@ "node": "*" } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", - "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", - "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", - "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", - "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", - "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", - "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", - "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", - "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@next/swc-win32-x64-msvc": { "version": "13.5.6", "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", @@ -6314,20 +6178,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -12137,6 +11987,126 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", + "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", + "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", + "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", + "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", + "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", + "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", + "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", + "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/src/app/manage/[clubId]/create/CreateDropdown.tsx b/src/app/manage/[clubId]/create/CreateDropdown.tsx new file mode 100644 index 00000000..ba05bf25 --- /dev/null +++ b/src/app/manage/[clubId]/create/CreateDropdown.tsx @@ -0,0 +1,19 @@ +'use client' + +import { useState, useMemo } from "react" +import { type SelectClub } from "@src/server/db/models" + +const CreateDropdown = ({ clubId, officerClubs }: { clubId: string, officerClubs: SelectClub[] }) => { + const [showDropdown, setShowDropdown] = useState(false); + const selected = useMemo(() => { + return officerClubs.filter((club) => club.id == clubId)[0]; + }, [clubId]) + + return (
+ +
); +} +export default CreateDropdown \ No newline at end of file diff --git a/src/app/manage/[clubId]/create/CreateEventForm.tsx b/src/app/manage/[clubId]/create/CreateEventForm.tsx new file mode 100644 index 00000000..098f28e6 --- /dev/null +++ b/src/app/manage/[clubId]/create/CreateEventForm.tsx @@ -0,0 +1,36 @@ +'use client' + +import { useState } from "react"; +import { type SelectClub } from "@src/server/db/models"; +import { createEventSchema } from "@src/utils/formSchemas"; +import { useForm } from "react-hook-form"; +import { api } from "@src/trpc/react"; +import { type z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useRouter } from "next/navigation"; + +const CreateEventForm = ({ clubId, officerClubs }: { clubId: string, officerClubs: SelectClub[]}) => { + const { + register, + handleSubmit, + watch, + formState: { errors }, + } = useForm>({ + resolver: zodResolver(createEventSchema), + defaultValues: { + clubId: clubId, + } + }); + + const router = useRouter(); + + const createMutation = api.event.createEvent.useMutation({ + onSuccess: () => { router.refresh() } + }) + + const onSubmit = handleSubmit((data) => { + if (createMutation.isLoading) return; + + createMutation.mutate(data); + }); +} \ No newline at end of file diff --git a/src/app/manage/[clubId]/create/page.tsx b/src/app/manage/[clubId]/create/page.tsx new file mode 100644 index 00000000..699dc9a7 --- /dev/null +++ b/src/app/manage/[clubId]/create/page.tsx @@ -0,0 +1,33 @@ +import Header from "@src/components/BaseHeader"; +import { getServerAuthSession } from "@src/server/auth"; +import { api } from "@src/trpc/server"; +import { signInRoute } from "@src/utils/redirect"; +import { redirect, notFound } from "next/navigation"; +import CreateDropdown from "./CreateDropdown"; + +const Page = async ({ params }: { params: { clubId: string } }) => { + const session = await getServerAuthSession(); + if (!session) { + redirect(signInRoute(`manage/${params.clubId}/create`)); + } + + const officerClubs = await api.club.getOfficerClubs.query(); + const currentClub = officerClubs.filter(val => { + return val.id == params.clubId + })[0]; + if (!currentClub) { + notFound(); + } + + return (
+
+
+
+ +
+
hello world
+
+ +
) +} +export default Page; \ No newline at end of file diff --git a/src/server/api/routers/event.ts b/src/server/api/routers/event.ts index 6f14cca3..83331cdb 100644 --- a/src/server/api/routers/event.ts +++ b/src/server/api/routers/event.ts @@ -15,7 +15,10 @@ import { z } from 'zod'; import { selectEvent } from '@src/server/db/models'; import { type DateRange } from 'react-day-picker'; import { add } from 'date-fns'; -import { userMetadataToEvents } from '@src/server/db/schema/users'; +import { userMetadataToClubs, userMetadataToEvents } from '@src/server/db/schema/users'; +import { createEventSchema } from '@src/utils/formSchemas'; +import { TRPCError } from '@trpc/server'; +import { events } from '@src/server/db/schema/events'; function isDateRange(value: unknown): value is DateRange { return Boolean(value && typeof value === 'object' && 'from' in value); @@ -232,6 +235,25 @@ export const eventRouter = createTRPCRouter({ ), ); }), + createEvent: protectedProcedure + .input(createEventSchema) + .mutation(async ({ input, ctx }) => { + const { clubId } = input + const userId = ctx.session.user.id; + + const isOfficer = await ctx.db.query.userMetadataToClubs.findFirst({ + where: and( + eq(userMetadataToClubs.userId, userId), + eq(userMetadataToClubs.clubId, clubId), + inArray(userMetadataToClubs.memberType, ["Officer", "President"]) + ) + }); + if (!isOfficer) { + throw new TRPCError({ code: "UNAUTHORIZED" }); + } + + await ctx.db.insert(events).values({ ...input }); + }), byName: publicProcedure.input(byNameSchema).query(async ({ input, ctx }) => { const { name, sortByDate } = input; try { diff --git a/src/server/db/migrations/0007_cool_stature.sql b/src/server/db/migrations/0007_cool_stature.sql new file mode 100644 index 00000000..e1c06168 --- /dev/null +++ b/src/server/db/migrations/0007_cool_stature.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS "feedback_form" ( + "id" text PRIMARY KEY DEFAULT nanoid(20) NOT NULL, + "rating" integer NOT NULL, + "likes" text DEFAULT '', + "dislikes" text DEFAULT '', + "features" text DEFAULT '', + "submit_on" timestamp with time zone NOT NULL +); diff --git a/src/server/db/migrations/meta/0007_snapshot.json b/src/server/db/migrations/meta/0007_snapshot.json new file mode 100644 index 00000000..c82ff67c --- /dev/null +++ b/src/server/db/migrations/meta/0007_snapshot.json @@ -0,0 +1,764 @@ +{ + "version": "5", + "dialect": "pg", + "id": "429d44fa-511e-4cb4-89bb-aae0f8d67bdb", + "prevId": "e36c6103-4f30-490d-aa6a-af8fdb4db2cd", + "tables": { + "admin": { + "name": "admin", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": true, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "admin_userId_user_metadata_id_fk": { + "name": "admin_userId_user_metadata_id_fk", + "tableFrom": "admin", + "tableTo": "user_metadata", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "carousel": { + "name": "carousel", + "schema": "", + "columns": { + "orgId": { + "name": "orgId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "startTime": { + "name": "startTime", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "endTime": { + "name": "endTime", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "carousel_orgId_club_id_fk": { + "name": "carousel_orgId_club_id_fk", + "tableFrom": "carousel", + "tableTo": "club", + "columnsFrom": [ + "orgId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "club": { + "name": "club", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "nanoid(20)" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'/nebula-logo.png'" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "approved": { + "name": "approved", + "type": "approved_enum", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "profile_image": { + "name": "profile_image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "soc": { + "name": "soc", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "contacts": { + "name": "contacts", + "schema": "", + "columns": { + "platform": { + "name": "platform", + "type": "platform", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "club_id": { + "name": "club_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "contacts_club_id_club_id_fk": { + "name": "contacts_club_id_club_id_fk", + "tableFrom": "contacts", + "tableTo": "club", + "columnsFrom": [ + "club_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "contacts_platform_club_id": { + "name": "contacts_platform_club_id", + "columns": [ + "platform", + "club_id" + ] + } + }, + "uniqueConstraints": {} + }, + "events": { + "name": "events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "nanoid(20)" + }, + "club_id": { + "name": "club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "start_time": { + "name": "start_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "end_time": { + "name": "end_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": {}, + "foreignKeys": { + "events_club_id_club_id_fk": { + "name": "events_club_id_club_id_fk", + "tableFrom": "events", + "tableTo": "club", + "columnsFrom": [ + "club_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "feedback_form": { + "name": "feedback_form", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "nanoid(20)" + }, + "rating": { + "name": "rating", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "likes": { + "name": "likes", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "dislikes": { + "name": "dislikes", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "features": { + "name": "features", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "submit_on": { + "name": "submit_on", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId": { + "name": "account_provider_providerAccountId", + "columns": [ + "provider", + "providerAccountId" + ] + } + }, + "uniqueConstraints": {} + }, + "session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_metadata": { + "name": "user_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "major": { + "name": "major", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "minor": { + "name": "minor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "year": { + "name": "year", + "type": "year", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "role", + "primaryKey": false, + "notNull": true + }, + "career": { + "name": "career", + "type": "career", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_metadata_to_clubs": { + "name": "user_metadata_to_clubs", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "club_id": { + "name": "club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "member_type": { + "name": "member_type", + "type": "member_type", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_metadata_to_clubs_user_id_user_metadata_id_fk": { + "name": "user_metadata_to_clubs_user_id_user_metadata_id_fk", + "tableFrom": "user_metadata_to_clubs", + "tableTo": "user_metadata", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_metadata_to_clubs_club_id_club_id_fk": { + "name": "user_metadata_to_clubs_club_id_club_id_fk", + "tableFrom": "user_metadata_to_clubs", + "tableTo": "club", + "columnsFrom": [ + "club_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_metadata_to_clubs_user_id_club_id": { + "name": "user_metadata_to_clubs_user_id_club_id", + "columns": [ + "user_id", + "club_id" + ] + } + }, + "uniqueConstraints": {} + }, + "user_metadata_to_events": { + "name": "user_metadata_to_events", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "user_metadata_to_events_user_id_user_id_fk": { + "name": "user_metadata_to_events_user_id_user_id_fk", + "tableFrom": "user_metadata_to_events", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_metadata_to_events_event_id_events_id_fk": { + "name": "user_metadata_to_events_event_id_events_id_fk", + "tableFrom": "user_metadata_to_events", + "tableTo": "events", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_metadata_to_events_user_id_event_id": { + "name": "user_metadata_to_events_user_id_event_id", + "columns": [ + "user_id", + "event_id" + ] + } + }, + "uniqueConstraints": {} + }, + "user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token": { + "name": "verificationToken_identifier_token", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {} + } + }, + "enums": { + "approved_enum": { + "name": "approved_enum", + "values": { + "approved": "approved", + "rejected": "rejected", + "pending": "pending" + } + }, + "career": { + "name": "career", + "values": { + "Healthcare": "Healthcare", + "Art and Music": "Art and Music", + "Engineering": "Engineering", + "Business": "Business", + "Sciences": "Sciences", + "Public Service": "Public Service" + } + }, + "member_type": { + "name": "member_type", + "values": { + "President": "President", + "Officer": "Officer", + "Member": "Member" + } + }, + "role": { + "name": "role", + "values": { + "Student": "Student", + "Student Organizer": "Student Organizer", + "Administrator": "Administrator" + } + }, + "year": { + "name": "year", + "values": { + "Freshman": "Freshman", + "Sophomore": "Sophomore", + "Junior": "Junior", + "Senior": "Senior", + "Grad Student": "Grad Student" + } + } + }, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/server/db/migrations/meta/_journal.json b/src/server/db/migrations/meta/_journal.json index 80169c70..322fc626 100644 --- a/src/server/db/migrations/meta/_journal.json +++ b/src/server/db/migrations/meta/_journal.json @@ -50,6 +50,13 @@ "when": 1710890177407, "tag": "0006_narrow_mad_thinker", "breakpoints": true + }, + { + "idx": 7, + "version": "5", + "when": 1712936415961, + "tag": "0007_cool_stature", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/utils/formSchemas.ts b/src/utils/formSchemas.ts index c58c9a0b..805fbe9a 100644 --- a/src/utils/formSchemas.ts +++ b/src/utils/formSchemas.ts @@ -42,6 +42,15 @@ export const editOfficerSchema = z.object({ .array(), }); +export const createEventSchema = z.object({ + clubId: z.string(), + name: z.string(), + location: z.string(), + description: z.string().max(1000), + startTime: z.date(), + endTime: z.date(), +}) + export const feedbackFormSchema = z.object({ rating: z.number().min(1).max(10), likes: z.string().default(''), From 520534991bf08c8faf356e09f9cb3769e0379919 Mon Sep 17 00:00:00 2001 From: BK2004 Date: Tue, 7 May 2024 10:57:20 -0500 Subject: [PATCH 2/4] create event form --- .../manage/[clubId]/create/CreateDropdown.tsx | 19 ----- .../[clubId]/create/CreateEventForm.tsx | 83 +++++++++++++++--- src/app/manage/[clubId]/create/TimeSelect.tsx | 85 +++++++++++++++++++ src/app/manage/[clubId]/create/page.tsx | 7 +- src/icons/Icons.tsx | 16 ++++ src/server/api/routers/event.ts | 2 +- src/utils/formSchemas.ts | 8 +- 7 files changed, 180 insertions(+), 40 deletions(-) delete mode 100644 src/app/manage/[clubId]/create/CreateDropdown.tsx create mode 100644 src/app/manage/[clubId]/create/TimeSelect.tsx diff --git a/src/app/manage/[clubId]/create/CreateDropdown.tsx b/src/app/manage/[clubId]/create/CreateDropdown.tsx deleted file mode 100644 index ba05bf25..00000000 --- a/src/app/manage/[clubId]/create/CreateDropdown.tsx +++ /dev/null @@ -1,19 +0,0 @@ -'use client' - -import { useState, useMemo } from "react" -import { type SelectClub } from "@src/server/db/models" - -const CreateDropdown = ({ clubId, officerClubs }: { clubId: string, officerClubs: SelectClub[] }) => { - const [showDropdown, setShowDropdown] = useState(false); - const selected = useMemo(() => { - return officerClubs.filter((club) => club.id == clubId)[0]; - }, [clubId]) - - return (
- -
); -} -export default CreateDropdown \ No newline at end of file diff --git a/src/app/manage/[clubId]/create/CreateEventForm.tsx b/src/app/manage/[clubId]/create/CreateEventForm.tsx index 098f28e6..3105d8d9 100644 --- a/src/app/manage/[clubId]/create/CreateEventForm.tsx +++ b/src/app/manage/[clubId]/create/CreateEventForm.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState } from "react"; +import { useEffect } from "react"; import { type SelectClub } from "@src/server/db/models"; import { createEventSchema } from "@src/utils/formSchemas"; import { useForm } from "react-hook-form"; @@ -8,29 +8,90 @@ import { api } from "@src/trpc/react"; import { type z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { useRouter } from "next/navigation"; +import { UploadIcon } from "@src/icons/Icons"; +import TimeSelect from "./TimeSelect"; const CreateEventForm = ({ clubId, officerClubs }: { clubId: string, officerClubs: SelectClub[]}) => { const { register, handleSubmit, watch, - formState: { errors }, + setValue, + getValues, } = useForm>({ resolver: zodResolver(createEventSchema), defaultValues: { clubId: clubId, - } + }, + mode: "onSubmit", }); - const router = useRouter(); + const [watchDescription, watchStartTime] = watch(['description', 'startTime']); + useEffect(() => { + const subscription = watch((data, {name}) => { + if (name == "clubId") { + router.replace(`/manage/${data.clubId}/create`); + } + }); + return () => subscription.unsubscribe(); + }, [router, watch]); - const createMutation = api.event.createEvent.useMutation({ - onSuccess: () => { router.refresh() } + const createMutation = api.event.create.useMutation({ + onSuccess: () => { location.reload(); } }) - const onSubmit = handleSubmit((data) => { - if (createMutation.isLoading) return; - - createMutation.mutate(data); + const onSubmit = handleSubmit((data: z.infer) => { + if (!createMutation.isLoading) { + createMutation.mutate(data); + } }); -} \ No newline at end of file + + return (
void onSubmit(e)} className="w-full flex flex-row flex-wrap justify-between gap-10 overflow-x-clip text-[#4D5E80] pb-4"> +
+
+ Create Club Event for + +
+
+

Event Picture

+

Drag or choose file to upload

+
+ +

JPEG, PNG, or SVG

+
+
+
+

Event Details

+
+ + +
+
+ + +
+
+
+ +

{watchDescription && watchDescription.length} of 1000 Characters used

+
+