Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
fc1f75d
Countries are now a dropdown
Monster0506 Jan 24, 2026
388d184
Countries are now a dropdown
Monster0506 Jan 24, 2026
dcb32cf
Mock data, good UI for judging page
Monster0506 Jan 23, 2026
7b436b7
Admin routes for judging stuff
Monster0506 Jan 24, 2026
adcacf3
CONFIGURABLE tracks, criterion, etc.
Monster0506 Jan 24, 2026
5176fbb
Merge branch 'judging' into dev
Monster0506 Jan 24, 2026
7104de8
Scoring page
Monster0506 Jan 24, 2026
2d83a6e
better font sizes
Monster0506 Jan 24, 2026
658087d
Better code for judging
Monster0506 Jan 24, 2026
442ed56
Group scores by track
Monster0506 Jan 24, 2026
ed72b77
polling for scores
Monster0506 Jan 24, 2026
66a65b4
Merge pull request #88 from hacksu/judging
Monster0506 Jan 24, 2026
00419ab
Send emails to all teams after judging with feedbacks
Monster0506 Jan 26, 2026
2f515a9
Per team feedback emails
Monster0506 Jan 26, 2026
5234b47
Move comments into the main form instead of two pages.
Monster0506 Jan 26, 2026
2c429cb
Manually assign judges to teams
Monster0506 Jan 26, 2026
fe7a55e
Merge pull request #91 from hacksu/judge/fix/single-page-comments
Monster0506 Jan 26, 2026
3035614
Merge pull request #92 from hacksu/judge/manual-assignment
Monster0506 Jan 26, 2026
bdf2edc
Judge team manually by number
Monster0506 Jan 26, 2026
277825d
Merge pull request #93 from hacksu/judge/manual-entry
Monster0506 Jan 26, 2026
0a1acb7
Remove enbasis :(
Monster0506 Jan 26, 2026
699f5cf
Fixed favicon
AndrewRoddy Jan 26, 2026
d65561d
Merge branch 'dev' of https://github.com/hacksu/khe-renaissance into …
Monster0506 Jan 27, 2026
e8e71ef
Merge remote-tracking branch 'origin/judge/email' into judge/manual-a…
Monster0506 Jan 27, 2026
dc70372
Judges manually assigned to a team can now only judge that team
Monster0506 Jan 27, 2026
edc6ead
Merge pull request #94 from hacksu/judge/manual-assignment-fix
Monster0506 Jan 27, 2026
fa97396
Email reminders to accounts that have not yet submitted an application
Monster0506 Jan 27, 2026
9fd084c
Revert "Remove enbasis :("
Monster0506 Jan 27, 2026
befa88c
OTP for judges to log in
Monster0506 Jan 28, 2026
2e24a1f
Merge pull request #96 from hacksu/judge/magic-links
Monster0506 Jan 28, 2026
36c559e
Judging curves!!
Monster0506 Jan 28, 2026
55afb5e
Merge pull request #97 from hacksu/judge/curve
Monster0506 Jan 28, 2026
9cc7e73
Remove emoji
Monster0506 Jan 28, 2026
d903210
Merge pull request #90 from hacksu/judge/email
Monster0506 Jan 29, 2026
91d3c92
Merge branch 'dev' into feat/poke-dead-accounts
Monster0506 Jan 29, 2026
015d2c8
Merge pull request #95 from hacksu/feat/poke-dead-accounts
Monster0506 Jan 29, 2026
f4a75f8
added tool list
YoyoJesus Feb 2, 2026
3a33256
fixed software/tools section
YoyoJesus Feb 3, 2026
5c2b9d7
swap tools & sponsors order
YoyoJesus Feb 3, 2026
9be649d
added comments with possible items/sponsors
YoyoJesus Feb 3, 2026
c0bd3b5
added comments with possible items/sponsors
YoyoJesus Feb 3, 2026
c2f385f
Fix navbar to not be underneath content. #98
Monster0506 Feb 3, 2026
cd17eb2
Merge branch 'dev' of https://github.com/hacksu/khe-renaissance into dev
YoyoJesus Feb 3, 2026
d74ee82
sizing fixes
YoyoJesus Feb 3, 2026
553f1e3
added AWS to sponsors
YoyoJesus Feb 10, 2026
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
109 changes: 109 additions & 0 deletions prisma/migrations/20260124034356_add_tracks_and_criteria/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
-- AlterTable
ALTER TABLE "application" ADD COLUMN "projectId" TEXT;

-- CreateTable
CREATE TABLE "project" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"tableNumber" TEXT,
"track" TEXT NOT NULL DEFAULT 'General',
"trackId" TEXT,

CONSTRAINT "project_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "track" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,

CONSTRAINT "track_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "judging_criterion" (
"id" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"maxScore" INTEGER NOT NULL DEFAULT 5,
"weight" DOUBLE PRECISION NOT NULL DEFAULT 1.0,
"order" INTEGER NOT NULL DEFAULT 0,

CONSTRAINT "judging_criterion_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "judge_assignment" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"projectId" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'assigned',
"priority" INTEGER NOT NULL DEFAULT 0,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

CONSTRAINT "judge_assignment_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "judgement" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"projectId" TEXT NOT NULL,
"comment" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "judgement_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "judgement_score" (
"id" TEXT NOT NULL,
"judgementId" TEXT NOT NULL,
"criterionId" TEXT NOT NULL,
"score" INTEGER NOT NULL,

CONSTRAINT "judgement_score_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "track_name_key" ON "track"("name");

-- CreateIndex
CREATE UNIQUE INDEX "judging_criterion_slug_key" ON "judging_criterion"("slug");

-- CreateIndex
CREATE UNIQUE INDEX "judge_assignment_userId_projectId_key" ON "judge_assignment"("userId", "projectId");

-- CreateIndex
CREATE UNIQUE INDEX "judgement_userId_projectId_key" ON "judgement"("userId", "projectId");

-- CreateIndex
CREATE UNIQUE INDEX "judgement_score_judgementId_criterionId_key" ON "judgement_score"("judgementId", "criterionId");

-- AddForeignKey
ALTER TABLE "application" ADD CONSTRAINT "application_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "project"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "project" ADD CONSTRAINT "project_trackId_fkey" FOREIGN KEY ("trackId") REFERENCES "track"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "judge_assignment" ADD CONSTRAINT "judge_assignment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "judge_assignment" ADD CONSTRAINT "judge_assignment_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "project"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "judgement" ADD CONSTRAINT "judgement_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "judgement" ADD CONSTRAINT "judgement_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "project"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "judgement_score" ADD CONSTRAINT "judgement_score_judgementId_fkey" FOREIGN KEY ("judgementId") REFERENCES "judgement"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "judgement_score" ADD CONSTRAINT "judgement_score_criterionId_fkey" FOREIGN KEY ("criterionId") REFERENCES "judging_criterion"("id") ON DELETE CASCADE ON UPDATE CASCADE;
2 changes: 2 additions & 0 deletions prisma/migrations/20260127161905_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "judge_assignment" ADD COLUMN "isManual" BOOLEAN NOT NULL DEFAULT false;
2 changes: 2 additions & 0 deletions prisma/migrations/20260128164453_curve/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "user" ADD COLUMN "curve" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
98 changes: 98 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ model User {
accounts Account[]
Application Application[]

judgeAssignments JudgeAssignment[]
judgements Judgement[]

role String?
curve Float @default(0.0)

@@unique([email])
@@map("user")
Expand Down Expand Up @@ -106,6 +110,100 @@ model Application {
user User @relation(fields: [userId], references: [id])
userId String

project Project? @relation(fields: [projectId], references: [id])
projectId String?

@@unique([userId])
@@map("application")
}

model Project {
id String @id @default(uuid())
name String
description String?
tableNumber String?

// Legacy track string (deprecated, use trackId relation)
track String @default("General")

trackId String?
Track Track? @relation(fields: [trackId], references: [id])

members Application[]
judgements Judgement[]
judgeAssignments JudgeAssignment[]

@@map("project")
}

model Track {
id String @id @default(uuid())
name String @unique
description String?

projects Project[]

@@map("track")
}

model JudgingCriterion {
id String @id @default(uuid())
slug String @unique
name String
description String?
maxScore Int @default(5)
weight Float @default(1.0)
order Int @default(0)

scores JudgementScore[]

@@map("judging_criterion")
}

model JudgeAssignment {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
projectId String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)

status String @default("assigned") // 'assigned', 'completed', 'skipped'
priority Int @default(0)
isManual Boolean @default(false)

createdAt DateTime @default(now())

@@unique([userId, projectId])
@@map("judge_assignment")
}

model Judgement {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
projectId String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)

// Dynamic Scores
scores JudgementScore[]

comment String? // @db.Text is not needed for raw postgres usually unless specific, String is fine

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@unique([userId, projectId])
@@map("judgement")
}

model JudgementScore {
id String @id @default(uuid())
judgementId String
judgement Judgement @relation(fields: [judgementId], references: [id], onDelete: Cascade)
criterionId String
criterion JudgingCriterion @relation(fields: [criterionId], references: [id], onDelete: Cascade)
score Int

@@unique([judgementId, criterionId])
@@map("judgement_score")
}
53 changes: 53 additions & 0 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
console.log('Seeding metadata...');

// --- Tracks ---
const tracks = [
{ name: 'General', description: 'General track for all projects' },
{ name: 'Business Analytics', description: 'Data driven business solutions' },
{ name: 'Education Tech', description: 'Improving education through technology' },
{ name: 'Healthcare', description: 'Health and wellness solutions' },
{ name: 'Consumer', description: 'Consumer facing products' },
{ name: 'New Frontiers', description: 'Experimental and cutting edge tech' },
];

for (const t of tracks) {
await prisma.track.upsert({
where: { name: t.name },
update: {},
create: t,
});
}
console.log('Tracks seeded.');

// --- Criteria ---
const criteria = [
{ slug: 'creativity', name: 'Creativity', order: 1, maxScore: 5 },
{ slug: 'mostLearned', name: 'Most Learned', order: 2, maxScore: 5 },
{ slug: 'technicality', name: 'Technicality', order: 3, maxScore: 5 },
{ slug: 'overall', name: 'Overall Score', order: 4, maxScore: 5 },
{ slug: 'trackFit', name: 'Track Fit', order: 5, maxScore: 5 },
];

for (const c of criteria) {
await prisma.judgingCriterion.upsert({
where: { slug: c.slug },
update: {},
create: c,
});
}
console.log('Criteria seeded.');
}

main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
Binary file added src/assets/software/BambuLab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/software/hakko.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/software/keysight.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions src/assets/software/tokenCompany.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 6 additions & 3 deletions src/components/Divider.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<script lang="ts">

const { children = undefined } = $props();
import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';

let { children, class: className, ...props }: { children?: Snippet, class?: string } & HTMLAttributes<HTMLDivElement> = $props();

</script>

{#if !children}
<div class="w-full h-[1px] border-[1px] my-2"></div>
<div class="w-full h-[1px] border-[1px] my-2 {className}" {...props}></div>
{:else}
<div class="flex h-full gap-2 items-center">
<div class="flex h-full gap-2 items-center {className}" {...props}>
<div class="w-full h-[1px] border-[1px] my-2"></div>
{@render children()}
<div class="w-full h-[1px] border-[1px] my-2"></div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/Highlight.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
const { children } = $props();
import type { Snippet } from 'svelte';
let { children }: { children?: Snippet } = $props();
</script>

<span class="font-bold [text-shadow:0_0_10px_rgba(255_255_255/_0.6)]">
Expand Down
27 changes: 22 additions & 5 deletions src/components/Modal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@
import Button from "./Button.svelte";
import Card from "./Card.svelte";

import type { Snippet } from 'svelte';

let {
open = false,
title = "Warning",
message = "",
confirmText = "Confirm",
cancelText = "Cancel",
onConfirm,
onCancel
onCancel,
children
}: {
open?: boolean;
title?: string;
message?: string;
confirmText?: string;
cancelText?: string;
onConfirm?: () => void;
onCancel?: () => void;
children?: Snippet;
} = $props();
</script>

Expand All @@ -16,10 +30,13 @@
<div class="w-full max-w-md">
<Card padded>
<h3 class="text-xl font-bold mb-2 text-red-600">{title}</h3>
<p class="mb-6 text-gray-100">{message}</p>
<div class="flex justify-end gap-2">
<Button type="button" onclick={onCancel} class="bg-gray-200 hover:bg-gray-300 text-black">Cancel</Button>
<Button type="button" onclick={onConfirm} class="bg-red-600 hover:bg-red-700 text-white">Confirm</Button>
{#if message}
<p class="mb-6 text-gray-100">{message}</p>
{/if}
{@render children?.()}
<div class="flex justify-end gap-2 mt-4">
<Button type="button" onclick={onCancel} class="bg-gray-200 hover:bg-gray-300 text-black">{cancelText}</Button>
<Button type="button" onclick={onConfirm} class="bg-red-600 hover:bg-red-700 text-white">{confirmText}</Button>
</div>
</Card>
</div>
Expand Down
Loading