fix: finanzplan scenario selector — load from API, no hardcoded UUID
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m4s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 29s
CI / test-python-voice (push) Successful in 27s
CI / test-bqas (push) Successful in 28s
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m4s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 29s
CI / test-python-voice (push) Successful in 27s
CI / test-bqas (push) Successful in 28s
Replaces the FM-name-based 'wandeldarlehen' hack with a proper scenario picker. Scenarios are fetched from /api/finanzplan, default is selected automatically. Dropdown appears when multiple scenarios exist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -61,8 +61,12 @@ function formatCell(v: number | undefined): string {
|
|||||||
return Math.round(v).toLocaleString('de-DE', { maximumFractionDigits: 0 })
|
return Math.round(v).toLocaleString('de-DE', { maximumFractionDigits: 0 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface FpScenario { id: string; name: string; is_default: boolean }
|
||||||
|
|
||||||
export default function FinanzplanSlide({ lang, investorId, preferredScenarioId }: FinanzplanSlideProps) {
|
export default function FinanzplanSlide({ lang, investorId, preferredScenarioId }: FinanzplanSlideProps) {
|
||||||
const [sheets, setSheets] = useState<SheetMeta[]>([])
|
const [sheets, setSheets] = useState<SheetMeta[]>([])
|
||||||
|
const [scenarios, setScenarios] = useState<FpScenario[]>([])
|
||||||
|
const [selectedScenarioId, setSelectedScenarioId] = useState<string>('')
|
||||||
const [activeSheet, setActiveSheet] = useState<string>('personalkosten')
|
const [activeSheet, setActiveSheet] = useState<string>('personalkosten')
|
||||||
const [rows, setRows] = useState<SheetRow[]>([])
|
const [rows, setRows] = useState<SheetRow[]>([])
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
@@ -77,19 +81,26 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId
|
|||||||
[fm.activeResults],
|
[fm.activeResults],
|
||||||
)
|
)
|
||||||
|
|
||||||
// Determine fp_scenario_id from the active FM scenario name
|
// Load sheet list + scenarios
|
||||||
const fpScenarioParam = fm.activeScenario?.name?.toLowerCase().includes('wandeldarlehen')
|
|
||||||
? '?scenarioId=c0000000-0000-0000-0000-000000000200'
|
|
||||||
: ''
|
|
||||||
|
|
||||||
// Load sheet list
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch('/api/finanzplan', { cache: 'no-store' })
|
fetch('/api/finanzplan', { cache: 'no-store' })
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => setSheets(data.sheets || []))
|
.then(data => {
|
||||||
|
setSheets(data.sheets || [])
|
||||||
|
const scens: FpScenario[] = data.scenarios || []
|
||||||
|
setScenarios(scens)
|
||||||
|
// Pick default scenario on first load
|
||||||
|
if (!selectedScenarioId) {
|
||||||
|
const def = scens.find(s => s.is_default) ?? scens[0]
|
||||||
|
if (def) setSelectedScenarioId(def.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const scenarioParam = selectedScenarioId ? `?scenarioId=${selectedScenarioId}` : ''
|
||||||
|
|
||||||
// Load sheet data
|
// Load sheet data
|
||||||
const loadSheet = useCallback(async (name: string) => {
|
const loadSheet = useCallback(async (name: string) => {
|
||||||
if (name === 'kpis' || name === 'charts') {
|
if (name === 'kpis' || name === 'charts') {
|
||||||
@@ -99,12 +110,12 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId
|
|||||||
}
|
}
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const r = await fetch(`/api/finanzplan/${name}${fpScenarioParam}`, { cache: 'no-store' })
|
const r = await fetch(`/api/finanzplan/${name}${scenarioParam}`, { cache: 'no-store' })
|
||||||
const data = await r.json()
|
const data = await r.json()
|
||||||
setRows(data.rows || [])
|
setRows(data.rows || [])
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}, [fpScenarioParam])
|
}, [scenarioParam])
|
||||||
|
|
||||||
useEffect(() => { loadSheet(activeSheet) }, [activeSheet, loadSheet])
|
useEffect(() => { loadSheet(activeSheet) }, [activeSheet, loadSheet])
|
||||||
|
|
||||||
@@ -112,7 +123,7 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId
|
|||||||
const handleCompute = async () => {
|
const handleCompute = async () => {
|
||||||
setComputing(true)
|
setComputing(true)
|
||||||
try {
|
try {
|
||||||
await fetch('/api/finanzplan/compute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' })
|
await fetch('/api/finanzplan/compute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ scenarioId: selectedScenarioId || undefined }) })
|
||||||
await loadSheet(activeSheet)
|
await loadSheet(activeSheet)
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
setComputing(false)
|
setComputing(false)
|
||||||
@@ -182,6 +193,17 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId
|
|||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
<div className="flex-1" />
|
<div className="flex-1" />
|
||||||
|
{scenarios.length > 1 && (
|
||||||
|
<select
|
||||||
|
value={selectedScenarioId}
|
||||||
|
onChange={e => setSelectedScenarioId(e.target.value)}
|
||||||
|
className="text-[10px] bg-white/[0.06] text-white/60 border border-white/10 rounded-lg px-2 py-1.5 mr-2"
|
||||||
|
>
|
||||||
|
{scenarios.map(s => (
|
||||||
|
<option key={s.id} value={s.id}>{s.name}{s.is_default ? ' ★' : ''}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={handleCompute}
|
onClick={handleCompute}
|
||||||
disabled={computing}
|
disabled={computing}
|
||||||
|
|||||||
Reference in New Issue
Block a user