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
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:
Vendored
+2
-1
@@ -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.
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user