Make KPI summary cards clickable - navigate to relevant sheets
Some checks are pending
CI / Engine — lint / typecheck / test (push) Waiting to run
CI / API — lint / typecheck / test (push) Waiting to run
CI / Web — typecheck / lint / build (push) Waiting to run

- Added onClick prop to KpiCard component
- SummarySheet now accepts onNavigate callback
- KPI cards now link to appropriate sheets:
  - Solved Tariff, Solar Y1 CUF, Wind Y1 PLF -> Generation
  - Equity IRR, Project IRR, LCOE, Payback -> IRR / Returns
  - Min DSCR, Avg DSCR, Total Capex, Debt -> Debt
  - IDC -> IDC / Phasing
- WorkbookView accepts optional onNavigate prop
- Scenario page passes onNavigate to switch active sheet
This commit is contained in:
Manohar Gupta 2026-05-22 17:57:32 +05:30
parent 5098bf86f4
commit 680df1a597
3 changed files with 92 additions and 41 deletions

View file

@ -249,6 +249,7 @@ export default function ScenarioPage() {
return inputs?.wind?.capacity_mw || inputs?.project?.capacity_wind_mw || 0;
} catch { return 0; }
})()}
onNavigate={(sheet) => setActiveSheet(sheet as ActiveSheet)}
/>
) : scenario?.status === "failed" ? (
<div className="border border-red-200 rounded-lg p-6 text-sm max-w-lg">

View file

@ -3,12 +3,14 @@ interface KpiCardProps {
value: string | null;
unit?: string;
highlight?: boolean;
onClick?: () => void;
}
export function KpiCard({ label, value, unit, highlight }: KpiCardProps) {
export function KpiCard({ label, value, unit, highlight, onClick }: KpiCardProps) {
return (
<div
className={`border rounded-lg p-4 flex flex-col gap-1 ${highlight ? "border-primary/40 bg-primary/5" : ""}`}
onClick={onClick}
className={`border rounded-lg p-4 flex flex-col gap-1 transition-all cursor-pointer hover:border-primary/50 hover:bg-primary/5 ${highlight ? "border-primary/40 bg-primary/5" : ""} ${onClick ? "cursor-pointer" : ""}`}
>
<span className="text-xs text-muted-foreground font-medium uppercase tracking-wide">
{label}

View file

@ -298,7 +298,7 @@ function buildDebtRows(debt: DebtYearRow[]): TableRow[] {
// Sheet views
// ---------------------------------------------------------------------------
function SummarySheet({ kpis, scenarioId }: { kpis: KpiSummary; scenarioId: string }) {
function SummarySheet({ kpis, scenarioId, onNavigate }: { kpis: KpiSummary; scenarioId: string; onNavigate?: (sheet: string) => void }) {
const { data: stmts } = useQuery({
queryKey: ["statements", scenarioId],
queryFn: () => getStatements(scenarioId),
@ -364,25 +364,72 @@ function SummarySheet({ kpis, scenarioId }: { kpis: KpiSummary; scenarioId: stri
value={kpis.solved_tariff_inr_per_kwh != null ? kpis.solved_tariff_inr_per_kwh.toFixed(2) : null}
unit="₹/kWh"
highlight
onClick={() => onNavigate?.("generation")}
/>
<KpiCard
label="Equity IRR"
value={kpis.equity_irr != null ? `${(kpis.equity_irr * 100).toFixed(1)}%` : null}
highlight
onClick={() => onNavigate?.("irr")}
/>
<KpiCard
label="Project IRR"
value={kpis.project_irr != null ? `${(kpis.project_irr * 100).toFixed(1)}%` : null}
onClick={() => onNavigate?.("irr")}
/>
<KpiCard
label="Min DSCR"
value={kpis.min_dscr?.toFixed(2) ?? null}
onClick={() => onNavigate?.("debt")}
/>
<KpiCard
label="Avg DSCR"
value={kpis.avg_dscr?.toFixed(2) ?? null}
onClick={() => onNavigate?.("debt")}
/>
<KpiCard
label="Total Capex"
value={kpis.total_capex_cr != null ? kpis.total_capex_cr.toFixed(1) : null}
unit="Cr"
onClick={() => onNavigate?.("debt")}
/>
<KpiCard
label="Debt"
value={kpis.debt_cr?.toFixed(1) ?? null}
unit="Cr"
onClick={() => onNavigate?.("debt")}
/>
<KpiCard
label="IDC"
value={kpis.idc_cr?.toFixed(1) ?? null}
unit="Cr"
onClick={() => onNavigate?.("idc")}
/>
<KpiCard
label="LCOE"
value={kpis.lcoe_inr_per_kwh?.toFixed(2) ?? null}
unit="₹/kWh"
onClick={() => onNavigate?.("irr")}
/>
<KpiCard
label="Payback"
value={kpis.payback_years?.toFixed(1) ?? null}
unit="yrs"
onClick={() => onNavigate?.("irr")}
/>
<KpiCard label="Project IRR" value={kpis.project_irr != null ? `${(kpis.project_irr * 100).toFixed(1)}%` : null} />
<KpiCard label="Min DSCR" value={kpis.min_dscr?.toFixed(2) ?? null} />
<KpiCard label="Avg DSCR" value={kpis.avg_dscr?.toFixed(2) ?? null} />
<KpiCard label="Total Capex" value={kpis.total_capex_cr != null ? kpis.total_capex_cr.toFixed(1) : null} unit="Cr" />
<KpiCard label="Debt" value={kpis.debt_cr?.toFixed(1) ?? null} unit="Cr" />
<KpiCard label="IDC" value={kpis.idc_cr?.toFixed(1) ?? null} unit="Cr" />
<KpiCard label="LCOE" value={kpis.lcoe_inr_per_kwh?.toFixed(2) ?? null} unit="₹/kWh" />
<KpiCard label="Payback" value={kpis.payback_years?.toFixed(1) ?? null} unit="yrs" />
{kpis.solar_y1_cuf != null && (
<KpiCard label="Solar Y1 CUF" value={`${(kpis.solar_y1_cuf * 100).toFixed(1)}%`} />
<KpiCard
label="Solar Y1 CUF"
value={`${(kpis.solar_y1_cuf * 100).toFixed(1)}%`}
onClick={() => onNavigate?.("generation")}
/>
)}
{kpis.wind_y1_plf != null && (
<KpiCard label="Wind Y1 PLF" value={`${(kpis.wind_y1_plf * 100).toFixed(1)}%`} />
<KpiCard
label="Wind Y1 PLF"
value={`${(kpis.wind_y1_plf * 100).toFixed(1)}%`}
onClick={() => onNavigate?.("generation")}
/>
)}
{kpis.rtc_cuf_achieved != null && (
<KpiCard label="RTC CUF" value={`${(kpis.rtc_cuf_achieved * 100).toFixed(1)}%`} highlight />
@ -997,9 +1044,10 @@ interface Props {
codYear?: number;
solarDCMW?: number;
windMW?: number;
onNavigate?: (sheet: string) => void;
}
export function WorkbookView({ scenarioId, kpis, debtScheduleJson, activeSheet, codYear, solarDCMW, windMW }: Props) {
export function WorkbookView({ scenarioId, kpis, debtScheduleJson, activeSheet, codYear, solarDCMW, windMW, onNavigate }: Props) {
const { data: stmts } = useQuery({
queryKey: ["statements", scenarioId],
queryFn: () => getStatements(scenarioId),
@ -1032,7 +1080,7 @@ export function WorkbookView({ scenarioId, kpis, debtScheduleJson, activeSheet,
All monetary values in INR Crore unless noted
</p>
{activeSheet === "summary" && <SummarySheet kpis={kpis} scenarioId={scenarioId} />}
{activeSheet === "summary" && <SummarySheet kpis={kpis} scenarioId={scenarioId} onNavigate={onNavigate} />}
{activeSheet === "pnl" && pnl.length > 0 && (
<HorizontalTable years={years} rows={buildPnLRows(pnl)} />
)}