diff --git a/apps/blade/src/app/_components/user-interface.tsx b/apps/blade/src/app/_components/user-interface.tsx
index d12417cd9..c8618ccdf 100644
--- a/apps/blade/src/app/_components/user-interface.tsx
+++ b/apps/blade/src/app/_components/user-interface.tsx
@@ -1,59 +1,19 @@
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@forge/ui/tabs";
-
-import HackathonDashboard from "~/app/_components/dashboard/hackathon-dashboard/hackathon-dashboard";
-import HackerDashboard from "~/app/_components/dashboard/hacker-dashboard/hacker-dashboard";
import MemberDashboard from "~/app/_components/dashboard/member-dashboard/member-dashboard";
-import { HackerAppCard, MemberAppCard } from "~/app/_components/option-cards";
+import { MemberAppCard } from "~/app/_components/option-cards";
import { api } from "~/trpc/server";
export async function UserInterface() {
- const [member, hacker] = await Promise.allSettled([
- api.member.getMember(),
- api.hackerQuery.getHacker({}),
- ]);
-
- const currentHackathonResult = await Promise.allSettled([
- api.hackathon.getCurrentHackathon(),
- ]);
- if (
- member.status === "rejected" ||
- hacker.status === "rejected" ||
- currentHackathonResult[0].status === "rejected"
- ) {
- return (
-
- Something went wrong. Please try again later.
-
- );
- }
+ const member = await api.member.getMember();
- const memberValue = member.value;
- const hackerValue = hacker.value;
- const currentHackathon = currentHackathonResult[0].value;
-
- if (!memberValue && !hackerValue) {
+ if (!member) {
return (
- You have not applied to be a Knight Hacks member or hacker for an
- upcoming Hackathon yet. Please fill out an application below to get
- started!
+ You have not applied to be a Knight Hacks member yet. Please fill out
+ an application below to get started!
- {currentHackathon && (
-
- )}
-
-
- );
- }
-
- if (memberValue && !currentHackathon) {
- return (
-
);
@@ -61,57 +21,9 @@ export async function UserInterface() {
return (
-
-
-
-
- Select Your Dashboard
-
-
-
- {!memberValue ? (
- "Become a Member"
- ) : (
- <>
- Member
- Member
- >
- )}
-
-
-
- {currentHackathon ? currentHackathon.displayName : "Hacker"}
-
-
- {currentHackathon
- ? `${currentHackathon.displayName}`
- : "Hacker Dashboard"}
-
-
-
-
-
-
-
-
-
-
-
-
- {hackerValue && (hackerValue.status as string) === "checkedin" ? (
-
- ) : (
-
- )}
-
-
-
+
+
+
);
}
diff --git a/apps/blade/src/app/hackathon/[slug]/page.tsx b/apps/blade/src/app/hackathon/[slug]/page.tsx
new file mode 100644
index 000000000..d7c71d1e2
--- /dev/null
+++ b/apps/blade/src/app/hackathon/[slug]/page.tsx
@@ -0,0 +1,55 @@
+import type { Metadata } from "next";
+import { notFound, redirect } from "next/navigation";
+
+import { auth } from "@forge/auth";
+
+import { BaseHackathonDashboard } from "~/app/_components/dashboard/hackathon-dashboard/components";
+import HackerDashboard from "~/app/_components/dashboard/hacker-dashboard/hacker-dashboard";
+import { SessionNavbar } from "~/app/_components/navigation/session-navbar";
+import { api, HydrateClient } from "~/trpc/server";
+
+export const metadata: Metadata = {
+ title: "Blade | Hackathon Dashboard",
+ description: "The official hackathon dashboard.",
+};
+
+export default async function HackathonSlugPage(props: {
+ params: Promise<{ slug: string }>;
+}) {
+ const { slug } = await props.params;
+
+ const session = await auth();
+
+ if (!session) {
+ redirect("/");
+ }
+
+ const hackathon = await api.hackathon.getHackathon({
+ hackathonName: slug,
+ });
+
+ if (!hackathon) {
+ notFound();
+ }
+
+ const hacker = await api.hackerQuery.getHacker({
+ hackathonName: hackathon.name,
+ });
+
+ return (
+
+
+
+
+
+ {hacker?.status === "checkedin" ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+}
diff --git a/apps/blade/src/app/hackathon/bloomknights/page.tsx b/apps/blade/src/app/hackathon/bloomknights/page.tsx
new file mode 100644
index 000000000..5a8fb4b59
--- /dev/null
+++ b/apps/blade/src/app/hackathon/bloomknights/page.tsx
@@ -0,0 +1,51 @@
+import type { Metadata } from "next";
+import { notFound, redirect } from "next/navigation";
+
+import { auth } from "@forge/auth";
+
+import { BaseHackathonDashboard } from "~/app/_components/dashboard/hackathon-dashboard/components";
+import HackerDashboard from "~/app/_components/dashboard/hacker-dashboard/hacker-dashboard";
+import { SessionNavbar } from "~/app/_components/navigation/session-navbar";
+import { api, HydrateClient } from "~/trpc/server";
+
+export const metadata: Metadata = {
+ title: "Blade | BloomKnights Dashboard",
+ description: "The official BloomKnights hackathon dashboard.",
+};
+
+export default async function BloomKnightsHackathonPage() {
+ const session = await auth();
+
+ if (!session) {
+ redirect("/");
+ }
+
+ const hackathon = await api.hackathon.getHackathon({
+ hackathonName: "bloomknights",
+ });
+
+ if (!hackathon) {
+ notFound();
+ }
+
+ const hacker = await api.hackerQuery.getHacker({
+ hackathonName: hackathon.name,
+ });
+
+ return (
+
+
+
+
+
+ {hacker?.status === "checkedin" ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+}
diff --git a/apps/blade/src/app/hackathon/page.tsx b/apps/blade/src/app/hackathon/page.tsx
new file mode 100644
index 000000000..ef7d6ca68
--- /dev/null
+++ b/apps/blade/src/app/hackathon/page.tsx
@@ -0,0 +1,48 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { redirect } from "next/navigation";
+
+import { auth } from "@forge/auth";
+
+import { api } from "~/trpc/server";
+
+export const metadata: Metadata = {
+ title: "Blade | Hackathon",
+ description: "Open the currently running Knight Hacks hackathon dashboard.",
+};
+
+export default async function CurrentHackathonPage() {
+ const session = await auth();
+
+ if (!session) {
+ redirect("/");
+ }
+
+ const currentHackathon = await api.hackathon.getCurrentHackathon();
+
+ if (!currentHackathon) {
+ return (
+
+
+
+ There's no Hackathon running right now.
+
+
+ Stay on the lookout for the next one by joining our{" "}
+
+ Discord
+
+ .
+
+
+
+ );
+ }
+
+ redirect(`/hackathon/${currentHackathon.name}`);
+}
diff --git a/packages/api/src/routers/hackathon.ts b/packages/api/src/routers/hackathon.ts
index 321baa31b..d83d80a8a 100644
--- a/packages/api/src/routers/hackathon.ts
+++ b/packages/api/src/routers/hackathon.ts
@@ -3,7 +3,7 @@ import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { HACKATHONS } from "@forge/consts";
-import { and, count, desc, eq, getTableColumns, lt } from "@forge/db";
+import { and, count, desc, eq, getTableColumns, gte, lt, lte } from "@forge/db";
import { db } from "@forge/db/client";
import {
Hackathon,
@@ -137,12 +137,12 @@ export const hackathonRouter = {
}),
getCurrentHackathon: publicProcedure.query(async () => {
- // Find first hackathon that hasnt ended yet
+ const now = new Date();
const hackathon = await db.query.Hackathon.findFirst({
orderBy: (t, { asc }) => asc(t.endDate),
- where: (t, { and, gte, lte }) =>
- and(gte(t.endDate, new Date()), lte(t.applicationOpen, new Date())),
+ where: and(lte(Hackathon.startDate, now), gte(Hackathon.endDate, now)),
});
+
return hackathon ?? null;
}),
diff --git a/packages/api/src/routers/hackers/mutations.ts b/packages/api/src/routers/hackers/mutations.ts
index 4263b77c0..47bb1acdd 100644
--- a/packages/api/src/routers/hackers/mutations.ts
+++ b/packages/api/src/routers/hackers/mutations.ts
@@ -529,11 +529,7 @@ export const hackerMutationRouter = {
hackathonId: z.string().uuid(),
assignedClassCheckin: z.string().superRefine((v, ctx) => {
//Idk man leave me alone
- if (
- !(
- AssignedClassCheckinSchema.options as unknown as string[]
- ).includes(v)
- ) {
+ if (!AssignedClassCheckinSchema.safeParse(v).success) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Invalid assignedClassCheckin",