Skip to content

Commit

Permalink
Merge pull request #43 from brendantwh/auth
Browse files Browse the repository at this point in the history
Profile, forgot password, reset password pages
  • Loading branch information
brendantwh authored Oct 17, 2024
2 parents 1716121 + 0a3fc9f commit 925621b
Show file tree
Hide file tree
Showing 24 changed files with 1,086 additions and 598 deletions.
80 changes: 80 additions & 0 deletions frontend/app/(authenticated)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use client"

import Link from "next/link";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { User, LogOut } from "lucide-react";
import { usePathname } from "next/navigation";

export default function AuthenticatedLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const pathname = usePathname();

return (
<div className="min-h-screen bg-white relative">
<header className="flex items-center justify-between px-8 py-4 fixed top-0 left-0 right-0 z-10 bg-white/80 backdrop-blur-sm">
<div className="flex items-center gap-2">
<Link
href="/"
className="text-2xl font-bold font-brand tracking-tight text-brand-700"
prefetch={false}
>
PeerPrep
</Link>
{process.env.NODE_ENV == "development" && (
<Badge variant="dev" className="ml-2 font-brand">
DEV
</Badge>
)}
</div>
<div className="hidden desktop:flex items-center gap-4">
<nav className="flex items-center gap-10 font-brand">
<Link
href="/questions"
className={`text-lg font-semibold uppercase transition duration-100
${pathname === '/questions'
? 'text-gray-700 drop-shadow-md'
: 'text-gray-700/50 hover:text-gray-700'
}`} prefetch={false}
>
Questions
</Link>
<Link
href="/question-repo"
className={`text-lg font-semibold uppercase transition duration-100
${pathname === '/question-repo'
? 'text-gray-700 drop-shadow-md'
: 'text-gray-700/50 hover:text-gray-700'
}`}
prefetch={false}
>
Repository
</Link>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="icon"
className="rounded-full text-gray-400 transition duration-100 hover:text-gray-400 hover:bg-white hover:border-2"
>
<User className="" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="font-sans">
<DropdownMenuLabel>Username</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem asChild><Link href="/profile" className="cursor-pointer"><User className="mr-2 h-4 w-4" />Profile</Link></DropdownMenuItem>
<DropdownMenuItem asChild><Link href="/" className="cursor-pointer"><LogOut className="mr-2 h-4 w-4" />Log out</Link></DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</nav>
</div>
</header>
{children}
</div>
);
}
100 changes: 100 additions & 0 deletions frontend/app/(authenticated)/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"use client";

import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { CircleX, Pencil, Save } from "lucide-react";
import React, { ChangeEvent, useState } from "react";

export default function Home() {
const [isEditing, setIsEditing] = useState(false);
const [userData, setUserData] = useState({
username: "johndoe",
email: "[email protected]",
password: "abcdefgh",
});

const handleEdit = () => {
if (isEditing) {
console.log("Saving changes:", userData);
}
setIsEditing(!isEditing);
};

const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
const { id, value } = e.target;
setUserData(prev => ({ ...prev, [id]: value }));
};

return (
<main className="flex items-center justify-center min-h-screen p-4 font-sans text-black">
<Card className="-mt-80 w-full max-w-xl rounded-2xl">
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle className="font-serif font-normal tracking-tight text-3xl">Profile</CardTitle>
{isEditing ? (
<div>
<Button variant="ghost" size="icon" onClick={handleEdit} className="border-none rounded-l-xl rounded-r-none text-gray-600 bg-gray-100 hover:bg-gray-200 hover:text-gray-800">
<CircleX className="h-4 w-4" />
</Button>
<Button variant="ghost" size="icon" onClick={handleEdit} className="border-none rounded-l-none rounded-r-xl text-white bg-green-600 hover:bg-green-700 hover:text-white">
<Save className="h-4 w-4" />
</Button>
</div>
) : (
<Button variant="ghost" size="icon" onClick={handleEdit} className="bg-primary text-primary-foreground border-none rounded-xl hover:bg-primary/85 hover:text-primary-foreground">
<Pencil className="h-4 w-4" />
</Button>
)}
</CardHeader>
<CardContent>
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">
<Label htmlFor="username">Username</Label>
<Input
id="username"
value={userData.username}
disabled={!isEditing}
onChange={handleInputChange}
/>
</div>
<div className="flex flex-col gap-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
value={userData.email}
disabled={!isEditing}
onChange={handleInputChange}
/>
</div>
<div className="flex flex-col gap-2">
<Label htmlFor="password">Password</Label>
<Input
id="password"
type="password"
value={userData.password}
disabled={!isEditing}
onChange={handleInputChange}
/>
</div>
<div className="flex justify-between">
<div className="text-left">
<Label>Questions Attempted</Label>
<div className="flex items-end gap-1.5 leading-7 font-mono">
<span className="text-2xl font-bold">11</span>
<span>/</span>
<span>20</span>
</div>
</div>
<div className="text-right">
<Label>Total Attempts</Label>
<p className="text-2xl font-bold font-mono">14</p>
</div>
</div>
</div>
</CardContent>
</Card>
</main>
);
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function DataTablePagination<TData>({
<SelectValue placeholder={table.getState().pagination.pageSize} />
</SelectTrigger>
<SelectContent side="top" className="font-sans">
{[10, 20, 30, 40, 50].map((pageSize) => (
{[5, 10, 20, 30, 40, 50].map((pageSize) => (
<SelectItem key={pageSize} value={`${pageSize}`}>
{pageSize}
</SelectItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ export function DataTable<TData, TValue>({
columnFilters,
rowSelection
},
initialState: {
pagination: {
pageSize: 5,
},
},
meta: {
removeSelectedRows: (selectedRows: number[]) => {
const filterFunc = (old: TData[]) => {
Expand All @@ -99,12 +104,12 @@ export function DataTable<TData, TValue>({
})

return (
<div className="font-sans text-black">
<div className="w-full font-sans text-black flex flex-col h-fit">
<div className="pb-4">
<DataTableToolbar table={table} data={data} setData={setData} />
</div>

<div className="rounded-md border">
<div className="rounded-md border flex-grow overflow-hidden flex flex-col">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
Expand All @@ -124,7 +129,7 @@ export function DataTable<TData, TValue>({
</TableRow>
))}
</TableHeader>
<TableBody>
<TableBody className="overflow-auto">
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import { useEffect, useState } from "react";
import { columns, Question } from "./columns"
import { DataTable } from "./data-table"
import { Badge, BadgeProps } from "@/components/ui/badge";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { BadgeProps } from "@/components/ui/badge";

const complexityList: Array<{
value: string;
Expand Down Expand Up @@ -77,44 +74,9 @@ export default function QuestionRepo() {
}, []);

return (
<div className="min-h-screen p-4 bg-white">
<header className="flex items-center justify-between p-4">
<div className="flex items-center gap-2">
<Link
href="/"
className="text-2xl font-bold font-branding tracking-tight text-brand-700"
prefetch={false}
>
PeerPrep
</Link>
{process.env.NODE_ENV == "development" && (
<Badge variant="dev" className="ml-2 font-branding">
DEV
</Badge>
)}
</div>
<div className="hidden desktop:flex items-center gap-4">
<nav className="flex items-center gap-10 font-branding">
<Link href="/questions" className="text-lg font-semibold uppercase text-gray-700/50 hover:text-gray-700 transition duration-150" prefetch={false}>
Questions
</Link>
<Link href="/question-repo" className="text-lg font-semibold uppercase text-gray-700 drop-shadow-md" prefetch={false}>
Repository
</Link>
<Button variant="ghost" size="icon" className="rounded-full">
<Avatar>
<AvatarImage src="/placeholder-user.jpg" alt="CR" />
<AvatarFallback className="font-branding">CR</AvatarFallback>
</Avatar>
</Button>
</nav>
</div>
</header>

<main className="mx-auto p-12">
<div className="mb-12"><span className="font-serif font-light text-4xl text-primary tracking-tight">Question Repository</span></div>
<DataTable columns={columns(setQuestionList)} data={questionList} setData={setQuestionList} loading={loading}/>
</main>
</div>
<main className="flex flex-col min-h-screen px-20 pt-24 pb-10">
<div className="mb-10"><span className="font-serif font-light text-4xl text-primary tracking-tight">Question Repository</span></div>
<DataTable columns={columns(setQuestionList)} data={questionList} setData={setQuestionList} loading={loading}/>
</main>
);
}
Loading

0 comments on commit 925621b

Please sign in to comment.