Skip to content
Merged
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
1 change: 1 addition & 0 deletions amplify/data/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ const schema = a
id: a.id().required(),
time: a.datetime().required(),
zoomLink: a.string().required(),
duration: a.integer(),
teamId: a.id().required(),
roomId: a.id().required(),
team: a.belongsTo("Team", "teamId"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export const handler: Schema["ScheduleTeamsAndJudges"]["functionHandler"] =
time: currTime.toISOString(),
roomId: roomIds[column],
zoomLink: "",
duration: presentationDuration,
},
},
}),
Expand Down
3 changes: 3 additions & 0 deletions amplify/graphql/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export type TeamRoom = {
time: string;
updatedAt: string;
zoomLink: string;
duration?: number | null;
};

export type Room = {
Expand Down Expand Up @@ -493,6 +494,7 @@ export type CreateTeamRoomInput = {
teamId: string;
time: string;
zoomLink: string;
duration?: number | null;
};

export type ModelUserConditionInput = {
Expand Down Expand Up @@ -623,6 +625,7 @@ export type UpdateTeamRoomInput = {
teamId?: string | null;
time?: string | null;
zoomLink?: string | null;
duration?: number | null;
};

export type UpdateUserInput = {
Expand Down
1 change: 1 addition & 0 deletions amplify/graphql/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ export const createTeamRoom = /* GraphQL */ `mutation CreateTeamRoom(
time
updatedAt
zoomLink
duration
__typename
}
}
Expand Down
2 changes: 2 additions & 0 deletions amplify/graphql/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ export const getTeamRoom = /* GraphQL */ `query GetTeamRoom($id: ID!) {
time
updatedAt
zoomLink
duration
__typename
}
}
Expand Down Expand Up @@ -427,6 +428,7 @@ export const listTeamRooms = /* GraphQL */ `query ListTeamRooms(
time
updatedAt
zoomLink
duration
__typename
}
nextToken
Expand Down
12 changes: 11 additions & 1 deletion src/app/admin/components/UsersTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,21 @@ export default function UsersTable({ users }: { users: User[] }) {
const deleteUser = async (id: Schema["User"]["deleteType"]) =>
client.models.User.delete(id);
const updateUser = async (updatedData: Schema["User"]["updateType"]) => {
if (updatedData.role) {
const roleUpdateResult = await client.mutations.AddUserToGroup({
userId: updatedData.id,
groupName: updatedData.role,
});

if (roleUpdateResult.errors) {
throw new Error("Failed to update user role in Cognito");
}
}

return client.models.User.update({
id: updatedData.id,
firstName: updatedData.firstName,
lastName: updatedData.lastName,
role: updatedData.role,
teamId: updatedData.teamId,
});
};
Expand Down
29 changes: 24 additions & 5 deletions src/app/admin/users/UserTablePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,28 @@ const selectionSet = [
export type User = Pick<Schema["User"]["type"], (typeof selectionSet)[number]>;

export default async function UserTablePage() {
const { data: users } = await client.models.User.list({
selectionSet,
});
if (!users || !Array.isArray(users)) return "No participants were found";
return <UsersTable users={users} />;
//paginate incoming data
let allUsers: User[] = [];
let nextToken: string | null | undefined = undefined;

do {
const {
data: users,
nextToken: token,
}: { data?: User[]; nextToken?: string | null } =
await client.models.User.list({
selectionSet,
nextToken,
limit: 1000,
});

if (users && Array.isArray(users)) {
allUsers = [...allUsers, ...users];
}

nextToken = token;
} while (nextToken);

if (!allUsers || allUsers.length === 0) return "No participants were found";
return <UsersTable users={allUsers} />;
}
44 changes: 22 additions & 22 deletions src/app/judging/JudgingTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export default function JudgingTable({
}) {
const [selectedTeam, setSelectedTeamId] = useState("");
const [teamName, setTeamName] = useState("");
const [teamsLeft, setTeamsLeft] = useState(0);

const { currentUser } = useUser();
const { data: roomData, isFetching: roomIsFetching } = useQuery({
Expand Down Expand Up @@ -51,30 +50,31 @@ export default function JudgingTable({
return teams;
},
});
const isFetching = roomIsFetching && teamsForRoomIsFetching;

const { data: teamsLeft = 0, isFetching: teamsLeftIsFetching } = useQuery({
queryKey: ["TeamsLeftCount", teamsForRoomData, currentUser.username],
queryFn: async () => {
if (!teamsForRoomData) return 0;
const boolArray = await Promise.all(
teamsForRoomData.map(async (team) => {
const scores = await team?.scores();
return (
scores?.data.filter(
(score) => score.judgeId === currentUser.username,
).length === 0
);
}),
);
return teamsForRoomData.filter((_, i) => boolArray[i]).length;
},
enabled: !!teamsForRoomData && !!currentUser.username,
});

const isFetching =
roomIsFetching || teamsForRoomIsFetching || teamsLeftIsFetching;
if (isFetching || !roomData || !teamsForRoomData) {
return <KevinLoadingRing />;
}
async function getFilteredTeamsCount() {
// https://medium.com/@debbs119/array-filter-and-array-map-with-async-functions-9636e1ae8d6e --> why it needs to map to a boolean array first
if (!teamsForRoomData) {
return;
}
const boolArray = await Promise.all(
teamsForRoomData?.map(async (team) => {
const scores = await team?.scores();
return (
scores?.data.filter((score) => score.judgeId === currentUser.username)
.length === 0
);
}),
);
setTeamsLeft(
teamsForRoomData?.filter((_, index) => boolArray[index]).length,
);
}

getFilteredTeamsCount();

const panelData = [
{
Expand Down
87 changes: 75 additions & 12 deletions src/app/judging/assigned-teams/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,81 @@
"use client";

import React from "react";
import { client } from "@/app/QueryProvider";
import { useUser } from "@/components/contexts/UserContext";
import KevinLoadingRing from "@/components/KevinLoadingRing";
import { useQuery } from "@tanstack/react-query";

const AssignedTeamsPage = () => {
const assignedTeams = [
{ id: 1, name: "Team Alpha" },
{ id: 2, name: "Team Beta" },
{ id: 3, name: "Team Gamma" },
];
const { currentUser } = useUser();

const { data: roomData, isLoading: roomLoading } = useQuery({
queryKey: ["RoomForJudge", currentUser?.JUDGE_roomId],
queryFn: async () => {
if (!currentUser?.JUDGE_roomId)
throw new Error("No room assigned to judge");
const { data, errors } = await client.models.Room.get({
id: currentUser.JUDGE_roomId,
});
if (errors) throw new Error(errors[0]?.message || "Failed to load room");
return data;
},
enabled: !!currentUser?.JUDGE_roomId,
});

const { data: teamsForRoom, isLoading: teamsLoading } = useQuery({
queryKey: ["TeamsForRoom", roomData?.id],
queryFn: async () => {
if (!roomData) return [];
const teamRooms = (await roomData.teamRoom())?.data;
if (!teamRooms) return [];
const teams = await Promise.all(
teamRooms.map(async (tr) => (await tr.team()).data),
);
return teams;
},
enabled: !!roomData,
});

if (!currentUser)
return <div className="p-6">Please sign in to see assigned teams.</div>;
if (roomLoading || teamsLoading)
return (
<div className="flex items-center justify-center pt-16">
<KevinLoadingRing />
</div>
);
if (!roomData)
return <div className="p-6">You have no room assigned yet.</div>;

return (
<div>
<h1> Put assinged teams here Assigned Teams</h1>
<ul>
{assignedTeams.map((team) => (
<li key={team.id}>{team.name}</li>
))}
</ul>
<div className="p-6">
<h1 className="mb-4 text-2xl font-semibold">
Your Teams: {roomData?.name ?? ""}
</h1>
{teamsForRoom && teamsForRoom.length > 0 ? (
<div className="grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{teamsForRoom.map((team: any) => (
<div
key={team.id}
className="flex flex-col justify-between rounded-lg border bg-white p-4 shadow-sm transition-shadow hover:shadow-lg"
>
<div>
<div className="text-lg font-bold text-gray-900">
<span>{team.name}</span>
</div>
<div className="mt-1 text-sm text-gray-500">
<span>Team ID: {team.id}</span>
</div>
</div>
</div>
))}
</div>
) : (
<div className="text-gray-600">
No teams assigned to your room yet. Check back later!
</div>
)}
</div>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/app/participant/resources/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ export default function ResourcePage() {
src="/svgs/resources/pinkSquiggly.svg"
alt="Pink Squiggly"
fill
className="pointer-events-none opacity-0 md:mt-[540px] md:opacity-100 lg:mt-[600px] xl:mt-[400px] 2xl:mt-52"
className="pointer-events-none opacity-0 md:mt-[540px] md:opacity-100 lg:mt-[600px] xl:mt-[400px] 2xl:mt-64"
/>
<Image
src="/svgs/resources/orangeSquiggly.svg"
alt="Orange Squiggly"
fill
className="pointer-events-none rotate-180 opacity-0 md:mt-[800px] md:opacity-100 lg:mt-[900px] xl:mt-[680px] 2xl:mt-[430px]"
className="pointer-events-none rotate-180 opacity-0 md:mt-[800px] md:opacity-100 lg:mt-[900px] xl:mt-[680px] 2xl:mt-[390px]"
/>
<div className="z-10 flex flex-col gap-12 bg-light-grey py-10">
<div className="mt-2 flex flex-row justify-center text-center">
Expand Down
3 changes: 1 addition & 2 deletions src/components/Dashboard/UserBasedNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ const navigationMap: Record<string, NavItem[]> = {
{ name: "Dashboard", route: "/participant" },
{ name: "Food Ticket", route: "/participant/profile/food-ticket" },
{ name: "Important Information", route: "/participant/important-info" },
// ADD RESOURCES BACK IN NEAR THE HACKATHON DATE
// { name: "Resources", route: "/participant/resources" },
{ name: "Resources", route: "/participant/resources" },
],
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/LandingPage/HeroSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export default async function HeroSection() {
return <div>Hackathon hasn't been created yet</div>;
}

const eventStartDate = new Date(hackathonData[0].startDate);
const eventEndDate = new Date(hackathonData[0].endDate);
const eventStartDate = new Date(2025, 10, 8, 9, 30, 0); // Month is 0-indexed → 10 = November
const eventEndDate = new Date(2025, 10, 9, 18, 0, 0); // Example: Sunday 5 PM

return (
<div className="relative flex flex-col items-center justify-center md:px-8 md:py-16 lg:px-32">
Expand Down
3 changes: 0 additions & 3 deletions src/components/LandingPage/JudgeShowcase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ export default async function JudgeShowcase() {
</div>
))}
</div>
<p className="mt-12 text-center text-2xl font-semibold text-gray-600 md:text-3xl">
Full List Coming Soon!
</p>
</div>
);
}
5 changes: 4 additions & 1 deletion src/components/admin/Judging/JudgingSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ export default function JudgingSchedule() {
.join(", ") || "No Team Name",
room_id: teamRoom.roomId,
start: new Date(teamRoom.time),
end: new Date(new Date(teamRoom.time).getTime() + 15 * 60 * 1000),
end: new Date(
new Date(teamRoom.time).getTime() +
(teamRoom.duration ?? 10) * 60 * 1000,
),
zoomLink: teamRoom.zoomLink,
}))
: [];
Expand Down
12 changes: 8 additions & 4 deletions src/components/admin/Judging/JudgingTimeline.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { Scheduler } from "@aldabil/react-scheduler";
import RedirectIcon from "../../RedirectIcon";

type JudgeRoom = {
roomName: string;
Expand Down Expand Up @@ -48,11 +49,14 @@ export default function JudgingTimeline({
deletable={false}
viewerExtraComponent={(fields, event) => {
return (
<p>
<a
href={event.zoomLink}
className="inline-flex flex-row items-center gap-1 text-dark-green hover:underline"
>
{/* Replace with actual zoom link not the room id */}
<span className="font-bold">Zoom Link:</span>{" "}
<a href={event.zoomLink}>{event.title}</a>
</p>
<span className="font-bold">Zoom Link</span>
<RedirectIcon />
</a>
);
}}
/>
Expand Down
Loading
Loading