Dashboard Componeets files are added some
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import Sidebar from "@/components/dashboard/sidebar";
|
import Sidebar from "@/components/dashboard/sidebar";
|
||||||
|
|
||||||
|
import OperationsDashboard from "@/components/dashboard/dashboard";
|
||||||
|
|
||||||
export default function DashboardPage() {
|
export default function DashboardPage() {
|
||||||
return (
|
return (
|
||||||
@@ -10,8 +11,8 @@ export default function DashboardPage() {
|
|||||||
<main className="flex bg-[#091522]">
|
<main className="flex bg-[#091522]">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
|
|
||||||
<div className="flex-1 p-10 text-white">
|
<div className="flex-1 p-6 text-white">
|
||||||
Main Content
|
<OperationsDashboard/>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</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 { SIDEBAR_ITEMS } from "@/constants/constant";
|
||||||
import SidebarItem from "./sideBarItem";
|
import SidebarItem from "./sideBarItem";
|
||||||
import {
|
import {
|
||||||
|
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
|
|
||||||
Activity,
|
Activity,
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
ChevronsLeft,
|
ChevronsLeft,
|
||||||
|
|
||||||
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
export default function Sidebar() {
|
export default function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<aside className="w-80 bg-[#071321] text-white h-screen overflow-y-auto">
|
<aside className=" 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 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-lg">
|
<div className="flex h-9 w-9 items-center justify-center rounded-lg
|
||||||
|
bg-[#3de0c4] font-bold text-[#05111d] text-sm">
|
||||||
K
|
K
|
||||||
</div>
|
</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>
|
KA<span className="text-[#3de0c4]">FM</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-3 my-2 flex rounded-xl bg-[#091624] p-1 border border-[#142538]">
|
<div className="mx-4 my-2 flex rounded-xl
|
||||||
<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">
|
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} />
|
<Activity size={14} />
|
||||||
Operations
|
Operations
|
||||||
</button>
|
</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} />
|
<ShieldCheck size={14} />
|
||||||
Admin
|
Admin
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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
|
Tenant runtime
|
||||||
</p>
|
</p>
|
||||||
<div className="py-4">
|
<div className="py-3">
|
||||||
{SIDEBAR_ITEMS.map((item) => (
|
{SIDEBAR_ITEMS.map((item) => (
|
||||||
<SidebarItem
|
<SidebarItem
|
||||||
key={item.title}
|
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,
|
BarChart3,
|
||||||
Sun,
|
Sun,
|
||||||
Shield,
|
Shield,
|
||||||
|
|
||||||
|
|
||||||
Settings,
|
Settings,
|
||||||
Wallet,
|
Wallet,
|
||||||
Radar,
|
Radar,
|
||||||
|
|
||||||
Cog,
|
Cog,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
@@ -129,3 +126,31 @@ export const SIDEBAR_ITEMS = [
|
|||||||
{ title: "Settings", href: "/configure/settings", icon: Sun },],
|
{ 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',
|
||||||
|
};
|
||||||
|
|||||||
@@ -7,3 +7,38 @@ export type Step = "login" | "verify" | "forgot";
|
|||||||
onForgotPassword?:()=>void;
|
onForgotPassword?:()=>void;
|
||||||
item?: any;
|
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