feat(iace): add withdrawn filter to norms library frontend
- Add withdrawn/valid_until/replaced_by to Norm interface - Add Status filter (Aktiv/Zurueckgezogen) — defaults to "Aktiv" - Withdrawn norms hidden by default, viewable via filter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,9 @@ export interface Norm {
|
|||||||
mandatory: boolean
|
mandatory: boolean
|
||||||
relevant_sections: string[]
|
relevant_sections: string[]
|
||||||
beuth_url: string
|
beuth_url: string
|
||||||
|
withdrawn?: boolean
|
||||||
|
valid_until?: string
|
||||||
|
replaced_by?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const PER_PAGE = 50
|
const PER_PAGE = 50
|
||||||
@@ -30,6 +33,11 @@ const MANDATORY_OPTIONS = [
|
|||||||
{ value: 'ja', label: 'Pflicht: Ja' },
|
{ value: 'ja', label: 'Pflicht: Ja' },
|
||||||
{ value: 'nein', label: 'Pflicht: Nein' },
|
{ value: 'nein', label: 'Pflicht: Nein' },
|
||||||
]
|
]
|
||||||
|
const STATUS_OPTIONS = [
|
||||||
|
{ value: '', label: 'Status: Alle' },
|
||||||
|
{ value: 'active', label: 'Aktiv' },
|
||||||
|
{ value: 'withdrawn', label: 'Zurueckgezogen' },
|
||||||
|
]
|
||||||
|
|
||||||
interface Props { norms: Norm[] }
|
interface Props { norms: Norm[] }
|
||||||
|
|
||||||
@@ -38,6 +46,7 @@ export default function NormenTab({ norms }: Props) {
|
|||||||
const [debounced, setDebounced] = useState('')
|
const [debounced, setDebounced] = useState('')
|
||||||
const [typeFilter, setTypeFilter] = useState('')
|
const [typeFilter, setTypeFilter] = useState('')
|
||||||
const [mandatoryFilter, setMandatoryFilter] = useState('')
|
const [mandatoryFilter, setMandatoryFilter] = useState('')
|
||||||
|
const [statusFilter, setStatusFilter] = useState('active')
|
||||||
const [page, setPage] = useState(1)
|
const [page, setPage] = useState(1)
|
||||||
const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||||
|
|
||||||
@@ -46,7 +55,7 @@ export default function NormenTab({ norms }: Props) {
|
|||||||
return () => { if (timer.current) clearTimeout(timer.current) }
|
return () => { if (timer.current) clearTimeout(timer.current) }
|
||||||
}, [search])
|
}, [search])
|
||||||
|
|
||||||
useEffect(() => { setPage(1) }, [debounced, typeFilter, mandatoryFilter])
|
useEffect(() => { setPage(1) }, [debounced, typeFilter, mandatoryFilter, statusFilter])
|
||||||
|
|
||||||
const filtered = useMemo(() => {
|
const filtered = useMemo(() => {
|
||||||
const q = debounced.toLowerCase()
|
const q = debounced.toLowerCase()
|
||||||
@@ -55,9 +64,11 @@ export default function NormenTab({ norms }: Props) {
|
|||||||
if (typeFilter && n.norm_type !== typeFilter) return false
|
if (typeFilter && n.norm_type !== typeFilter) return false
|
||||||
if (mandatoryFilter === 'ja' && !n.mandatory) return false
|
if (mandatoryFilter === 'ja' && !n.mandatory) return false
|
||||||
if (mandatoryFilter === 'nein' && n.mandatory) return false
|
if (mandatoryFilter === 'nein' && n.mandatory) return false
|
||||||
|
if (statusFilter === 'active' && n.withdrawn) return false
|
||||||
|
if (statusFilter === 'withdrawn' && !n.withdrawn) return false
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}, [norms, debounced, typeFilter, mandatoryFilter])
|
}, [norms, debounced, typeFilter, mandatoryFilter, statusFilter])
|
||||||
|
|
||||||
const totalPages = Math.ceil(filtered.length / PER_PAGE)
|
const totalPages = Math.ceil(filtered.length / PER_PAGE)
|
||||||
const pageItems = filtered.slice((page - 1) * PER_PAGE, page * PER_PAGE)
|
const pageItems = filtered.slice((page - 1) * PER_PAGE, page * PER_PAGE)
|
||||||
@@ -70,6 +81,7 @@ export default function NormenTab({ norms }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
<FilterDropdown label="Normtyp" value={typeFilter} options={TYPE_OPTIONS} onChange={setTypeFilter} />
|
<FilterDropdown label="Normtyp" value={typeFilter} options={TYPE_OPTIONS} onChange={setTypeFilter} />
|
||||||
<FilterDropdown label="Pflicht" value={mandatoryFilter} options={MANDATORY_OPTIONS} onChange={setMandatoryFilter} />
|
<FilterDropdown label="Pflicht" value={mandatoryFilter} options={MANDATORY_OPTIONS} onChange={setMandatoryFilter} />
|
||||||
|
<FilterDropdown label="Status" value={statusFilter} options={STATUS_OPTIONS} onChange={setStatusFilter} />
|
||||||
<span className="text-sm text-gray-500 dark:text-gray-400 ml-auto">
|
<span className="text-sm text-gray-500 dark:text-gray-400 ml-auto">
|
||||||
{norms.length} Normen{filtered.length !== norms.length && ` (${filtered.length} gefiltert)`}
|
{norms.length} Normen{filtered.length !== norms.length && ` (${filtered.length} gefiltert)`}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user