Build Hierarchy Node Editor form UI
epic-organizational-hierarchy-management-assignment-aggregation-task-010 — Implement the full-screen form widget for creating and editing individual hierarchy nodes. Include fields for node name, level type selector (chapter/region/national), and a searchable parent dropdown that lazy-loads organizational units. Wire form submission through Hierarchy Structure Validator to surface cycle and depth-limit errors inline before save. Follow WCAG 2.2 AA accessibility requirements with proper semantics and focus management.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Use a BLoC (HierarchyNodeEditorBloc) with states: HierarchyNodeEditorInitial, HierarchyNodeEditorLoading, HierarchyNodeEditorValidationError (carries Map
Use Flutter's FocusTraversalGroup to enforce logical focus order. Wrap all error Text widgets in Semantics(liveRegion: true, child: ...) for proper screen-reader announcement. In edit mode, initialize BLoC with a HierarchyNodeEditorEditRequested(nodeId) event that pre-loads the node and populates form fields. Avoid StatefulWidget local state beyond TextEditingControllers — push all validation state into BLoC.
Testing Requirements
Unit tests (flutter_test): test LevelTypeSelector emits correct BLoC events on selection; test ParentUnitSearchDropdown debounce logic with fake timers (FakeAsync); test InlineValidationMessage renders correct text for each validation error type. Widget tests: pump HierarchyNodeEditorForm in both create and edit modes and verify field pre-population; verify submit button disabled state during async validation; verify focus traversal order using FocusNode.nextFocus() assertions. Accessibility tests: use flutter_test's SemanticsController to assert all fields have labels, error messages have liveRegion, and contrast ratios pass. Integration tests (on device/emulator): verify parent dropdown lazy-load triggers on scroll, search filters results, and debounce suppresses calls.
Target 85%+ line coverage on form widget and child components.
Recursive aggregation queries across four hierarchy levels (national → region → local) with 1,400 leaf nodes may be too slow for real-time dashboard requests, exceeding the 200ms target and causing spinner timeouts.
Mitigation & Contingency
Mitigation: Implement aggregation as a Supabase RPC using a single recursive CTE rather than multiple round-trip queries. Pre-compute aggregations nightly via a scheduled Edge Function and cache results. For real-time needs, aggregate only the immediate subtree on demand.
Contingency: Surface a 'Refreshing...' indicator and serve stale cached aggregations immediately. Queue an async recalculation and push updated data via Supabase Realtime when ready, avoiding blocking the admin dashboard.
The 5-chapter limit and primary-assignment constraint are NHF-specific. Applying these rules globally may break HLF and Blindeforbundet configurations where different limits apply, requiring per-organization configuration that was not initially scoped.
Mitigation & Contingency
Mitigation: Make the maximum assignment count a configurable value stored in the organization's feature-flag or settings table rather than a hardcoded constant. Design the assignment service to read this limit at runtime per organization.
Contingency: Default the limit to a high value (e.g., 100) for organizations other than NHF, effectively making it non-restrictive, while keeping the enforcement logic intact for when per-org configuration is fully implemented.
The searchable parent dropdown in HierarchyNodeEditor must search across up to 1,400 units efficiently. Client-side filtering of the full hierarchy may be slow; server-side search adds complexity and latency.
Mitigation & Contingency
Mitigation: Use the in-memory hierarchy cache as the search corpus — since the cache already holds the flat unit list, client-side filtering with a debounced input is sufficient and avoids extra Supabase calls. Pre-build a search index on cache load.
Contingency: Cap the dropdown to showing the 50 most recently accessed units by default, with a 'search all' option that triggers a server-side full-text query. This keeps the common case fast while supporting edge cases.