"use client"; import { useState, useCallback } from "react"; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, ReferenceLine, LineChart, Line, CartesianGrid, Legend, } from "recharts"; import { getAvailableProfiles, getProfileStats, getSolarProfile, getWindProfile, profileCsvUrl, type ProfileStats, } from "@/lib/api"; const LOCATIONS = [ { id: "GJ", name: "Gujarat" }, { id: "KA", name: "Karnataka" }, { id: "RJ", name: "Rajasthan" }, ]; const SOLAR_COLOR = "#f97316"; const WIND_COLOR = "#3b82f6"; interface StatsCardProps { label: string; value: string; color?: string; } function StatsCard({ label, value, color }: StatsCardProps) { return (
{label}
{value}
); } function CustomTooltip({ active, payload, label }: { active?: boolean; payload?: { value: number; name: string }[]; label?: string }) { if (!active || !payload?.length) return null; return (

{label}

{payload.map((entry, i) => (
{entry.name}: {(entry.value * 100).toFixed(2)}%
))}
); } export function ProfileViewer() { const [isOpen, setIsOpen] = useState(false); const [activeTab, setActiveTab] = useState<"solar" | "wind" | "compare">("solar"); const [uploadedProfiles, setUploadedProfiles] = useState<{ solar?: number[]; wind?: number[]; filename?: string; }>({}); const [isUploading, setIsUploading] = useState(false); const [uploadError, setUploadError] = useState(null); const [selectedFile, setSelectedFile] = useState<{ name: string; path: string; data: string[][]; } | null>(null); const [isLoadingFile, setIsLoadingFile] = useState(false); const API_BASE = typeof window !== "undefined" ? (typeof window !== "undefined" && (window as { location?: { hostname?: string } }).location?.hostname === "localhost" ? "http://localhost:8000" : (window as { env?: { NEXT_PUBLIC_API_URL?: string } }).env?.NEXT_PUBLIC_API_URL || "/") : "http://localhost:8000"; async function fetchAndDisplayFile(path: string, name: string) { console.log("fetchAndDisplayFile called:", path, name); setIsLoadingFile(true); try { const url = `${API_BASE}${path}?as_csv=true`; console.log("Fetching:", url); const res = await fetch(url); console.log("Response status:", res.status); const text = await res.text(); console.log("Response length:", text.length); const lines = text.trim().split("\n"); console.log("Lines count:", lines.length); const data = lines.slice(1).map((line) => line.split(",")); console.log("Data rows:", data.length); setSelectedFile({ name, path, data }); } catch (err) { console.error("Failed to fetch file:", err); } finally { setIsLoadingFile(false); } } const calculateStats = (data: number[]) => { const sorted = [...data].sort((a, b) => a - b); const sum = data.reduce((a, b) => a + b, 0); return { avg: sum / data.length, max: Math.max(...data), min: Math.min(...data), median: sorted[Math.floor(sorted.length / 2)], }; }; const handleFileUpload = useCallback(async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; setIsUploading(true); setUploadError(null); try { const text = await file.text(); const lines = text.trim().split("\n"); if (lines.length < 2) { throw new Error("File must have at least a header row and one data row"); } const header = lines[0].toLowerCase(); let parsedData: number[] = []; if (header.includes("%_generation")) { const cols = header.split(","); const colIdx = cols.indexOf("%_generation"); if (colIdx === -1) throw new Error("Could not find %_generation column"); parsedData = lines.slice(1).map((line) => { const vals = line.split(","); let val = parseFloat(vals[colIdx]); if (isNaN(val)) return 0; if (val > 1) val = val / 100; return val; }); } else if (header.includes("irradiance") || header.includes("wind_speed") || header.includes("e_grid")) { parsedData = lines.slice(1).map((line) => { const vals = line.split(","); let val = parseFloat(vals[1]); if (isNaN(val)) return 0; if (val > 1) val = val / 1000; if (val > 1) val = val / 100; return val; }); } else { parsedData = lines.slice(1).map((line) => { const vals = line.split(","); let val = parseFloat(vals[0]); if (isNaN(val)) return 0; return val; }); } if (parsedData.length !== 8760) { throw new Error(`Expected 8760 values, got ${parsedData.length}`); } const isSolar = parsedData.reduce((a, b, i) => { const hourOfDay = i % 24; if (hourOfDay >= 6 && hourOfDay <= 18) return a + b; return a; }, 0) / parsedData.reduce((a, b) => a + b, 0) > 0.7; setUploadedProfiles({ solar: isSolar ? parsedData : undefined, wind: !isSolar ? parsedData : undefined, filename: file.name, }); } catch (err) { setUploadError(err instanceof Error ? err.message : "Failed to parse file"); } finally { setIsUploading(false); } }, []); const getMonthlyAverages = (data: number[]) => { const MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; const monthNames = ["Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar"]; const monthPositions = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]; return monthNames.map((name, i) => { const month = monthPositions[i]; const start = MONTH_DAYS.slice(0, month - 1).reduce((a, d) => a + d, 0) * 24; const days = MONTH_DAYS[month - 1]; const monthData = data.slice(start, start + days * 24); const avg = monthData.reduce((a, b) => a + b, 0) / monthData.length; return { name, avg: avg * 100 }; }); }; return ( <> {isOpen && (
setIsOpen(false)} />

File Reference Library

{uploadError && {uploadError}}
{isLoadingFile ? (

Loading file data...

) : selectedFile ? (
{selectedFile.name.includes("Solar") ? "☀️" : "💨"}

{selectedFile.name}

{selectedFile.data.length} rows of data

Download CSV
{selectedFile.data.map((row: string[], i: number) => ( ))}
Hour Date Month Day Hour of Day % Generation
{row[0]} {row[1]} {row[2]} {row[3]} {row[4]} {row[5]}
) : ( <>

📂 Click on any file below to view its contents:

{[ { name: "Solar - Gujarat", path: "/api/profiles/solar/GJ", type: "solar" }, { name: "Solar - Karnataka", path: "/api/profiles/solar/KA", type: "solar" }, { name: "Solar - Rajasthan", path: "/api/profiles/solar/RJ", type: "solar" }, { name: "Wind - Gujarat", path: "/api/profiles/wind/GJ", type: "wind" }, { name: "Wind - Karnataka", path: "/api/profiles/wind/KA", type: "wind" }, { name: "Wind - Rajasthan", path: "/api/profiles/wind/RJ", type: "wind" }, ].map((profile) => ( ))}
{activeTab === "solar" && (

Monthly Average Solar Irradiance

} />
{uploadedProfiles.solar && (

Your Uploaded Solar Profile

{(() => { const stats = calculateStats(uploadedProfiles.solar); return ( <> ); })()}
)}
)} {activeTab === "wind" && (

Monthly Average Wind Speed (m/s)

{uploadedProfiles.wind && (

Your Uploaded Wind Profile

{(() => { const stats = calculateStats(uploadedProfiles.wind); return ( <> ); })()}
)}
)} {activeTab === "compare" && (

Solar vs Wind CUF (Typical Daily Pattern)

`${(v * 100).toFixed(0)}%`} /> } />
)} )}
)} ); }