mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-01 07:23:11 +00:00
Wire up dashboard tiles with live data, keep tables
- Fetch stats from /api/Dashboard/Stats endpoint - KPI tiles show real counts and navigate on click - Restore Priority Analysis and Invoice Analysis tables (placeholder data)
This commit is contained in:
parent
2477bcf5a6
commit
5aa194c7be
2 changed files with 67 additions and 39 deletions
|
|
@ -25,6 +25,12 @@
|
|||
align-items: center;
|
||||
gap: 15px;
|
||||
min-height: 100px;
|
||||
cursor: pointer;
|
||||
transition: filter 0.15s;
|
||||
}
|
||||
|
||||
.kpiCard:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
.bg-success { background-color: #28a745; }
|
||||
|
|
|
|||
|
|
@ -1,48 +1,71 @@
|
|||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { get } from "../apiUtil";
|
||||
import { API_URL } from "../constants";
|
||||
import "./Dashboard.css";
|
||||
|
||||
const Dashboard = () => {
|
||||
const navigate = useNavigate();
|
||||
const [stats, setStats] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
get(`${API_URL}/Dashboard/Stats`)
|
||||
.then((data) => setStats(data))
|
||||
.catch(() => {})
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
const kpis = [
|
||||
{ title: "Create a Work Order", icon: "✓", color: "success", desc: "Report a problem you need fixed" },
|
||||
{ title: "Open Work Orders", icon: "📂", color: "primary", stat: "885" },
|
||||
{ title: "Not Dispatched", icon: "⏱", color: "info", stat: "503" },
|
||||
{ title: "Completed Orders", icon: "📋", color: "warning", stat: "4,088" },
|
||||
];
|
||||
|
||||
const priorities = [
|
||||
{ priority: "5", total: "665", "0-14": "83", "15-29": "79", "30-59": "62", "60+": "441" },
|
||||
{ priority: "4", total: "327", "0-14": "4", "15-29": "19", "30-59": "3", "60+": "301" },
|
||||
{ priority: "3", total: "295", "0-14": "69", "15-29": "64", "30-59": "42", "60+": "120" },
|
||||
{ priority: "2", total: "95", "0-14": "26", "15-29": "38", "30-59": "11", "60+": "20" },
|
||||
];
|
||||
|
||||
const invoices = [
|
||||
{ name: "Draft", count: 0, amount: "0.00" },
|
||||
{ name: "Challenged", count: 0, amount: "0.00" },
|
||||
{ name: "Pending Approval", count: 0, amount: "0.00" },
|
||||
{ name: "Approved", count: 0, amount: "0.00" },
|
||||
{ name: "Paid", count: 0, amount: "0.00" },
|
||||
{
|
||||
title: "Create a Work Order",
|
||||
icon: "fa-plus",
|
||||
color: "success",
|
||||
desc: "Report a problem you need fixed",
|
||||
onClick: () => navigate("/workorders/new"),
|
||||
},
|
||||
{
|
||||
title: "Open Work Orders",
|
||||
icon: "fa-folder-open",
|
||||
color: "primary",
|
||||
stat: loading ? "..." : stats?.open ?? 0,
|
||||
onClick: () => navigate("/workorders"),
|
||||
},
|
||||
{
|
||||
title: "Not Dispatched",
|
||||
icon: "fa-clock-o",
|
||||
color: "info",
|
||||
stat: loading ? "..." : stats?.notDispatched ?? 0,
|
||||
onClick: () => navigate("/workorders"),
|
||||
},
|
||||
{
|
||||
title: "Completed Orders",
|
||||
icon: "fa-check-circle",
|
||||
color: "warning",
|
||||
stat: loading ? "..." : stats?.completed ?? 0,
|
||||
onClick: () => navigate("/workorders"),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="dashboardPage">
|
||||
<div className="pageTitle">Dashboard</div>
|
||||
|
||||
{/* KPI Cards */}
|
||||
<div className="kpiContainer">
|
||||
{kpis.map((kpi, idx) => (
|
||||
<div key={idx} className={`kpiCard bg-${kpi.color}`}>
|
||||
<div className="kpiIcon">{kpi.icon}</div>
|
||||
<div key={idx} className={`kpiCard bg-${kpi.color}`} onClick={kpi.onClick}>
|
||||
<div className="kpiIcon">
|
||||
<i className={`fa ${kpi.icon}`}></i>
|
||||
</div>
|
||||
<div className="kpiContent">
|
||||
<h5>{kpi.title}</h5>
|
||||
{kpi.stat && <div className="kpiStat">{kpi.stat}</div>}
|
||||
{kpi.stat !== undefined && <div className="kpiStat">{kpi.stat?.toLocaleString?.() ?? kpi.stat}</div>}
|
||||
{kpi.desc && <p>{kpi.desc}</p>}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Priority Analysis */}
|
||||
<div className="card mt-4">
|
||||
<div className="cardHeader">
|
||||
<h3>Priority Analysis</h3>
|
||||
|
|
@ -61,14 +84,14 @@ const Dashboard = () => {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{priorities.map((row, idx) => (
|
||||
<tr key={idx}>
|
||||
<td>{row.priority}</td>
|
||||
<td className="text-right">{row.total}</td>
|
||||
<td className="text-right">{row["0-14"]}</td>
|
||||
<td className="text-right">{row["15-29"]}</td>
|
||||
<td className="text-right">{row["30-59"]}</td>
|
||||
<td className="text-right">{row["60+"]}</td>
|
||||
{[5, 4, 3, 2, 1].map((p) => (
|
||||
<tr key={p}>
|
||||
<td>{p}</td>
|
||||
<td className="text-right">—</td>
|
||||
<td className="text-right">—</td>
|
||||
<td className="text-right">—</td>
|
||||
<td className="text-right">—</td>
|
||||
<td className="text-right">—</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
|
@ -76,7 +99,6 @@ const Dashboard = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Invoice Analysis */}
|
||||
<div className="card mt-4">
|
||||
<div className="cardHeader">
|
||||
<h3>Invoice Analysis</h3>
|
||||
|
|
@ -91,11 +113,11 @@ const Dashboard = () => {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{invoices.map((inv, idx) => (
|
||||
<tr key={idx}>
|
||||
<td>{inv.name}</td>
|
||||
<td className="text-right">{inv.count}</td>
|
||||
<td className="text-right">${inv.amount}</td>
|
||||
{["Draft", "Challenged", "Pending Approval", "Approved", "Paid"].map((s) => (
|
||||
<tr key={s}>
|
||||
<td>{s}</td>
|
||||
<td className="text-right">0</td>
|
||||
<td className="text-right">$0.00</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue