Merge version_2 into main #2
208
src/app/dashboard/page.tsx
Normal file
208
src/app/dashboard/page.tsx
Normal file
@@ -0,0 +1,208 @@
|
||||
"use client";
|
||||
|
||||
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import { BarChart3, TrendingUp, Truck, AlertCircle, Clock, MapPin, Users, Activity } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
export default function DashboardPage() {
|
||||
const [selectedLoad, setSelectedLoad] = useState<string | null>(null);
|
||||
|
||||
const loads = [
|
||||
{
|
||||
id: "LOAD-001", origin: "Los Angeles, CA", destination: "Las Vegas, NV", status: "in-transit", driver: "John Smith", distance: "270 miles", eta: "2:30 PM", progress: 65,
|
||||
vehicle: "Truck #12"
|
||||
},
|
||||
{
|
||||
id: "LOAD-002", origin: "Phoenix, AZ", destination: "Denver, CO", status: "dispatched", driver: "Sarah Johnson", distance: "600 miles", eta: "Next Day", progress: 0,
|
||||
vehicle: "Truck #8"
|
||||
},
|
||||
{
|
||||
id: "LOAD-003", origin: "Denver, CO", destination: "Chicago, IL", status: "delivered", driver: "Mike Chen", distance: "1000 miles", eta: "Completed", progress: 100,
|
||||
vehicle: "Truck #15"
|
||||
},
|
||||
{
|
||||
id: "LOAD-004", origin: "Dallas, TX", destination: "Houston, TX", status: "in-transit", driver: "Emma Wilson", distance: "240 miles", eta: "1:15 PM", progress: 45,
|
||||
vehicle: "Truck #5"
|
||||
},
|
||||
{
|
||||
id: "LOAD-005", origin: "Portland, OR", destination: "Seattle, WA", status: "pending", driver: "Unassigned", distance: "170 miles", eta: "Pending Assignment", progress: 0,
|
||||
vehicle: "Available"
|
||||
},
|
||||
];
|
||||
|
||||
const metrics = [
|
||||
{ icon: Truck, label: "Active Loads", value: "12", color: "bg-blue-500" },
|
||||
{ icon: TrendingUp, label: "Completed Today", value: "8", color: "bg-green-500" },
|
||||
{ icon: Clock, label: "Avg Delivery Time", value: "2.3h", color: "bg-purple-500" },
|
||||
{ icon: AlertCircle, label: "Delays", value: "1", color: "bg-red-500" },
|
||||
];
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case "in-transit":
|
||||
return "bg-blue-100 text-blue-700";
|
||||
case "delivered":
|
||||
return "bg-green-100 text-green-700";
|
||||
case "dispatched":
|
||||
return "bg-yellow-100 text-yellow-700";
|
||||
case "pending":
|
||||
return "bg-gray-100 text-gray-700";
|
||||
default:
|
||||
return "bg-gray-100 text-gray-700";
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusLabel = (status: string) => {
|
||||
return status.charAt(0).toUpperCase() + status.slice(1).replace("-", " ");
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="soft"
|
||||
contentWidth="mediumSmall"
|
||||
sizing="mediumLarge"
|
||||
background="noiseDiagonalGradient"
|
||||
cardStyle="layered-gradient"
|
||||
primaryButtonStyle="shadow"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingInline
|
||||
brandName="DispatchPro"
|
||||
navItems={[
|
||||
{ name: "Features", id: "features" },
|
||||
{ name: "Pricing", id: "pricing" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Dashboard", id: "/dashboard" },
|
||||
{ name: "Contact", id: "contact" }
|
||||
]}
|
||||
button={{
|
||||
text: "Logout", href: "/"
|
||||
}}
|
||||
animateOnLoad={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen bg-background pt-24 pb-12">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold text-foreground mb-2">Fleet Dashboard</h1>
|
||||
<p className="text-foreground/60">Track and manage all active loads and dispatcher operations</p>
|
||||
</div>
|
||||
|
||||
{/* Metrics Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
{metrics.map((metric, idx) => {
|
||||
const Icon = metric.icon;
|
||||
return (
|
||||
<div key={idx} className="bg-card rounded-lg p-6 border border-accent/20">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className={`${metric.color} p-3 rounded-lg`}>
|
||||
<Icon className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-foreground/60 text-sm mb-1">{metric.label}</p>
|
||||
<p className="text-3xl font-bold text-foreground">{metric.value}</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Loads Section */}
|
||||
<div className="bg-card rounded-lg border border-accent/20 overflow-hidden">
|
||||
<div className="bg-gradient-to-r from-primary-cta/10 to-accent/10 px-6 py-4 border-b border-accent/20">
|
||||
<h2 className="text-2xl font-bold text-foreground flex items-center gap-2">
|
||||
<Activity className="w-6 h-6" />
|
||||
Active Loads & Dispatcher Management
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead className="bg-background/50 border-b border-accent/20">
|
||||
<tr>
|
||||
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Load ID</th>
|
||||
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Route</th>
|
||||
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Driver</th>
|
||||
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Vehicle</th>
|
||||
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Status</th>
|
||||
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Progress</th>
|
||||
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">ETA</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{loads.map((load) => (
|
||||
<tr
|
||||
key={load.id}
|
||||
onClick={() => setSelectedLoad(selectedLoad === load.id ? null : load.id)}
|
||||
className="border-b border-accent/10 hover:bg-background/30 cursor-pointer transition-colors"
|
||||
>
|
||||
<td className="px-6 py-4 text-sm font-mono font-semibold text-foreground">{load.id}</td>
|
||||
<td className="px-6 py-4 text-sm text-foreground">
|
||||
<div className="flex items-center gap-2">
|
||||
<MapPin className="w-4 h-4 text-accent" />
|
||||
<span className="text-xs">{load.origin} → {load.destination}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-foreground">{load.driver}</td>
|
||||
<td className="px-6 py-4 text-sm text-foreground">{load.vehicle}</td>
|
||||
<td className="px-6 py-4 text-sm">
|
||||
<span className={`px-3 py-1 rounded-full text-xs font-semibold ${getStatusColor(load.status)}`}>
|
||||
{getStatusLabel(load.status)}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm">
|
||||
<div className="w-full bg-background rounded-full h-2 overflow-hidden">
|
||||
<div
|
||||
className="bg-gradient-to-r from-primary-cta to-accent h-full transition-all"
|
||||
style={{ width: `${load.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
<span className="text-xs text-foreground/60 mt-1 block">{load.progress}%</span>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-foreground">{load.eta}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Selected Load Details */}
|
||||
{selectedLoad && (
|
||||
<div className="mt-8 bg-card rounded-lg border border-accent/20 p-6">
|
||||
<h3 className="text-xl font-bold text-foreground mb-4">Load Details: {selectedLoad}</h3>
|
||||
{loads
|
||||
.filter((load) => load.id === selectedLoad)
|
||||
.map((load) => (
|
||||
<div key={load.id} className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<p className="text-foreground/60 text-sm mb-1">Origin</p>
|
||||
<p className="text-foreground font-semibold mb-4">{load.origin}</p>
|
||||
<p className="text-foreground/60 text-sm mb-1">Driver</p>
|
||||
<p className="text-foreground font-semibold mb-4">{load.driver}</p>
|
||||
<p className="text-foreground/60 text-sm mb-1">Distance</p>
|
||||
<p className="text-foreground font-semibold">{load.distance}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/60 text-sm mb-1">Destination</p>
|
||||
<p className="text-foreground font-semibold mb-4">{load.destination}</p>
|
||||
<p className="text-foreground/60 text-sm mb-1">Vehicle</p>
|
||||
<p className="text-foreground font-semibold mb-4">{load.vehicle}</p>
|
||||
<p className="text-foreground/60 text-sm mb-1">ETA</p>
|
||||
<p className="text-foreground font-semibold">{load.eta}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -34,6 +34,7 @@ export default function LandingPage() {
|
||||
{ name: "Features", id: "features" },
|
||||
{ name: "Pricing", id: "pricing" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Dashboard", id: "/dashboard" },
|
||||
{ name: "Contact", id: "contact" }
|
||||
]}
|
||||
button={{
|
||||
|
||||
Reference in New Issue
Block a user