Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
376 changes: 376 additions & 0 deletions .agents/skills/neon-postgres/SKILL.md

Large diffs are not rendered by default.

343 changes: 343 additions & 0 deletions .agents/skills/neon/SKILL.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .neon
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Empty file added DEV.MD
Empty file.
808 changes: 582 additions & 226 deletions bun.lock

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -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;
4 changes: 3 additions & 1 deletion next.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
/* config options here */
turbopack: {
root: process.cwd(),
},
};

export default nextConfig;
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@
"start": "next start",
"lint": "biome check",
"format": "biome format --write"

},
"dependencies": {
"class-variance-authority": "^0.7.1",
"@neondatabase/auth": "^0.4.2-beta",
"@neondatabase/serverless": "^1.1.0",
"drizzle-orm": "^0.45.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^1.16.0",
"next": "16.2.6",
"postcss": "^8.5.15",
"radix-ui": "^1.4.3",
"react": "19.2.4",
"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",
Expand All @@ -28,7 +34,8 @@
"@types/react": "^19",
"@types/react-dom": "^19",
"tailwindcss": "^4",
"typescript": "^5"
"typescript": "^5",
"drizzle-kit": "^0.31.10"
},
"ignoreScripts": [
"sharp",
Expand Down
10 changes: 10 additions & 0 deletions proxy.disabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { auth } from './src/lib/auth/server';

export default auth.middleware({
loginUrl: '/auth/sign-in',
});

export const config = {
matcher: ['/account/:path*'],
};

12 changes: 12 additions & 0 deletions skills-lock.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
{
"version": 1,
"skills": {
"neon": {
"source": "neondatabase/agent-skills",
"sourceType": "github",
"skillPath": "skills/neon/SKILL.md",
"computedHash": "fc1eef695e3db102c44e5f3b262f5a5db21667fe27aaf2d53f2e5818c906a7f9"
},
"neon-postgres": {
"source": "neondatabase/agent-skills",
"sourceType": "github",
"skillPath": "skills/neon-postgres/SKILL.md",
"computedHash": "08bdd8c25761c92b21f1ecca076d4a8fe1c9b8924d0d5b5bd39d2041b2880fa1"
},
"shadcn": {
"source": "shadcn/ui",
"sourceType": "github",
Expand Down
3 changes: 3 additions & 0 deletions src/app/api/auth/[...path]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { auth } from "@/lib/auth/server";

export const { GET, POST } = auth.handler();
93 changes: 93 additions & 0 deletions src/app/api/dashboard/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { members, profiles, assignments, events, requests } from "@/db/schema";
import { eq } from "drizzle-orm";
import { auth } from "@/lib/auth/server";

export async function GET(req: Request) {
try {
console.log("▶️ 1. Hitting Dashboard API...");

// 💡 Fetch session directly from the auth object (Neon handles the headers/cookies)
const { data: session } = await auth.getSession();

console.log("▶️ 2. Session found:", !!session?.user);

if (!session?.user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}

const userEmail = session.user.email;
console.log("▶️ 3. Looking up member for email:", userEmail);

// ... The rest of your exact code stays exactly the same
const member = await db.query.members.findFirst({
where: eq(members.email, userEmail),
});

if (!member) {
console.log("❌ Member not found in database.");
return NextResponse.json({ error: "Member not found in database" }, { status: 404 });
}

console.log("▶️ 4. Member found. Fetching relations...");

const profile = await db.query.profiles.findFirst({
where: eq(profiles.memberId, member.id),
});

const userAssignments = await db.select({
title: events.eventName,
status: assignments.status,
})
.from(assignments)
.innerJoin(events, eq(assignments.eventId, events.id))
.where(eq(assignments.memberId, member.id))
.limit(5);

const allEvents = await db.query.events.findMany({
limit: 3,
});

const userRequests = await db.query.requests.findMany({
where: eq(requests.memberId, member.id),
});

console.log("▶️ 5. All database queries succeeded. Formatting response...");
/*
const pending = userRequests.filter(r => r.status?.toLowerCase() === 'pending').length;
const approved = userRequests.filter(r => r.status?.toLowerCase() === 'approved').length;
const rejected = userRequests.filter(r => r.status?.toLowerCase() === 'rejected').length;
*/

const pending = 0;
const approved = 0;
const rejected = 0;
return NextResponse.json({

profile: {
name: member.name,
role: member.role,
domain: profile?.domain || "Unassigned",
badges: profile?.badges ? (profile.badges as string[]).length : 0,
totalPoints: profile?.totalPoints || 0,
},
assignments: userAssignments,
events: allEvents.map(e => ({
name: e.eventName,
date: "TBD",
venue: "TBD"
})),
requests: { pending, approved, rejected },
badges: profile?.badges || [],
});

} catch (error) {
console.error("🔴 DASHBOARD API CRASH:", error);

return NextResponse.json(
{ error: "Internal Server Error" },
{ status: 500 }
);
}
}
38 changes: 38 additions & 0 deletions src/app/api/register/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { members, profiles } from "@/db/schema";

export async function POST(req: Request) {
try {
const body = await req.json();
const { name, email, role, joinDate, domain, department } = body;

if (!name || !email) {
return NextResponse.json({ error: "Missing required fields" }, { status: 400 });
}

const [newMember] = await db.insert(members).values({
name,
email,
role: role.toLowerCase(),
join_date: new Date(joinDate),
}).returning();

await db.insert(profiles).values({
memberId: newMember.id,
domain,
collegeDept: department,
expertiseLevel: "Beginner",
totalPoints: 0,
badges: [],
});

return NextResponse.json({ message: "Success" }, { status: 201 });
} catch (error: any) {
console.error("Registration Error:", error);
if (error.code === '23505') {
return NextResponse.json({ error: "Email already exists." }, { status: 409 });
}
return NextResponse.json({ error: "Failed to save profile." }, { status: 500 });
}
}
Loading