redesign the dashboard
Build & Deploy / Build & Push Docker Image (push) Failing after 43s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 4m59s
Test / Marketplace Unit Tests (push) Has been cancelled
Test / Admin Unit Tests (push) Has been cancelled
Test / Dashboard Unit Tests (push) Has been cancelled
Test / API Integration Tests (push) Has been cancelled

This commit is contained in:
root
2026-06-24 02:00:31 -04:00
parent 6c50458aca
commit 8ee9bc0bca
32 changed files with 1314 additions and 260 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+72 -1
View File
@@ -2,7 +2,7 @@
import Link from 'next/link'
import { useEffect, useState } from 'react'
import { Calendar, Car, Users, DollarSign, AlertTriangle, Clock, XCircle } from 'lucide-react'
import { Calendar, Car, Users, DollarSign, AlertTriangle, Clock, XCircle, Plus, BarChart3, FileText, TrendingUp } from 'lucide-react'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend } from 'recharts'
import StatCard from '@/components/ui/StatCard'
import { EMPLOYEE_PROFILE_KEY, apiFetch } from '@/lib/api'
@@ -40,6 +40,9 @@ interface DashboardData {
interface EmployeeProfile {
role?: string
firstName?: string
lastName?: string
email?: string
}
const STATUS_COLORS: Record<string, string> = {
@@ -50,6 +53,30 @@ const STATUS_COLORS: Record<string, string> = {
CANCELLED: 'badge-red',
}
interface QuickAction {
icon: React.ReactNode
label: string
href: string
color: string
}
function QuickActionsSection({ actions }: { actions: QuickAction[] }) {
return (
<div className="flex flex-wrap gap-3">
{actions.map((action) => (
<Link
key={action.href}
href={action.href}
className={`flex items-center gap-2 px-4 py-3 rounded-lg border border-slate-200 hover:border-slate-300 hover:bg-slate-50 transition-all ${action.color}`}
>
{action.icon}
<span className="text-sm font-medium">{action.label}</span>
</Link>
))}
</div>
)
}
function SubscriptionBanner({
status,
trialEndsAt,
@@ -108,12 +135,14 @@ function SubscriptionBanner({
export default function DashboardPage() {
const { dict, language } = useDashboardI18n()
const d = dict.dashboardPage
const nav = dict.nav
const localeCode = language === 'fr' ? 'fr-FR' : language === 'ar' ? 'ar-MA' : 'en-US'
const [data, setData] = useState<DashboardData | null>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<{ code: string; message: string } | null>(null)
const [employeeRole, setEmployeeRole] = useState<string | null>(null)
const [employeeName, setEmployeeName] = useState<string | null>(null)
useEffect(() => {
try {
@@ -121,6 +150,8 @@ export default function DashboardPage() {
if (!cached) return
const profile = JSON.parse(cached) as EmployeeProfile
setEmployeeRole(profile.role ?? null)
const fullName = [profile.firstName, profile.lastName].filter(Boolean).join(' ') || null
setEmployeeName(fullName)
} catch {}
}, [])
@@ -158,6 +189,46 @@ export default function DashboardPage() {
return (
<div className="space-y-6">
{/* Welcome Section */}
<div>
<h1 className="text-2xl font-bold text-slate-900 mb-1">
Welcome back{employeeName ? `, ${employeeName}` : ''}!
</h1>
<p className="text-sm text-slate-600 mb-4">
Here's what's happening with your fleet today
</p>
</div>
{/* Quick Actions */}
<QuickActionsSection
actions={[
{
icon: <Plus className="w-4 h-4" />,
label: 'New Reservation',
href: '/reservations/new',
color: 'text-blue-600',
},
{
icon: <Car className="w-4 h-4" />,
label: nav.fleet,
href: '/fleet',
color: 'text-green-600',
},
{
icon: <Users className="w-4 h-4" />,
label: nav.customers,
href: '/customers',
color: 'text-purple-600',
},
{
icon: <FileText className="w-4 h-4" />,
label: nav.reports,
href: '/reports',
color: 'text-orange-600',
},
]}
/>
{data?.subscription && (
<SubscriptionBanner
status={data.subscription.status}
+1 -1
View File
@@ -15,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{