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
754 changes: 754 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
},
"dependencies": {
"@hookform/resolvers": "^4.1.3",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-navigation-menu": "^1.2.5",
"@radix-ui/react-slot": "^1.1.2",
"@tailwindcss/vite": "^4.0.9",
"class-variance-authority": "^0.7.1",
Expand Down
42 changes: 0 additions & 42 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,42 +0,0 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
}
15 changes: 12 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import LoginPage from './pages/LoginPage';
import React from 'react';
import AuthContext from './context/AuthContext';
import connectToBlockchain from './config';
import Layout from '@/pages/layout';

function App() {
const auth = React.useContext(AuthContext);
Expand Down Expand Up @@ -56,9 +57,17 @@ function App() {

return (
<Routes>
<Route path="/register" element={<LoginPage />} />
<Route path="/" element={<div>home</div>} />
<Route path="*" element={<div>not found return 404</div>} />
<Route element={<Layout />}>
<Route path="/" element={<div>home</div>} />
<Route path="/voter/add" element={<LoginPage />} />
<Route path="/election">
<Route path="past" element={<div>past election</div>} />
<Route path="upcoming" element={<div>upcoming election</div>} />
<Route path="create" element={<div>create election</div>} />
<Route path="active" element={<div>active election</div>} />
</Route>
<Route path="*" element={<div>not found return 404</div>} />
</Route>
</Routes>
);
}
Expand Down
242 changes: 242 additions & 0 deletions src/components/shared/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import type React from 'react';
import { useState } from 'react';
import { Link } from 'react-router';
import { Vote, Menu, User, LogOut } from 'lucide-react';

import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from '@/components/ui/navigation-menu';
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';

export default function Navbar() {
const [isOpen, setIsOpen] = useState(false);

return (
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 px-2">
<div className="container flex h-16 items-center justify-between">
<div className="flex items-center gap-2">
<Link to="/" className="flex items-center gap-2">
<Vote className="h-6 w-6 text-primary" />
<span className="text-xl font-bold text-primary">VoteChain</span>
</Link>
</div>

{/* Desktop Navigation */}
<NavigationMenu className="hidden md:flex">
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuLink className={navigationMenuTriggerStyle()} href="/">
Home
</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Elections</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
<li className="row-span-3">
<NavigationMenuLink
className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-primary/50 to-primary p-6 no-underline outline-none focus:shadow-md"
href="/elections/active"
>
<div className="mt-4 mb-2 text-lg font-medium text-primary-foreground">
Active Elections
</div>
<p className="text-sm leading-tight text-primary-foreground/90">
View and participate in ongoing elections secured by blockchain technology
</p>
</NavigationMenuLink>
</li>
<ListItem href="/elections/past" title="Past Elections">
View results from completed elections
</ListItem>
<ListItem href="/elections/upcoming" title="Upcoming Elections">
Elections scheduled to start soon
</ListItem>
<ListItem href="/elections/create" title="Create Election">
Set up a new secure blockchain election
</ListItem>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="/how-it-works" className={navigationMenuTriggerStyle()}>
How It Works
</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink className={navigationMenuTriggerStyle()} href="/about">
About
</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>

<div className="flex items-center gap-4">
{/* User Account Dropdown */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon" className="hidden md:flex">
<User className="h-5 w-5" />
<span className="sr-only">User account</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<Link to="/profile" className="flex w-full">
My Profile
</Link>
</DropdownMenuItem>
<DropdownMenuItem>
<Link to="/my-votes" className="flex w-full">
My Votes
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<Link to="/logout" className="flex w-full items-center">
<LogOut className="mr-2 h-4 w-4" />
Logout
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

<Button className="hidden md:inline-flex">Connect Wallet</Button>

<Sheet open={isOpen} onOpenChange={setIsOpen}>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="md:hidden">
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle menu</span>
</Button>
</SheetTrigger>
<SheetContent side="right">
<div className="flex flex-col gap-6 py-6 px-2">
<Link to="/" className="flex items-center gap-2" onClick={() => setIsOpen(false)}>
<Vote className="h-6 w-6 text-primary" />
<span className="text-xl font-bold text-primary">BlockVote</span>
</Link>
<nav className="flex flex-col gap-4">
<Link to="/" className="text-lg font-medium" onClick={() => setIsOpen(false)}>
Home
</Link>
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<Link
to="/active-elections"
className="text-lg font-medium"
onClick={() => setIsOpen(false)}
>
Elections
</Link>
</div>
<div className="flex flex-col gap-2 pl-4">
<Link
to="/active-elections"
className="text-sm"
onClick={() => setIsOpen(false)}
>
Active Elections
</Link>
<Link
to="/past-elections"
className="text-sm"
onClick={() => setIsOpen(false)}
>
Past Elections
</Link>
<Link
to="/upcoming-elections"
className="text-sm"
onClick={() => setIsOpen(false)}
>
Upcoming Elections
</Link>
<Link
to="/create-election"
className="text-sm"
onClick={() => setIsOpen(false)}
>
Create Election
</Link>
</div>
</div>
<Link
to="/how-it-works"
className="text-lg font-medium"
onClick={() => setIsOpen(false)}
>
How It Works
</Link>
<Link
to="/about"
className="text-lg font-medium"
onClick={() => setIsOpen(false)}
>
About
</Link>
<Link
to="/profile"
className="text-lg font-medium"
onClick={() => setIsOpen(false)}
>
My Profile
</Link>
<Link
to="/my-votes"
className="text-lg font-medium"
onClick={() => setIsOpen(false)}
>
My Votes
</Link>
</nav>
<Button className="w-full" onClick={() => setIsOpen(false)}>
Connect Wallet
</Button>
</div>
</SheetContent>
</Sheet>
</div>
</div>
</header>
);
}

const ListItem = ({
className,
title,
children,
...props
}: React.ComponentPropsWithoutRef<'a'> & { title: string }) => {
return (
<li>
<NavigationMenuLink asChild>
<a
className={cn(
'block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground',
className
)}
{...props}
>
<div className="text-sm font-medium leading-none">{title}</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p>
</a>
</NavigationMenuLink>
</li>
);
};
13 changes: 4 additions & 9 deletions src/components/shared/auth/Login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ export function LoginForm() {
<Form {...form}>
<form className={cn('flex flex-col gap-6')} onSubmit={form.handleSubmit(onSubmit)}>
<div className="flex flex-col items-center gap-2 text-center">
<h1 className="text-2xl font-bold">Login to your account</h1>
<h1 className="text-2xl font-bold">Register as a Voter</h1>
<p className="text-balance text-sm text-muted-foreground">
Enter your Name below to login to your account
Enter your Name below to register as a voter. You will be verified by the admin before
you can vote.
</p>
</div>
<div className="grid gap-6">
Expand All @@ -96,15 +97,9 @@ export function LoginForm() {
</div>
<FormError message={error} />
<Button type="submit" className="w-full" disabled={isPending}>
Login
Register as Voter
</Button>
</div>
<div className="text-center text-sm">
Don&apos;t have an account?{' '}
<a href="#" className="underline underline-offset-4">
Sign up
</a>
</div>
</form>
</Form>
);
Expand Down
Loading
Loading