stylize darkmode

This commit is contained in:
Syasya 2025-08-07 16:46:11 +08:00
parent 4ba953f44c
commit b22ddecdf5
12 changed files with 367 additions and 62 deletions

View File

@ -19,7 +19,7 @@ const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
<div className="main-content">
{/* This is where your page content will be injected */}
<div className="p-6 space-y-4 min-h-screen">
<div className="p-6 space-y-4 min-h-screen dark:bg-rtgray-900">
{children}
</div>
</div>

View File

@ -167,7 +167,7 @@ const AdminDashboard = () => {
return (
<DashboardLayout>
<div className="px-6 space-y-6">
<h1 className="text-lg font-semibold">Admin Dashboard</h1>
<h1 className="text-lg font-semibold dark:text-white">Admin Dashboard</h1>
<div className="grid md:grid-cols-2 gap-6">
<div className="space-y-4">

View File

@ -14,6 +14,10 @@ import {
endOfYear,
} from 'date-fns';
import { fetchPowerTimeseries, fetchForecast } from '@/app/utils/api';
import { color } from 'html2canvas/dist/types/css/types/color';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import './datepicker-dark.css'; // custom dark mode styles
ChartJS.register(zoomPlugin);
@ -81,6 +85,22 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
const [selectedDate, setSelectedDate] = useState(new Date());
const [forecast, setForecast] = useState<TimeSeriesEntry[]>([]);
function useIsDarkMode() {
const [isDark, setIsDark] = useState(() =>
typeof document !== 'undefined'
? document.body.classList.contains('dark')
: false
);
useEffect(() => {
const check = () => setIsDark(document.body.classList.contains('dark'));
const observer = new MutationObserver(check);
observer.observe(document.body, { attributes: true, attributeFilter: ['class'] });
return () => observer.disconnect();
}, []);
return isDark;
}
useEffect(() => {
const now = new Date();
@ -200,6 +220,11 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
const maxValue = allValues.length > 0 ? Math.max(...allValues) : 0;
const yAxisSuggestedMax = maxValue * 1.15;
const isDark = useIsDarkMode();
const axisColor = isDark ? '#fff' : '#222';
const data = {
labels: filteredLabels.map(formatLabel),
datasets: [
@ -235,7 +260,12 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'top' as const },
legend: {
position: 'top',
labels: {
color: axisColor, // legend text color
},
},
zoom: {
zoom: {
wheel: { enabled: true },
@ -244,12 +274,22 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
},
pan: { enabled: true, mode: 'x' as const },
},
tooltip: { enabled: true, mode: 'index' as const, intersect: false },
tooltip: {
enabled: true,
mode: 'index',
intersect: false,
backgroundColor: isDark ? '#232b3e' : '#fff',
titleColor: axisColor,
bodyColor: axisColor,
borderColor: isDark ? '#444' : '#ccc',
borderWidth: 1,
},
},
scales: {
x: {
title: {
display: true,
color: axisColor,
text:
viewMode === 'day'
? 'Time (HH:MM)'
@ -260,7 +300,10 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
: viewMode === 'monthly'
? 'Month'
: 'Year',
font: { weight: 'bold' as const },
font: { weight: 'normal' as const },
},
ticks: {
color: axisColor,
},
},
y: {
@ -269,9 +312,14 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
title: {
display: true,
text: 'Power (kW)',
font: { weight: 'bold' as const },
color: axisColor,
font: { weight: 'normal' as const },
},
ticks: {
color: axisColor,
},
},
},
} as const;
@ -280,7 +328,7 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
};
return (
<div className="bg-white p-4 rounded-lg shadow-md dark:bg-gray-800 dark:text-white-light">
<div className="bg-white p-4 rounded-lg shadow-md dark:bg-rtgray-800 dark:text-white-light">
<div className="h-98 w-full">
<div className="flex justify-between items-center mb-2">
<h2 className="text-lg font-bold dark:text-white-light">Energy Consumption & Generation</h2>
@ -289,15 +337,15 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
</button>
</div>
<div className="mb-4 flex gap-4 items-center">
<div className="mb-4 flex gap-4 items-center dark:text-white">
{viewMode === 'day' && (
<label className="font-medium">
Date:{' '}
<input
type="date"
value={selectedDate.toISOString().split('T')[0]}
onChange={(e) => setSelectedDate(new Date(e.target.value))}
className="border rounded p-1"
<DatePicker
selected={selectedDate}
onChange={(date) => setSelectedDate(date!)}
dateFormat="dd/MM/yyyy" // ✅ sets correct format
className="dark:bg-rtgray-700 dark:text-white bg-white border border-rounded text-black p-1 rounded"
/>
</label>
)}
@ -310,7 +358,7 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
const val = Number(e.target.value);
setStartIndex(val <= endIndex ? val : endIndex);
}}
className="border rounded p-1"
className="dark:bg-rtgray-700 border dark:border-rtgray-700 rounded p-1"
>
{allTimes.map((label, idx) => (
<option key={idx} value={idx}>{formatLabel(label)}</option>
@ -325,7 +373,7 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
const val = Number(e.target.value);
setEndIndex(val >= startIndex ? val : startIndex);
}}
className="border rounded p-1"
className="dark:bg-rtgray-700 border dark:border-rtgray-700 rounded p-1"
>
{allTimes.map((label, idx) => (
<option key={idx} value={idx}>{formatLabel(label)}</option>
@ -337,7 +385,7 @@ const EnergyLineChart = ({ siteId }: EnergyLineChartProps) => {
<select
value={viewMode}
onChange={(e) => setViewMode(e.target.value as typeof viewMode)}
className="border rounded p-1"
className="dark:bg-rtgray-700 border dark:border-rtgray-700 rounded p-1"
>
<option value="day">Day</option>
<option value="daily">Daily</option>

View File

@ -17,7 +17,6 @@ interface MonthlyKPI {
load_factor: number | null;
}
const KPI_Table: React.FC<KPI_TableProps> = ({ siteId, month }) => {
const [kpiData, setKpiData] = useState<MonthlyKPI | null>(null);
const [loading, setLoading] = useState(false);
@ -81,22 +80,21 @@ const data = [
{ kpi: 'Load Factor', value: `${load_factor.toFixed(2)} kW` }, // ✅ added
];
return (
<div>
<h2 className="text-lg font-bold mb-2">Monthly KPI</h2>
<table className="min-h-[275px] w-full border-collapse border border-gray-700 text-black bg-white">
<h2 className="text-lg font-bold mb-2 dark:text-white">Monthly KPI</h2>
<table className="min-h-[275px] w-full border-collapse border border-gray-300 dark:border-rtgray-700 text-black dark:text-white bg-white dark:bg-rtgray-700">
<thead>
<tr className="bg-gray-800 text-black">
<th className="border border-gray-700 p-3 text-left">KPI</th>
<th className="border border-gray-700 p-3 text-left">Value</th>
<tr className="bg-rtgray-100 dark:bg-rtgray-800 text-black dark:text-white">
<th className="border border-rtgray-300 dark:border-rtgray-700 p-3 text-left dark:bg-rtgray-900">KPI</th>
<th className="border border-rtgray-300 dark:border-rtgray-700 p-3 text-left dark:bg-rtgray-900">Value</th>
</tr>
</thead>
<tbody>
{data.map((row) => (
<tr key={row.kpi}>
<td className="border border-gray-700 p-2.5">{row.kpi}</td>
<td className="border border-gray-700 p-2.5">{row.value}</td>
<tr key={row.kpi} className="even:bg-rtgray-50 dark:even:bg-rtgray-800">
<td className="border border-rtgray-300 dark:border-rtgray-700 p-2.5">{row.kpi}</td>
<td className="border border-rtgray-300 dark:border-rtgray-700 p-2.5">{row.value}</td>
</tr>
))}
</tbody>

View File

@ -11,6 +11,7 @@ import {
import { format } from 'date-fns';
import { fetchPowerTimeseries } from '@/app/utils/api';
interface MonthlyBarChartProps {
siteId: string;
}
@ -39,8 +40,7 @@ const groupTimeSeries = (
}));
};
const consumptionColor = '#003049';
const generationColor = '#669bbc';
const MonthlyBarChart: React.FC<MonthlyBarChartProps> = ({ siteId }) => {
const [chartData, setChartData] = useState<
@ -48,6 +48,32 @@ const MonthlyBarChart: React.FC<MonthlyBarChartProps> = ({ siteId }) => {
>([]);
const [loading, setLoading] = useState(true);
function useIsDarkMode() {
const [isDark, setIsDark] = useState(() =>
typeof document !== 'undefined'
? document.body.classList.contains('dark')
: false
);
useEffect(() => {
const check = () => setIsDark(document.body.classList.contains('dark'));
check();
// Listen for class changes on <body>
const observer = new MutationObserver(check);
observer.observe(document.body, { attributes: true, attributeFilter: ['class'] });
return () => observer.disconnect();
}, []);
return isDark;
}
const isDark = useIsDarkMode();
const consumptionColor = isDark ? '#ba8e23' : '#003049';
const generationColor = isDark ? '#fcd913' : '#669bbc';
useEffect(() => {
if (!siteId) return;
@ -100,7 +126,7 @@ const MonthlyBarChart: React.FC<MonthlyBarChartProps> = ({ siteId }) => {
if (loading || !siteId || chartData.length === 0) {
return (
<div className="bg-white p-4 rounded-lg shadow-md dark:bg-gray-800 dark:text-white-light">
<div className="bg-white p-4 rounded-lg shadow-md dark:bg-rtgray-800 dark:text-white-light">
<div className="flex justify-between items-center mb-2">
<h2 className="text-lg font-bold pb-3">Monthly Energy Yield</h2>
</div>
@ -114,7 +140,7 @@ const MonthlyBarChart: React.FC<MonthlyBarChartProps> = ({ siteId }) => {
}
return (
<div className="bg-white p-4 rounded-lg shadow-md dark:bg-gray-800 dark:text-white-light">
<div className="bg-white p-4 rounded-lg shadow-md dark:bg-rtgray-800 dark:text-white-light">
<div className="flex justify-between items-center mb-2">
<h2 className="text-lg font-bold pb-3">Monthly Energy Yield</h2>
</div>
@ -122,13 +148,38 @@ const MonthlyBarChart: React.FC<MonthlyBarChartProps> = ({ siteId }) => {
<div className="lg:h-[22.6vw] h-[290px] w-full pt-10">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={chartData}>
<XAxis dataKey="month" tick={{ fontSize: 10 }} />
<YAxis tick={{ fontSize: 10 }} />
<XAxis
dataKey="month"
tick={{ fontSize: 10, fill: isDark ? '#fff' : '#222' }}
axisLine={{ stroke: isDark ? '#fff' : '#222' }}
tickLine={{ stroke: isDark ? '#fff' : '#222' }}
/>
<YAxis
tick={{ fontSize: 10, fill: isDark ? '#fff' : '#222' }}
axisLine={{ stroke: isDark ? '#fff' : '#222' }}
tickLine={{ stroke: isDark ? '#fff' : '#222' }}
/>
<Tooltip
formatter={(value: number) => [`${value.toFixed(2)} kWh`]}
labelFormatter={(label) => `${label}`}
contentStyle={{
background: isDark ? '#232b3e' : '#fff',
color: isDark ? '#fff' : '#222',
border: isDark ? '1px solid #444' : '1px solid #ccc',
}}
labelStyle={{
color: isDark ? '#fff' : '#222',
}}
cursor={{
fill: isDark ? '#808080' : '#e0e7ef', // dark mode bg, light mode bg
fillOpacity: isDark ? 0.6 : 0.3, // adjust opacity as you like
}}
/>
<Legend
wrapperStyle={{
color: isDark ? '#fff' : '#222',
}}
/>
<Legend />
<Bar dataKey="consumption" fill={consumptionColor} name="Consumption (kWh)" />
<Bar dataKey="generation" fill={generationColor} name="Generation (kWh)" />
</BarChart>

View File

@ -8,10 +8,10 @@ type SiteSelectorProps = {
const SiteSelector = ({ selectedSite, setSelectedSite }: SiteSelectorProps) => {
return (
<div className="flex flex-col ">
<label htmlFor="site" className="font-semibold text-lg">Select Site:</label>
<label htmlFor="site" className="font-semibold text-lg dark:text-white">Select Site:</label>
<select
id="site"
className="border p-2 rounded"
className="border p-2 rounded dark:text-white dark:bg-rtgray-800 dark:border-rtgray-700"
value={selectedSite}
onChange={(e) => setSelectedSite(e.target.value as SiteName)}
>

View File

@ -105,12 +105,12 @@ const SiteStatus = ({
};
return (
<div className="bg-white p-4 rounded-lg shadow-md space-y-2 dark:bg-gray-800 dark:text-white-light">
<div className="bg-white p-4 rounded-lg shadow-md space-y-2 dark:bg-rtgray-800 dark:text-white-light">
<h2 className="text-xl font-semibold mb-3">Site Details</h2>
{/* Status */}
<div className="flex justify-between items-center text-base">
<p className="text-gray-600 dark:text-gray-400 font-medium">Status:</p>
<p className="text-gray-600 dark:text-white/85 font-medium">Status:</p>
<p className={`font-semibold ${
statusMap[selectedSite] === 'Active' ? 'text-green-500' :
statusMap[selectedSite] === 'Inactive' ? 'text-orange-500' :
@ -122,31 +122,31 @@ const SiteStatus = ({
{/* Site ID */}
<div className="flex justify-between items-center text-base">
<p className="text-gray-600 dark:text-gray-400 font-medium">Site ID:</p>
<p className="text-gray-600 dark:text-white/85 font-medium">Site ID:</p>
<p className="font-medium">{siteId}</p>
</div>
{/* Location */}
<div className="flex justify-between items-center text-base">
<p className="text-gray-600 dark:text-gray-400 font-medium">Location:</p>
<p className="text-gray-600 dark:text-white/85 font-medium">Location:</p>
<p className="font-medium">{location}</p>
</div>
{/* Inverter Provider */}
<div className="flex justify-between items-center text-base">
<p className="text-gray-600 dark:text-gray-400 font-medium">Inverter Provider:</p>
<p className="text-gray-600 dark:text-white/85 font-medium">Inverter Provider:</p>
<p className="font-medium">{inverterProvider}</p>
</div>
{/* Emergency Contact */}
<div className="flex justify-between items-center text-base">
<p className="text-gray-600 dark:text-gray-400 font-medium">Emergency Contact:</p>
<p className="text-gray-600 dark:text-white/85 font-medium">Emergency Contact:</p>
<p className="font-medium">{emergencyContact}</p>
</div>
{/* Last Sync */}
<div className="flex justify-between items-center text-base">
<p className="text-gray-600 dark:text-gray-400 font-medium">Last Sync:</p>
<p className="text-gray-600 dark:text-white/85 font-medium">Last Sync:</p>
<p className="font-medium">{lastSyncTimestamp}</p>
</div>

View File

@ -0,0 +1,77 @@
/* ========== LIGHT MODE (Default) ========== */
.react-datepicker {
background-color: #ffffff; /* white bg */
color: #111827; /* dark gray text */
border: 1px solid #d1d5db; /* light gray border */
}
.react-datepicker__header {
background-color: #f3f4f6;
border-bottom: 1px solid #e5e7eb;
color: #111827;
}
.react-datepicker__day,
.react-datepicker__day-name,
.react-datepicker__current-month {
color: #111827;
}
.react-datepicker__navigation-icon::before {
border-color: #111827;
}
.react-datepicker__day--selected,
.react-datepicker__day--keyboard-selected {
background-color: #3b82f6; /* blue highlight */
color: #ffffff;
}
.react-datepicker__day:hover {
background-color: #e5e7eb;
color: #111827;
}
.react-datepicker__day--disabled {
color: #9ca3af;
}
/* ========== DARK MODE (Wrap in `.dark`) ========== */
.dark .react-datepicker {
background-color: #141624;
color: #ffffff;
border: 1px solid #374151;
}
.dark .react-datepicker__header {
background-color: #080912;
border-bottom: 1px solid #4b5563;
color: #ffffff;
}
.dark .react-datepicker__day,
.dark .react-datepicker__day-name,
.dark .react-datepicker__current-month {
color: #ffffff;
}
.dark .react-datepicker__navigation-icon::before {
border-color: #ffffff;
}
.dark .react-datepicker__day--selected,
.dark .react-datepicker__day--keyboard-selected {
background-color: #fcd913;
color: #000000;
}
.dark .react-datepicker__day:hover {
background-color: #374151;
color: #ffffff;
}
.dark .react-datepicker__day--disabled {
color: #555;
}

View File

@ -84,7 +84,7 @@ const Sidebar = () => {
</div>
<PerfectScrollbar className="relative h-[calc(100vh-80px)] ">
<ul className="relative space-y-0.5 p-4 py-0 font-md">
<h2 className="-mx-4 mb-1 flex items-center bg-white-light/30 px-7 py-3 font-extrabold uppercase dark:bg-dark dark:bg-opacity-[0.08]">
<h2 className="-mx-4 mb-1 flex items-center bg-white-light/30 px-7 py-3 font-extrabold uppercase dark:bg-dark dark:bg-opacity-[0.08] dark:text-white dark:active:text-white">
<IconMinus className="hidden h-5 w-4 flex-none" />
<span>Customer</span>
</h2>
@ -92,7 +92,7 @@ const Sidebar = () => {
<Link href="#" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Dashboard</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white dark:active:text-white">Dashboard</span>
</div>
</Link>
</li>
@ -100,7 +100,7 @@ const Sidebar = () => {
<Link href="#" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Sites</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white dark:active:text-white">Sites</span>
</div>
</Link>
</li>
@ -108,7 +108,7 @@ const Sidebar = () => {
<button type="button" className={`nav-link group w-full`} onClick={() => toggleMenu('setting')}>
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Setting</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white dark:active:text-white">Setting</span>
</div>
<div className={currentMenu !== 'setting' ? '-rotate-90 rtl:rotate-90' : ''}>
@ -128,7 +128,7 @@ const Sidebar = () => {
<h2 className="-mx-4 mb-1 flex items-center bg-white-light/30 px-7 py-3 font-extrabold uppercase dark:bg-dark dark:bg-opacity-[0.08]">
<h2 className="-mx-4 mb-1 flex items-center bg-white-light/30 px-7 py-3 font-extrabold uppercase dark:bg-dark dark:text-white dark:bg-opacity-[0.08] dark:active:text-white">
<IconMinus className="hidden h-5 w-4 flex-none" />
<span>Admin</span>
</h2>
@ -136,7 +136,7 @@ const Sidebar = () => {
<Link href="/adminDashboard" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Dashboard</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white dark:active:text-white">Dashboard</span>
</div>
</Link>
</li>
@ -144,7 +144,7 @@ const Sidebar = () => {
<Link href="/sites" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Sites</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white">Sites</span>
</div>
</Link>
</li>
@ -152,11 +152,11 @@ const Sidebar = () => {
<Link href="#" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Devices</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white">Devices</span>
</div>
</Link>
</li>
<h2 className="-mx-4 mb-1 flex items-center px-7 py-3 font-extrabold uppercase dark:bg-opacity-[0.08]">
<h2 className="-mx-4 mb-1 flex items-center px-7 py-3 font-extrabold uppercase dark:bg-opacity-[0.08] dark:group-hover:text-white dark:text-white">
<IconMinus className="hidden h-5 w-4 flex-none" />
<span>Providers</span>
</h2>
@ -164,7 +164,7 @@ const Sidebar = () => {
<Link href="#" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Solis</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white">Solis</span>
</div>
</Link>
</li>
@ -172,7 +172,7 @@ const Sidebar = () => {
<Link href="#" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Huawei</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white">Huawei</span>
</div>
</Link>
</li>
@ -181,7 +181,7 @@ const Sidebar = () => {
<button type="button" className={`${currentMenu === 'sungrow' ? 'active' : ''} nav-link group w-full`} onClick={() => toggleMenu('sungrow')}>
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Sungrow</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white">Sungrow</span>
</div>
<div className={currentMenu !== 'component' ? '-rotate-90 rtl:rotate-90' : ''}>
@ -190,7 +190,7 @@ const Sidebar = () => {
</button>
<AnimateHeight duration={300} height={currentMenu === 'sungrow' ? 'auto' : 0}>
<ul className="sub-menu text-gray-500">
<ul className="sub-menu text-gray-500 dark:text-white/90">
<li>
<Link href="/sungrow/plant">Plant</Link>
</li>
@ -208,7 +208,7 @@ const Sidebar = () => {
<Link href="#" className="nav-link group">
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">CSI</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white">CSI</span>
</div>
</Link>
</li>
@ -217,7 +217,7 @@ const Sidebar = () => {
<button type="button" className={`${currentMenu === 'chint' ? 'active' : ''} nav-link group w-full`} onClick={() => toggleMenu('chint')}>
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">Chint</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-white dark:group-hover:text-white">Chint</span>
</div>
<div className={currentMenu !== 'component' ? '-rotate-90 rtl:rotate-90' : ''}>
@ -226,7 +226,7 @@ const Sidebar = () => {
</button>
<AnimateHeight duration={300} height={currentMenu === 'chint' ? 'auto' : 0}>
<ul className="sub-menu text-gray-500">
<ul className="sub-menu text-gray-500 dark:text-white/90">
<li>
<Link href="/chint/sites">Sites</Link>
</li>

130
package-lock.json generated
View File

@ -36,6 +36,7 @@
"react-animate-height": "^3.1.0",
"react-apexcharts": "^1.7.0",
"react-chartjs-2": "^5.3.0",
"react-datepicker": "^8.4.0",
"react-dom": "18.2.0",
"react-hot-toast": "^2.5.2",
"react-i18next": "^12.1.5",
@ -334,6 +335,59 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@floating-ui/core": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz",
"integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==",
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.7.3",
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/react": {
"version": "0.27.15",
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.15.tgz",
"integrity": "sha512-0LGxhBi3BB1DwuSNQAmuaSuertFzNAerlMdPbotjTVnvPtdOs7CkrHLaev5NIXemhzDXNC0tFzuseut7cWA5mw==",
"license": "MIT",
"dependencies": {
"@floating-ui/react-dom": "^2.1.5",
"@floating-ui/utils": "^0.2.10",
"tabbable": "^6.0.0"
},
"peerDependencies": {
"react": ">=17.0.0",
"react-dom": ">=17.0.0"
}
},
"node_modules/@floating-ui/react-dom": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.5.tgz",
"integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.7.3"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
"license": "MIT"
},
"node_modules/@headlessui/react": {
"version": "1.7.8",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.8.tgz",
@ -5005,6 +5059,21 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-datepicker": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-8.4.0.tgz",
"integrity": "sha512-6nPDnj8vektWCIOy9ArS3avus9Ndsyz5XgFCJ7nBxXASSpBdSL6lG9jzNNmViPOAOPh6T5oJyGaXuMirBLECag==",
"license": "MIT",
"dependencies": {
"@floating-ui/react": "^0.27.3",
"clsx": "^2.1.1",
"date-fns": "^4.1.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc",
"react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc"
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@ -5750,6 +5819,12 @@
"url": "https://opencollective.com/unts"
}
},
"node_modules/tabbable": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
"license": "MIT"
},
"node_modules/tailwindcss": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",
@ -6535,6 +6610,46 @@
"strip-json-comments": "^3.1.1"
}
},
"@floating-ui/core": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
"requires": {
"@floating-ui/utils": "^0.2.10"
}
},
"@floating-ui/dom": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz",
"integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==",
"requires": {
"@floating-ui/core": "^1.7.3",
"@floating-ui/utils": "^0.2.10"
}
},
"@floating-ui/react": {
"version": "0.27.15",
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.15.tgz",
"integrity": "sha512-0LGxhBi3BB1DwuSNQAmuaSuertFzNAerlMdPbotjTVnvPtdOs7CkrHLaev5NIXemhzDXNC0tFzuseut7cWA5mw==",
"requires": {
"@floating-ui/react-dom": "^2.1.5",
"@floating-ui/utils": "^0.2.10",
"tabbable": "^6.0.0"
}
},
"@floating-ui/react-dom": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.5.tgz",
"integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==",
"requires": {
"@floating-ui/dom": "^1.7.3"
}
},
"@floating-ui/utils": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
},
"@headlessui/react": {
"version": "1.7.8",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.8.tgz",
@ -9765,6 +9880,16 @@
"integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==",
"requires": {}
},
"react-datepicker": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-8.4.0.tgz",
"integrity": "sha512-6nPDnj8vektWCIOy9ArS3avus9Ndsyz5XgFCJ7nBxXASSpBdSL6lG9jzNNmViPOAOPh6T5oJyGaXuMirBLECag==",
"requires": {
"@floating-ui/react": "^0.27.3",
"clsx": "^2.1.1",
"date-fns": "^4.1.0"
}
},
"react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@ -10260,6 +10385,11 @@
"tslib": "^2.4.0"
}
},
"tabbable": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
},
"tailwindcss": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",

View File

@ -37,6 +37,7 @@
"react-animate-height": "^3.1.0",
"react-apexcharts": "^1.7.0",
"react-chartjs-2": "^5.3.0",
"react-datepicker": "^8.4.0",
"react-dom": "18.2.0",
"react-hot-toast": "^2.5.2",
"react-i18next": "^12.1.5",

View File

@ -51,12 +51,12 @@
}
.sidebar .nav-item > button.active,
.sidebar .nav-item > a.active {
@apply bg-[#000]/[0.08] text-black dark:bg-[#181f32] dark:text-white-dark;
@apply bg-[#000]/[0.08] text-black dark:bg-[#181f32] dark:text-white;
}
.sidebar .nav-item > button.active > div > span,
.sidebar .nav-item > a.active > div > span {
@apply dark:!text-white-dark;
@apply dark:!text-white;
}
.sidebar ul.sub-menu li button,