Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 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
47 changes: 47 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"dependencies": {
"@hookform/resolvers": "^5.2.1",
"@monaco-editor/react": "^4.7.0",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
Expand Down
19 changes: 17 additions & 2 deletions frontend/src/app/collab/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import ContentPage from "../components/collab/ContentPage";
import ChatComponent from "../components/collab/ChatComponent";
import CodingComponent from "../components/collab/CodingComponent";
import QuestionComponent from "../components/collab/QuestionComponent";
import SessionHeader from "../components/collab/SessionHeader";

export default function CollabPage() {
return (
<main className="bg-stone-900 h-screen flex flex-col items-center">
<SessionHeader />
<ContentPage />

<div className="flex flex-1 w-full bg-stone-800 ">
<div className="flex-1 p-5">
<QuestionComponent />
</div>

<div className="flex-[2]">
<CodingComponent />
</div>

<div className="flex-1 p-5">
<ChatComponent />
</div>
</div>
</main>
);
}
20 changes: 20 additions & 0 deletions frontend/src/app/components/collab/ChatComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { ChevronRightIcon } from "lucide-react";

export default function ChatComponent() {
const chatMessages = ["HELLO", "HOW ARE YOU?"];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed that there is some boiler plate chat messages here. Do you intend to render them for this PR, as its currently not rendered?


return (
<div className="flex flex-col h-full bg-stone-900 p-1">
<div className="flex bg-stone-500 h-full mb-5 rounded-lg"></div>

<div className="flex w-full mt-auto gap-2">
<Input className="bg-white" />
<Button variant="secondary" size="icon" className="size-9">
<ChevronRightIcon />
</Button>
</div>
</div>
);
}
69 changes: 69 additions & 0 deletions frontend/src/app/components/collab/CodingComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"use client";

import Editor from "@monaco-editor/react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { ChevronDown, CircleUser } from "lucide-react";

export default function CodingComponent() {
const [codeContent, setCodeContent] = useState<string>("");
const [selectedLanguage, setSeletedLanguage] = useState<string>("JavaScript");

function setInitialContent(value: string | undefined) {
if (value != undefined) {
setCodeContent(value);
}
}

return (
<div className="mt-5">
<div className="flex justify-between mb-4">
<DropdownMenu>
<DropdownMenuTrigger asChild className="flex justify-between">
<Button className="w-40 bg-white text-black hover:bg-gray-500">
{selectedLanguage} <ChevronDown />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-10" align="start">
<DropdownMenuGroup>
<DropdownMenuItem
onClick={() => setSeletedLanguage("JavaScript")}
>
Javascript
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setSeletedLanguage("Python")}>
Python
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setSeletedLanguage("C")}>
C
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setSeletedLanguage("C++")}>
C++
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setSeletedLanguage("Java")}>
Java
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
<div className="flex justify-center items-center">
<div className="text-white mr-3">[email protected]</div>
<CircleUser className="text-white mr-2" size="25" />
</div>
</div>
<Editor
height="85vh"
theme="vs-dark"
defaultLanguage={selectedLanguage.toLowerCase()}
onChange={(value) => setInitialContent(value)}
></Editor>
</div>
);
}
15 changes: 0 additions & 15 deletions frontend/src/app/components/collab/ContentPage.tsx

This file was deleted.

43 changes: 43 additions & 0 deletions frontend/src/app/components/collab/QuestionComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";

export default function QuestionComponent() {
const difficultyMapping = {
Hard: "bg-red-900 text-black",
Medium: "bg-yellow-900 text-black",
Easy: "bg-green-900 text-black",
};

return (
<Card className="h-full flex flex-col bg-stone-900 border-black">
{/* Criteria */}
<CardHeader>
<CardTitle className="text-white text-4xl">Two Sum</CardTitle>
<div className="flex pt-5 items-start gap-2">
<Badge className="bg-red-900 text-black">Difficult</Badge>
</div>
</CardHeader>

<CardContent className="flex flex-col flex-1">
{/* Question Description */}
<div className="flex-1 text-white">
Description : We, the citizens of Singapore, pledge ourselves as one
united people, regardless of race, language or religion, to build a
democratic society based on justice and equality so as to achieve
happiness, prosperity and progress for our nation.
</div>

{/* Examples Section */}
<div className="flex-1 mt-5 p-2 bg-black text-white rounded-lg text-sm">
Input : Test case 1 Output : Correct answer Explanation : Because it
is correct
</div>

{/* Constraints Section */}
<div className="mt-5 p-2 flex-1 text-white">
1 is less than n There will be a total of 1 trillion test cases
</div>
</CardContent>
</Card>
);
}
25 changes: 23 additions & 2 deletions frontend/src/app/components/collab/SessionHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
"use client";
import { Button } from "@/components/ui/button";
import { Mic } from "lucide-react";
import Image from "next/image";

export default function SessionHeader() {
return (
<header className="bg-stone-800 w-full h-[5%] text-white border-b-2 border-stone-700">
Session Header
<header
className="flex
justify-end
items-center
gap-3
bg-stone-800
w-full
h-15
text-white
border-b-2
border-stone-700"
>
<Button>
<Mic />
</Button>
<Button className="bg-red-500 text-black mr-3 hover:bg-red-300">
Leave Session
</Button>
</header>
);
}
3 changes: 2 additions & 1 deletion frontend/src/app/components/layout/NavbarWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ export default function NavbarWrapper() {

// Don't show navbar on auth pages
const isAuthPage = pathname.startsWith("/auth");
const isCollabPage = pathname.startsWith("/collab");

if (isAuthPage) {
if (isAuthPage || isCollabPage) {
return null;
}

Expand Down
46 changes: 46 additions & 0 deletions frontend/src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "@/lib/utils";

const badgeVariants = cva(
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
secondary:
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
destructive:
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);

function Badge({
className,
variant,
asChild = false,
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span";

return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
);
}

export { Badge, badgeVariants };