mirror of
https://github.com/EdiFarcas/Car-Fuel-Tracking-App.git
synced 2026-06-22 07:00:55 +03:00
Navbar Update, UI Upgrade
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
+39
-25
@@ -1,14 +1,15 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { signIn } from 'next-auth/react';
|
import { signIn } from 'next-auth/react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -27,30 +28,43 @@ export default function LoginPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="max-w-md mx-auto p-8 bg-[var(--muted)] rounded-xl shadow space-y-6">
|
<main className="w-full flex justify-center bg-[var(--background)] px-4 md:px-0 pt-10">
|
||||||
<h1 className="text-2xl font-bold text-[var(--primary)]">Login</h1>
|
<div className="w-full max-w-2xl flex flex-col items-center p-8 bg-[var(--muted)] rounded-2xl shadow space-y-6">
|
||||||
<form onSubmit={handleSubmit} className="space-y-5">
|
<h1 className="text-3xl font-bold text-[var(--primary)]">Login</h1>
|
||||||
<input
|
<form onSubmit={handleSubmit} className="w-full flex flex-col gap-6 items-center">
|
||||||
type="email"
|
<input
|
||||||
placeholder="Email"
|
type="email"
|
||||||
value={email}
|
placeholder="Email"
|
||||||
required
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
required
|
||||||
className="w-full border border-[var(--border)] px-4 py-3 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
/>
|
className="w-full max-w-2xl text-lg border border-[var(--border)] px-6 py-4 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--primary)] text-gray-900 placeholder:text-gray-500"
|
||||||
<input
|
/>
|
||||||
type="password"
|
<div className="relative w-full max-w-2xl">
|
||||||
placeholder="Password"
|
<input
|
||||||
value={password}
|
type={showPassword ? "text" : "password"}
|
||||||
required
|
placeholder="Password"
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
value={password}
|
||||||
className="w-full border border-[var(--border)] px-4 py-3 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
|
required
|
||||||
/>
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
<button type="submit" className="w-full bg-[var(--primary)] text-white py-3 rounded-lg font-semibold shadow hover:bg-blue-700 transition">
|
className="w-full text-lg border border-[var(--border)] px-6 py-4 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--primary)] text-gray-900 placeholder:text-gray-500 pr-16"
|
||||||
Sign In
|
/>
|
||||||
</button>
|
<button
|
||||||
{error && <p className="text-red-500 text-center">{error}</p>}
|
type="button"
|
||||||
</form>
|
onClick={() => setShowPassword((v) => !v)}
|
||||||
|
className="absolute right-4 top-1/2 -translate-y-1/2 text-base text-gray-500 hover:text-[var(--primary)] focus:outline-none"
|
||||||
|
tabIndex={-1}
|
||||||
|
aria-label={showPassword ? "Hide password" : "Show password"}
|
||||||
|
>
|
||||||
|
{showPassword ? "Hide" : "Show"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="w-full max-w-2xl bg-[var(--primary)] text-white py-4 text-lg rounded-lg font-semibold shadow hover:bg-blue-700 hover:scale-105 hover:shadow-lg transition-all duration-200">
|
||||||
|
Sign In
|
||||||
|
</button>
|
||||||
|
{error && <p className="text-red-500 text-center w-full">{error}</p>}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export default function RegisterPage() {
|
|||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
const handleRegister = async (e: React.FormEvent) => {
|
const handleRegister = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -25,30 +26,43 @@ export default function RegisterPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="max-w-md mx-auto p-8 bg-[var(--muted)] rounded-xl shadow space-y-6">
|
<main className="w-full flex justify-center bg-[var(--background)] px-4 md:px-0 pt-10">
|
||||||
<h1 className="text-2xl font-bold text-[var(--secondary)]">Register</h1>
|
<div className="w-full max-w-2xl flex flex-col items-center p-8 bg-[var(--muted)] rounded-2xl shadow space-y-6">
|
||||||
<form onSubmit={handleRegister} className="space-y-5">
|
<h1 className="text-3xl font-bold text-[var(--secondary)]">Register</h1>
|
||||||
<input
|
<form onSubmit={handleRegister} className="w-full flex flex-col gap-6 items-center">
|
||||||
type="email"
|
<input
|
||||||
placeholder="Email"
|
type="email"
|
||||||
value={email}
|
placeholder="Email"
|
||||||
required
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
required
|
||||||
className="w-full border border-[var(--border)] px-4 py-3 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--secondary)]"
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
/>
|
className="w-full max-w-2xl text-lg border border-[var(--border)] px-6 py-4 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--secondary)] text-gray-900 placeholder:text-gray-500"
|
||||||
<input
|
/>
|
||||||
type="password"
|
<div className="relative w-full max-w-2xl">
|
||||||
placeholder="Password"
|
<input
|
||||||
value={password}
|
type={showPassword ? "text" : "password"}
|
||||||
required
|
placeholder="Password"
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
value={password}
|
||||||
className="w-full border border-[var(--border)] px-4 py-3 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--secondary)]"
|
required
|
||||||
/>
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
<button type="submit" className="w-full bg-[var(--secondary)] text-white py-3 rounded-lg font-semibold shadow hover:bg-green-700 transition">
|
className="w-full text-lg border border-[var(--border)] px-6 py-4 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-[var(--secondary)] text-gray-900 placeholder:text-gray-500 pr-16"
|
||||||
Register
|
/>
|
||||||
</button>
|
<button
|
||||||
{error && <p className="text-red-500 text-center">{error}</p>}
|
type="button"
|
||||||
</form>
|
onClick={() => setShowPassword((v) => !v)}
|
||||||
|
className="absolute right-4 top-1/2 -translate-y-1/2 text-base text-gray-500 hover:text-[var(--secondary)] focus:outline-none"
|
||||||
|
tabIndex={-1}
|
||||||
|
aria-label={showPassword ? "Hide password" : "Show password"}
|
||||||
|
>
|
||||||
|
{showPassword ? "Hide" : "Show"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="w-full max-w-2xl bg-[var(--secondary)] text-white py-4 text-lg rounded-lg font-semibold shadow hover:bg-green-700 hover:scale-105 hover:shadow-lg transition-all duration-200">
|
||||||
|
Register
|
||||||
|
</button>
|
||||||
|
{error && <p className="text-red-500 text-center w-full">{error}</p>}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-15
@@ -1,7 +1,8 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import Link from "next/link";
|
import ClientNavbar from "../components/ClientNavbar";
|
||||||
|
import Providers from "./providers";
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
variable: "--font-geist-sans",
|
variable: "--font-geist-sans",
|
||||||
@@ -18,7 +19,7 @@ export const metadata: Metadata = {
|
|||||||
description: "Track your car's fuel and mileage easily.",
|
description: "Track your car's fuel and mileage easily.",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@@ -28,19 +29,15 @@ export default function RootLayout({
|
|||||||
<body
|
<body
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-[var(--background)] text-[var(--foreground)]`}
|
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-[var(--background)] text-[var(--foreground)]`}
|
||||||
>
|
>
|
||||||
<header className="w-full px-6 py-4 flex items-center justify-between border-b border-[var(--border)] bg-[var(--muted)] shadow-sm">
|
<Providers>
|
||||||
<Link href="/dashboard" className="text-2xl font-bold tracking-tight text-[var(--primary)]">
|
<header className="w-full px-6 py-4 border-b border-[var(--border)] bg-[var(--muted)]/80 backdrop-blur-md shadow-lg rounded-b-xl z-30 sticky top-0">
|
||||||
🚗 Car Fuel Tracker
|
<ClientNavbar />
|
||||||
</Link>
|
</header>
|
||||||
<nav className="flex gap-4">
|
<div className="min-h-screen flex flex-col">
|
||||||
<Link href="/dashboard" className="hover:text-[var(--primary)] transition">Dashboard</Link>
|
<div className="h-4" /> {/* Spacer between navbar and content */}
|
||||||
<Link href="/dashboard/cars/new" className="hover:text-[var(--secondary)] transition">Add Car</Link>
|
{children}
|
||||||
</nav>
|
</div>
|
||||||
</header>
|
</Providers>
|
||||||
<div className="min-h-screen flex flex-col">
|
|
||||||
<div className="h-4" /> {/* Spacer between navbar and content */}
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
+108
-29
@@ -1,48 +1,127 @@
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { getSession } from "@/lib/auth";
|
||||||
|
|
||||||
|
export default async function Home() {
|
||||||
|
const session = await getSession();
|
||||||
|
const isLoggedIn = !!session;
|
||||||
|
|
||||||
export default function Home() {
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col min-h-screen bg-[var(--background)] text-[var(--foreground)]">
|
<div className="flex flex-col min-h-screen bg-[var(--background)] text-[var(--foreground)]">
|
||||||
|
{/* Hero Section */}
|
||||||
<section className="flex-1 flex flex-col items-center justify-center gap-10 p-8 sm:p-20">
|
<section className="flex-1 flex flex-col items-center justify-center gap-10 p-8 sm:p-20">
|
||||||
<div className="flex flex-col items-center gap-4">
|
<div className="flex flex-col items-center gap-4">
|
||||||
<Image
|
<Image
|
||||||
className="dark:invert"
|
src="/Car_Dashboard.jpg"
|
||||||
src="/next.svg"
|
alt="Car dashboard illustration"
|
||||||
alt="Next.js logo"
|
width={480}
|
||||||
width={120}
|
height={270}
|
||||||
height={30}
|
className="mb-2 rounded-xl shadow max-w-full h-auto object-cover"
|
||||||
priority
|
priority
|
||||||
/>
|
/>
|
||||||
<h1 className="text-4xl font-bold tracking-tight text-[var(--primary)] mb-2">
|
<h1 className="text-5xl font-extrabold tracking-tight text-[var(--primary)] mb-2 text-center">
|
||||||
Welcome to Car Fuel Tracker
|
{isLoggedIn ? "Welcome Back!" : "Track Your Car’s Fuel & Mileage"}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-gray-500 max-w-xl text-center">
|
<p className="text-lg text-gray-600 max-w-2xl text-center">
|
||||||
Track your car's fuel fill-ups, mileage, and stats with a beautiful,
|
{isLoggedIn
|
||||||
simple dashboard.
|
? "Jump right into your dashboard to log fill-ups, view stats, and manage your cars."
|
||||||
|
: "Effortlessly log fill-ups, monitor fuel costs, and analyze your driving habits—all in one beautiful dashboard."}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-4 flex-wrap justify-center">
|
<div className="flex gap-4 flex-wrap justify-center">
|
||||||
<Link
|
{isLoggedIn ? (
|
||||||
href="/dashboard"
|
<Link
|
||||||
className="rounded-lg bg-[var(--primary)] text-white px-6 py-3 font-semibold shadow hover:bg-blue-700 transition"
|
href="/dashboard"
|
||||||
>
|
className="rounded-lg bg-[var(--primary)] text-white px-8 py-4 text-lg font-bold shadow hover:bg-blue-700 transition"
|
||||||
Go to Dashboard
|
>
|
||||||
</Link>
|
Go to Dashboard
|
||||||
<a
|
</Link>
|
||||||
className="rounded-lg border border-[var(--border)] bg-[var(--muted)] text-[var(--primary)] px-6 py-3 font-semibold hover:bg-[var(--primary)] hover:text-white transition"
|
) : (
|
||||||
href="https://nextjs.org/docs"
|
<>
|
||||||
target="_blank"
|
<Link
|
||||||
rel="noopener noreferrer"
|
href="/auth/login"
|
||||||
>
|
className="rounded-lg bg-[var(--primary)] text-white px-8 py-4 text-lg font-bold shadow hover:bg-blue-700 transition"
|
||||||
Next.js Docs
|
>
|
||||||
</a>
|
Login
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/auth/register"
|
||||||
|
className="rounded-lg border border-[var(--primary)] bg-[var(--muted)] text-[var(--primary)] px-8 py-4 text-lg font-bold hover:bg-[var(--primary)] hover:text-white transition"
|
||||||
|
>
|
||||||
|
Register
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<footer className="w-full py-4 flex items-center justify-center border-t border-[var(--border)] bg-[var(--muted)] text-sm text-gray-500">
|
|
||||||
<span>
|
{/* Features Section */}
|
||||||
© {new Date().getFullYear()} Car Fuel Tracker. Built with Next.js.
|
<section className="w-full max-w-4xl mx-auto grid grid-cols-1 sm:grid-cols-3 gap-8 py-12 px-4">
|
||||||
</span>
|
<div className="flex flex-col items-center text-center gap-2 bg-[var(--muted)] rounded-xl shadow p-6 border border-[var(--border)]">
|
||||||
|
<span className="text-4xl text-[var(--primary)]">⛽</span>
|
||||||
|
<h2 className="font-semibold text-lg text-[var(--foreground)]">
|
||||||
|
Log Fill-Ups
|
||||||
|
</h2>
|
||||||
|
<p className="text-[var(--foreground)] opacity-80">
|
||||||
|
Quickly add fuel entries and keep your records organized.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center text-center gap-2 bg-[var(--muted)] rounded-xl shadow p-6 border border-[var(--border)]">
|
||||||
|
<span className="text-4xl text-[var(--secondary)]">📊</span>
|
||||||
|
<h2 className="font-semibold text-lg text-[var(--foreground)]">
|
||||||
|
Analyze Stats
|
||||||
|
</h2>
|
||||||
|
<p className="text-[var(--foreground)] opacity-80">
|
||||||
|
Visualize your fuel consumption, costs, and mileage trends.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center text-center gap-2 bg-[var(--muted)] rounded-xl shadow p-6 border border-[var(--border)]">
|
||||||
|
<span className="text-4xl text-[var(--accent)]">🚗</span>
|
||||||
|
<h2 className="font-semibold text-lg text-[var(--foreground)]">
|
||||||
|
Manage Cars
|
||||||
|
</h2>
|
||||||
|
<p className="text-[var(--foreground)] opacity-80">
|
||||||
|
Track multiple vehicles and switch between them easily.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Testimonial Section */}
|
||||||
|
<section className="w-full max-w-2xl mx-auto py-8 px-4">
|
||||||
|
<div className="bg-[var(--muted)] rounded-xl shadow p-6 flex flex-col items-center gap-3 border border-[var(--border)]">
|
||||||
|
<span className="text-3xl text-[var(--secondary)]">“</span>
|
||||||
|
<p className="text-center text-lg text-[var(--foreground)] font-medium">
|
||||||
|
This app made it so easy to track my car’s fuel expenses and spot
|
||||||
|
trends. Highly recommended for anyone who wants to save money and
|
||||||
|
understand their driving habits!
|
||||||
|
</p>
|
||||||
|
<span className="text-sm text-gray-500">— Happy Driver</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<footer className="w-full py-6 flex flex-col items-center justify-center border-t border-[var(--border)] bg-[var(--muted)] text-sm text-gray-500 gap-2 mt-auto">
|
||||||
|
<nav className="flex gap-6 mb-1">
|
||||||
|
<Link
|
||||||
|
href="/about"
|
||||||
|
className="hover:text-[var(--primary)] transition"
|
||||||
|
>
|
||||||
|
About
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/contact"
|
||||||
|
className="hover:text-[var(--primary)] transition"
|
||||||
|
>
|
||||||
|
Contact
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/privacy"
|
||||||
|
className="hover:text-[var(--primary)] transition"
|
||||||
|
>
|
||||||
|
Privacy Policy
|
||||||
|
</Link>
|
||||||
|
</nav>
|
||||||
|
<span>© {new Date().getFullYear()} Car Fuel Tracker.</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
"use client";
|
||||||
|
import { SessionProvider } from "next-auth/react";
|
||||||
|
|
||||||
|
export default function Providers({ children }: { children: React.ReactNode }) {
|
||||||
|
return <SessionProvider>{children}</SessionProvider>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
"use client";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
|
||||||
|
export default function ClientNavbar() {
|
||||||
|
const { data: session } = useSession();
|
||||||
|
const isLoggedIn = !!session;
|
||||||
|
const pathname = usePathname();
|
||||||
|
const userInitial = session?.user?.name?.[0]?.toUpperCase() || session?.user?.email?.[0]?.toUpperCase() || "U";
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
|
||||||
|
const isActive = pathname === href;
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
className={`px-4 py-2 rounded-lg font-semibold transition hover:bg-[var(--primary)] hover:text-white focus:outline-none focus:ring-2 focus:ring-[var(--primary)] ${isActive ? "underline text-[var(--primary)]" : "text-[var(--foreground)]"}`}
|
||||||
|
aria-current={isActive ? "page" : undefined}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="flex w-full items-center justify-between">
|
||||||
|
<Link href="/" className="flex items-center gap-2 text-2xl font-bold tracking-tight text-[var(--primary)] hover:scale-105 transition">
|
||||||
|
<span className="text-3xl">🚗</span>
|
||||||
|
<span>Car Fuel Tracker</span>
|
||||||
|
</Link>
|
||||||
|
{/* Desktop nav */}
|
||||||
|
<div className="hidden md:flex gap-4 items-center">
|
||||||
|
<NavLink href="/dashboard">Dashboard</NavLink>
|
||||||
|
{isLoggedIn && <NavLink href="/dashboard/cars/new">Add Car</NavLink>}
|
||||||
|
{isLoggedIn ? (
|
||||||
|
<div className="flex items-center gap-2 ml-4">
|
||||||
|
<span className="w-9 h-9 rounded-full bg-[var(--primary)] text-white flex items-center justify-center font-bold text-lg border-2 border-[var(--border)] shadow" title={session.user?.name || session.user?.email || undefined}>{userInitial}</span>
|
||||||
|
<form action="/api/auth/signout" method="post">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="px-4 py-2 rounded-lg bg-[var(--accent)] text-white font-semibold shadow hover:bg-purple-800 transition focus:outline-none focus:ring-2 focus:ring-[var(--accent)]"
|
||||||
|
>
|
||||||
|
Log Out
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Link href="/auth/login" className="px-4 py-2 rounded-lg border border-[var(--primary)] text-[var(--primary)] font-semibold hover:bg-[var(--primary)] hover:text-white transition focus:outline-none focus:ring-2 focus:ring-[var(--primary)]">Login</Link>
|
||||||
|
<Link href="/auth/register" className="px-4 py-2 rounded-lg bg-[var(--primary)] text-white font-semibold shadow hover:bg-blue-700 transition focus:outline-none focus:ring-2 focus:ring-[var(--primary)]">Register</Link>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* Hamburger for mobile */}
|
||||||
|
<div className="md:hidden relative">
|
||||||
|
<button
|
||||||
|
className="w-10 h-10 flex items-center justify-center rounded-lg border border-[var(--border)] bg-[var(--muted)] text-[var(--primary)] hover:bg-[var(--primary)] hover:text-white transition focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
|
||||||
|
aria-label="Open menu"
|
||||||
|
onClick={() => setOpen((v) => !v)}
|
||||||
|
>
|
||||||
|
<span className="text-2xl">☰</span>
|
||||||
|
</button>
|
||||||
|
{open && (
|
||||||
|
<div className="absolute right-0 mt-2 w-48 bg-[var(--muted)] rounded-xl shadow-lg border border-[var(--border)] z-50 flex flex-col p-2 gap-2 animate-fade-in">
|
||||||
|
<NavLink href="/dashboard">Dashboard</NavLink>
|
||||||
|
{isLoggedIn && <NavLink href="/dashboard/cars/new">Add Car</NavLink>}
|
||||||
|
{isLoggedIn ? (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="w-8 h-8 rounded-full bg-[var(--primary)] text-white flex items-center justify-center font-bold text-base border-2 border-[var(--border)] shadow">{userInitial}</span>
|
||||||
|
<form action="/api/auth/signout" method="post" className="w-full">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="w-full px-4 py-2 rounded-lg bg-[var(--accent)] text-white font-semibold shadow hover:bg-purple-800 transition mt-2 focus:outline-none focus:ring-2 focus:ring-[var(--accent)]"
|
||||||
|
>
|
||||||
|
Log Out
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Link href="/auth/login" className="w-full px-4 py-2 rounded-lg border border-[var(--primary)] text-[var(--primary)] font-semibold hover:bg-[var(--primary)] hover:text-white transition focus:outline-none focus:ring-2 focus:ring-[var(--primary)]">Login</Link>
|
||||||
|
<Link href="/auth/register" className="w-full px-4 py-2 rounded-lg bg-[var(--primary)] text-white font-semibold shadow hover:bg-blue-700 transition focus:outline-none focus:ring-2 focus:ring-[var(--primary)]">Register</Link>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user