Effektive Werte als eingebettete Ansicht statt Pop-up
Deploy App / deploy (push) Successful in 1m4s

Klick auf "Effektive Werte" in der Sidebar oeffnet neu -- analog zu
"Szenarien" -- eine Liste im Hauptbereich statt eines Modals. Neuer
Plan-Tab "actuals"; ActualsDialog bekommt einen embedded-Modus (ohne
Overlay, Backdrop und Schliessen-Knopf). Der Modal-Weg ueber den
Matrix-Knopf bleibt bestehen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 22:36:48 +02:00
parent 74d1577bd8
commit 489390a4a3
2 changed files with 51 additions and 16 deletions
+29 -10
View File
@@ -105,7 +105,7 @@ function AppShellInner({ username }: { username: string }) {
const [showHistory, setShowHistory] = useState(false);
const [showActuals, setShowActuals] = useState(false);
// Plan-Ebene: Dashboard / Szenarien-Liste / Analysen. Null = kein Plan-View aktiv.
const [planNav, setPlanNav] = useState<{ planId: string; tab: "dashboard" | "scenarios" | "analyses" } | null>(null);
const [planNav, setPlanNav] = useState<{ planId: string; tab: "dashboard" | "scenarios" | "actuals" | "analyses" } | null>(null);
// Welche Szenario-Bäume in der Seitenleiste aufgeklappt sind. Standard: eingeklappt.
const [expandedTrees, setExpandedTrees] = useState<Record<string, boolean>>({});
const [savedAnalysisId, setSavedAnalysisId] = useState<string | null>(null);
@@ -182,7 +182,7 @@ function AppShellInner({ username }: { username: string }) {
// Plan-Ebene öffnen (Dashboard / Szenarien / Analysen). Räumt die Szenario- und Wissens-
// Ansichten weg -- es kann immer nur eine Hauptansicht aktiv sein.
function openPlanTab(planId: string, tab: "dashboard" | "scenarios" | "analyses") {
function openPlanTab(planId: string, tab: "dashboard" | "scenarios" | "actuals" | "analyses") {
setPlanNav({ planId, tab });
setSelectedScenarioId(null);
setShowSpec(false);
@@ -204,13 +204,13 @@ function AppShellInner({ username }: { username: string }) {
else setShowLiveSim(true);
}
// Effektive Werte von der Plan-Ebene aus öffnen (braucht das Basisszenario geladen).
async function openActualsForPlan(planId: string) {
// Effektive-Werte-Ansicht (Plan-Ebene, eingebettet). Lädt das Basisszenario, das der
// eingebettete Dialog als Ausgangspunkt braucht, und öffnet dann den Tab.
async function openActualsTab(planId: string) {
const plan = plans.find((p) => p.id === planId);
const baseId = plan?.scenarios.find((s) => s.isBase)?.id ?? plan?.scenarios[0]?.id;
if (!baseId) return;
if (detail?.meta.id !== baseId) await loadDetail(baseId, true);
setShowActuals(true);
if (baseId && detail?.meta.id !== baseId) await loadDetail(baseId, true);
openPlanTab(planId, "actuals");
}
async function handleDeletePlan(id: string) {
@@ -347,7 +347,7 @@ function AppShellInner({ username }: { username: string }) {
{plans.map((p) => {
const navHere = planNav?.planId === p.id;
const subItem = (tab: "dashboard" | "scenarios" | "analyses", label: string, Icon: typeof FolderKanban) => (
const subItem = (tab: "dashboard" | "scenarios" | "actuals" | "analyses", label: string, Icon: typeof FolderKanban) => (
<button
type="button"
onClick={() => openPlanTab(p.id, tab)}
@@ -418,8 +418,10 @@ function AppShellInner({ username }: { username: string }) {
)}
<button
type="button"
onClick={() => openActualsForPlan(p.id)}
className="flex w-full items-center gap-2 rounded-lg py-1.5 pl-8 pr-3 text-left text-xs font-medium text-muted transition-colors hover:bg-surface-2"
onClick={() => void openActualsTab(p.id)}
className={`flex w-full items-center gap-2 rounded-lg py-1.5 pl-8 pr-3 text-left text-xs font-medium transition-colors ${
navHere && planNav?.tab === "actuals" ? "bg-accent-soft text-accent-soft-fg" : "text-muted hover:bg-surface-2"
}`}
>
<CalendarClock className="h-3.5 w-3.5 shrink-0" />
Effektive Werte
@@ -540,6 +542,23 @@ function AppShellInner({ username }: { username: string }) {
}}
/>
)}
{!showSpec && !showSystemParams && planNav?.tab === "actuals" && activePlan && (
detail && detail.meta.planId === planNav.planId ? (
<ActualsDialog
key={planNav.planId}
embedded
planId={planNav.planId}
planName={activePlan.name}
scenarioMetas={activePlan.scenarios}
initial={{ id: detail.meta.id, name: detail.meta.name, isBase: detail.meta.isBase, plan: detail.plan }}
onClose={() => {}}
onChanged={refreshCurrent}
/>
) : (
<p className="text-sm text-muted">Wird geladen</p>
)
)}
{!showSpec && !showSystemParams && planNav?.tab === "analyses" && (
<AnalysesView
planId={planNav.planId}