Merge version_2 into main #4

Merged
bender merged 4 commits from version_2 into main 2026-03-04 06:46:59 +00:00
4 changed files with 562 additions and 318 deletions

View File

@@ -1,141 +1,438 @@
"use client";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import FooterLogoReveal from '@/components/sections/footer/FooterLogoReveal';
import Link from 'next/link';
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { LogOut, Plus, Download, Filter, ChevronDown, TrendingUp, Clock, AlertCircle } from "lucide-react";
interface TransportAction {
id: string;
vehicleId: string;
vehiclePlate: string;
driverName: string;
actionType: "entry" | "exit";
timestamp: string;
location: string;
notes: string;
}
export default function DashboardPage() {
const router = useRouter();
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [actions, setActions] = useState<TransportAction[]>([]);
const [filteredActions, setFilteredActions] = useState<TransportAction[]>([]);
const [filterType, setFilterType] = useState<"all" | "entry" | "exit">("all");
const [searchTerm, setSearchTerm] = useState("");
const [showEntryForm, setShowEntryForm] = useState(false);
const [showExitForm, setShowExitForm] = useState(false);
const [formData, setFormData] = useState({
vehicleId: "", vehiclePlate: "", driverName: "", location: "", notes: ""
});
// Check authentication
useEffect(() => {
const user = localStorage.getItem("user");
if (!user) {
router.push("/login");
} else {
setIsLoggedIn(true);
setIsLoading(false);
loadActions();
}
}, [router]);
const loadActions = () => {
const savedActions = localStorage.getItem("transportActions");
const parsed = savedActions ? JSON.parse(savedActions) : [];
setActions(parsed);
filterActions(parsed);
};
const filterActions = (acts: TransportAction[], type: "all" | "entry" | "exit" = filterType, search: string = searchTerm) => {
let filtered = acts;
if (type !== "all") {
filtered = filtered.filter((a) => a.actionType === type);
}
if (search) {
filtered = filtered.filter(
(a) =>
a.vehiclePlate.toLowerCase().includes(search.toLowerCase()) ||
a.driverName.toLowerCase().includes(search.toLowerCase()) ||
a.vehicleId.toLowerCase().includes(search.toLowerCase())
);
}
setFilteredActions(filtered);
};
const handleFilterChange = (type: "all" | "entry" | "exit") => {
setFilterType(type);
filterActions(actions, type, searchTerm);
};
const handleSearchChange = (term: string) => {
setSearchTerm(term);
filterActions(actions, filterType, term);
};
const handleAddEntry = () => {
if (!formData.vehiclePlate || !formData.driverName) {
alert("Please fill in vehicle plate and driver name");
return;
}
const newAction: TransportAction = {
id: Date.now().toString(),
vehicleId: formData.vehicleId,
vehiclePlate: formData.vehiclePlate,
driverName: formData.driverName,
actionType: "entry", timestamp: new Date().toISOString(),
location: formData.location,
notes: formData.notes
};
const updated = [newAction, ...actions];
setActions(updated);
localStorage.setItem("transportActions", JSON.stringify(updated));
filterActions(updated);
setFormData({ vehicleId: "", vehiclePlate: "", driverName: "", location: "", notes: "" });
setShowEntryForm(false);
};
const handleAddExit = () => {
if (!formData.vehiclePlate || !formData.driverName) {
alert("Please fill in vehicle plate and driver name");
return;
}
const newAction: TransportAction = {
id: Date.now().toString(),
vehicleId: formData.vehicleId,
vehiclePlate: formData.vehiclePlate,
driverName: formData.driverName,
actionType: "exit", timestamp: new Date().toISOString(),
location: formData.location,
notes: formData.notes
};
const updated = [newAction, ...actions];
setActions(updated);
localStorage.setItem("transportActions", JSON.stringify(updated));
filterActions(updated);
setFormData({ vehicleId: "", vehiclePlate: "", driverName: "", location: "", notes: "" });
setShowExitForm(false);
};
const downloadReport = () => {
if (filteredActions.length === 0) {
alert("No data to download");
return;
}
const csv = [
["ID", "Vehicle ID", "Vehicle Plate", "Driver Name", "Action Type", "Timestamp", "Location", "Notes"],
...filteredActions.map((a) => [
a.id,
a.vehicleId,
a.vehiclePlate,
a.driverName,
a.actionType,
new Date(a.timestamp).toLocaleString(),
a.location,
a.notes
])
]
.map((row) => row.map((cell) => `"${cell}"`).join(","))
.join("\n");
const blob = new Blob([csv], { type: "text/csv" });
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `transport-log-${new Date().toISOString().split("T")[0]}.csv`;
a.click();
window.URL.revokeObjectURL(url);
};
const handleLogout = () => {
localStorage.removeItem("user");
router.push("/login");
};
if (isLoading) {
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center">
<div className="text-center">
<div className="inline-block animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
<p className="mt-4 text-gray-600">Loading dashboard...</p>
</div>
</div>
);
}
if (!isLoggedIn) {
return null;
}
const entryCount = actions.filter((a) => a.actionType === "entry").length;
const exitCount = actions.filter((a) => a.actionType === "exit").length;
return (
<ThemeProvider
defaultButtonVariant="bounce-effect"
defaultTextAnimation="entrance-slide"
borderRadius="soft"
contentWidth="smallMedium"
sizing="largeSmallSizeMediumTitles"
background="fluid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="glass"
headingFontWeight="light"
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Home", id: "home" },
{ name: "Features", id: "features" },
{ name: "How It Works", id: "how-it-works" },
{ name: "About", id: "about" },
{ name: "Contact", id: "contact" }
]}
button={{ text: "Login", href: "/login" }}
brandName="TransportLog"
/>
</div>
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
{/* Header */}
<header className="bg-white shadow-sm sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 py-4 flex items-center justify-between">
<Link href="/" className="flex items-center space-x-2">
<div className="text-2xl font-bold text-blue-600">TransportLog</div>
</Link>
<button
onClick={handleLogout}
className="flex items-center space-x-2 text-red-600 hover:text-red-700 font-semibold"
>
<LogOut className="w-5 h-5" />
<span>Logout</span>
</button>
</div>
</header>
<div id="dashboard-hero" data-section="dashboard-hero" className="min-h-screen flex items-center justify-center bg-gradient-to-br from-gray-50 to-gray-100 px-4">
<div className="text-center max-w-2xl mx-auto">
<h1 className="text-5xl md:text-6xl font-light text-foreground mb-6">
Your Transport Dashboard
</h1>
<p className="text-xl text-gray-600 mb-8">
Real-time monitoring of all vehicle entries and exits. Track movements, access logs, and generate reports from a single unified dashboard.
</p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-12">
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h3 className="text-2xl font-bold text-accent mb-2">150+</h3>
<p className="text-gray-600">Vehicles Tracked</p>
<div className="max-w-7xl mx-auto px-4 py-8">
{/* Stats */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-600 text-sm font-medium">Total Entries</p>
<p className="text-3xl font-bold text-blue-600 mt-2">{entryCount}</p>
</div>
<Plus className="w-12 h-12 text-blue-100" />
</div>
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h3 className="text-2xl font-bold text-accent mb-2">99.9%</h3>
<p className="text-gray-600">System Uptime</p>
</div>
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-600 text-sm font-medium">Total Exits</p>
<p className="text-3xl font-bold text-green-600 mt-2">{exitCount}</p>
</div>
<ChevronDown className="w-12 h-12 text-green-100" />
</div>
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h3 className="text-2xl font-bold text-accent mb-2">24/7</h3>
<p className="text-gray-600">Real-Time Monitoring</p>
</div>
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-600 text-sm font-medium">Total Records</p>
<p className="text-3xl font-bold text-indigo-600 mt-2">{actions.length}</p>
</div>
<TrendingUp className="w-12 h-12 text-indigo-100" />
</div>
</div>
</div>
</div>
<div id="dashboard-features" data-section="dashboard-features" className="py-20 px-4 bg-white">
<div className="max-w-4xl mx-auto">
<h2 className="text-4xl font-light text-foreground mb-12 text-center">
Dashboard Features
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="bg-gradient-to-br from-blue-50 to-gray-50 rounded-lg p-8 border border-gray-200">
<div className="text-accent text-3xl mb-4">📊</div>
<h3 className="text-2xl font-semibold text-foreground mb-3">Live Vehicle Tracking</h3>
<p className="text-gray-600">
See all vehicle movements in real-time. Know exactly when each vehicle enters and exits your facility with precise timestamps and location data.
</p>
{/* Action Buttons */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
<button
onClick={() => setShowEntryForm(!showEntryForm)}
className="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 px-4 rounded-lg flex items-center justify-center space-x-2 transition"
>
<Plus className="w-5 h-5" />
<span>Record Entry</span>
</button>
<button
onClick={() => setShowExitForm(!showExitForm)}
className="bg-green-600 hover:bg-green-700 text-white font-semibold py-3 px-4 rounded-lg flex items-center justify-center space-x-2 transition"
>
<ChevronDown className="w-5 h-5" />
<span>Record Exit</span>
</button>
<button
onClick={downloadReport}
className="bg-indigo-600 hover:bg-indigo-700 text-white font-semibold py-3 px-4 rounded-lg flex items-center justify-center space-x-2 transition"
>
<Download className="w-5 h-5" />
<span>Download Report</span>
</button>
</div>
{/* Forms */}
{(showEntryForm || showExitForm) && (
<div className="bg-white rounded-lg shadow p-6 mb-8">
<h3 className="text-xl font-bold text-gray-900 mb-4">
{showEntryForm ? "Record Vehicle Entry" : "Record Vehicle Exit"}
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<input
type="text"
placeholder="Vehicle ID"
value={formData.vehicleId}
onChange={(e) => setFormData({ ...formData, vehicleId: e.target.value })}
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
/>
<input
type="text"
placeholder="Vehicle Plate (e.g., ABC-1234)"
value={formData.vehiclePlate}
onChange={(e) => setFormData({ ...formData, vehiclePlate: e.target.value })}
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
/>
<input
type="text"
placeholder="Driver Name"
value={formData.driverName}
onChange={(e) => setFormData({ ...formData, driverName: e.target.value })}
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
/>
<input
type="text"
placeholder="Location"
value={formData.location}
onChange={(e) => setFormData({ ...formData, location: e.target.value })}
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
/>
</div>
<div className="bg-gradient-to-br from-blue-50 to-gray-50 rounded-lg p-8 border border-gray-200">
<div className="text-accent text-3xl mb-4">📝</div>
<h3 className="text-2xl font-semibold text-foreground mb-3">Complete Audit Trail</h3>
<p className="text-gray-600">
Every action is logged with driver information, cargo details, and system metadata. Perfect for compliance and historical analysis.
</p>
<textarea
placeholder="Additional notes (optional)"
value={formData.notes}
onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none mb-4"
rows={3}
/>
<div className="flex space-x-3">
{showEntryForm && (
<button
onClick={handleAddEntry}
className="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-6 rounded-lg transition"
>
Save Entry
</button>
)}
{showExitForm && (
<button
onClick={handleAddExit}
className="bg-green-600 hover:bg-green-700 text-white font-semibold py-2 px-6 rounded-lg transition"
>
Save Exit
</button>
)}
<button
onClick={() => {
setShowEntryForm(false);
setShowExitForm(false);
setFormData({ vehicleId: "", vehiclePlate: "", driverName: "", location: "", notes: "" });
}}
className="bg-gray-300 hover:bg-gray-400 text-gray-800 font-semibold py-2 px-6 rounded-lg transition"
>
Cancel
</button>
</div>
<div className="bg-gradient-to-br from-blue-50 to-gray-50 rounded-lg p-8 border border-gray-200">
<div className="text-accent text-3xl mb-4">📥</div>
<h3 className="text-2xl font-semibold text-foreground mb-3">Entry Management</h3>
<p className="text-gray-600">
Quick entry recording with automatic timestamp, vehicle recognition, and anomaly detection for unusual patterns.
</p>
</div>
)}
{/* Filters & Search */}
<div className="bg-white rounded-lg shadow p-6 mb-8">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 items-end">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Search</label>
<input
type="text"
placeholder="Search by vehicle plate, driver name, or ID..."
value={searchTerm}
onChange={(e) => handleSearchChange(e.target.value)}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
/>
</div>
<div className="bg-gradient-to-br from-blue-50 to-gray-50 rounded-lg p-8 border border-gray-200">
<div className="text-accent text-3xl mb-4">📤</div>
<h3 className="text-2xl font-semibold text-foreground mb-3">Exit Documentation</h3>
<p className="text-gray-600">
Capture exit details including cargo status, fuel levels, and maintenance notes for complete vehicle history tracking.
</p>
</div>
<div className="bg-gradient-to-br from-blue-50 to-gray-50 rounded-lg p-8 border border-gray-200">
<div className="text-accent text-3xl mb-4">📊</div>
<h3 className="text-2xl font-semibold text-foreground mb-3">Advanced Analytics</h3>
<p className="text-gray-600">
Visualize trends, patterns, and performance metrics. Identify peak times, vehicle utilization, and operational efficiency opportunities.
</p>
</div>
<div className="bg-gradient-to-br from-blue-50 to-gray-50 rounded-lg p-8 border border-gray-200">
<div className="text-accent text-3xl mb-4">🔐</div>
<h3 className="text-2xl font-semibold text-foreground mb-3">Secure Access Control</h3>
<p className="text-gray-600">
Role-based permissions ensure only authorized personnel can view specific data. Multi-factor authentication protects sensitive information.
</p>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Filter by Type</label>
<div className="flex space-x-2">
<button
onClick={() => handleFilterChange("all")}
className={`px-4 py-2 rounded-lg font-semibold transition ${
filterType === "all" ? "bg-blue-600 text-white" : "bg-gray-200 text-gray-700 hover:bg-gray-300"
}`}
>
All
</button>
<button
onClick={() => handleFilterChange("entry")}
className={`px-4 py-2 rounded-lg font-semibold transition ${
filterType === "entry" ? "bg-blue-600 text-white" : "bg-gray-200 text-gray-700 hover:bg-gray-300"
}`}
>
Entry
</button>
<button
onClick={() => handleFilterChange("exit")}
className={`px-4 py-2 rounded-lg font-semibold transition ${
filterType === "exit" ? "bg-blue-600 text-white" : "bg-gray-200 text-gray-700 hover:bg-gray-300"
}`}
>
Exit
</button>
</div>
</div>
</div>
</div>
</div>
<div id="dashboard-cta" data-section="dashboard-cta" className="py-20 px-4 bg-gradient-to-r from-accent to-blue-900">
<div className="max-w-3xl mx-auto text-center">
<h2 className="text-4xl font-light text-white mb-6">
Ready to Access Your Dashboard?
</h2>
<p className="text-xl text-blue-100 mb-8">
Log in now to start monitoring your transport operations with real-time precision.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link href="/login" className="bg-white text-accent px-8 py-3 rounded-lg font-semibold hover:bg-gray-100 transition">
Log In Now
</Link>
<Link href="/" className="bg-transparent text-white border-2 border-white px-8 py-3 rounded-lg font-semibold hover:bg-white hover:bg-opacity-10 transition">
Back to Home
</Link>
</div>
{/* Data Table */}
<div className="bg-white rounded-lg shadow overflow-hidden">
{filteredActions.length === 0 ? (
<div className="p-12 text-center">
<AlertCircle className="w-12 h-12 text-gray-300 mx-auto mb-4" />
<p className="text-gray-500 text-lg">No transport records found</p>
<p className="text-gray-400 text-sm mt-1">Start by recording vehicle entries or exits</p>
</div>
) : (
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-gray-50 border-b border-gray-200">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Vehicle Plate</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Driver Name</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Action Type</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Timestamp</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Location</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Notes</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
{filteredActions.map((action) => (
<tr key={action.id} className="hover:bg-gray-50 transition">
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{action.vehiclePlate}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-600">{action.driverName}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm">
<span
className={`px-3 py-1 rounded-full text-xs font-semibold ${
action.actionType === "entry"
? "bg-blue-100 text-blue-800"
: "bg-green-100 text-green-800"
}`}
>
{action.actionType.charAt(0).toUpperCase() + action.actionType.slice(1)}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-600">
{new Date(action.timestamp).toLocaleString()}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-600">{action.location}</td>
<td className="px-6 py-4 text-sm text-gray-600 max-w-xs truncate">{action.notes}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
{/* Pagination Info */}
<div className="mt-4 text-center text-sm text-gray-600">
Showing {filteredActions.length} of {actions.length} records
</div>
</div>
<div id="footer" data-section="footer">
<FooterLogoReveal
logoText="TransportLog"
leftLink={{ text: "Privacy Policy", href: "/" }}
rightLink={{ text: "Terms of Service", href: "/" }}
/>
</div>
</ThemeProvider>
</div>
);
}
}

View File

@@ -1,55 +1,20 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { Open_Sans } from "next/font/google";
import "./globals.css";
import { ServiceWrapper } from "@/components/ServiceWrapper";
import Tag from "@/tag/Tag";
const inter = Inter({
variable: "--font-inter",
subsets: ["latin"],
});
const openSans = Open_Sans({
variable: "--font-open-sans",
subsets: ["latin"],
});
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "TransportLog - Real-Time Transport Action Tracking",
description: "Record vehicle entries and exits instantly. Secure authentication, real-time dashboards, downloadable reports for complete transport visibility.",
keywords: "transport tracking, vehicle logging, fleet management, entry exit logs, logistics software, downloadable reports",
robots: {
index: true,
follow: true,
},
openGraph: {
title: "TransportLog - Real-Time Transport Action Tracking",
description: "Track every transport movement with precision. Entry/exit logging, secure access, downloadable reports.",
type: "website",
siteName: "TransportLog",
},
twitter: {
card: "summary_large_image",
title: "TransportLog - Real-Time Transport Action Tracking",
description: "Track every transport movement with precision. Entry/exit logging, secure access, downloadable reports.",
},
};
title: "TransportLog - Transport Action Recording System", description: "Record vehicle entries and exits. Track transport movements with real-time monitoring and downloadable reports."};
export default function RootLayout({
children,
}: Readonly<{
}: {
children: React.ReactNode;
}>) {
}) {
return (
<html lang="en" suppressHydrationWarning>
<ServiceWrapper>
<body
className={`${inter.variable} ${openSans.variable} antialiased`}
>
<Tag />
{children}
<html lang="en">
<body className={inter.className}>{children}
<script
dangerouslySetInnerHTML={{
__html: `
@@ -1417,7 +1382,6 @@ export default function RootLayout({
}}
/>
</body>
</ServiceWrapper>
</html>
);
}
}

View File

@@ -1,166 +1,149 @@
"use client";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import FooterLogoReveal from '@/components/sections/footer/FooterLogoReveal';
import Link from 'next/link';
import { Lock, Mail } from 'lucide-react';
import { useState } from 'react';
import { useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { LogIn, Eye, EyeOff, AlertCircle } from "lucide-react";
export default function LoginPage() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const router = useRouter();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [error, setError] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
setIsLoading(true);
try {
// Simulate login - in production, call your API
if (!email || !password) {
setError("Please enter both email and password");
return;
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
setError("Please enter a valid email address");
return;
}
if (password.length < 6) {
setError("Password must be at least 6 characters");
return;
}
// Simulate successful login
localStorage.setItem("user", JSON.stringify({ email, isLoggedIn: true }));
router.push("/dashboard");
} catch (err) {
setError("Login failed. Please try again.");
} finally {
setIsLoading(false);
}
};
return (
<ThemeProvider
defaultButtonVariant="bounce-effect"
defaultTextAnimation="entrance-slide"
borderRadius="soft"
contentWidth="smallMedium"
sizing="largeSmallSizeMediumTitles"
background="fluid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="glass"
headingFontWeight="light"
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Home", id: "home" },
{ name: "Features", id: "features" },
{ name: "How It Works", id: "how-it-works" },
{ name: "About", id: "about" },
{ name: "Contact", id: "contact" }
]}
button={{ text: "Login", href: "/login" }}
brandName="TransportLog"
/>
</div>
<div id="login-hero" data-section="login-hero" className="min-h-screen flex items-center justify-center bg-gradient-to-br from-gray-50 to-gray-100 px-4 py-20">
<div className="w-full max-w-md">
<div className="bg-white rounded-lg shadow-lg border border-gray-200 p-8">
<div className="text-center mb-8">
<h1 className="text-3xl font-light text-foreground mb-2">
Welcome Back
</h1>
<p className="text-gray-600">
Sign in to access your transport dashboard
</p>
</div>
<form className="space-y-6">
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Email Address
</label>
<div className="relative">
<Mail className="absolute left-3 top-3.5 text-gray-400 h-5 w-5" />
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@example.com"
className="w-full pl-10 pr-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-foreground mb-2">
Password
</label>
<div className="relative">
<Lock className="absolute left-3 top-3.5 text-gray-400 h-5 w-5" />
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="••••••••"
className="w-full pl-10 pr-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent"
/>
</div>
</div>
<div className="flex items-center justify-between">
<label className="flex items-center">
<input type="checkbox" className="w-4 h-4 text-accent border-gray-300 rounded" />
<span className="ml-2 text-sm text-gray-600">Remember me</span>
</label>
<Link href="#" className="text-sm text-accent hover:underline">
Forgot password?
</Link>
</div>
<button
type="submit"
className="w-full bg-accent text-white py-2.5 rounded-lg font-semibold hover:bg-blue-900 transition"
>
Sign In
</button>
</form>
<div className="mt-6 pt-6 border-t border-gray-200 text-center">
<p className="text-gray-600 text-sm">
Don't have an account?{" "}
<Link href="/" className="text-accent font-semibold hover:underline">
Start free trial
</Link>
</p>
</div>
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center p-4">
<div className="w-full max-w-md">
<div className="bg-white rounded-lg shadow-xl p-8">
{/* Header */}
<div className="flex items-center justify-center mb-8">
<LogIn className="w-8 h-8 text-blue-600 mr-3" />
<h1 className="text-3xl font-bold text-gray-900">TransportLog</h1>
</div>
<div className="mt-8 bg-blue-50 rounded-lg p-6 border border-blue-200">
<h3 className="font-semibold text-foreground mb-3">Demo Credentials:</h3>
<p className="text-sm text-gray-700 mb-2">
<strong>Email:</strong> demo@transportlog.com
</p>
<p className="text-sm text-gray-700">
<strong>Password:</strong> demo123456
</p>
<h2 className="text-2xl font-bold text-gray-900 mb-2 text-center">Welcome Back</h2>
<p className="text-gray-600 text-center mb-8">Sign in to your account to continue</p>
{/* Error Alert */}
{error && (
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg flex items-start">
<AlertCircle className="w-5 h-5 text-red-600 mr-3 flex-shrink-0 mt-0.5" />
<p className="text-red-700 text-sm">{error}</p>
</div>
)}
{/* Form */}
<form onSubmit={handleSubmit} className="space-y-6">
{/* Email */}
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
Email Address
</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@example.com"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition"
/>
</div>
{/* Password */}
<div>
<label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-2">
Password
</label>
<div className="relative">
<input
id="password"
type={showPassword ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="••••••••"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-2.5 text-gray-500 hover:text-gray-700"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
</div>
</div>
{/* Remember & Forgot */}
<div className="flex items-center justify-between">
<label className="flex items-center">
<input type="checkbox" className="w-4 h-4 text-blue-600 rounded" />
<span className="ml-2 text-sm text-gray-700">Remember me</span>
</label>
<Link href="#" className="text-sm text-blue-600 hover:text-blue-700">
Forgot password?
</Link>
</div>
{/* Submit Button */}
<button
type="submit"
disabled={isLoading}
className="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-semibold py-2 px-4 rounded-lg transition duration-200"
>
{isLoading ? "Signing in..." : "Sign In"}
</button>
</form>
{/* Demo Credentials */}
<div className="mt-8 p-4 bg-blue-50 rounded-lg border border-blue-200">
<p className="text-sm font-semibold text-blue-900 mb-2">Demo Credentials:</p>
<p className="text-sm text-blue-800">Email: <span className="font-mono">demo@transportlog.com</span></p>
<p className="text-sm text-blue-800">Password: <span className="font-mono">demo123456</span></p>
</div>
{/* Footer */}
<p className="mt-8 text-center text-gray-600 text-sm">
New to TransportLog?{" "}
<Link href="/" className="text-blue-600 hover:text-blue-700 font-semibold">
Sign up
</Link>
</p>
</div>
</div>
<div id="login-features" data-section="login-features" className="py-16 px-4 bg-white">
<div className="max-w-4xl mx-auto">
<h2 className="text-3xl font-light text-foreground mb-12 text-center">
Why Transport Companies Trust TransportLog
</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
<div className="text-center">
<div className="text-4xl mb-4">🔒</div>
<h3 className="text-xl font-semibold text-foreground mb-2">Enterprise Security</h3>
<p className="text-gray-600">
Military-grade encryption protects your data with multi-factor authentication
</p>
</div>
<div className="text-center">
<div className="text-4xl mb-4"></div>
<h3 className="text-xl font-semibold text-foreground mb-2">Lightning Fast</h3>
<p className="text-gray-600">
Real-time updates and instant report generation for immediate insights
</p>
</div>
<div className="text-center">
<div className="text-4xl mb-4">📱</div>
<h3 className="text-xl font-semibold text-foreground mb-2">Mobile Ready</h3>
<p className="text-gray-600">
Access your dashboard anywhere, anytime with full mobile support
</p>
</div>
</div>
</div>
</div>
<div id="footer" data-section="footer">
<FooterLogoReveal
logoText="TransportLog"
leftLink={{ text: "Privacy Policy", href: "/" }}
rightLink={{ text: "Terms of Service", href: "/" }}
/>
</div>
</ThemeProvider>
</div>
);
}
}

View File

@@ -28,7 +28,7 @@ export default function HomePage() {
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Home", id: "home" },
{ name: "Home", id: "/" },
{ name: "Features", id: "features" },
{ name: "How It Works", id: "how-it-works" },
{ name: "About", id: "about" },
@@ -208,4 +208,4 @@ export default function HomePage() {
</div>
</ThemeProvider>
);
}
}