Dashboard Componeets files are added some
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import Sidebar from "@/components/dashboard/sidebar";
|
||||
|
||||
import OperationsDashboard from "@/components/dashboard/dashboard";
|
||||
|
||||
export default function DashboardPage() {
|
||||
return (
|
||||
@@ -10,8 +11,8 @@ export default function DashboardPage() {
|
||||
<main className="flex bg-[#091522]">
|
||||
<Sidebar />
|
||||
|
||||
<div className="flex-1 p-10 text-white">
|
||||
Main Content
|
||||
<div className="flex-1 p-6 text-white">
|
||||
<OperationsDashboard/>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
28
components/dashboard/activityFeed.tsx
Normal file
28
components/dashboard/activityFeed.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { ActivityFeedProps } from "@/constants/types"
|
||||
|
||||
|
||||
|
||||
export default function ActivityFeed({ activities }: ActivityFeedProps) {
|
||||
return (
|
||||
<div className="rounded-xl border border-[#14253d] bg-[#0c1a2c] p-6 flex flex-col">
|
||||
<h3 className="text-base font-semibold text-white mb-4">Recent activity</h3>
|
||||
<hr className="border-[#14253d] mb-6" />
|
||||
<div className="divide-y divide-[#14253d] flex-1 flex flex-col justify-between">
|
||||
{activities.map((activity, index) => {
|
||||
const parts = activity.text.split(activity.boldText);
|
||||
|
||||
return (
|
||||
<div key={index} className="py-3.5 flex items-start text-sm gap-4 first:pt-0 last:pb-0">
|
||||
<span className="text-gray-500 font-medium tabular-nums shrink-0">{activity.time}</span>
|
||||
<p className="text-gray-300">
|
||||
{parts[0]}
|
||||
<span className="font-semibold text-white">{activity.boldText}</span>
|
||||
{parts[1]}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
34
components/dashboard/barchart.tsx
Normal file
34
components/dashboard/barchart.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import {BarChartProps} from "@/constants/types";
|
||||
|
||||
|
||||
|
||||
export default function BarChart({ data }: BarChartProps) {
|
||||
return (
|
||||
<div className="rounded-xl border border-[#14253d] bg-[#0c1a2c]
|
||||
p-4 flex flex-col justify-between">
|
||||
<div className="flex items-center justify-between mb-4 ">
|
||||
<h3 className="text-base font-semibold text-white">TFM requests · monthly</h3>
|
||||
<span className="text-xs text-gray-500">2026 · auto-refresh 60s</span>
|
||||
</div>
|
||||
<hr className="border-[#14253d] mb-6" />
|
||||
|
||||
<div>
|
||||
{/* Bars */}
|
||||
<div className="flex items-end justify-between h-40 px-2 border-b border-[#1b3454] pb-2">
|
||||
{data.map((item, idx) => (
|
||||
<div key={idx} className="flex flex-col items-center flex-1 group">
|
||||
<div className={`w-5 ${item.height} bg-teal-400 rounded-t transition-all duration-300 group-hover:bg-teal-300`} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* X-Axis */}
|
||||
<div className="flex justify-between pt-3 px-2 text-xs font-medium text-gray-500">
|
||||
{data.map((item, idx) => (
|
||||
<span key={idx} className="w-5 text-center">{item.month}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
14
components/dashboard/cardHeader.tsx
Normal file
14
components/dashboard/cardHeader.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
export function CardHeader({ title, subtitle }: { title: string; subtitle?: string }) {
|
||||
return (
|
||||
<div className="flex justify-between items-baseline mb-2 border-b border-[#162942]/50 pb-3">
|
||||
<h3 className="text-white text-base font-semibold tracking-wide">{title}</h3>
|
||||
{subtitle && (
|
||||
<span className="text-[#4e6178] text-xs font-medium uppercase tracking-wider">
|
||||
{subtitle}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
8
components/dashboard/cardWrapper.tsx
Normal file
8
components/dashboard/cardWrapper.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export function Card({ children, className = "" }: { children: React.ReactNode; className?: string }) {
|
||||
return (
|
||||
<div className={`bg-[#0a1526] border border-[#162942] rounded-xl p-3
|
||||
shadow-xl flex flex-col justify-between ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
189
components/dashboard/dashboard.tsx
Normal file
189
components/dashboard/dashboard.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
|
||||
import { Check } from 'lucide-react';
|
||||
import Navbar from "@/components/dashboard/navbar";
|
||||
import BarChart from "@/components/dashboard/barchart";
|
||||
import StatCard from "@/components/dashboard/statCard";
|
||||
import ActivityFeed from "@/components/dashboard/activityFeed";
|
||||
import {activities, chartData} from "@/constants/constant"
|
||||
import { Card } from '@/components/dashboard/cardWrapper';
|
||||
import {CardHeader} from '@/components/dashboard/cardHeader';
|
||||
import {ProgressBarRow }from '@/components/dashboard/progressBarRow';
|
||||
import {StatusProgressRow} from '@/components/dashboard/statusProgressRow';
|
||||
|
||||
export default function Dashboard() {
|
||||
|
||||
|
||||
return (
|
||||
<div className=" bg-[#071321] text-[#93a3b8] font-sans antialiased">
|
||||
<Navbar />
|
||||
|
||||
<main >
|
||||
{/* Title Section */}
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<div className="flex items-center gap-2
|
||||
text-xs font-bold uppercase tracking-widest text-teal-500 mt-8">
|
||||
<span>Apple One — HQ Tower</span>
|
||||
<span className="text-gray-600">·</span>
|
||||
<span className="text-gray-400">Tenant</span>
|
||||
<span className="text-gray-600">·</span>
|
||||
<span className="text-gray-400">Apple One</span>
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold text-white tracking-tight">Operations dashboard</h1>
|
||||
<p className="mt-2 text-sm text-gray-400 max-w-xl leading-relaxed">
|
||||
Live snapshot scoped to Apple One. The layout below is the dashboard published for this tenant in Administration.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-20 flex items-center gap-1 rounded-full border border-teal-500/30 bg-teal-500/10 px-2 py-1 text-xs font-medium text-teal-400">
|
||||
<Check className="h-3.5 w-3.5 " />
|
||||
<span>Published layout</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 4 Cards Grid */}
|
||||
<div className="mt-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2">
|
||||
<StatCard title="Open Requests" value={14} subtitle="+4 overdue" progress={70} color="teal" />
|
||||
<StatCard title="Checklists Due" value={6} subtitle="of 10 scheduled" progress={60} color="amber" />
|
||||
<StatCard title="PPM Attention" value={4} subtitle="assets off-plan" progress={40} color="rose" />
|
||||
<StatCard title="Assets Tracked" value={8} subtitle="across blocks" progress={65} color="emerald" />
|
||||
</div>
|
||||
|
||||
{/* Lower Row Grid */}
|
||||
<div className=" mt-4 grid grid-cols-1 lg:grid-cols-12 gap-4">
|
||||
<div className="lg:col-span-7">
|
||||
<BarChart data={chartData} />
|
||||
</div>
|
||||
<div className="lg:col-span-5">
|
||||
<ActivityFeed activities={activities} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="mt-4 grid grid-cols-1 lg:grid-cols-12 gap-6">
|
||||
|
||||
{/* Schedule Performance MMR */}
|
||||
<div className="lg:col-span-7">
|
||||
<Card>
|
||||
<CardHeader title="Schedule performance • MMR" subtitle="ppm & amc" />
|
||||
<div className="overflow-x-auto mt-2">
|
||||
<table className=" text-left border-collapse">
|
||||
<thead>
|
||||
<tr className="text-[#4b5f7a] text-xs font-bold uppercase tracking-wider border-b border-[#1b2b41]/40 pb-3">
|
||||
<th className="pb-3">Schedule</th>
|
||||
<th className="pb-3 text-right">Total</th>
|
||||
<th className="pb-3 text-right">Done</th>
|
||||
<th className="pb-3 text-right">On Time</th>
|
||||
<th className="pb-3 text-right">Delayed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-[#1b2b41]/30 text-sm font-semibold">
|
||||
<tr className="hover:bg-[#11233a]/25 transition-colors">
|
||||
<td className="py-4 text-white">PPM</td>
|
||||
<td className="py-4 text-right text-slate-300">24</td>
|
||||
<td className="py-4 text-right text-slate-300">19</td>
|
||||
<td className="py-4 text-right text-slate-300">17</td>
|
||||
<td className="py-4 text-right text-red-500">2</td>
|
||||
</tr>
|
||||
<tr className="hover:bg-[#11233a]/25 transition-colors">
|
||||
<td className="py-4 text-white">AMC</td>
|
||||
<td className="py-4 text-right text-slate-300">8</td>
|
||||
<td className="py-4 text-right text-slate-300">6</td>
|
||||
<td className="py-4 text-right text-slate-300">6</td>
|
||||
<td className="py-4 text-right text-slate-400">0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Energy Today */}
|
||||
<div className="lg:col-span-5 ">
|
||||
<Card>
|
||||
<CardHeader title="Energy • today"
|
||||
subtitle="day-wise" />
|
||||
<div className="space-y-2
|
||||
text-sm mt-2 font-mono">
|
||||
<div className="flex justify-between items-baseline">
|
||||
<span className="text-[#4b5f7a] font-semibold text-xs tracking-wider uppercase">Electricity</span>
|
||||
<span className="text-white text-base font-bold">1,284 <span className="text-xs font-normal text-slate-400 font-sans">kwh</span></span>
|
||||
</div>
|
||||
<div className="flex justify-between items-baseline">
|
||||
<span className="text-[#4b5f7a] font-semibold text-xs tracking-wider uppercase">Water</span>
|
||||
<span className="text-white text-base font-bold">312 <span className="text-xs font-normal text-slate-400 font-sans">kL</span></span>
|
||||
</div>
|
||||
<div className="flex justify-between items-baseline">
|
||||
<span className="text-[#4b5f7a] font-semibold text-xs tracking-wider uppercase">Diesel</span>
|
||||
<span className="text-white text-base font-bold">48 <span className="text-xs font-normal text-slate-400 font-sans">L</span></span>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center pt-4 border-t border-[#1b2b41]/40">
|
||||
<span className="text-[#4b5f7a] font-semibold text-xs tracking-wider uppercase">Vs Avg</span>
|
||||
<div className="flex items-center space-x-3">
|
||||
<span className="bg-[#0b2723] text-[#17cbb5] border border-[#17cbb5]/20 text-[10px] font-bold px-3 py-1 rounded-full flex items-center gap-1.5 uppercase">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#17cbb5] inline-block animate-pulse"></span>
|
||||
Completed
|
||||
</span>
|
||||
<span className="text-[#17cbb5] font-bold text-sm">-6%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* ROW 2: Sub-metrics and Tracking widgets */}
|
||||
<div className="mt-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
|
||||
{/* Top 5 Requester */}
|
||||
<Card>
|
||||
<CardHeader title="Top 5 requester" subtitle="this month" />
|
||||
<div className="space-y-3 mt-1">
|
||||
<ProgressBarRow label="Academic Block" value={18} maxValue={18} />
|
||||
<ProgressBarRow label="Hostel Block" value={13} maxValue={18} />
|
||||
<ProgressBarRow label="HVAC Plant" value={9} maxValue={18} />
|
||||
<ProgressBarRow label="Pump Room" value={6} maxValue={18} />
|
||||
<ProgressBarRow label="Lobby" value={4} maxValue={18} />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Asset Register */}
|
||||
<Card>
|
||||
<CardHeader title="Asset register" subtitle="live" />
|
||||
<div className="flex items-baseline space-x-3 my-4">
|
||||
<span className="text-5xl font-light text-[#17cbb5]">8</span>
|
||||
<span className="text-[#5b7391] text-xs font-semibold uppercase tracking-wider">assets tracked</span>
|
||||
</div>
|
||||
<div className="space-y-3 text-sm font-semibold border-t border-[#1b2b41]/40 pt-4">
|
||||
<div className="flex justify-between py-1">
|
||||
<span className="text-[#4b5f7a] text-xs uppercase tracking-wider">On Plan</span>
|
||||
<span className="text-white">3</span>
|
||||
</div>
|
||||
<div className="flex justify-between py-1">
|
||||
<span className="text-[#4b5f7a] text-xs uppercase tracking-wider">Attention</span>
|
||||
<span className="text-red-500">5</span>
|
||||
</div>
|
||||
<div className="flex justify-between py-1">
|
||||
<span className="text-[#4b5f7a] text-xs uppercase tracking-wider">Groups</span>
|
||||
<span className="text-white">4</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* PM Plan vs Started */}
|
||||
<Card>
|
||||
<CardHeader title="PM plan vs started" subtitle="this month" />
|
||||
<div className="space-y-4 mt-1">
|
||||
<StatusProgressRow label="Planned" value={24} total={24} barColor="bg-[#52647c]" />
|
||||
<StatusProgressRow label="Started" value={19} total={24} barColor="bg-[#17cbb5]" />
|
||||
<StatusProgressRow label="Completed" value={17} total={24} barColor="bg-[#10b981]" />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
80
components/dashboard/navbar.tsx
Normal file
80
components/dashboard/navbar.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import { Search, HelpCircle, Globe, Sun, Bell, ChevronDown, MapPin } from 'lucide-react';
|
||||
|
||||
export default function Navbar() {
|
||||
return (
|
||||
<header className="flex items-center justify-between
|
||||
bg-[#071321] ">
|
||||
|
||||
{/* Left Group */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Company Selector */}
|
||||
<div className="flex items-center gap-2 rounded-full bg-[#0a1826]
|
||||
px-3 py-1.5 text-sm font-semibold text-[#10b981]
|
||||
border border-[#132338] cursor-pointer hover:bg-[#0f2338] transition whitespace-nowrap">
|
||||
<span className="h-2 w-2 rounded-full bg-[#10b981] shrink-0"></span>
|
||||
<span className="font-semibold">Apple One</span>
|
||||
<ChevronDown className="h-3.5 w-3.5 text-[#10b981]" />
|
||||
</div>
|
||||
|
||||
{/* Location Selector */}
|
||||
<div className="flex items-center gap-2 rounded-full bg-[#0a1826] px-4 py-2 text-sm font-medium text-[#cbd5e1] border border-[#132338] cursor-pointer hover:bg-[#0f2338] transition whitespace-nowrap">
|
||||
<MapPin className="h-4 w-4 text-gray-500 shrink-0" />
|
||||
<span className="whitespace-nowrap">
|
||||
Apple One — <span className="text-[#cbd5e1] font-semibold">HQ Tower</span>
|
||||
</span>
|
||||
<ChevronDown className="h-4 w-4 text-gray-500 shrink-0" />
|
||||
</div>
|
||||
|
||||
{/* Search Bar */}
|
||||
<div className="relative w-60">
|
||||
<Search className="absolute left-4 top-3 h-4 w-4 text-gray-500" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search requests, equipment, met"
|
||||
className="w-full rounded-xl bg-[#0a1826] pl-10 pr-4 py-2 text-sm text-white placeholder-gray-500 border border-[#132338] focus:outline-none focus:border-teal-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Utilities */}
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Tour */}
|
||||
<button className="flex items-center gap-2 rounded-xl border border-[#132338] bg-[#0a1826] px-4 py-2 text-sm font-semibold text-white transition hover:bg-[#14253d]">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<span>Tour</span>
|
||||
</button>
|
||||
|
||||
{/* Language */}
|
||||
<div className="flex items-center gap-1.5 rounded-xl border border-[#132338] bg-[#0a1826] px-4 py-2 text-sm font-semibold text-[#cbd5e1] cursor-pointer hover:bg-[#14253d]">
|
||||
<Globe className="h-4 w-4 text-gray-400" />
|
||||
<span>English</span>
|
||||
<ChevronDown className="h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
|
||||
{/* Live Indicator */}
|
||||
<div className="flex items-center gap-2 px-1 text-sm font-bold text-[#10b981] tracking-wider">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-[#10b981]"></span>
|
||||
<span className="text-xs font-bold text-gray-400">LIVE</span>
|
||||
</div>
|
||||
|
||||
{/* Theme Toggle */}
|
||||
<button className="flex h-9 w-9 items-center justify-center rounded-xl border border-[#132338] bg-[#0a1826] text-gray-400 hover:text-white transition">
|
||||
<Sun className="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
{/* Notifications */}
|
||||
<div className="relative flex h-9 w-9 items-center justify-center rounded-xl border border-[#132338] bg-[#0a1826] cursor-pointer hover:bg-[#14253d] transition">
|
||||
<Bell className="h-4 w-4 text-gray-400" />
|
||||
<span className="absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-[#ef4444] text-[9px] font-bold text-white">
|
||||
8
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Profile Avatar */}
|
||||
<div className="flex h-9 w-9 items-center justify-center rounded-full bg-[#1b3454] text-xs font-bold text-white cursor-pointer hover:opacity-90 transition">
|
||||
DH
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
18
components/dashboard/progressBarRow.tsx
Normal file
18
components/dashboard/progressBarRow.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
import { ProgressBarProps } from "@/constants/types";
|
||||
export function ProgressBarRow({ label, value, maxValue }: ProgressBarProps) {
|
||||
const percentage = (value / maxValue) * 100;
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between py-1.5 text-sm">
|
||||
<span className="text-[#899db7] w-32 truncate">{label}</span>
|
||||
<div className="flex-1 mx-4 bg-[#122238] h-2.5 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="bg-[#17cbb5] h-full rounded-full transition-all duration-500"
|
||||
style={{ width: `${percentage}%` }}
|
||||
/>
|
||||
</div>
|
||||
<span className="text-white font-bold w-6 text-right">{value}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,42 +1,44 @@
|
||||
import { SIDEBAR_ITEMS } from "@/constants/constant";
|
||||
import SidebarItem from "./sideBarItem";
|
||||
import {
|
||||
|
||||
ShieldCheck,
|
||||
|
||||
ShieldCheck,
|
||||
Activity,
|
||||
ChevronDown,
|
||||
ChevronsLeft,
|
||||
|
||||
|
||||
} from "lucide-react";
|
||||
|
||||
export default function Sidebar() {
|
||||
return (
|
||||
<aside className="w-80 bg-[#071321] text-white h-screen overflow-y-auto">
|
||||
<div className="flex items-center gap-2.5 px-4 pt-4 pb-3">
|
||||
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-[#3de0c4] font-bold text-[#05111d] text-lg">
|
||||
<aside className=" bg-[#071321] text-white h-screen overflow-y-auto">
|
||||
<div className="flex items-center gap-2 px-2 pt-2 pb-3">
|
||||
<div className="flex h-9 w-9 items-center justify-center rounded-lg
|
||||
bg-[#3de0c4] font-bold text-[#05111d] text-sm">
|
||||
K
|
||||
</div>
|
||||
<span className="text-xl font-bold tracking-tight text-white">
|
||||
<span className="text-sm font-bold tracking-tight text-white">
|
||||
KA<span className="text-[#3de0c4]">FM</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="mx-3 my-2 flex rounded-xl bg-[#091624] p-1 border border-[#142538]">
|
||||
<button className="flex flex-1 items-center justify-center gap-1.5 rounded-lg bg-[#3de0c4] py-1.5 text-xs text-black font-semibold shadow-sm">
|
||||
<div className="mx-4 my-2 flex rounded-xl
|
||||
bg-[#091624] p-2 border border-[#142538]">
|
||||
<button className="flex flex-1
|
||||
items-center justify-center gap-1 rounded-lg bg-[#3de0c4] py-1.5 text-xs
|
||||
text-black font-bold shadow-sm">
|
||||
<Activity size={14} />
|
||||
Operations
|
||||
</button>
|
||||
<button className="flex flex-1 items-center justify-center gap-1.5 rounded-lg py-1.5 text-xs text-slate-400 font-medium hover:text-white transition-colors">
|
||||
<button className="flex flex-1 items-center justify-center gap-1
|
||||
rounded-lg py-1 text-xs text-slate-400 font-medium hover:text-white transition-colors">
|
||||
<ShieldCheck size={14} />
|
||||
Admin
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="px-4 pt-2 pb-1 text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
<p className="px-4 pt-2 pb-1 text-xs font-semibold uppercase
|
||||
tracking-wider text-slate-500">
|
||||
Tenant runtime
|
||||
</p>
|
||||
<div className="py-4">
|
||||
<div className="py-3">
|
||||
{SIDEBAR_ITEMS.map((item) => (
|
||||
<SidebarItem
|
||||
key={item.title}
|
||||
|
||||
24
components/dashboard/statCard.tsx
Normal file
24
components/dashboard/statCard.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { StatCardProps } from "@/constants/types";
|
||||
import { colorMap } from "@/constants/constant";
|
||||
|
||||
|
||||
|
||||
export default function StatCard({ title, value, subtitle, progress, color }: StatCardProps) {
|
||||
return (
|
||||
<div className="rounded-xl border border-[#14253d] bg-[#0c1a2c] p-4 flex flex-col justify-between ">
|
||||
<div>
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-gray-400">{title}</span>
|
||||
<div className="text-4xl font-bold text-white mt-1">{value}</div>
|
||||
</div>
|
||||
<div >
|
||||
<span className="text-xs text-gray-400">{subtitle}</span>
|
||||
<div className="w-full bg-[#162a45] h-1.5 rounded-full mt-2 overflow-hidden">
|
||||
<div
|
||||
className={`h-1.5 rounded-full ${colorMap[color]} transition-all duration-500`}
|
||||
style={{ width: `${progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
21
components/dashboard/statusProgressRow.tsx
Normal file
21
components/dashboard/statusProgressRow.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
import { StatusProgressProps } from "@/constants/types";
|
||||
|
||||
export function StatusProgressRow({ label, value, total, barColor = "bg-[#17cbb5]" }: StatusProgressProps) {
|
||||
const percentage = (value / total) * 100;
|
||||
|
||||
return (
|
||||
<div className="space-y-2 py-1.5">
|
||||
<div className="flex justify-between text-xs font-semibold">
|
||||
<span className="text-white">{label}</span>
|
||||
<span className="text-[#5b7391]">{value}/{total}</span>
|
||||
</div>
|
||||
<div className="bg-[#122238] h-3 rounded-full overflow-hidden">
|
||||
<div
|
||||
className={`${barColor} h-full rounded-full transition-all duration-500`}
|
||||
style={{ width: `${percentage}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -31,12 +31,9 @@ import {
|
||||
BarChart3,
|
||||
Sun,
|
||||
Shield,
|
||||
|
||||
|
||||
Settings,
|
||||
Wallet,
|
||||
Radar,
|
||||
|
||||
Cog,
|
||||
} from "lucide-react";
|
||||
|
||||
@@ -128,4 +125,32 @@ export const SIDEBAR_ITEMS = [
|
||||
{ title: "User Location", href: "/configure/user-location", icon: MapPin },
|
||||
{ title: "Settings", href: "/configure/settings", icon: Sun },],
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export const chartData = [
|
||||
{ month: 'J', height: 'h-24' },
|
||||
{ month: 'F', height: 'h-16' },
|
||||
{ month: 'M', height: 'h-32' },
|
||||
{ month: 'A', height: 'h-20' },
|
||||
{ month: 'M', height: 'h-28' },
|
||||
{ month: 'J', height: 'h-12' },
|
||||
{ month: 'J', height: 'h-32' },
|
||||
{ month: 'A', height: 'h-24' },
|
||||
{ month: 'S', height: 'h-30' },
|
||||
{ month: 'O', height: 'h-20' },
|
||||
{ month: 'N', height: 'h-26' },
|
||||
{ month: 'D', height: 'h-24' },
|
||||
];
|
||||
|
||||
export const activities = [
|
||||
{ time: '09:42', text: '6/1009 assigned to ME Local', boldText: '6/1009' },
|
||||
{ time: '09:18', text: 'Location checklist Block 1/2 completed', boldText: 'Block 1/2' },
|
||||
{ time: '08:55', text: 'Meter MTR-1 reading logged · 58.45 kWh', boldText: 'Meter MTR-1' },
|
||||
{ time: '08:30', text: 'PPM job card printed for APP-1100', boldText: 'APP-1100' },
|
||||
];
|
||||
export const colorMap = {
|
||||
teal: 'bg-teal-400',
|
||||
amber: 'bg-amber-500',
|
||||
rose: 'bg-rose-500',
|
||||
emerald: 'bg-emerald-500',
|
||||
};
|
||||
|
||||
@@ -6,4 +6,39 @@ export type Step = "login" | "verify" | "forgot";
|
||||
onSuccess?: () => void;
|
||||
onForgotPassword?:()=>void;
|
||||
item?: any;
|
||||
}
|
||||
interface Activity {
|
||||
time: string;
|
||||
text: string;
|
||||
boldText: string;
|
||||
}
|
||||
|
||||
export interface ActivityFeedProps {
|
||||
activities: Activity[];
|
||||
}
|
||||
interface ChartItem {
|
||||
month: string;
|
||||
height: string; // Tailwind h-class like 'h-24'
|
||||
}
|
||||
|
||||
export interface BarChartProps {
|
||||
data: ChartItem[];
|
||||
}
|
||||
export interface StatCardProps {
|
||||
title: string;
|
||||
value: number | string;
|
||||
subtitle: string;
|
||||
progress: number;
|
||||
color: 'teal' | 'amber' | 'rose' | 'emerald';
|
||||
}
|
||||
export interface ProgressBarProps {
|
||||
label: string;
|
||||
value: number;
|
||||
maxValue: number;
|
||||
}
|
||||
export interface StatusProgressProps {
|
||||
label: string;
|
||||
value: number;
|
||||
total: number;
|
||||
barColor?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user