Lebensphasen-Zellen oeffnen jetzt ein Popup (statt unterem Detail-Panel)
Deploy App / deploy (push) Successful in 1m5s
Deploy App / deploy (push) Successful in 1m5s
Klick auf eine Element-Zelle in einer Lebensphase oeffnet neu ein kleines Popup (PhaseCellDialog mit ElementDetail) - analog zu den Uebergangszellen. Das untere Detail-Panel dient nur noch der Phasen-Kopf-Bearbeitung. Popup ist per key stabil (kein Uebertrag des Formularzustands zwischen Elementen). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+62
-32
@@ -75,7 +75,6 @@ type Column =
|
||||
| { kind: "transition"; fromPhase: PhaseComputed; toPhase: PhaseComputed };
|
||||
|
||||
type Selection =
|
||||
| { type: "phaseCell"; elementId: string; phaseId: string }
|
||||
| { type: "phase"; phaseId: string };
|
||||
|
||||
export function PlanView({
|
||||
@@ -94,6 +93,7 @@ export function PlanView({
|
||||
const [showSettings, setShowSettings] = useState(false);
|
||||
const [reviewFromPhaseId, setReviewFromPhaseId] = useState<string | null>(null);
|
||||
const [editTransition, setEditTransition] = useState<{ elementId: string; fromPhaseId: string } | null>(null);
|
||||
const [editPhaseCell, setEditPhaseCell] = useState<{ elementId: string; phaseId: string } | null>(null);
|
||||
|
||||
const columns = useMemo<Column[]>(() => {
|
||||
const cols: Column[] = [];
|
||||
@@ -389,17 +389,13 @@ export function PlanView({
|
||||
{columns.map((col) => {
|
||||
if (col.kind === "phase") {
|
||||
const ce = computedElement(col.phase.id, el.id);
|
||||
const isSel =
|
||||
selected?.type === "phaseCell" &&
|
||||
selected.elementId === el.id &&
|
||||
selected.phaseId === col.phase.id;
|
||||
return (
|
||||
<td
|
||||
key={col.phase.id}
|
||||
onClick={() => setSelected({ type: "phaseCell", elementId: el.id, phaseId: col.phase.id })}
|
||||
onClick={() => setEditPhaseCell({ elementId: el.id, phaseId: col.phase.id })}
|
||||
className={`cursor-pointer border-b border-r border-border px-2 py-1.5 text-center text-xs ${
|
||||
isSel ? "bg-accent-soft" : ""
|
||||
} ${ce?.locked ? "text-faint" : "text-fg"}`}
|
||||
ce?.locked ? "text-faint" : "text-fg"
|
||||
}`}
|
||||
>
|
||||
{phaseCellContent(ce)}
|
||||
</td>
|
||||
@@ -443,10 +439,7 @@ export function PlanView({
|
||||
{/* Detail-Panel. Der key erzwingt beim Wechsel von Zelle/Phase einen Neuaufbau,
|
||||
damit der lokale Formular-Zustand nicht vom vorher geoeffneten Element uebrig bleibt. */}
|
||||
{selected && (
|
||||
<div
|
||||
key={selected.type === "phase" ? `ph-${selected.phaseId}` : `pc-${selected.elementId}-${selected.phaseId}`}
|
||||
className="rounded-xl border border-accent bg-surface p-4 shadow-sm"
|
||||
>
|
||||
<div key={`ph-${selected.phaseId}`} className="rounded-xl border border-accent bg-surface p-4 shadow-sm">
|
||||
{renderDetail()}
|
||||
</div>
|
||||
)}
|
||||
@@ -526,6 +519,31 @@ export function PlanView({
|
||||
/>
|
||||
);
|
||||
})()}
|
||||
|
||||
{editPhaseCell && (() => {
|
||||
const element = plan.elements.find((e) => e.id === editPhaseCell.elementId);
|
||||
const phase = computed.phases.find((p) => p.id === editPhaseCell.phaseId);
|
||||
if (!element || !phase) return null;
|
||||
const context = buildPhaseContext(phase, element);
|
||||
return (
|
||||
<PhaseCellDialog
|
||||
key={`${editPhaseCell.elementId}-${editPhaseCell.phaseId}`}
|
||||
element={element}
|
||||
phase={phase}
|
||||
context={context}
|
||||
phaseData={element.phaseValues[phase.id] ?? {}}
|
||||
onClose={() => setEditPhaseCell(null)}
|
||||
onSaved={() => {
|
||||
setEditPhaseCell(null);
|
||||
onChanged();
|
||||
}}
|
||||
onDeleted={() => {
|
||||
setEditPhaseCell(null);
|
||||
deleteElement(element.id);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -541,8 +559,6 @@ export function PlanView({
|
||||
|
||||
function renderDetail() {
|
||||
if (!selected) return null;
|
||||
|
||||
if (selected.type === "phase") {
|
||||
const phase = computed.phases.find((p) => p.id === selected.phaseId);
|
||||
const phaseInput = plan.phases.find((p) => p.id === selected.phaseId);
|
||||
if (!phase || !phaseInput) return null;
|
||||
@@ -562,24 +578,6 @@ export function PlanView({
|
||||
);
|
||||
}
|
||||
|
||||
const element = plan.elements.find((e) => e.id === selected.elementId);
|
||||
if (!element) return null;
|
||||
|
||||
// phaseCell
|
||||
const phase = computed.phases.find((p) => p.id === selected.phaseId)!;
|
||||
const context = buildPhaseContext(phase, element);
|
||||
return (
|
||||
<ElementDetail
|
||||
element={element}
|
||||
context={context}
|
||||
phaseData={element.phaseValues[phase.id] ?? {}}
|
||||
transitionData={{}}
|
||||
onSaved={onChanged}
|
||||
onDeleteElement={() => deleteElement(element.id)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
async function deleteElement(id: string) {
|
||||
if (!confirm("Dieses Element wirklich loeschen (aus allen Phasen)?")) return;
|
||||
await api.delete(`/api/elements/${id}`);
|
||||
@@ -1040,6 +1038,38 @@ function TransitionReviewDialog({
|
||||
);
|
||||
}
|
||||
|
||||
// --- Dialog: Element-Werte einer Lebensphase (per Klick auf eine Phasenzelle) ---
|
||||
function PhaseCellDialog({
|
||||
element,
|
||||
phase,
|
||||
context,
|
||||
phaseData,
|
||||
onClose,
|
||||
onSaved,
|
||||
onDeleted,
|
||||
}: {
|
||||
element: ElementInput;
|
||||
phase: PhaseComputed;
|
||||
context: CellContext;
|
||||
phaseData: PhaseData;
|
||||
onClose: () => void;
|
||||
onSaved: () => void;
|
||||
onDeleted: () => void;
|
||||
}) {
|
||||
return (
|
||||
<DialogShell title={`Lebensphase: ${phase.name}`} onClose={onClose} wide>
|
||||
<ElementDetail
|
||||
element={element}
|
||||
context={context}
|
||||
phaseData={phaseData}
|
||||
transitionData={{}}
|
||||
onSaved={onSaved}
|
||||
onDeleteElement={onDeleted}
|
||||
/>
|
||||
</DialogShell>
|
||||
);
|
||||
}
|
||||
|
||||
// --- Dialog: einzelner Übergangs-Entscheid (per Klick auf eine Übergangszelle) ---
|
||||
function TransitionCellDialog({
|
||||
element,
|
||||
|
||||
Reference in New Issue
Block a user