From 928ff406013bf8e1de65f3d79d67e175f7e634f4 Mon Sep 17 00:00:00 2001 From: kpranat Date: Sat, 30 May 2026 12:40:56 +0530 Subject: [PATCH 01/17] added dev md --- DEV.MD | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 DEV.MD diff --git a/DEV.MD b/DEV.MD new file mode 100644 index 0000000..e69de29 From bb0f96f112646669fb0e7b9db1b47d52616bec31 Mon Sep 17 00:00:00 2001 From: akankshaxa Date: Wed, 3 Jun 2026 18:38:37 +0530 Subject: [PATCH 02/17] initialised backend infrastructure with neon and drizzle --- drizzle.config.ts | 0 src/db/schema.ts | 0 src/lib/db.ts | 5 +++++ 3 files changed, 5 insertions(+) create mode 100644 drizzle.config.ts create mode 100644 src/db/schema.ts create mode 100644 src/lib/db.ts diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/db/schema.ts b/src/db/schema.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/db.ts b/src/lib/db.ts new file mode 100644 index 0000000..227f306 --- /dev/null +++ b/src/lib/db.ts @@ -0,0 +1,5 @@ +import { neon } from '@neondatabase/serverless'; +import { drizzle } from 'drizzle-orm/neon-http'; + +const sql = neon(process.env.DATABASE_URL!); +export const db = drizzle(sql); \ No newline at end of file From 60106ad154485b79aad2f83cc1478ef87c23b6aa Mon Sep 17 00:00:00 2001 From: akankshaxa Date: Wed, 3 Jun 2026 18:55:25 +0530 Subject: [PATCH 03/17] finalised data schema and confirmed connection --- bun.lock | 188 +++++++++++++++++++++++++++++++++++++++++++++- drizzle.config.ts | 8 ++ package.json | 6 +- 3 files changed, 200 insertions(+), 2 deletions(-) diff --git a/bun.lock b/bun.lock index 97904d2..8b7706f 100644 --- a/bun.lock +++ b/bun.lock @@ -5,8 +5,10 @@ "": { "name": "performance-trakcer", "dependencies": { + "@neondatabase/serverless": "^1.1.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "drizzle-orm": "^0.45.2", "lucide-react": "^1.16.0", "next": "16.2.6", "radix-ui": "^1.4.3", @@ -15,6 +17,7 @@ "shadcn": "^4.8.0", "tailwind-merge": "^3.6.0", "tw-animate-css": "^1.4.0", + "zod": "^4.4.3", }, "devDependencies": { "@biomejs/biome": "2.2.0", @@ -22,6 +25,7 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "drizzle-kit": "^0.31.10", "tailwindcss": "^4", "typescript": "^5", }, @@ -109,10 +113,68 @@ "@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.69.1", "", { "dependencies": { "commander": "^11.1.0", "dotenv": "^17.2.1", "eciesjs": "^0.4.10", "enquirer": "^2.4.1", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "picomatch": "^4.0.4", "which": "^4.0.0", "yocto-spinner": "^1.1.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-kwQB5KcAegxw/+NGUgXAo5ovyOSjlMhoXSSnSEpDhoHJwzMcMO0HE1U0VCYZ7jbAeCMGamed9XdWzOA5ixtTNg=="], + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], + "@ecies/ciphers": ["@ecies/ciphers@0.2.6", "", { "peerDependencies": { "@noble/ciphers": "^1.0.0" } }, "sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g=="], "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], + + "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="], @@ -197,6 +259,8 @@ "@mswjs/interceptors": ["@mswjs/interceptors@0.41.9", "", { "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" } }, "sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w=="], + "@neondatabase/serverless": ["@neondatabase/serverless@1.1.0", "", {}, "sha512-r3ZZhRjEcfEdKIZnoB1RusNgvHuaBRqfCzV4Gi+5A9yUX0S4HTws/ASWqt13wL4y4I+0rqsWGdA2w7EQXHi3+Q=="], + "@next/env": ["@next/env@16.2.6", "", {}, "sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw=="], "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg=="], @@ -435,6 +499,8 @@ "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], @@ -515,6 +581,10 @@ "dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], + "drizzle-kit": ["drizzle-kit@0.31.10", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "tsx": "^4.21.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-7OZcmQUrdGI+DUNNsKBn1aW8qSoKuTH7d0mYgSP8bAzdFzKoovxEFnoGQp2dVs82EOJeYycqRtciopszwUf8bw=="], + + "drizzle-orm": ["drizzle-orm@0.45.2", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "prisma": "*", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "prisma", "sql.js", "sqlite3"] }, "sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q=="], + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "eciesjs": ["eciesjs@0.4.18", "", { "dependencies": { "@ecies/ciphers": "^0.2.5", "@noble/ciphers": "^1.3.0", "@noble/curves": "^1.9.7", "@noble/hashes": "^1.8.0" } }, "sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ=="], @@ -541,6 +611,8 @@ "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], @@ -591,6 +663,8 @@ "fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], "fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="], @@ -611,6 +685,8 @@ "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], + "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="], + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], @@ -859,6 +935,8 @@ "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], "rettime": ["rettime@0.11.11", "", {}, "sha512-ILJRqVWBCTlg9r42fFgwVZx1gnFAcQF8mRoMkbgQfIrjEDf9nbBFDFx00oloOa+Q869FUtaYDXZvEfnecQSCoQ=="], @@ -909,6 +987,8 @@ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], @@ -953,6 +1033,8 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "tsx": ["tsx@4.22.4", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg=="], + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], "type-fest": ["type-fest@5.6.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA=="], @@ -1007,7 +1089,7 @@ "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], - "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], @@ -1021,6 +1103,10 @@ "@dotenvx/dotenvx/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="], + "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], + + "@modelcontextprotocol/sdk/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "@mswjs/interceptors/@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], @@ -1059,6 +1145,10 @@ "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], + "shadcn/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "tsx/esbuild": ["esbuild@0.28.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.0", "@esbuild/android-arm": "0.28.0", "@esbuild/android-arm64": "0.28.0", "@esbuild/android-x64": "0.28.0", "@esbuild/darwin-arm64": "0.28.0", "@esbuild/darwin-x64": "0.28.0", "@esbuild/freebsd-arm64": "0.28.0", "@esbuild/freebsd-x64": "0.28.0", "@esbuild/linux-arm": "0.28.0", "@esbuild/linux-arm64": "0.28.0", "@esbuild/linux-ia32": "0.28.0", "@esbuild/linux-loong64": "0.28.0", "@esbuild/linux-mips64el": "0.28.0", "@esbuild/linux-ppc64": "0.28.0", "@esbuild/linux-riscv64": "0.28.0", "@esbuild/linux-s390x": "0.28.0", "@esbuild/linux-x64": "0.28.0", "@esbuild/netbsd-arm64": "0.28.0", "@esbuild/netbsd-x64": "0.28.0", "@esbuild/openbsd-arm64": "0.28.0", "@esbuild/openbsd-x64": "0.28.0", "@esbuild/openharmony-arm64": "0.28.0", "@esbuild/sunos-x64": "0.28.0", "@esbuild/win32-arm64": "0.28.0", "@esbuild/win32-ia32": "0.28.0", "@esbuild/win32-x64": "0.28.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw=="], + "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], "wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1079,6 +1169,50 @@ "@dotenvx/dotenvx/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="], + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], + "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -1087,6 +1221,58 @@ "enquirer/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA=="], + + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.0", "", { "os": "android", "cpu": "arm" }, "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ=="], + + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.0", "", { "os": "android", "cpu": "arm64" }, "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw=="], + + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.0", "", { "os": "android", "cpu": "x64" }, "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA=="], + + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q=="], + + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ=="], + + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q=="], + + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw=="], + + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw=="], + + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A=="], + + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ=="], + + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg=="], + + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w=="], + + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg=="], + + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ=="], + + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q=="], + + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.0", "", { "os": "linux", "cpu": "x64" }, "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ=="], + + "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw=="], + + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.0", "", { "os": "none", "cpu": "x64" }, "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw=="], + + "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g=="], + + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA=="], + + "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w=="], + + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw=="], + + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA=="], + + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA=="], + + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.0", "", { "os": "win32", "cpu": "x64" }, "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw=="], + "wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], diff --git a/drizzle.config.ts b/drizzle.config.ts index e69de29..d7652f2 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -0,0 +1,8 @@ +export default { + schema: "./src/db/schema.ts", + out: "./drizzle", + dialect: "postgresql", + dbCredentials: { + url: process.env.DATABASE_URL!, + }, +} satisfies import("drizzle-kit").Config; \ No newline at end of file diff --git a/package.json b/package.json index c10c3a7..18d8f65 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "format": "biome format --write" }, "dependencies": { + "@neondatabase/serverless": "^1.1.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "drizzle-orm": "^0.45.2", "lucide-react": "^1.16.0", "next": "16.2.6", "radix-ui": "^1.4.3", @@ -19,7 +21,8 @@ "react-dom": "19.2.4", "shadcn": "^4.8.0", "tailwind-merge": "^3.6.0", - "tw-animate-css": "^1.4.0" + "tw-animate-css": "^1.4.0", + "zod": "^4.4.3" }, "devDependencies": { "@biomejs/biome": "2.2.0", @@ -27,6 +30,7 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "drizzle-kit": "^0.31.10", "tailwindcss": "^4", "typescript": "^5" }, From ccbb419503032707f02ae738a61dfbb78e459083 Mon Sep 17 00:00:00 2001 From: akankshaxa Date: Mon, 8 Jun 2026 12:36:52 +0530 Subject: [PATCH 04/17] members data --- src/db/schema.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/db/schema.ts b/src/db/schema.ts index e69de29..5b48ee2 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -0,0 +1,9 @@ +import { pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"; + +export const members = pgTable("members", { + id: serial("id").primaryKey(), + name: text("name").notNull(), + email: text("email").unique().notNull(), + role: text("role").default("member").notNull(), + createdAt: timestamp("created_at").defaultNow(), +}); From f95034ea01263c81057101e0cd97853e69f56d50 Mon Sep 17 00:00:00 2001 From: akankshaxa Date: Tue, 9 Jun 2026 18:35:54 +0530 Subject: [PATCH 05/17] added complete database schema --- src/db/schema.ts | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/db/schema.ts b/src/db/schema.ts index 5b48ee2..c73bc4b 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -1,9 +1,55 @@ -import { pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"; +import { pgTable, serial, text, timestamp, integer, jsonb } from "drizzle-orm/pg-core"; export const members = pgTable("members", { id: serial("id").primaryKey(), name: text("name").notNull(), email: text("email").unique().notNull(), role: text("role").default("member").notNull(), + join_date: timestamp("join_date").defaultNow(), createdAt: timestamp("created_at").defaultNow(), }); + +export const profiles = pgTable("profiles", { + id: serial("id").primaryKey(), + memberId: integer("member_id").references(() => members.id), + domain: text("domain").notNull(), + expertiseLevel: text("expertise_level").notNull(), + totalPoints: integer("total_points").default(0), + collegeDept: text("college_dept").notNull(), +}); + +export const leads = pgTable("leads", { + id: serial("id").primaryKey(), + memberId: integer("member_id").references(() => members.id), + domain: text("domain").notNull(), +}); + +export const events = pgTable("events", { + id: serial("id").primaryKey(), + eventName: text("event_name").notNull(), + createdBy: integer("created_by").references(() => members.id), +}); + +export const assignments = pgTable("assignments", { + id: serial("id").primaryKey(), + memberId: integer("member_id").references(() => members.id), + eventId: integer("event_id").references(() => events.id), + pointsAwarded: integer("points_awarded").default(0), + //status: text("status").default("Assigned").notNull(), +}); + +export const formComponents = pgTable("form_components", { + id: serial("id").primaryKey(), + eventId: integer("event_id").references(() => events.id), + domainDist: jsonb("domain_dist").notNull(), + venueName: text("venue_name").notNull(), + venueCapacity: integer("venue_capacity").notNull(), +}); + +export const freeHours = pgTable("free_hours", { + id: serial("id").primaryKey(), + memberId: integer("member_id").references(() => members.id), + dayOrder: integer("day_order"), + startTime: time("start_time"), + endTime: time("end_time"), +}); \ No newline at end of file From 65b554807dd4b84ded9b622c75210f1b56b993e7 Mon Sep 17 00:00:00 2001 From: akankshaxa Date: Tue, 9 Jun 2026 20:06:37 +0530 Subject: [PATCH 06/17] updated schema with status --- src/db/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/db/schema.ts b/src/db/schema.ts index c73bc4b..2da1ef9 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -35,7 +35,7 @@ export const assignments = pgTable("assignments", { memberId: integer("member_id").references(() => members.id), eventId: integer("event_id").references(() => events.id), pointsAwarded: integer("points_awarded").default(0), - //status: text("status").default("Assigned").notNull(), + status: text("status").default("Assigned").notNull(), }); export const formComponents = pgTable("form_components", { From c3ed7710ef22f9cfe36579b2cef7e5e8790522e1 Mon Sep 17 00:00:00 2001 From: akankshaxa Date: Mon, 15 Jun 2026 16:37:20 +0530 Subject: [PATCH 07/17] added auth login and tests --- bun.lock | 10 ++++++++++ package.json | 2 ++ src/auth.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/db/schema.ts | 3 ++- src/test.ts | 31 +++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/auth.ts create mode 100644 src/test.ts diff --git a/bun.lock b/bun.lock index 8b7706f..369c00e 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,7 @@ "name": "performance-trakcer", "dependencies": { "@neondatabase/serverless": "^1.1.0", + "bcrypt": "^6.0.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "drizzle-orm": "^0.45.2", @@ -22,6 +23,7 @@ "devDependencies": { "@biomejs/biome": "2.2.0", "@tailwindcss/postcss": "^4", + "@types/bcrypt": "^6.0.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", @@ -455,6 +457,8 @@ "@ts-morph/common": ["@ts-morph/common@0.27.0", "", { "dependencies": { "fast-glob": "^3.3.3", "minimatch": "^10.0.1", "path-browserify": "^1.0.1" } }, "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ=="], + "@types/bcrypt": ["@types/bcrypt@6.0.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ=="], + "@types/node": ["@types/node@20.19.41", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ=="], "@types/react": ["@types/react@19.2.15", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q=="], @@ -491,6 +495,8 @@ "baseline-browser-mapping": ["baseline-browser-mapping@2.10.32", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg=="], + "bcrypt": ["bcrypt@6.0.0", "", { "dependencies": { "node-addon-api": "^8.3.0", "node-gyp-build": "^4.8.4" } }, "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg=="], + "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], "brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], @@ -849,10 +855,14 @@ "next": ["next@16.2.6", "", { "dependencies": { "@next/env": "16.2.6", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.6", "@next/swc-darwin-x64": "16.2.6", "@next/swc-linux-arm64-gnu": "16.2.6", "@next/swc-linux-arm64-musl": "16.2.6", "@next/swc-linux-x64-gnu": "16.2.6", "@next/swc-linux-x64-musl": "16.2.6", "@next/swc-win32-arm64-msvc": "16.2.6", "@next/swc-win32-x64-msvc": "16.2.6", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw=="], + "node-addon-api": ["node-addon-api@8.8.0", "", {}, "sha512-c5Ko1fZJIJmzhFIkhRN76WTq+fC6tWnGy9CXA0fA+XygsWZmEwG8vmbkNqxMyoaa0Tin4djul49NzdVcJJcjeA=="], + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], + "node-releases": ["node-releases@2.0.46", "", {}, "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ=="], "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], diff --git a/package.json b/package.json index 18d8f65..cb6a22f 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@neondatabase/serverless": "^1.1.0", + "bcrypt": "^6.0.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "drizzle-orm": "^0.45.2", @@ -27,6 +28,7 @@ "devDependencies": { "@biomejs/biome": "2.2.0", "@tailwindcss/postcss": "^4", + "@types/bcrypt": "^6.0.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", diff --git a/src/auth.ts b/src/auth.ts new file mode 100644 index 0000000..8ad238a --- /dev/null +++ b/src/auth.ts @@ -0,0 +1,45 @@ +import bcrypt from "bcrypt"; +import { db } from "./lib/db"; +import { members } from "./db/schema"; +import { eq } from "drizzle-orm"; + +export async function loginUser(email: string, password: string) { + const users = await db.select().from(members).where(eq(members.email, email)).limit(1); + + if (users.length === 0) { + return { success: false, message: "User not found" }; + } + + const foundUser = users[0]; + + + const isMatch = await bcrypt.compare(password, foundUser.password_hash); + + + if (isMatch) { + return { success: true, user: foundUser }; + } else { + return { success: false, message: "Invalid password" }; + } +} + +export async function registerMember(name: string, email: string, plainTextPassword: string) { + try { + + const saltRounds = 12; + const hashedPassword = await bcrypt.hash(plainTextPassword, saltRounds); + + const newMember = await db.insert(members).values({ + name: name, + email: email, + password_hash: hashedPassword, + }).returning(); + + console.log("Success! Member created:", newMember[0].name); + return { success: true, member: newMember[0] }; + + } catch (error) { + console.error("Error creating member:", error); + return { success: false, message: "Failed to register member. Email might already exist." }; + } +} \ No newline at end of file diff --git a/src/db/schema.ts b/src/db/schema.ts index 2da1ef9..f4c1adb 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -1,9 +1,10 @@ -import { pgTable, serial, text, timestamp, integer, jsonb } from "drizzle-orm/pg-core"; +import { pgTable, serial, text, timestamp, time, integer, jsonb } from "drizzle-orm/pg-core"; export const members = pgTable("members", { id: serial("id").primaryKey(), name: text("name").notNull(), email: text("email").unique().notNull(), + password_hash: text("password_hash").notNull(), role: text("role").default("member").notNull(), join_date: timestamp("join_date").defaultNow(), createdAt: timestamp("created_at").defaultNow(), diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..dcef2af --- /dev/null +++ b/src/test.ts @@ -0,0 +1,31 @@ +import { registerMember, loginUser } from "./src/auth"; + +async function runTests() { + console.log("--- Starting Backend Tests ---"); + + console.log("\nTesting Registration..."); + const registerResult = await registerMember( + "Test User", + "testuser@example.com", + "mySecretPassword123" + ); + console.log(registerResult); + + console.log("\nTesting Login..."); + const loginResult = await loginUser( + "testuser@example.com", + "mySecretPassword123" + ); + console.log(loginResult); + + console.log("\nTesting Failed Login..."); + const failedLogin = await loginUser( + "testuser@example.com", + "wrongpassword!" + ); + console.log(failedLogin); + + process.exit(0); +} + +runTests(); \ No newline at end of file From 234fdc160af606b36f202302ec98c9754e39c453 Mon Sep 17 00:00:00 2001 From: akankshaxa Date: Mon, 15 Jun 2026 16:44:20 +0530 Subject: [PATCH 08/17] updated file directory --- src/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test.ts b/src/test.ts index dcef2af..cb39972 100644 --- a/src/test.ts +++ b/src/test.ts @@ -1,4 +1,4 @@ -import { registerMember, loginUser } from "./src/auth"; +import { registerMember, loginUser } from "./auth"; async function runTests() { console.log("--- Starting Backend Tests ---"); From 30eba1723cd2b2b4e4586bd54c5a732f4ac5ed25 Mon Sep 17 00:00:00 2001 From: TeenaSahu406 Date: Tue, 30 Jun 2026 15:41:56 +0530 Subject: [PATCH 09/17] Frontend --- bun.lock | 9 +- package.json | 7 +- src/app/assignments/page.tsx | 270 ++++++++++++++++ src/app/availability/page.tsx | 242 ++++++++++++++ src/app/dashboard/page.tsx | 574 +++++++++++++++++++++++++++++++++ src/app/events/page.tsx | 284 ++++++++++++++++ src/app/globals.css | 25 ++ src/app/layout.tsx | 92 ++++-- src/app/login/page.tsx | 115 +++++++ src/app/page.tsx | 23 +- src/app/profile/page.tsx | 409 +++++++++++++++++++++++ src/app/register/page.tsx | 167 ++++++++++ src/app/requests/page.tsx | 314 ++++++++++++++++++ src/components/NavBar.tsx | 29 ++ src/components/login-form.tsx | 17 + src/components/ui/badge.tsx | 49 +++ src/components/ui/card.tsx | 103 ++++++ src/components/ui/checkbox.tsx | 33 ++ src/components/ui/input.tsx | 19 ++ src/components/ui/label.tsx | 24 ++ 20 files changed, 2761 insertions(+), 44 deletions(-) create mode 100644 src/app/assignments/page.tsx create mode 100644 src/app/availability/page.tsx create mode 100644 src/app/dashboard/page.tsx create mode 100644 src/app/events/page.tsx create mode 100644 src/app/globals.css create mode 100644 src/app/login/page.tsx create mode 100644 src/app/profile/page.tsx create mode 100644 src/app/register/page.tsx create mode 100644 src/app/requests/page.tsx create mode 100644 src/components/NavBar.tsx create mode 100644 src/components/login-form.tsx create mode 100644 src/components/ui/badge.tsx create mode 100644 src/components/ui/card.tsx create mode 100644 src/components/ui/checkbox.tsx create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/label.tsx diff --git a/bun.lock b/bun.lock index 97904d2..2d42071 100644 --- a/bun.lock +++ b/bun.lock @@ -7,8 +7,9 @@ "dependencies": { "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^1.16.0", + "lucide-react": "^1.18.0", "next": "16.2.6", + "postcss": "^8.5.15", "radix-ui": "^1.4.3", "react": "19.2.4", "react-dom": "19.2.4", @@ -18,11 +19,11 @@ }, "devDependencies": { "@biomejs/biome": "2.2.0", - "@tailwindcss/postcss": "^4", + "@tailwindcss/postcss": "^4.3.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "tailwindcss": "^4", + "tailwindcss": "^4.3.0", "typescript": "^5", }, }, @@ -733,7 +734,7 @@ "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - "lucide-react": ["lucide-react@1.16.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-dYwyPzb4MEKpGUmNYk3WKWPnMrHs3FKM+q94kAnJrcDIqqn1hq2xY8scaS2ovsOCM5D51ey2gaRG3PBb1vgoYQ=="], + "lucide-react": ["lucide-react@1.18.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-LZDb7H/0YfM+RJncD0hDQRCAu+vSGODqpe35TuVI8EuXaRjkczbsx7p8dY4J87F/MUSj6bpYqeI8nw8qXaAdmA=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], diff --git a/package.json b/package.json index c10c3a7..484a3dd 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,9 @@ "dependencies": { "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^1.16.0", + "lucide-react": "^1.18.0", "next": "16.2.6", + "postcss": "^8.5.15", "radix-ui": "^1.4.3", "react": "19.2.4", "react-dom": "19.2.4", @@ -23,11 +24,11 @@ }, "devDependencies": { "@biomejs/biome": "2.2.0", - "@tailwindcss/postcss": "^4", + "@tailwindcss/postcss": "^4.3.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "tailwindcss": "^4", + "tailwindcss": "^4.3.0", "typescript": "^5" }, "ignoreScripts": [ diff --git a/src/app/assignments/page.tsx b/src/app/assignments/page.tsx new file mode 100644 index 0000000..74106bb --- /dev/null +++ b/src/app/assignments/page.tsx @@ -0,0 +1,270 @@ +"use client"; + +import { NavBar } from "@/components/NavBar"; +import { + Card, + CardContent, + CardHeader, + CardTitle, +} from "@/components/ui/card"; + +import { Badge } from "@/components/ui/badge"; + +import { + ClipboardList, + CheckCircle2, + Clock, + Trophy, +} from "lucide-react"; + +export default function AssignmentsPage() { + + // Backend integration later + + const assignments = [ + // { + // eventName:"", + // status:"", + // pointsAwarded:0 + // } + ]; + + return ( + +
+ + + +
+ +
+ +

+ Assignments +

+ +

+ View your assigned events and contribution status. +

+ +
+ + {/* Summary */} + +
+ + + + + + + Total Assignments + + + + + + +
+ +

+ + {assignments.length} + +

+ + + +
+ +
+ +
+ + + + + + + + Assigned + + + + + + + +
+ +

+ + { + assignments.filter( + (item:any)=>item.status==="Assigned" + ).length + } + +

+ + + +
+ +
+ +
+ + + + + + + + Completed + + + + + + + +
+ +

+ + { + assignments.filter( + (item:any)=>item.status==="Completed" + ).length + } + +

+ + + +
+ +
+ +
+ +
+ {/* Assignments Table */} + + + + + + + My Assignments + + + + + + + {assignments.length === 0 ? ( + +
+ + + +

+ No Assignments +

+ +

+ You don't have any assignments yet. +

+ +
+ + ) : ( + +
+ + + + + + + + + + + + + + + + + + + + {assignments.map((assignment: any, index: number) => ( + + + + + + + + + + + + ))} + + + +
+ Event + + Status + + Points Awarded +
+ + {assignment.eventName} + + + + + + {assignment.status} + + + + + + {assignment.pointsAwarded} + +
+ +
+ + )} + +
+ +
+ +
+ +
+ + ); + +} \ No newline at end of file diff --git a/src/app/availability/page.tsx b/src/app/availability/page.tsx new file mode 100644 index 0000000..c8240e4 --- /dev/null +++ b/src/app/availability/page.tsx @@ -0,0 +1,242 @@ +"use client"; + +import { useState } from "react"; + +import { NavBar } from "@/components/NavBar"; + +import { + Card, + CardContent, + CardHeader, + CardTitle, + CardFooter, +} from "@/components/ui/card"; + +import { Button } from "@/components/ui/button"; + +import { Label } from "@/components/ui/label"; + +import { Clock, Plus } from "lucide-react"; + +export default function AvailabilityPage() { + + // Backend integration later + + const [slots, setSlots] = useState([ + { + day: "", + startTime: "", + endTime: "", + }, + ]); + + const addSlot = () => { + + setSlots([ + ...slots, + { + day: "", + startTime: "", + endTime: "", + }, + ]); + + }; + + const updateSlot = ( + index: number, + field: string, + value: string + ) => { + + const updated = [...slots]; + + updated[index] = { + ...updated[index], + [field]: value, + }; + + setSlots(updated); + + }; + + return ( + +
+ + + +
+ +
+ +

+ + Availability + +

+ +

+ + Add your available time slots for event assignments. + +

+ +
+ + + + + + + + + + Free Hours + + + + + + + {slots.map((slot, index) => ( + +
+ + {/* Day */} + +
+ + + + + +
+ + {/* Start Time */} + +
+ + + + + updateSlot(index, "startTime", e.target.value) + } + className=" + w-full + mt-2 + rounded-xl + border + border-gray-300 + px-4 + py-3 + " + /> + +
+ + {/* End Time */} + +
+ + + + + updateSlot(index, "endTime", e.target.value) + } + className=" + w-full + mt-2 + rounded-xl + border + border-gray-300 + px-4 + py-3 + " + /> + +
+ +
+ + ))} + +
+ + + + + + + + + +
+ +
+ +
+ + ); + +} \ No newline at end of file diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 0000000..84160a6 --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,574 @@ +"use client"; + +import { NavBar } from "@/components/NavBar"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; + +import { + LayoutDashboard, + CalendarDays, + Clock, + Award, + Users, + CheckCircle2, + Trophy, + ArrowRight, +} from "lucide-react"; + +export default function DashboardPage() { + /* + Temporary Dummy Data + Backend integration later + */ + + const role = "member"; + // member + // associate_lead + // lead + // vice_president + // president + + const profile = { + name: "", + domain: "", + badges: 0, + totalPoints: 0, + }; + const assignments: { + title: string; + status: string; + }[] = []; + const events: { + name: string; + date: string; + venue: string; + }[] = []; + + const requests = { + pending: 0, + approved: 0, + rejected: 0, + }; + + const badges: string[] = []; + + return ( +
+ + + +
+ + {/* Header */} + +
+ +
+ +
+ + + +

+ Performance Tracker +

+ +
+ +

+ Welcome back +

+ +
+ +
+ +

+ Current Role +

+ +

+ {role.replace("_", " ")} +

+ +
+ +
+ {/* Stats */} + +
+ + {/* Domain */} + + + + + + + Domain + + + + + + + + +

+ {profile.domain} +

+ +
+ +
+ + {/* Badges */} + + + + + + + Badges + + + + + + + + +

+ {profile.badges} +

+ +
+ +
+ + {/* Pending */} + + + + + + + Pending Tasks + + + + + + + + +

+ { + assignments.filter( + (item) => item.status === "Pending" + ).length + } +

+ +
+ +
+ + {/* Completed */} + + + + + + + Completed + + + + + + + + +

+ { + assignments.filter( + (item) => item.status === "Completed" + ).length + } +

+ +
+ +
+ +
+ + {/* Lead Analytics */} + + {(role === "lead" || + role === "associate_lead" || + role === "vice_president" || + role === "president") && ( + + + + + + + + + + Lead Analytics + + + + + + + +
+ +
+ +

+ Total Points +

+ +

+ {profile.totalPoints} +

+ +
+ +
+ +

+ Active Events +

+ +

+ {events.length} +

+ +
+ +
+ +

+ Total Badges +

+ +

+ {profile.badges} +

+ +
+ +
+ +
+ +
+ + )} + + {/* Progress */} + + {/* + + + +
+ + + Contribution Progress + + + + 65% + + +
+ +
+ +
+ +
+ +

+ Complete more assignments to earn new badges. +

+ + + + */} + + {/* Main Grid */} + +
+ {/* Upcoming Events */} + + + + + + + + + + Upcoming Events + + + + + + + + {events.map((event, index) => ( + +
+ +
+ +

+ {event.name} +

+ +

+ {event.venue} +

+ +
+ + + {event.date} + + +
+ + ))} + +
+ +
+ + {/* Quick Actions */} + + + + + + + + Quick Actions + + + + + + + + + + + + + + {(role === "lead" || + role === "associate_lead" || + role === "vice_president" || + role === "president") && ( + + + + )} + + + + + + {/* Recent Activity */} + + + + + + + + Recent Activity + + + + + + + + {assignments.map((assignment, index) => ( + +
+ +
+ +

+ {assignment.title} +

+ +

+ Assignment +

+ +
+ + + {assignment.status} + + +
+ + ))} + +
+ +
+ {/* My Requests */} + + + + + + + + My Requests + + + + + + + +
+ + Pending + + + {requests.pending} + + +
+ +
+ + Approved + + + {requests.approved} + + +
+ +
+ + Rejected + + + {requests.rejected} + + +
+ +
+ +
+ + {/* Achievements */} + + + + + + + + Achievements + + + + + + + + {badges.map((badge, index) => ( + +
+ +
+ + + + {badge} + +
+ + + +
+ + ))} + +
+ +
+ +
+ +
+ +
+ ); +} \ No newline at end of file diff --git a/src/app/events/page.tsx b/src/app/events/page.tsx new file mode 100644 index 0000000..93379fc --- /dev/null +++ b/src/app/events/page.tsx @@ -0,0 +1,284 @@ +"use client"; + +import { useState } from "react"; + +import { NavBar } from "@/components/NavBar"; + +import { + Card, + CardContent, + CardHeader, + CardTitle, + CardFooter, +} from "@/components/ui/card"; + +import { Button } from "@/components/ui/button"; + +import { Input } from "@/components/ui/input"; + +import { Label } from "@/components/ui/label"; + +import { + CalendarPlus, + MapPin, + Building2, + Users, +} from "lucide-react"; + +export default function EventsPage() { + + // Backend Integration Later + + const role = "member"; + // member + // associate_lead + // lead + // vice_president + // president + + const [event, setEvent] = useState({ + eventName: "", + venueName: "", + venueCapacity: "", + tech: "", + operations: "", + design: "", + }); + + const handleChange = ( + e: React.ChangeEvent + ) => { + + setEvent({ + ...event, + [e.target.id]: e.target.value, + }); + + }; + + const canCreateEvent = + role === "lead" || + role === "associate_lead" || + role === "vice_president" || + role === "president"; + + return ( + +
+ + + +
+ +
+ +

+ Events +

+ +

+ Manage club events and volunteer requirements. +

+ +
+ + {!canCreateEvent ? ( + + + + + + + +

+ + Event Creation Restricted + +

+ +

+ + Only Leads, Associate Leads, + Vice President and President + can create new events. + +

+ +
+ +
+ + ) : ( + + + + + + + + Create Event + + + + + + + {/* Event Name */} + +
+ + + + + +
+ + {/* Venue */} + +
+ + + +
+ + + + + +
+ +
+ + {/* Venue Capacity */} + +
+ + + +
+ + + + + +
+ +
+ + {/* Domain Distribution */} + +
+ + + +

+ Number of volunteers required from each domain. +

+ +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ +
+ +
+ + + + + + + +
+ + )} + +
+ +
+ + ); + +} \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 0000000..008af93 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,25 @@ +/* @import "tailwindcss"; */ +@import "tailwindcss"; + +body { + background: + radial-gradient(circle at top left, #f8f4ee 0%, transparent 40%), + radial-gradient(circle at bottom right, #f2efe9 0%, transparent 40%), + #faf8f5; + + min-height: 100vh; +} + +h1, +h2, +h3 { + letter-spacing: 1px; +} + +.card-luxury { + background: rgba(255,255,255,0.75); + backdrop-filter: blur(20px); + border-radius: 24px; + border: 1px solid rgba(255,255,255,0.6); + box-shadow: 0 20px 40px rgba(0,0,0,0.08); +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a21a30f..6d01823 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,39 +1,75 @@ -import type { Metadata } from "next"; -import { Instrument_Serif, Inter } from "next/font/google"; -import "@/styles/globals.css"; -import { cn } from "@/lib/utils"; +// import type { Metadata } from "next"; +// import { Instrument_Serif, Inter } from "next/font/google"; +// import "@/styles/globals.css"; +// import { cn } from "@/lib/utils"; -const serif = Instrument_Serif({ - variable: "--font-serif", - subsets: ["latin"], - weight: "400", -}); +// const serif = Instrument_Serif({ +// variable: "--font-serif", +// subsets: ["latin"], +// weight: "400", +// }); + +// const inter = Inter({ subsets: ["latin"], variable: "--font-sans" }); -const inter = Inter({ subsets: ["latin"], variable: "--font-sans" }); +// export const metadata: Metadata = { +// title: "Performance Tracker", +// description: "Numbers. Loads of Numbers.", +// }; -export const metadata: Metadata = { - title: "Performance Tracker", - description: "Numbers. Loads of Numbers.", -}; +// export default function RootLayout({ +// children, +// }: Readonly<{ +// children: React.ReactNode; +// }>) { +// return ( +// +// {children} +// +// ); +// } + +import "./globals.css"; +import { Cormorant_Garamond } from "next/font/google"; + +const cormorant = Cormorant_Garamond({ + subsets: ["latin"], + weight: ["400", "500", "600", "700"], +}); export default function RootLayout({ children, -}: Readonly<{ +}: { children: React.ReactNode; -}>) { +}) { return ( - - {children} + + + {children} + ); } + +// import "./globals.css"; + +// export default function RootLayout({ +// children, +// }: { +// children: React.ReactNode; +// }) { +// return ( +// +// {children} +// +// ); +// } diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx new file mode 100644 index 0000000..588f693 --- /dev/null +++ b/src/app/login/page.tsx @@ -0,0 +1,115 @@ +"use client"; + +import { useState } from "react"; +import Link from "next/link"; +import { Card, CardFooter } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Mail, Lock, LogIn } from "lucide-react"; + +export default function LoginPage() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + + const handleLogin = (e: React.FormEvent) => { + e.preventDefault(); + + // TODO: Connect login API + }; + + return ( +
+ {/* Left Side */} +
+

+ PERFORMANCE +

+ +

+ TRACKER +

+ +

+ Track • Contribute • Grow +

+
+ + {/* Right Side */} +
+ +
+
+
+ +
+ +

+ Welcome Back +

+ +

+ Sign in to continue +

+
+ +
+
+
+ + +
+ + + setEmail(e.target.value)} + /> +
+
+ +
+ + +
+ + + setPassword(e.target.value)} + /> +
+
+ + +
+
+ + +

+ Don't have an account?{" "} + + Create one + +

+
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 6918a22..9e6c9cf 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,9 +1,14 @@ -const Home = () => { - return ( -
-

Performance Tracker

- Happy Coding{" <3"} -
- ); -}; -export default Home; +// const Home = () => { +// return ( +//
+//

Performance Tracker

+// Happy Coding{" <3"} +//
+// ); +// }; +// export default Home; +import { redirect } from "next/navigation"; + +export default function Home() { + redirect("/login"); +} \ No newline at end of file diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx new file mode 100644 index 0000000..2af450d --- /dev/null +++ b/src/app/profile/page.tsx @@ -0,0 +1,409 @@ +"use client"; + +import { NavBar } from "@/components/NavBar"; +import { + Card, + CardContent, + CardHeader, + CardTitle, +} from "@/components/ui/card"; + +import { + User, + Mail, + BadgeCheck, + Calendar, + Building2, + Globe, + Award, + Trophy, +} from "lucide-react"; + +export default function ProfilePage() { + + // Temporary placeholders + // Backend integration later + + const role = "member"; + // member + // associate_lead + // lead + // vice_president + // president + + const profile = { + name: "", + email: "", + joinDate: "", + domain: "", + expertiseLevel: "", + collegeDept: "", + badges: [] as string[], + totalPoints: 0, + }; + + return ( +
+ + + +
+ + {/* Header */} + +
+ +

+ My Profile +

+ +

+ View your volunteer information and contribution details. +

+ +
+ + {/* Profile Summary */} + + + + + +
+ +
+ + + +
+ +
+ +

+ + {profile.name || "Member Name"} + +

+ +

+ + {role.replace("_", " ")} + +

+ +
+ + + + {profile.domain || "Domain"} + + + + + + {profile.expertiseLevel || "Expertise"} + + + +
+ +
+ +
+ +
+ +
+ + {/* Information Cards */} + +
+ {/* Personal Information */} + + + + + + + Personal Information + + + + + + +
+ + + +
+ +

+ Full Name +

+ +

+ {profile.name || "Not Available"} +

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

+ Email +

+ +

+ {profile.email || "Not Available"} +

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

+ Role +

+ +

+ {role.replace("_", " ")} +

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

+ Join Date +

+ +

+ {profile.joinDate || "Not Available"} +

+ +
+ +
+ +
+ +
+ + {/* Academic & Club Details */} + + + + + + + Academic & Club Details + + + + + + +
+ + + +
+ +

+ Domain +

+ +

+ {profile.domain || "Not Assigned"} +

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

+ Expertise Level +

+ +

+ {profile.expertiseLevel || "Not Available"} +

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

+ College Department +

+ +

+ {profile.collegeDept || "Not Available"} +

+ +
+ +
+ +
+ +
+ {/* Badges */} + + + + + + + Achievements + + + + + + + {profile.badges.length === 0 ? ( + +
+ + No badges earned yet. + +
+ + ) : ( + +
+ + {profile.badges.map((badge, index) => ( + +
+ + + + + {badge} + + +
+ + ))} + +
+ + )} + +
+ +
+ + {/* Lead Information */} + + {(role === "lead" || + role === "associate_lead" || + role === "vice_president" || + role === "president") && ( + + + + + + + Lead Statistics + + + + + + +
+ + + +
+ +

+ Total Contribution Points +

+ +

+ + {profile.totalPoints} + +

+ +
+ +
+ +
+ +
+ + )} + +
+ {/* Empty State */} + + {profile.name === "" && ( + + + + + + + +

+ Profile Not Available +

+ +

+ Your profile information will appear here once your account + has been synced with the database. +

+ +
+ +
+ + )} + +
+ +
+ + ); +} \ No newline at end of file diff --git a/src/app/register/page.tsx b/src/app/register/page.tsx new file mode 100644 index 0000000..ead7b47 --- /dev/null +++ b/src/app/register/page.tsx @@ -0,0 +1,167 @@ +"use client"; + +import { useState } from "react"; +import { Card, CardFooter } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { + User, + Mail, + Calendar, + Globe, + Building2, + UserPlus, +} from "lucide-react"; + +export default function RegisterPage() { + const [form, setForm] = useState({ + name: "", + email: "", + role: "", + joinDate: "", + domain: "", + department: "", + }); + + const handleChange = (e: React.ChangeEvent) => { + setForm({ + ...form, + [e.target.id]: e.target.value, + }); + }; + + return ( +
+ {/* Left Side */} +
+

+ JOIN THE +

+ +

+ COMMUNITY +

+ +

+ Contribute • Track • Grow +

+
+ + {/* Right Side */} +
+ +
+
+
+ +
+ +

+ Create Account +

+ +

+ Start your Tracker journey +

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

+ Already have an account?{" "} + + Sign In + +

+
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/app/requests/page.tsx b/src/app/requests/page.tsx new file mode 100644 index 0000000..71170d8 --- /dev/null +++ b/src/app/requests/page.tsx @@ -0,0 +1,314 @@ +"use client"; + +import { useState } from "react"; + +import { NavBar } from "@/components/NavBar"; + +import { + Card, + CardContent, + CardHeader, + CardTitle, + CardFooter, +} from "@/components/ui/card"; + +import { Button } from "@/components/ui/button"; + +import { Input } from "@/components/ui/input"; + +import { Label } from "@/components/ui/label"; + +import { Badge } from "@/components/ui/badge"; + +import { + FileText, + Send, +} from "lucide-react"; + +export default function RequestsPage() { + + // Backend Integration Later + + const [form, setForm] = useState({ + requestType: "", + event: "", + reason: "", + }); + + const requests: { + requestType: string; + event: string; + status: string; + createdAt: string; + }[] = []; + + const handleChange = ( + e: React.ChangeEvent + ) => { + + setForm({ + ...form, + [e.target.id]: e.target.value, + }); + + }; + + return ( + +
+ + + +
+ +
+ +

+ + Requests + +

+ +

+ + Submit leave or availability related requests. + +

+ +
+ + + + + + + + Raise Request + + + + + + + {/* Request Type */} + +
+ + + + + +
+ + {/* Event */} + +
+ + + + + +
+ + {/* Reason */} + +
+ + + +