2025-06-05 12:27:51 +08:00

170 lines
5.1 KiB
TypeScript

'use client';
import { useState, useEffect, useRef } from 'react';
import { useRouter, usePathname, useSearchParams } from 'next/navigation';
import SiteSelector from '@/components/dashboards/SiteSelector';
import SiteStatus from '@/components/dashboards/SiteStatus';
import KPI_Table from '@/components/dashboards/KPIStatus';
import DashboardLayout from './dashlayout';
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
import dynamic from 'next/dynamic';
const EnergyLineChart = dynamic(() => import('@/components/dashboards/EnergyLineChart'), {
ssr: false,
});
const MonthlyBarChart = dynamic(() => import('@/components/dashboards/MonthlyBarChart'), {
ssr: false,
});
import { SiteName, SiteDetails, mockSiteData } from '@/types/SiteData';
const AdminDashboard = () => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const siteParam = searchParams?.get('site');
const validSiteNames: SiteName[] = ['Site A', 'Site B', 'Site C'];
const [selectedSite, setSelectedSite] = useState<SiteName>(() => {
if (siteParam && validSiteNames.includes(siteParam as SiteName)) {
return siteParam as SiteName;
}
return 'Site A';
});
// Keep siteParam and selectedSite in sync
useEffect(() => {
if (
siteParam &&
validSiteNames.includes(siteParam as SiteName) &&
siteParam !== selectedSite
) {
setSelectedSite(siteParam as SiteName);
}
}, [siteParam, selectedSite]);
// Update query string when site is changed manually
const handleSiteChange = (newSite: SiteName) => {
setSelectedSite(newSite);
const newUrl = `${pathname}?site=${encodeURIComponent(newSite)}`;
router.push(newUrl);
};
const currentSiteDetails: SiteDetails = mockSiteData[selectedSite] || {
location: 'N/A',
inverterProvider: 'N/A',
emergencyContact: 'N/A',
lastSyncTimestamp: 'N/A',
consumptionData: [],
generationData: [],
systemStatus: 'N/A',
temperature: 'N/A',
solarPower: 0,
realTimePower: 0,
installedPower: 0,
};
const handleCSVExport = () => {
alert('Exported raw data to CSV (mock)');
};
const energyChartRef = useRef(null);
const monthlyChartRef = useRef(null);
const handlePDFExport = async () => {
const doc = new jsPDF('p', 'mm', 'a4'); // portrait, millimeters, A4
const chartRefs = [
{ ref: energyChartRef, title: 'Energy Line Chart' },
{ ref: monthlyChartRef, title: 'Monthly Energy Yield' }
];
let yOffset = 10;
for (const chart of chartRefs) {
if (!chart.ref.current) continue;
// Capture chart as image
const canvas = await html2canvas(chart.ref.current, {
scale: 2, // Higher scale for better resolution
});
const imgData = canvas.toDataURL('image/png');
const imgProps = doc.getImageProperties(imgData);
const pdfWidth = doc.internal.pageSize.getWidth() - 20; // 10 margin each side
const imgHeight = (imgProps.height * pdfWidth) / imgProps.width;
// Add title and image
doc.setFontSize(14);
doc.text(chart.title, 10, yOffset);
yOffset += 6; // Space between title and chart
// If content will overflow page, add a new page
if (yOffset + imgHeight > doc.internal.pageSize.getHeight()) {
doc.addPage();
yOffset = 10;
}
doc.addImage(imgData, 'PNG', 10, yOffset, pdfWidth, imgHeight);
yOffset += imgHeight + 10; // Update offset for next chart
}
doc.save('dashboard_charts.pdf');
};
return (
<DashboardLayout>
<div className="px-6 space-y-6">
<h1 className="text-lg font-semibold">Admin Dashboard</h1>
<div className="grid md:grid-cols-2 gap-6">
<div className="space-y-4">
<SiteSelector
selectedSite={selectedSite}
setSelectedSite={handleSiteChange}
/>
<SiteStatus
selectedSite={selectedSite}
location={currentSiteDetails.location}
inverterProvider={currentSiteDetails.inverterProvider}
emergencyContact={currentSiteDetails.emergencyContact}
lastSyncTimestamp={currentSiteDetails.lastSyncTimestamp}
/>
</div>
<div>
<KPI_Table siteData={currentSiteDetails} />
</div>
</div>
<div className="grid md:grid-cols-2 gap-6 lg:flex-col justify-center">
<div ref={energyChartRef} className="pb-5">
<EnergyLineChart
consumptionData={currentSiteDetails.consumptionData}
generationData={currentSiteDetails.generationData}
/>
</div>
<div ref={monthlyChartRef} className="pb-5">
<MonthlyBarChart siteData={currentSiteDetails} />
</div>
</div>
<div className="flex flex-col md:flex-row gap-4 justify-center">
<button onClick={handleCSVExport} className="text-sm lg:text-lg btn-primary">
Export Raw Data to CSV
</button>
<button onClick={handlePDFExport} className="text-sm lg:text-lg btn-primary">
Export Chart Images to PDF
</button>
</div>
</div>
</DashboardLayout>
);
};
export default AdminDashboard;