quantum-hybrid-portfolio / web /src /hooks /useReportGeneration.ts
rocRevyAreGoals15's picture
Initial HF Space deployment
9e89154
Raw
History Blame Contribute Delete
4.89 kB
"use client";
import { useCallback, useMemo, useState } from "react";
import { useLedgerSession } from "@/context/LedgerSessionContext";
import { optimizePortfolio } from "@/lib/api";
import { DEFAULT_TICKERS, DEFAULT_WEIGHT_MAX, DEFAULT_WEIGHT_MIN } from "@/lib/defaultUniverse";
import {
buildReportPayload,
downloadFile,
mergeOptimizeResponse,
reportToCsv,
type ReportProvenance,
type ReportType,
type ReportContext,
} from "@/lib/reportExport";
export type ExportFormat = "json" | "csv";
function buildAndDownload(
selectedType: ReportType,
format: ExportFormat,
data: Record<string, unknown>,
tickers: string[],
reportCtx: ReportContext,
provenance: ReportProvenance,
): Record<string, unknown> {
const report = buildReportPayload(
selectedType,
data,
tickers,
reportCtx,
provenance
);
const ts = new Date().toISOString().replace(/[:.]/g, "-");
if (format === "json") {
downloadFile(
JSON.stringify(report, null, 2),
`quantum_ledger_${selectedType}_${ts}.json`,
"application/json"
);
} else {
downloadFile(
reportToCsv(report as Record<string, unknown>),
`quantum_ledger_${selectedType}_${ts}.csv`,
"text/csv"
);
}
return report;
}
export function useReportGeneration() {
const { session } = useLedgerSession();
const [selectedType, setSelectedType] = useState<ReportType>("full");
const [format, setFormat] = useState<ExportFormat>("json");
const [generating, setGenerating] = useState(false);
const [lastReport, setLastReport] = useState<Record<string, unknown> | null>(
null
);
const [error, setError] = useState<string | null>(null);
const hasSnapshot = session.lastOptimize !== null;
const snapshotAt = session.lastOptimize?.at ?? null;
const reportCtx = useMemo<ReportContext>(
() => ({
objective: session.lastOptimize?.objective ?? session.objective,
weightMin: session.constraints.weightMin,
weightMax: session.constraints.weightMax,
}),
[session.lastOptimize?.objective, session.objective, session.constraints.weightMin, session.constraints.weightMax]
);
const generateReport = useCallback(async () => {
setGenerating(true);
setError(null);
try {
let data: Record<string, unknown>;
let tickers: string[];
let provenance: ReportProvenance;
if (session.lastOptimize) {
data = session.lastOptimize.payload;
tickers = session.lastOptimize.tickers;
provenance = {
source: "snapshot",
snapshot_at: session.lastOptimize.at,
};
} else {
const useTickers =
session.tickers.length > 0 ? session.tickers : [...DEFAULT_TICKERS];
const resp = (await optimizePortfolio({
tickers: useTickers,
objective: session.objective || "hybrid",
weight_min: session.constraints.weightMin ?? DEFAULT_WEIGHT_MIN,
maxWeight: session.constraints.weightMax ?? DEFAULT_WEIGHT_MAX,
})) as Record<string, unknown>;
data = mergeOptimizeResponse(resp);
tickers = useTickers;
provenance = { source: "fresh", snapshot_at: null };
}
const report = buildAndDownload(
selectedType,
format,
data,
tickers,
reportCtx,
provenance
);
setLastReport(report);
} catch (e) {
const msg =
e instanceof Error ? e.message : "Report generation failed";
setError(msg);
} finally {
setGenerating(false);
}
}, [selectedType, format, session, reportCtx]);
const generateReportFresh = useCallback(async () => {
setGenerating(true);
setError(null);
try {
const useTickers =
session.tickers.length > 0 ? session.tickers : [...DEFAULT_TICKERS];
const resp = (await optimizePortfolio({
tickers: useTickers,
objective: session.objective || "hybrid",
weight_min: session.constraints.weightMin ?? DEFAULT_WEIGHT_MIN,
maxWeight: session.constraints.weightMax ?? DEFAULT_WEIGHT_MAX,
})) as Record<string, unknown>;
const data = mergeOptimizeResponse(resp);
const provenance: ReportProvenance = {
source: "fresh",
snapshot_at: null,
};
const report = buildAndDownload(
selectedType,
format,
data,
useTickers,
reportCtx,
provenance
);
setLastReport(report);
} catch (e) {
const msg =
e instanceof Error ? e.message : "Report generation failed";
setError(msg);
} finally {
setGenerating(false);
}
}, [selectedType, format, session, reportCtx]);
return {
selectedType,
setSelectedType,
format,
setFormat,
generating,
lastReport,
error,
hasSnapshot,
snapshotAt,
generateReport,
generateReportFresh,
};
}