Klick auf eine Einheit zeigt ihre Angaben
All checks were successful
CI / Lint, Typen, Tests, Build (push) Successful in 11m56s
CI / Migrationen auf leerer Datenbank (push) Successful in 10m7s

Die naheliegendste Geste in dieser Ansicht war ohne Wirkung: eine Karte im
Organigramm liess sich anklicken und antwortete nicht. Jetzt oeffnet sie eine
Leiste mit dem, was an der Einheit steht -- Orgnummer, Art, die Kette nach
oben, Gueltigkeit, Leitung, Belegschaft, unbesetzte Planstellen, die direkt
untergeordneten Einheiten und die Zahl der Personen im ganzen Teilbaum. Dazu
dieselben zwei Handlungen wie auf der Karte, nur beschriftet statt als Symbol.

Alles daraus stammt aus den Daten, die die Struktursicht ohnehin geladen hat.
Kein zusaetzlicher Gang zur Datenbank und damit auch keine zweite Wahrheit --
was die Leiste zeigt, ist dasselbe, woraus der Baum daneben gezeichnet ist.

Die Liste klickt sich genauso: beide Ansichten kommen aus einem Baum, und eine
Handlung, die es nur in einer von beiden gibt, findet man in der anderen nie.

org_units liefert dafuer zusaetzlich valid_from und valid_to, aber nur an die
Struktursicht. Der Druck kommt ohne sie aus; auf OrgUnitNode stehen sie deshalb
als optionale Felder und nicht als zwei weitere Spalten, die ueberall
mitgeschleppt werden.
This commit is contained in:
2026-09-28 21:27:36 +02:00
parent a3dde61ec1
commit ab50c21b8a
7 changed files with 259 additions and 7 deletions

View File

@@ -17,6 +17,8 @@ export type OrgChartNodeData = {
/** Nur in der Struktursicht gesetzt — ohne sie bleibt die Karte unverändert. */
onAddUnit?: (unitId: string) => void;
onDeleteUnit?: (unitId: string) => void;
/** Klick auf die Karte einer Einheit — öffnet ihre Angaben. */
onSelectUnit?: (unitId: string) => void;
};
export type OrgChartRFNode = Node<OrgChartNodeData, "orgNode">;
@@ -45,7 +47,7 @@ const KIND_SHELL: Record<ChartNodeKind, string> = {
// React Flow re-renders node components on every pan/zoom frame — memo is
// required, not just tidy, to keep that smooth at a few hundred nodes.
export const OrgChartNode = memo(function OrgChartNode({ id, data }: NodeProps<OrgChartRFNode>) {
const { chartNode, expanded, hasChildren, childCount, onToggle, onAddUnit, onDeleteUnit } = data;
const { chartNode, expanded, hasChildren, childCount, onToggle, onAddUnit, onDeleteUnit, onSelectUnit } = data;
const { kind, label, sublabel, avatar, href, vacant, totalReports, absent, coveredBy, coveringFor, unitId } = chartNode;
const isMatch = chartNode.matched ?? false;
const { width, height } = NODE_DIMENSIONS[kind];
@@ -161,6 +163,18 @@ export const OrgChartNode = memo(function OrgChartNode({ id, data }: NodeProps<O
<Link href={href} className="nodrag nopan flex min-w-0 flex-1 items-center gap-2.5 py-2 pl-3.5 pr-3">
{content}
</Link>
) : unitId && onSelectUnit ? (
// Die ganze Karte, nicht ein Symbol darin: bei achtzig Einheiten ist
// die Fläche das Ziel, das man trifft, ohne hinzusehen.
<button
type="button"
onClick={() => onSelectUnit(unitId)}
aria-label={`Angaben zu ${label}`}
className="nodrag nopan flex min-w-0 flex-1 items-center gap-2.5 py-2 pl-3.5 pr-3 text-left
focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-500"
>
{content}
</button>
) : (
<div className="flex min-w-0 flex-1 items-center gap-2.5 py-2 pl-3.5 pr-3">{content}</div>
)}