Client portal: profile, activity pages + middleware fix
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { FolderOpen, FileText, AlertCircle } from "lucide-react"
|
||||
|
||||
export default function ClientDashboard() {
|
||||
const router = useRouter()
|
||||
const [counts, setCounts] = useState({ projects: 0, invoices: 0, tickets: 0 })
|
||||
const [name, setName] = useState("")
|
||||
|
||||
useEffect(() => {
|
||||
fetch("/client-portal/api/projects", { credentials: "include" })
|
||||
.then((r) => r.json())
|
||||
.then((d) => setCounts((prev) => ({ ...prev, projects: d.projects?.length || 0 })))
|
||||
.catch(() => {})
|
||||
|
||||
fetch("/client-portal/api/invoices", { credentials: "include" })
|
||||
.then((r) => r.json())
|
||||
.then((d) => setCounts((prev) => ({ ...prev, invoices: d.invoices?.length || 0 })))
|
||||
.catch(() => {})
|
||||
|
||||
fetch("/client-portal/api/support", { credentials: "include" })
|
||||
.then((r) => r.json())
|
||||
.then((d) => setCounts((prev) => ({ ...prev, tickets: d.tickets?.length || 0 })))
|
||||
.catch(() => {})
|
||||
|
||||
fetch("/api/auth/me", { credentials: "include" })
|
||||
.then((r) => r.json())
|
||||
.then((d) => setName(d.firstName || d.email || "Client"))
|
||||
.catch(() => {})
|
||||
}, [])
|
||||
|
||||
const cards = [
|
||||
{ label: "Active Projects", value: counts.projects, icon: FolderOpen, color: "#1BB0CE", href: "/client-portal/projects" },
|
||||
{ label: "Invoices", value: counts.invoices, icon: FileText, color: "#a855f7", href: "/client-portal/invoices" },
|
||||
{ label: "Support Tickets", value: counts.tickets, icon: AlertCircle, color: "#f59e0b", href: "/client-portal/support" },
|
||||
]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-white mb-1">Welcome, {name}</h1>
|
||||
<p className="text-sm text-[#6a6a75] mb-6">Your project overview at a glance</p>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
{cards.map((card) => {
|
||||
const Icon = card.icon
|
||||
return (
|
||||
<button
|
||||
key={card.label}
|
||||
onClick={() => router.push(card.href)}
|
||||
className="bg-[#0d1117] border border-[#1a1a24] rounded-xl p-5 text-left hover:border-[#1BB0CE]/30 transition-all group"
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<div className="w-10 h-10 rounded-lg flex items-center justify-center" style={{ backgroundColor: `${card.color}15` }}>
|
||||
<Icon className="h-5 w-5" style={{ color: card.color }} />
|
||||
</div>
|
||||
<span className="text-2xl font-bold text-white">{card.value}</span>
|
||||
</div>
|
||||
<p className="text-sm text-[#8a8a95]">{card.label}</p>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user