mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 16:03:41 +00:00
fix: improve CodingPage filter UX and prevent race conditions
- Show grand total count (data.total) instead of items.length - Display active fallgruppe filter label prominently - Add AbortController to cancel stale requests on rapid filter changes - Clarify badge to show "X / Y auf dieser Seite codiert" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
35b9d5a7c9
commit
d5b357b60d
1 changed files with 29 additions and 9 deletions
|
|
@ -59,11 +59,12 @@ export function CodingPage() {
|
|||
|
||||
// Fetch coding queue
|
||||
useEffect(() => {
|
||||
const controller = new AbortController()
|
||||
setLoading(true)
|
||||
const params: Record<string, string | number> = { page, per_page: 50 }
|
||||
if (fallgruppe !== '__all__') params.fallgruppe = fallgruppe
|
||||
|
||||
api.get<CaseListResponse>('/coding/queue', { params })
|
||||
api.get<CaseListResponse>('/coding/queue', { params, signal: controller.signal })
|
||||
.then((res) => {
|
||||
setData(res.data)
|
||||
// Initialize form states for each case
|
||||
|
|
@ -75,8 +76,14 @@ export function CodingPage() {
|
|||
setSavedIds(new Set())
|
||||
setErrors({})
|
||||
})
|
||||
.catch(() => setData(null))
|
||||
.finally(() => setLoading(false))
|
||||
.catch(() => {
|
||||
if (!controller.signal.aborted) setData(null)
|
||||
})
|
||||
.finally(() => {
|
||||
if (!controller.signal.aborted) setLoading(false)
|
||||
})
|
||||
|
||||
return () => controller.abort()
|
||||
}, [page, fallgruppe])
|
||||
|
||||
const updateFormField = (caseId: number, field: keyof CodingFormState, value: unknown) => {
|
||||
|
|
@ -124,19 +131,32 @@ export function CodingPage() {
|
|||
}
|
||||
}
|
||||
|
||||
// Count coded cases
|
||||
// Count coded cases on current page
|
||||
const codedCount = data
|
||||
? data.items.filter((c) => savedIds.has(c.id) || c.gutachten_typ !== null).length
|
||||
: 0
|
||||
const totalCount = data?.items.length ?? 0
|
||||
const grandTotal = data?.total ?? 0
|
||||
const activeFilterLabel = fallgruppe !== '__all__'
|
||||
? FALLGRUPPEN_LABELS[fallgruppe] || fallgruppe
|
||||
: null
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-4">
|
||||
<div className="flex flex-wrap items-center justify-between gap-4">
|
||||
<h1 className="text-2xl font-bold">Coding-Warteschlange</h1>
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">Coding-Warteschlange</h1>
|
||||
{!loading && data && (
|
||||
<p className="text-sm text-muted-foreground mt-0.5">
|
||||
{grandTotal} {grandTotal === 1 ? 'Fall' : 'Fälle'} offen
|
||||
{activeFilterLabel && (
|
||||
<> — gefiltert nach <span className="font-medium text-foreground">{activeFilterLabel}</span></>
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Badge variant="outline" className="text-sm py-1 px-3">
|
||||
{codedCount} von {totalCount} Fälle codiert
|
||||
{codedCount} / {data?.items.length ?? 0} auf dieser Seite codiert
|
||||
</Badge>
|
||||
<Select value={fallgruppe} onValueChange={(v) => { setFallgruppe(v); setPage(1) }}>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
|
|
@ -152,11 +172,11 @@ export function CodingPage() {
|
|||
</div>
|
||||
|
||||
{/* Progress bar */}
|
||||
{data && totalCount > 0 && (
|
||||
{data && grandTotal > 0 && (
|
||||
<div className="h-2 w-full rounded-full bg-muted overflow-hidden">
|
||||
<div
|
||||
className="h-full rounded-full bg-primary transition-all duration-300"
|
||||
style={{ width: `${(codedCount / totalCount) * 100}%` }}
|
||||
style={{ width: `${(codedCount / (data.items.length || 1)) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in a new issue