diff --git a/.env.example b/.env.example index ece81426..68b51259 100644 --- a/.env.example +++ b/.env.example @@ -1,15 +1,15 @@ -AWS_ACCESS_KEY_ID="43242s387fg44638s244fh24" -AWS_REGION="us-east-2" -AWS_S3_BUCKET="hackathon-backups" -AWS_S3_ENDPOINT="https://dfh7346398578dhgsds.r2.cloudflarestorage.com" -AWS_S3_REGION="auto" -AWS_SECRET_ACCESS_KEY="4258722gyrgejw78gfg2u20974fhihdfs02" -AWS_SES_ACCESS_KEY="ADEIAFHJ3HKFU48FHJK" -AWS_SES_EMAIL_FROM="no-reply@[your_organization].org" -AWS_SES_SECRET_ACCESS_KEY="AfBHKrDFh/Q03u+37iyGrwjFJ" -BACKUP_CRON_SCHEDULE="0 */6 * * *" -BACKUP_DATABASE_URL="postgres://default:RtN4q5qefsTO@ui-painted-hills-e5ddlb.us-east-2.aws.neon.tech:4576/verceldb?sslmode=require" -BLOB_READ_WRITE_TOKEN="vercel_blob_rw_fhb9DH2kOEIO3EOI_3dBKKFHBGDLNSjnjDOIJHF" +# AWS_ACCESS_KEY_ID="43242s387fg44638s244fh24" +# AWS_REGION="us-east-2" +# AWS_S3_BUCKET="hackathon-backups" +# AWS_S3_ENDPOINT="https://dfh7346398578dhgsds.r2.cloudflarestorage.com" +# AWS_S3_REGION="auto" +# AWS_SECRET_ACCESS_KEY="4258722gyrgejw78gfg2u20974fhihdfs02" +# AWS_SES_ACCESS_KEY="ADEIAFHJ3HKFU48FHJK" +# AWS_SES_EMAIL_FROM="no-reply@[your_organization].org" +# AWS_SES_SECRET_ACCESS_KEY="AfBHKrDFh/Q03u+37iyGrwjFJ" +# BACKUP_CRON_SCHEDULE="0 */6 * * *" +# BACKUP_DATABASE_URL="postgres://default:RtN4q5qefsTO@ui-painted-hills-e5ddlb.us-east-2.aws.neon.tech:4576/verceldb?sslmode=require" +# BLOB_READ_WRITE_TOKEN="vercel_blob_rw_fhb9DH2kOEIO3EOI_3dBKKFHBGDLNSjnjDOIJHF" BOT_API_URL="https://hackkit-actions-bots.up.railway.app" CLERK_SECRET_KEY="sk_test_AFNJKABF2uhkbDBUKAFAKBAHBj3r" CLOUDFLARE_ACCOUNT_ID="cdcdJB3453KKJFBDSBHA54546UIBF" @@ -19,21 +19,21 @@ DISCORD_DEV_VERIFY_CHANNEL_ID="52872856278050172988890" DISCORD_PROD_SERVER_ID="528728562780501729853789" DISCORD_PROD_VERIFY_CHANNEL_ID="5287378262780501729853789" DISCORD_SECRET_TOKEN="FHBAHJABDhbHSUeyi7398.S72ljd.HKBVAfug73gifa-74gfwiyB-BHJBDHV07hAJf83" -HK_ENV="development" +NODE_ENV="development" INTERNAL_AUTH_KEY="bwgybgidbsi-4784gyfgs-475hhkdsbfs-bwgybgidbsi-4784gyfgs-475hhkdsbfs-bwgybgidbsi-4784gyfgs-475hhkdsbfs-fbnauib4783-bhfbsjfbs" NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_YRGIBHSBIbabffjdhvbuYGI7BK" NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in" NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up" -PLUNK_API_KEY="sk_279y482gibfai7g74gikbga345" -PLUNK_API_URL="https://plunk.[your_org_name].org/api/[version_number]" -POSTGRES_DATABASE="verceldb" -POSTGRES_HOST="ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech" -POSTGRES_PASSWORD="dkhjbIYBFABUI" -POSTGRES_PRISMA_URL="postgres://default:dkhjbIYBFABUI@ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech/verceldb?pgbouncer=true&connect_timeout=15&sslmode=require" -POSTGRES_URL="postgres://default:dkhjbIYBFABUI@ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech/verceldb?sslmode=require" -POSTGRES_URL_NO_SSL="postgres://default:dkhjbIYBFABUI@ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech/verceldb" -POSTGRES_URL_NON_POOLING="postgres://default:dkhjbIYBFABUI@ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech/verceldb?sslmode=require" -POSTGRES_USER="default" +# PLUNK_API_KEY="sk_279y482gibfai7g74gikbga345" +# PLUNK_API_URL="https://plunk.[your_org_name].org/api/[version_number]" +# POSTGRES_DATABASE="verceldb" +# POSTGRES_HOST="ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech" +# POSTGRES_PASSWORD="dkhjbIYBFABUI" +# POSTGRES_PRISMA_URL="postgres://default:dkhjbIYBFABUI@ep-rising-pfahbeke-spooler.us-east-2.aws.neon.tech/verceldb?pgbouncer=true&connect_timeout=15&sslmode=require" +# POSTGRES_URL="postgres://default:dkhjbIYBFABUI@ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech/verceldb?sslmode=require" +# POSTGRES_URL_NO_SSL="postgres://default:dkhjbIYBFABUI@ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech/verceldb" +# POSTGRES_URL_NON_POOLING="postgres://default:dkhjbIYBFABUI@ep-rising-sky-adbkfahbeke-spooler.us-east-2.aws.neon.tech/verceldb?sslmode=require" +# POSTGRES_USER="default" R2_ACCESS_KEY_ID="1bfkhbfyiayi38uhidfis" R2_BUCKET_NAME="your-org-name-userdata" R2_SECRET_ACCESS_KEY="279y45g79tgbjsbfhbsiufhbs89hg487hsiufs" diff --git a/apps/backups/.gitignore b/apps/backups/.gitignore deleted file mode 100644 index e319e063..00000000 --- a/apps/backups/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# prod -dist/ - -# dev -.yarn/ -!.yarn/releases -.vscode/* -!.vscode/launch.json -!.vscode/*.code-snippets -.idea/workspace.xml -.idea/usage.statistics.xml -.idea/shelf - -# deps -node_modules/ -.wrangler - -# env -.env -.env.production -.dev.vars - -# logs -logs/ -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -# misc -.DS_Store diff --git a/apps/backups/package.json b/apps/backups/package.json deleted file mode 100644 index b7eb2cf0..00000000 --- a/apps/backups/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "backups", - "scripts": { - "dev": "wrangler dev --test-scheduled", - "deploy": "wrangler deploy --minify", - "cf-typegen": "wrangler types --env-interface CloudflareBindings" - }, - "dependencies": { - "@aws-sdk/client-s3": "^3.840.0", - "@t3-oss/env-core": "^0.13.8", - "@types/node": "20.14.11", - "db": "workspace:*", - "hono": "^4.8.3", - "typescript": "5.5.3", - "zod": "^3.25.67" - }, - "devDependencies": { - "@cloudflare/workers-types": "^4.20250628.0", - "wrangler": "^4.4.0" - } -} \ No newline at end of file diff --git a/apps/backups/src/env.ts b/apps/backups/src/env.ts deleted file mode 100644 index 0adfe7b1..00000000 --- a/apps/backups/src/env.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { createEnv } from "@t3-oss/env-core"; -import { z } from "zod"; -export const env = createEnv({ - server: { - BACKUPS_SECRET_KEY: z.string({ - description: - "This is a secret key used to sign and verify requests. It should be kept secret and not shared with anyone.", - }), - BACKUPS_DATABSE_NAME: z.string(), - BACKUPS_ORGANIZATION_SLUG: z.string(), - BACKUPS_CLOUDFLARE_ACCOUNT_ID: z.string({ - description: - "Account ID for the Cloudflare account. Note that this ID should be the same one the bucket is hosted in.", - }), - BACKUPS_BUCKET_ACCESS_KEY_ID: z.string(), - BACKUPS_BUCKET_SECRET_ACCESS_KEY: z.string(), - BACKUPS_DB_BEARER: z.string({ - description: - "This is a bearer token to access the databases. If serverless DB provider allows, try to make this token read-only.", - }), - BACKUPS_BUCKET_NAME: z.string(), - }, - onValidationError: (issues) => { - console.log("all process variables:", process.env); - console.error("❌ Invalid environment variables:", issues); - throw new Error("Invalid environment variables"); - }, - // Called when server variables are accessed on the client. - onInvalidAccess: (variable: string) => { - console.log( - `❌ Attempted to access server-side environment variable "${variable}" on the client.`, - ); - throw new Error( - "❌ Attempted to access a server-side environment variable on the client", - ); - }, - // skipValidation: true, - runtimeEnv: process.env, - emptyStringAsUndefined: true, -}); diff --git a/apps/backups/src/functions.ts b/apps/backups/src/functions.ts deleted file mode 100644 index b79f4de4..00000000 --- a/apps/backups/src/functions.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { env } from "./env"; -import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; - -const S3 = new S3Client({ - region: "auto", - endpoint: `https://${env.BACKUPS_CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`, - credentials: { - accessKeyId: env.BACKUPS_BUCKET_ACCESS_KEY_ID, - secretAccessKey: env.BACKUPS_BUCKET_SECRET_ACCESS_KEY, - }, -}); - -async function getDatabaseDump(databseName: string, organizationSlug: string) { - const res = await fetch( - `https://${databseName}-${organizationSlug}.turso.io/dump`, - { - method: "GET", - headers: new Headers({ - Authorization: `Bearer ${env.BACKUPS_DB_BEARER}`, - }), - }, - ); - - if (!res.ok) { - throw new Error( - `Failed to get database dump: ${res.status} ${res.statusText}`, - ); - } - - return res.text(); -} - -async function uploadToS3(fileName: string, dumpFile: string) { - const cmd = new PutObjectCommand({ - Key: fileName, - Bucket: env.BACKUPS_BUCKET_NAME, - Body: Buffer.from(dumpFile, "utf-8"), - }); - return S3.send(cmd); -} - -async function doBackup() { - const backupData = await getDatabaseDump( - env.BACKUPS_DATABSE_NAME, - env.BACKUPS_ORGANIZATION_SLUG, - ); - const date = new Date().toISOString(); - const timestamp = date.replace(/[:.]+/g, "-"); - const fileName = `${env.BACKUPS_DATABSE_NAME}-${env.BACKUPS_ORGANIZATION_SLUG}-${timestamp}.sql`; - const res = await uploadToS3(fileName, backupData); - - if (res.$metadata.httpStatusCode !== 200) { - throw new Error( - `Failed to upload file to S3: ${res.$metadata.httpStatusCode}`, - ); - } - return true; -} - -export { doBackup, getDatabaseDump, uploadToS3 }; diff --git a/apps/backups/src/index.ts b/apps/backups/src/index.ts deleted file mode 100644 index fc11f549..00000000 --- a/apps/backups/src/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Hono } from "hono"; -import { - type ScheduledController, - type ExecutionContext, -} from "@cloudflare/workers-types"; -import { timingSafeEqual } from "node:crypto"; -import { cors } from "hono/cors"; -import { env } from "./env"; -import { doBackup } from "./functions"; - -interface Env {} - -// api stuff -const api = new Hono(); - -// middleware -api.use("/backup/*", cors()).use("/backup/*", async (c, next) => { - // grab the bearer token from the request headers - const authToken = c.req.header("Authorization") || ""; - const encoder = new TextEncoder(); - const expected = `Bearer ${env.BACKUPS_SECRET_KEY}`; - if ( - authToken.length !== expected.length || - !timingSafeEqual(encoder.encode(authToken), encoder.encode(expected)) - ) { - return c.json({ error: "Unauthorized" }, 401); - } - - await next(); -}); - -api.get("/health", (c) => { - return c.json({ status: "ok" }, 200); -}); - -api.post("/backup", async (c) => { - await doBackup(); - return c.json({ status: "Backup completed successfully" }, 200); -}); - -// cron stuff -/** - * Notes for the future: no specific job schedule is specified here as in the future, - * the ideal would be to have an endpoint that takes in a schedule and an instance (of hackkit, clubkit, etc) and allow the endpoint to use the cloudflare API to - * modify the builld itself and assign jobs that way. - * Basically you would have a db table that would hold the instance ID, and the schedule and another one for the unique cron entires and then tie them together. - */ -const cron = async ( - _controller: ScheduledController, - _env: Env, - ctx: ExecutionContext, -) => { - ctx.waitUntil(doBackup()); -}; - -export default { - fetch: api.fetch, - scheduled: cron, -}; diff --git a/apps/backups/tsconfig.json b/apps/backups/tsconfig.json deleted file mode 100644 index 23345376..00000000 --- a/apps/backups/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "Bundler", - "strict": true, - "skipLibCheck": true, - "lib": [ - "ESNext" - ], - "jsx": "react-jsx", - "jsxImportSource": "hono/jsx" - }, -} \ No newline at end of file diff --git a/apps/backups/wrangler.jsonc b/apps/backups/wrangler.jsonc deleted file mode 100644 index a6fdba21..00000000 --- a/apps/backups/wrangler.jsonc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "node_modules/wrangler/config-schema.json", - "name": "backups", - "main": "src/index.ts", - "compatibility_date": "2025-06-30", - "observability": { - "enabled": true, - "head_sampling_rate": 1, - }, - "compatibility_flags": [ - "nodejs_compat", - "nodejs_compat_populate_process_env", - ], -} diff --git a/apps/infrastructure-migrator/driver.ts b/apps/infrastructure-migrator/driver.ts deleted file mode 100644 index 5e6b180f..00000000 --- a/apps/infrastructure-migrator/driver.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { sql } from "@vercel/postgres"; -import { drizzle as pgDrizzle } from "drizzle-orm/vercel-postgres"; -import { drizzle } from "drizzle-orm/libsql"; -import * as pgSchema from "./schema"; -import { createClient } from "@libsql/client"; -export * from "drizzle-orm"; -import dotenv from "dotenv"; -import * as schema from "db/schema"; -import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; -import c, { staticUploads } from "config"; -import { eq } from "drizzle-orm"; - -dotenv.config({ - path: "../../.env", -}); - -export const S3 = new S3Client({ - region: "auto", - endpoint: `https://${process.env.CLOUDFLARE_ACCOUNT_ID!}.r2.cloudflarestorage.com`, - credentials: { - accessKeyId: process.env.R2_ACCESS_KEY_ID!, - secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!, - }, -}); - -const dbPostgres = pgDrizzle(sql, { schema: pgSchema }); - -const allUserCommonDataPromise = dbPostgres.query.userCommonData.findMany(); -const allUserHackerDataPromise = dbPostgres.query.userHackerData.findMany(); -const allEventsPromise = dbPostgres.query.events.findMany(); -const allFilesPromise = dbPostgres.query.files.findMany(); -const allScansPromise = dbPostgres.query.scans.findMany(); -const allErrorLogsPromise = dbPostgres.query.errorLog.findMany(); -const alldiscordVerificationPromise = - dbPostgres.query.discordVerification.findMany(); -const allTicketsPromise = dbPostgres.query.tickets.findMany(); -const allChatsPromise = dbPostgres.query.chats.findMany(); -const allChatMessagesPromise = dbPostgres.query.chatMessages.findMany(); -const allTicketsToUsersPromise = dbPostgres.query.ticketsToUsers.findMany(); -const allChatsToUsersPromise = dbPostgres.query.chatsToUsers.findMany(); - -async function migratePostgresSqLite() { - console.log("Starting Migration 🚀"); - console.log("Fetching Postgres Data 🐘"); - const turso = createClient({ - url: process.env.TURSO_DATABASE_URL!, - authToken: process.env.TURSO_AUTH_TOKEN, - }); - const db = drizzle(turso, { schema }); - - const [ - allUserCommonData, - allUserHackerData, - allEvents, - allFiles, - allScans, - allErrorLogs, - alldiscordVerification, - allTickets, - allChats, - allChatMessages, - allTicketsToUsers, - allChatsToUsers, - ] = await Promise.all([ - allUserCommonDataPromise, - allUserHackerDataPromise, - allEventsPromise, - allFilesPromise, - allScansPromise, - allErrorLogsPromise, - alldiscordVerificationPromise, - allTicketsPromise, - allChatsPromise, - allChatMessagesPromise, - allTicketsToUsersPromise, - allChatsToUsersPromise, - ]); - console.log("Postgres data fetched 📦"); - - console.log("Migrating Users 👥"); - - if (allUserCommonData.length > 0) { - ///@ts-expect-error - await db.insert(schema.userCommonData).values(allUserCommonData); - // run bucket mover updates here - } - - console.log("Migrated Users ✅\n\n"); - - console.log("Migrating Hacker Data 🧑‍💻"); - - if (allUserHackerData.length > 0) { - // we need to filter our data to ensure that we do not have any repeating clerkIDs - const filteredHackerData = allUserHackerData.filter( - (value, index, self) => - self.findIndex((t) => t.clerkID === value.clerkID) === index && - allUserCommonData.find((t) => t.clerkID === value.clerkID) != - null, - ); - await db.insert(schema.userHackerData).values(filteredHackerData); - } - - console.log("Migrated Hacker Data ✅\n\n"); - - console.log("Migrating Events 📅"); - - if (allEvents.length > 0) { - await db.insert(schema.events).values(allEvents); - } - - console.log("Migrated Events ✅\n\n"); - - console.log("Migrating Files 📁"); - - if (allFiles.length > 0) { - ///@ts-expect-error - await db.insert(schema.files).values(allFiles); - } - - console.log("Migrated Files ✅\n\n"); - - console.log("Migrating Scans 📡"); - - if (allScans.length > 0) { - await db.insert(schema.scans).values(allScans); - } - - console.log("Migrated Scans ✅\n\n"); - - console.log("Migrating Error Logs 📝"); - - if (allErrorLogs.length > 0) { - await db.insert(schema.errorLog).values(allErrorLogs); - } - - console.log("Migrated Error Logs ✅\n\n"); - - console.log("Migrating Discord Verification 🤖"); - - if (alldiscordVerification.length > 0) { - await db - .insert(schema.discordVerification) - .values(alldiscordVerification); - } - - console.log("Migrated Discord Verification ✅\n\n"); - - console.log("Migrating Tickets 🎫"); - - if (allTickets.length > 0) { - await db.insert(schema.tickets).values(allTickets); - } - - console.log("Migrated Tickets ✅\n\n"); - - console.log("Migrating Chats 💬"); - - if (allChats.length > 0) { - await db.insert(schema.chats).values(allChats); - } - - console.log("Migrated Chats ✅\n\n"); - - console.log("Migrating Chat Messages 💬"); - - if (allChatMessages.length > 0) { - await db.insert(schema.chatMessages).values(allChatMessages); - } - - console.log("Migrated Chat Messages ✅\n\n"); - - console.log("Migrating Tickets To Users 🎫"); - - if (allTicketsToUsers.length > 0) { - await db.insert(schema.ticketsToUsers).values(allTicketsToUsers); - } - - console.log("Migrated Tickets To Users ✅\n\n"); - - console.log("Migrating Chats To Users 💬"); - - if (allChatsToUsers.length > 0) { - await db.insert(schema.chatsToUsers).values(allChatsToUsers); - } - - console.log("Migrated Chats To Users ✅\n\n"); - - console.log("Migrating Vercel Blob Files To R2"); - - const resumeData = await db.query.userHackerData.findMany({ - columns: { resume: true, clerkID: true }, - }); - - for (let resumeEntry of resumeData) { - const { resume: resumeUrlAsString, clerkID: userID } = resumeEntry; - if ( - !resumeUrlAsString.length || - resumeUrlAsString === c.noResumeProvidedURL || - resumeUrlAsString.startsWith("/api") - ) - continue; - - const resumeUrl = new URL(resumeUrlAsString); - const resumeFetchResponse = await fetch(resumeUrl); - - if (!resumeFetchResponse.ok) { - console.log("resume fetch failed"); - } - const resumeBlob = await resumeFetchResponse.blob(); - - let key = decodeURIComponent(resumeUrl.pathname); - // if the first character is a slash, remove it - if (key.charAt(0) === "/") { - key = key.slice(1); - } - - const buffer = await resumeBlob.arrayBuffer(); - - const cmd = new PutObjectCommand({ - Key: key, - Bucket: process.env.R2_BUCKET_NAME, - ContentType: "application/pdf", - ///@ts-expect-error - Body: buffer, - }); - - await S3.send(cmd); - - // New url to correspond to an api route - const newResumeUrl = `/api/upload/resume/view?key=${key}`; - - await db - .update(schema.userHackerData) - .set({ resume: newResumeUrl.toString() }) - .where(eq(schema.userHackerData.clerkID, userID)); - } - - console.log("Migrated Vercel Blob Files To R2"); - - return process.exit(0); -} - -migratePostgresSqLite().catch((e) => { - console.error(e); - process.exit(1); -}); diff --git a/apps/infrastructure-migrator/package.json b/apps/infrastructure-migrator/package.json deleted file mode 100644 index 312adf4a..00000000 --- a/apps/infrastructure-migrator/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "infrastructure-migrator", - "version": "1.0.0", - "description": "Helper app to make the transfer to sqlite smoother", - "main": "driver.ts", - "scripts": { - "migrate": "node -r esbuild-register driver.ts" - }, - "author": "", - "license": "ISC", - "dependencies": { - "@aws-sdk/client-s3": "^3.758.0", - "@libsql/client": "^0.14.0", - "@vercel/postgres": "^0.9.0", - "config": "workspace:*", - "db": "workspace:*", - "dotenv": "^16.4.5", - "drizzle-orm": "^0.39.3", - "esbuild-register": "^3.5.0", - "web": "workspace:*" - } -} diff --git a/apps/infrastructure-migrator/schema.ts b/apps/infrastructure-migrator/schema.ts deleted file mode 100644 index c050daa5..00000000 --- a/apps/infrastructure-migrator/schema.ts +++ /dev/null @@ -1,328 +0,0 @@ -/* - -When changes are made to this file, you must run the following command to create the SQL migrations: - -pnpm run generate - -more info: https://orm.drizzle.team/kit-docs/overview - -*/ - -import { - bigserial, - text, - varchar, - boolean, - timestamp, - integer, - json, - pgEnum, - primaryKey, - pgTable, -} from "drizzle-orm/pg-core"; -import { relations } from "drizzle-orm"; - -export const roles = pgEnum("role", [ - "hacker", - "volunteer", - "mentor", - "mlh", - "admin", - "super_admin", -]); - -export const fileTypesEnum = pgEnum("type", ["generic", "resume"]); - -export const inviteType = pgEnum("invite_status", [ - "pending", - "accepted", - "declined", -]); - -export const chatType = pgEnum("chat_type", ["ticket"]); - -export const ticketStatus = pgEnum("ticket_status", [ - "awaiting", - "in_progress", - "completed", -]); - -export const discordVerificationStatus = pgEnum("discord_status", [ - "pending", - "expired", - "accepted", - "rejected", -]); - -export const userCommonData = pgTable("user_common_data", { - // id - clerkID: varchar("clerk_id", { length: 255 }).primaryKey(), - - // data - firstName: varchar("first_name", { length: 50 }).notNull(), - lastName: varchar("last_name", { length: 50 }).notNull(), - email: varchar("email", { length: 255 }).notNull().unique(), - hackerTag: varchar("hacker_tag", { length: 50 }).notNull().unique(), - age: integer("age").notNull(), - gender: varchar("gender", { length: 50 }).notNull(), - race: varchar("race", { length: 75 }).notNull(), - ethnicity: varchar("ethnicity", { length: 50 }).notNull(), - shirtSize: varchar("shirt_size", { length: 5 }).notNull(), - dietRestrictions: json("diet_restrictions").notNull(), - accommodationNote: text("accommodation_note"), - discord: varchar("discord", { length: 60 }), - pronouns: varchar("pronouns", { length: 20 }).notNull(), - bio: text("bio").notNull(), - skills: json("skills").notNull().$type().default([]), - profilePhoto: varchar("profile_photo", { length: 255 }).notNull(), - phoneNumber: varchar("phone_number", { length: 30 }).notNull(), - countryOfResidence: varchar("country_of_residence", { - length: 3, - }).notNull(), - - // metadata - isFullyRegistered: boolean("is_fully_registered").notNull().default(false), - signupTime: timestamp("signup_time").notNull().defaultNow(), - isSearchable: boolean("is_searchable").notNull().default(true), - role: roles("role").notNull().default("hacker"), - checkinTimestamp: timestamp("checkin_timestamp"), - isRSVPed: boolean("is_rsvped").notNull().default(false), - isApproved: boolean("is_approved").notNull().default(false), -}); - -export const userCommonRelations = relations( - userCommonData, - ({ one, many }) => ({ - hackerData: one(userHackerData, { - fields: [userCommonData.clerkID], - references: [userHackerData.clerkID], - }), - discordVerification: one(discordVerification, { - fields: [userCommonData.clerkID], - references: [discordVerification.clerkID], - }), - files: many(files), - scans: many(scans), - tickets: many(ticketsToUsers), - chats: many(chatsToUsers), - messages: many(chatMessages), - }), -); - -export const userHackerData = pgTable("user_hacker_data", { - // id - clerkID: varchar("clerk_id", { length: 255 }).primaryKey(), - - // data - university: varchar("university", { length: 200 }).notNull(), - major: varchar("major", { length: 200 }).notNull(), - schoolID: varchar("school_id", { length: 50 }).notNull(), - levelOfStudy: varchar("level_of_study", { length: 50 }).notNull(), - hackathonsAttended: integer("hackathons_attended").notNull(), - softwareExperience: varchar("software_experience", { - length: 25, - }).notNull(), - heardFrom: varchar("heard_from", { length: 50 }), - GitHub: varchar("github", { length: 100 }), - LinkedIn: varchar("linkedin", { length: 100 }), - PersonalWebsite: varchar("personal_website", { length: 100 }), - resume: varchar("resume", { length: 255 }) - .notNull() - .default("https://static.acmutsa.org/No%20Resume%20Provided.pdf"), - - // metadata - group: integer("group").notNull(), - hasAcceptedMLHCoC: boolean("has_accepted_mlh_coc").notNull(), - hasSharedDataWithMLH: boolean("has_shared_data_with_mlh").notNull(), - isEmailable: boolean("is_emailable").notNull(), -}); - -export const userHackerRelations = relations( - userHackerData, - ({ one, many }) => ({ - commonData: one(userCommonData, { - fields: [userHackerData.clerkID], - references: [userCommonData.clerkID], - }), - }), -); - -export const events = pgTable("events", { - id: bigserial("id", { mode: "number" }).notNull().primaryKey().unique(), - title: varchar("name", { length: 255 }).notNull(), - startTime: timestamp("start_time").notNull(), - endTime: timestamp("end_time").notNull(), - location: varchar("location", { length: 255 }).default("TBD"), - description: text("description").notNull(), - type: varchar("type", { length: 50 }).notNull(), - host: varchar("host", { length: 255 }), - hidden: boolean("hidden").notNull().default(false), -}); - -export const eventsRelations = relations(events, ({ many }) => ({ - scans: many(scans), -})); - -export const files = pgTable("files", { - id: varchar("id", { length: 255 }).notNull().primaryKey().unique(), - presignedURL: text("presigned_url").notNull(), - key: varchar("key", { length: 500 }).notNull().unique(), - validated: boolean("validated").notNull().default(false), - type: fileTypesEnum("type").notNull(), - ownerID: varchar("owner_id", { length: 255 }).notNull(), -}); - -export const filesRelations = relations(files, ({ one }) => ({ - owner: one(userCommonData, { - fields: [files.ownerID], - references: [userCommonData.clerkID], - }), -})); - -export const scans = pgTable( - "scans", - { - updatedAt: timestamp("updated_at").notNull().defaultNow(), - userID: varchar("user_id", { length: 255 }).notNull(), - eventID: integer("event_id").notNull(), - count: integer("count").notNull(), - }, - (table) => ({ - id: primaryKey({ columns: [table.userID, table.eventID] }), - }), -); - -export const scansRelations = relations(scans, ({ one }) => ({ - user: one(userCommonData, { - fields: [scans.userID], - references: [userCommonData.clerkID], - }), - event: one(events, { - fields: [scans.eventID], - references: [events.id], - }), -})); - -export const errorLog = pgTable("error_log", { - id: varchar("id", { length: 50 }).notNull().primaryKey(), - createdAt: timestamp("created_at").notNull().defaultNow(), - userID: varchar("user_id", { length: 255 }), - route: varchar("route", { length: 255 }), - message: text("message").notNull(), -}); - -export const discordVerification = pgTable("discord_verification", { - code: varchar("code", { length: 255 }).notNull().primaryKey(), - createdAt: timestamp("created_at").notNull().defaultNow(), - clerkID: varchar("clerk_id", { length: 255 }), - discordUserID: varchar("discord_user_id", { length: 255 }).notNull(), - discordUserTag: varchar("discord_user_tag", { length: 255 }).notNull(), - discordProfilePhoto: varchar("discord_profile_photo", { - length: 255, - }).notNull(), - discordName: varchar("discord_name", { length: 255 }).notNull(), - status: discordVerificationStatus("status").notNull().default("pending"), - guild: varchar("guild", { length: 100 }).notNull(), -}); - -/* Tickets */ - -export const tickets = pgTable("tickets", { - id: text("id").primaryKey(), - title: varchar("title", { length: 255 }).notNull(), - description: text("description").notNull(), - status: ticketStatus("status").notNull().default("awaiting"), - createdAt: timestamp("created_at").notNull().defaultNow(), -}); - -export const ticketRelations = relations(tickets, ({ one, many }) => ({ - chat: one(chats, { - fields: [tickets.id], - references: [chats.ticketID], - }), - tickets: many(ticketsToUsers), -})); - -export const chats = pgTable("chats", { - id: text("id").primaryKey(), - type: chatType("type").notNull(), - ticketID: text("ticket_id").references(() => tickets.id), - author: text("author").notNull(), - createdAt: timestamp("created_at").notNull().defaultNow(), -}); - -export const chatRelations = relations(chats, ({ many }) => ({ - messages: many(chatMessages), - members: many(chatsToUsers), -})); - -export const chatMessages = pgTable("chat_messages", { - id: bigserial("id", { mode: "number" }).primaryKey(), - chatID: text("chat_id").notNull(), - message: text("message").notNull(), - authorID: text("author_id").notNull(), - createdAt: timestamp("created_at").notNull().defaultNow(), -}); - -export const chatMessageRelations = relations(chatMessages, ({ one }) => ({ - chat: one(chats, { - fields: [chatMessages.chatID], - references: [chats.id], - }), - author: one(userCommonData, { - fields: [chatMessages.authorID], - references: [userCommonData.clerkID], - }), -})); - -export const ticketsToUsers = pgTable( - "tickets_to_users", - { - ticketID: text("ticket_id") - .notNull() - .references(() => tickets.id), - userID: text("user_id") - .notNull() - .references(() => userCommonData.clerkID), - }, - (t) => ({ - pk: primaryKey({ columns: [t.userID, t.ticketID] }), - }), -); - -export const ticketsToUserRelations = relations(ticketsToUsers, ({ one }) => ({ - ticket: one(tickets, { - fields: [ticketsToUsers.ticketID], - references: [tickets.id], - }), - user: one(userCommonData, { - fields: [ticketsToUsers.userID], - references: [userCommonData.clerkID], - }), -})); - -export const chatsToUsers = pgTable( - "chats_to_users", - { - chatID: text("chat_id") - .notNull() - .references(() => chats.id), - userID: text("user_id") - .notNull() - .references(() => userCommonData.clerkID), - }, - (t) => ({ - pk: primaryKey({ columns: [t.userID, t.chatID] }), - }), -); - -export const chatsToUserRelations = relations(chatsToUsers, ({ one }) => ({ - chat: one(chats, { - fields: [chatsToUsers.chatID], - references: [chats.id], - }), - user: one(userCommonData, { - fields: [chatsToUsers.userID], - references: [userCommonData.clerkID], - }), -})); diff --git a/apps/web/.gitignore b/apps/web/.gitignore index c77e391b..867448ea 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -35,4 +35,5 @@ yarn-error.log* next-env.d.ts # react-email -.react-email/ \ No newline at end of file +.react-email/ +certificates \ No newline at end of file diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index f4fa4300..f98177b1 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -1,6 +1,5 @@ import { fileURLToPath } from "node:url"; import createJiti from "jiti"; -import { setupDevPlatform } from "@cloudflare/next-on-pages/next-dev"; const jiti = createJiti(fileURLToPath(import.meta.url)); jiti("./src/env"); @@ -28,8 +27,4 @@ const nextConfig = { }, }; -if (process.env.NODE_ENV === "development") { - await setupDevPlatform(); -} - export default nextConfig; diff --git a/apps/web/package.json b/apps/web/package.json index 00f634f2..c92d4485 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -11,10 +11,8 @@ }, "dependencies": { "@aws-sdk/client-s3": "^3.750.0", - "@aws-sdk/client-ses": "^3.616.0", "@aws-sdk/s3-request-presigner": "^3.750.0", "@clerk/nextjs": "^6.12.12", - "@gsap/react": "^2.1.1", "@hookform/resolvers": "^3.9.0", "@internationalized/date": "^3.5.4", "@planetscale/database": "^1.18.0", @@ -32,22 +30,9 @@ "@react-email/components": "^0.0.21", "@t3-oss/env-nextjs": "^0.10.1", "@tanstack/match-sorter-utils": "^8.19.4", - "@tanstack/react-query": "^5.51.11", "@tanstack/react-table": "^8.19.3", - "@trpc/client": "11.0.0-rc.466", - "@trpc/next": "11.0.0-rc.466", - "@trpc/react-query": "11.0.0-rc.466", - "@trpc/server": "11.0.0-rc.466", - "@types/node": "20.14.11", - "@types/react": "18.3.3", - "@types/react-dom": "18.3.0", "@upstash/redis": "^1.34.4", - "@vercel/analytics": "^1.3.1", - "@vercel/blob": "^0.10.0", - "@vercel/postgres": "^0.9.0", "@yudiel/react-qr-scanner": "^2.1.0", - "autoprefixer": "10.4.19", - "axios": "^1.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cmdk": "^1.0.0", @@ -55,32 +40,21 @@ "date-fns": "^3.6.0", "date-fns-tz": "^3.1.3", "db": "workspace:*", - "dotenv": "^16.4.5", "drizzle-orm": "^0.39.3", "drizzle-zod": "^0.7.0", "embla-carousel": "8.1.7", - "embla-carousel-autoplay": "8.1.7", "embla-carousel-react": "8.1.7", - "framer-motion": "^11.3.8", - "gsap": "^3.12.5", - "jiti": "^1.21.6", "lucide-react": "^0.411.0", "nanoid": "^5.0.7", "next": "14.2.25", "next-safe-action": "^7.9.3", "nextjs@4": "link:clerk/nextjs@4", "no-profanity": "^1.5.1", - "pg": "^8.12.0", - "postcss": "8.4.39", - "postgres": "^3.4.4", - "pusher-js": "8.4.0-rc2", "react": "18.3.1", "react-aria": "^3.33.1", "react-confetti": "^6.1.0", "react-dom": "18.3.1", "react-dropzone": "^14.2.3", - "react-email": "^2.1.5", - "react-fast-marquee": "^1.6.5", "react-hook-form": "7.52.1", "react-loader-spinner": "^6.1.6", "react-parallax-tilt": "^1.7.232", @@ -92,9 +66,6 @@ "sonner": "^1.5.0", "superjson": "^2.2.1", "tailwind-merge": "^2.4.0", - "tailwindcss": "3.4.6", - "tailwindcss-animate": "^1.0.7", - "typescript": "5.5.3", "use-debounce": "^10.0.1", "usehooks-ts": "^3.1.0", "vaul": "^0.9.1", @@ -102,6 +73,16 @@ }, "devDependencies": { "@cloudflare/next-on-pages": "^1.13.10", - "esbuild-register": "^3.5.0" + "@types/node": "20.14.11", + "@types/react": "18.3.3", + "@types/react-dom": "18.3.0", + "autoprefixer": "10.4.19", + "dotenv": "16.4.5", + "esbuild-register": "^3.5.0", + "jiti": "1.21.6", + "postcss": "8.4.39", + "tailwindcss": "3.4.6", + "tailwindcss-animate": "1.0.7", + "typescript": "5.5.3" } } diff --git a/apps/web/src/app/admin/check-in/page.tsx b/apps/web/src/app/admin/check-in/page.tsx index 2d35a8ed..c2ebe82c 100644 --- a/apps/web/src/app/admin/check-in/page.tsx +++ b/apps/web/src/app/admin/check-in/page.tsx @@ -53,5 +53,4 @@ export default async function Page({ ); } -export const runtime = "edge"; export const dynamic = "force-dynamic"; diff --git a/apps/web/src/app/admin/events/new/page.tsx b/apps/web/src/app/admin/events/new/page.tsx index 95ec6faa..2de0a160 100644 --- a/apps/web/src/app/admin/events/new/page.tsx +++ b/apps/web/src/app/admin/events/new/page.tsx @@ -22,5 +22,3 @@ export default async function Page() { ); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/admin/layout.tsx b/apps/web/src/app/admin/layout.tsx index a9f02eda..6ce3f59a 100644 --- a/apps/web/src/app/admin/layout.tsx +++ b/apps/web/src/app/admin/layout.tsx @@ -104,5 +104,3 @@ export default async function AdminLayout({ children }: AdminLayoutProps) { ); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/admin/page.tsx b/apps/web/src/app/admin/page.tsx index 46952290..e02bb336 100644 --- a/apps/web/src/app/admin/page.tsx +++ b/apps/web/src/app/admin/page.tsx @@ -8,10 +8,9 @@ import { } from "@/components/shadcn/ui/card"; import { Users, UserCheck, User2, TimerReset, MailCheck } from "lucide-react"; import type { User } from "db/types"; -import { notFound } from "next/navigation"; +import c from "config"; import { getAllUsers } from "db/functions"; import Link from "next/link"; -import { getRequestContext } from "@cloudflare/next-on-pages"; import { formatInTimeZone } from "date-fns-tz"; import { getClientTimeZone } from "@/lib/utils/client/shared"; import { getCurrentUser } from "@/lib/utils/server/user"; @@ -27,9 +26,8 @@ export default async function Page() { recentSignupCount, recentRegisteredUsers, } = getRecentRegistrationData(allUsers); - const { cf } = getRequestContext(); - const timezone = getClientTimeZone(cf.timezone); + const timezone = getClientTimeZone(c.hackathonTimezone); return (
@@ -192,5 +190,3 @@ function getRecentRegistrationData(users: User[]) { recentRegisteredUsers, }; } - -export const runtime = "edge"; diff --git a/apps/web/src/app/admin/points/page.tsx b/apps/web/src/app/admin/points/page.tsx deleted file mode 100644 index 3c7c79b3..00000000 --- a/apps/web/src/app/admin/points/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Points() { - return ( -
-

Coming soon...

-
- ); -} diff --git a/apps/web/src/app/admin/scanner/[id]/page.tsx b/apps/web/src/app/admin/scanner/[id]/page.tsx index 10378306..07bf230c 100644 --- a/apps/web/src/app/admin/scanner/[id]/page.tsx +++ b/apps/web/src/app/admin/scanner/[id]/page.tsx @@ -84,5 +84,4 @@ export default async function Page({ ); } -export const runtime = "edge"; export const dynamic = "force-dynamic"; diff --git a/apps/web/src/app/admin/toggles/landing/page.tsx b/apps/web/src/app/admin/toggles/landing/page.tsx index 7d47f644..c4e5108d 100644 --- a/apps/web/src/app/admin/toggles/landing/page.tsx +++ b/apps/web/src/app/admin/toggles/landing/page.tsx @@ -25,5 +25,4 @@ export default async function Page() { ); } -export const runtime = "edge"; export const dynamic = "force-dynamic"; diff --git a/apps/web/src/app/admin/toggles/registration/page.tsx b/apps/web/src/app/admin/toggles/registration/page.tsx index 0da223e0..fbd6ecbc 100644 --- a/apps/web/src/app/admin/toggles/registration/page.tsx +++ b/apps/web/src/app/admin/toggles/registration/page.tsx @@ -46,5 +46,3 @@ export default async function Page() {
); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/admin/toggles/tickets/page.tsx b/apps/web/src/app/admin/toggles/tickets/page.tsx deleted file mode 100644 index c82873b7..00000000 --- a/apps/web/src/app/admin/toggles/tickets/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Page() { - return

Coming soon

; -} diff --git a/apps/web/src/app/admin/users/[slug]/page.tsx b/apps/web/src/app/admin/users/[slug]/page.tsx index de613c26..b407523e 100644 --- a/apps/web/src/app/admin/users/[slug]/page.tsx +++ b/apps/web/src/app/admin/users/[slug]/page.tsx @@ -40,6 +40,10 @@ export default async function Page({ params }: { params: { slug: string } }) { return

User Not Found

; } + const roles = await db.query.roles.findMany({ + columns: { id: true, name: true }, + }); + const banInstance = await db.query.bannedUsers.findFirst({ where: eq(bannedUsers.userID, subject.clerkID), }); @@ -83,6 +87,7 @@ export default async function Page({ params }: { params: { slug: string } }) { name={`${subject.firstName} ${subject.lastName}`} currentRoleId={subject.role_id} userID={subject.clerkID} + roles={roles} /> @@ -146,6 +151,7 @@ export default async function Page({ params }: { params: { slug: string } }) { name={`${subject.firstName} ${subject.lastName}`} currentRoleId={subject.role_id} userID={subject.clerkID} + roles={roles} /> @@ -203,5 +209,3 @@ export default async function Page({ params }: { params: { slug: string } }) { ); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/admin/users/page.tsx b/apps/web/src/app/admin/users/page.tsx index fedcb66d..aebc72e2 100644 --- a/apps/web/src/app/admin/users/page.tsx +++ b/apps/web/src/app/admin/users/page.tsx @@ -53,5 +53,4 @@ export default async function Page() { ); } -export const runtime = "edge"; export const revalidate = 10; diff --git a/apps/web/src/app/api/admin/export/route.ts b/apps/web/src/app/api/admin/export/route.ts index ffeebcf0..bbb3e8c4 100644 --- a/apps/web/src/app/api/admin/export/route.ts +++ b/apps/web/src/app/api/admin/export/route.ts @@ -75,5 +75,3 @@ export async function GET() { }, }); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/api/trpc/[trpc]/route.ts b/apps/web/src/app/api/trpc/[trpc]/route.ts deleted file mode 100644 index b30be48a..00000000 --- a/apps/web/src/app/api/trpc/[trpc]/route.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { fetchRequestHandler } from "@trpc/server/adapters/fetch"; -import { type NextRequest } from "next/server"; - -import { env } from "@/env"; -import { appRouter } from "@/server/api/root"; -import { createTRPCContext } from "@/server/api/trpc"; - -/** - * This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when - * handling a HTTP request (e.g. when you make requests from Client Components). - */ -const createContext = async (req: NextRequest) => { - return createTRPCContext({ - headers: req.headers, - }); -}; - -const handler = (req: NextRequest) => - fetchRequestHandler({ - endpoint: "/api/trpc", - req, - router: appRouter, - createContext: () => createContext(req), - onError: - env.NODE_ENV === "development" - ? ({ path, error }) => { - console.error( - `❌ tRPC failed on ${path ?? ""}: ${error.message}`, - ); - } - : undefined, - }); - -export { handler as GET, handler as POST }; diff --git a/apps/web/src/app/api/upload/pfp/route.ts b/apps/web/src/app/api/upload/pfp/route.ts index 187c34ae..eefc7620 100644 --- a/apps/web/src/app/api/upload/pfp/route.ts +++ b/apps/web/src/app/api/upload/pfp/route.ts @@ -39,5 +39,3 @@ export async function POST(request: Request): Promise { ); } } - -export const runtime = "edge"; diff --git a/apps/web/src/app/api/upload/resume/register/route.ts b/apps/web/src/app/api/upload/resume/register/route.ts index b05e53e6..d8d5f7a4 100644 --- a/apps/web/src/app/api/upload/resume/register/route.ts +++ b/apps/web/src/app/api/upload/resume/register/route.ts @@ -38,5 +38,3 @@ export async function POST(request: Request): Promise { ); } } - -export const runtime = "edge"; diff --git a/apps/web/src/app/api/upload/resume/view/route.ts b/apps/web/src/app/api/upload/resume/view/route.ts index 5e54bf21..67bfae86 100644 --- a/apps/web/src/app/api/upload/resume/view/route.ts +++ b/apps/web/src/app/api/upload/resume/view/route.ts @@ -31,5 +31,3 @@ export async function GET(request: Request) { return redirect(presignedViewingUrl); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/dash/layout.tsx b/apps/web/src/app/dash/layout.tsx index 5e85035c..38d1bbb5 100644 --- a/apps/web/src/app/dash/layout.tsx +++ b/apps/web/src/app/dash/layout.tsx @@ -8,8 +8,6 @@ import DashNavItem from "@/components/dash/shared/DashNavItem"; import { redirect } from "next/navigation"; import ProfileButton from "@/components/shared/ProfileButton"; import ClientToast from "@/components/shared/ClientToast"; - -import { TRPCReactProvider } from "@/trpc/react"; import { getUser } from "db/functions"; interface DashLayoutProps { @@ -35,62 +33,58 @@ export default async function DashLayout({ children }: DashLayoutProps) { return ( <> - - -
-
- - {c.hackathonName - + +
+
+ + {c.hackathonName + -
-

Dashboard

-
-
- - - - - - - - - - -
-
- -
+
+

Dashboard

+
+
+ + + + + + + + + +
-
- {Object.entries(c.dashPaths.dash).map(([name, path]) => ( - - ))} +
+
- {children} - +
+
+ {Object.entries(c.dashPaths.dash).map(([name, path]) => ( + + ))} +
+ {children} ); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/dash/page.tsx b/apps/web/src/app/dash/page.tsx index 0706c249..90cdef25 100644 --- a/apps/web/src/app/dash/page.tsx +++ b/apps/web/src/app/dash/page.tsx @@ -41,5 +41,3 @@ export default async function Page() {
); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/dash/pass/page.tsx b/apps/web/src/app/dash/pass/page.tsx index baf48a46..e4cdcb7d 100644 --- a/apps/web/src/app/dash/pass/page.tsx +++ b/apps/web/src/app/dash/pass/page.tsx @@ -134,5 +134,3 @@ function EventPass({ qrPayload, user, clerk, guild }: EventPassProps) {
); } - -export const runtime = "edge"; diff --git a/apps/web/src/app/dash/schedule/page.tsx b/apps/web/src/app/dash/schedule/page.tsx index 1185bf63..0508ba6c 100644 --- a/apps/web/src/app/dash/schedule/page.tsx +++ b/apps/web/src/app/dash/schedule/page.tsx @@ -1,12 +1,12 @@ import ScheduleTimeline from "./schedule-timeline"; import { getAllEvents } from "db/functions"; import { getClientTimeZone } from "@/lib/utils/client/shared"; -import { getRequestContext } from "@cloudflare/next-on-pages"; +import c from "config"; + export default async function Page() { const sched = await getAllEvents(); - const { cf } = getRequestContext(); - const userTimeZoneHeaderKey = cf.timezone; - const userTimeZone = getClientTimeZone(userTimeZoneHeaderKey); + + const userTimeZone = getClientTimeZone(c.hackathonTimezone); return ( <>

Schedule

@@ -15,5 +15,4 @@ export default async function Page() { ); } -export const runtime = "edge"; export const revalidate = 60; diff --git a/apps/web/src/app/dash/tickets/layout.tsx b/apps/web/src/app/dash/tickets/layout.tsx deleted file mode 100644 index 57fa0115..00000000 --- a/apps/web/src/app/dash/tickets/layout.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import TicketList from "@/components/dash/tickets/TicketList"; - -export default function TicketsLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( -
- -
{children}
-
- ); -} diff --git a/apps/web/src/app/dash/tickets/new/page.tsx b/apps/web/src/app/dash/tickets/new/page.tsx deleted file mode 100644 index 82e0ddff..00000000 --- a/apps/web/src/app/dash/tickets/new/page.tsx +++ /dev/null @@ -1,60 +0,0 @@ -"use client"; -import { useState } from "react"; -import { Input } from "@/components/shadcn/ui/input"; -import { Label } from "@/components/shadcn/ui/label"; -import { Textarea } from "@/components/shadcn/ui/textarea"; -import { Button } from "@/components/shadcn/ui/button"; -import { api } from "@/trpc/react"; -import { toast } from "sonner"; - -export default function Page() { - const [title, setTitle] = useState(""); - const [description, setDescription] = useState(""); - - const createTicket = api.tickets.create.useMutation(); - - async function runCreateTicket() { - if (title.length > 3 && description.length > 10) { - const result = await createTicket.mutateAsync({ - title, - description, - }); - if (result.success) { - toast.success("Ticket created successfully!"); - console.log( - "created ticket with ID " + - result.ticketID + - " and chat with ID " + - result.chatID, - ); - } - } else { - toast.error( - "Your title or description is too short! Please try again.", - ); - } - } - - return ( -
-
-

New Ticket

-
-
- - setTitle(e.target.value)} /> -
-
- -