Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add team selection to website #266

Merged
merged 1 commit into from
Sep 30, 2024
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
31 changes: 31 additions & 0 deletions web/app/api/protected/db/user/getTeam/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { getSession } from "@auth0/nextjs-auth0";
import { NextResponse } from "next/server";
import prisma from "@/prisma/prismaClient";

export async function GET() {
try {
const session = await getSession();

if (!session?.user?.sub) {
return NextResponse.json({ message: "Not logged in" }, { status: 401 });
}

const user = (await prisma.user.findUnique({
where: { uid: session.user.sub },
include: { team: { include: { members: { include: { profile: true } } } } },
}));
const teamName = user?.teamName;
const teamMembers = user?.team?.members;

var teamMemberNames: String[] = [];
for (const teamMember of teamMembers || []) {
if (teamMember.uid == user?.uid) continue;
teamMemberNames.push(`${teamMember.profile?.firstName} ${teamMember.profile?.lastName}`);
}

return NextResponse.json({ teamName, teamMemberNames, status: 200 });
} catch (error: any) {
console.error(error);
return NextResponse.json({ message: error.message }, { status: 500 });
}
}
28 changes: 28 additions & 0 deletions web/app/api/protected/db/user/setTeam/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { getSession } from "@auth0/nextjs-auth0";
import { NextResponse } from "next/server";
import prisma from "@/prisma/prismaClient";

export async function POST(req: Request) {
try {
const session = await getSession();

if (!session?.user?.sub) {
return NextResponse.json({ message: "Not logged in" }, { status: 401 });
}

const { newTeam } = await req.json();

console.log(`Updated team to be ${newTeam}`);
await prisma.team.upsert({ where: { name: newTeam }, update: {}, create: { name: newTeam } });

await prisma.user.update({
where: { uid: session.user.sub },
data: { teamName: newTeam }
});

return NextResponse.json({ message: "success", status: 200 });
} catch (error: any) {
console.error(error);
return NextResponse.json({ message: error.message }, { status: 500 });
}
}
2 changes: 1 addition & 1 deletion web/app/contact/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export default function Contact() {
<dd>
<a
className="hover:text-white"
href="mailto:[email protected]">
href="mailto:[email protected]">
[email protected]
</a>
</dd>
Expand Down
13 changes: 7 additions & 6 deletions web/app/dash/dash-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
ArrowDownOnSquareIcon,
ArrowTrendingUpIcon,
ArrowUpTrayIcon,
UserPlusIcon,
Bars3Icon,
QuestionMarkCircleIcon,
XMarkIcon,
Expand Down Expand Up @@ -47,12 +48,12 @@ const navigation = [
icon: ArrowUpTrayIcon,
activeName: "/dash/submit",
},
// {
// name: "Partner Settings",
// href: "/dash/group",
// icon: UserPlusIcon,
// activeName: "/dash/group",
// },
{
name: "Partner Settings",
href: "/dash/group",
icon: UserPlusIcon,
activeName: "/dash/group",
},
];

function classNames(...classes: any) {
Expand Down
110 changes: 110 additions & 0 deletions web/app/dash/group/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'use client'
import { UsersIcon } from '@heroicons/react/20/solid'
import { useState, useEffect, useRef } from "react"
import Swal from 'sweetalert2'

export default function Groups() {
const teamNameRef = useRef<HTMLInputElement>(null);

const [team, setTeam] = useState("");
const [teamMembers, setTeamMembers] = useState([]);

useEffect(() => {
const getTeam = async () => {
const currentTeam = await fetch("/api/protected/db/user/getTeam");
const { teamName, teamMemberNames } = await currentTeam.json();
setTeam(teamName);
setTeamMembers(teamMemberNames);
};
getTeam();
}, []);

async function handleSetTeamHandler() {
if (teamNameRef?.current?.value == null) { return }
const newTeamName = teamNameRef.current.value;
if (newTeamName == team) return;
const response = await fetch("/api/protected/db/user/setTeam", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ newTeam: newTeamName }),
});

if (response.ok) {
await Swal.fire({ icon: 'success', title: 'Team Updated', text: `Team is now ${newTeamName}` });
} else {
await Swal.fire({ icon: 'error', title: 'Setting team failed', text: 'Please contact [email protected]' });
}

setTeam(teamNameRef.current.value);
}

return (
<div className="relative min-h-screen flex items-center justify-center">
<div className="flex items-center justify-center p-4 text-center sm:p-0">
<div className="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl sm:my-8 sm:w-full sm:max-w-lg sm:p-6">
<div>
<div className="mt-1 text-center">
<h1 className="text-xl font-semibold leading-6 text-gray-900">
Team Registration
</h1>
<div className="mt-2">
<p className="text-base text-gray-500">
To form a team, create a team name and have your teammates enter the same on their computers.
</p>
</div>
</div>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium leading-6 text-gray-900 mt-4">
Team Name
</label>
<div className="mt-2 flex rounded-md shadow-sm">
<div className="relative flex flex-grow items-stretch focus-within:z-10">
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<UsersIcon aria-hidden="true" className="h-5 w-5 text-gray-400" />
</div>
<input
id="team"
name="team"
type="team"
defaultValue={team}
ref={teamNameRef}
className="block w-full rounded-none rounded-l-md border-0 py-1.5 pl-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
</div>
<div className="mt-5 sm:mt-6">
<button
type="button"
className="inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
onClick={handleSetTeamHandler}
>
Save Team
</button>
</div>
{teamMembers.length > 0 && <div><div className="relative mt-5">
<div aria-hidden="true" className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300" />
</div>
<div className="relative flex justify-center">
<span className="bg-white px-2 text-sm text-gray-500">Team Members</span>
</div>
</div>
<dl className="mt-5 grid gap-5 grid-cols-3 text-center">
{teamMembers.map((item) => (
<div key={item} className="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6 col-span-1">
<dd className="mt-1 text-lg font-semibold tracking-tight text-gray-900">{item}</dd>
</div>
))}
</dl></div>}
</div>


</div>
</div >

);
}
16 changes: 16 additions & 0 deletions web/prisma/migrations/20240922195531_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- AlterTable
ALTER TABLE "users" ADD COLUMN "teamId" INTEGER;

-- CreateTable
CREATE TABLE "Team" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,

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

-- CreateIndex
CREATE UNIQUE INDEX "Team_name_key" ON "Team"("name");

-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team"("id") ON DELETE SET NULL ON UPDATE CASCADE;
15 changes: 15 additions & 0 deletions web/prisma/migrations/20240922195636_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
Warnings:
- You are about to drop the column `teamId` on the `users` table. All the data in the column will be lost.
- You are about to drop the `Team` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_teamId_fkey";

-- AlterTable
ALTER TABLE "users" DROP COLUMN "teamId";

-- DropTable
DROP TABLE "Team";
9 changes: 9 additions & 0 deletions web/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,19 @@ model User {
Algo Algo[]
profile Profile?
AlgoFile AlgoFile[]
team Team? @relation(fields: [teamName], references: [name])
teamName String?
@@map("users")
}

model Team {
name String @id @unique
members User[]
@@map("teams")
}

model Algo {
algoFileS3Key String @id
name String @unique
Expand Down
Loading