Reduce demo to 3 charts, fix back-button district name bug
Deploy to git-pages / deploy (push) Successful in 26s

Fixes the deep-link/back-button bug where the district name showed
"Unknown District" on return: App.jsx was passing the LEAID as a text
search query to searchDistricts() (a name search), which never matches a
numeric ID. Resolves it instead via fetchDistrictEstimates(leaid, ...) and
reads lea_name/state directly from the returned row - correct regardless
of how the page was reached (fresh load, refresh, or browser back/forward).

Cuts the demo from 6 charts to 3, per request: arrests over time (kept),
arrest rate by student group restructured into Female/Male box-and-whisker
panels (kept), and the posterior density ridge chart restructured from a
2x2 model-quadrant grid into a single selected model (dropdown, default
three-year + referral rate) with Female/Male ridge columns. Removes
DistrictVsNational, ModelDrawsComparison, and ExceedanceProbability
entirely, along with the student-group filter (no longer needed - the
remaining charts always show the full breakdown) and the national-rates
fetch/plumbing that only those removed charts used.

Also updates LoadingAnimation's copy and dedupes its STUDENT_GROUPS/
MODEL_QUADRANTS constants against the shared ones in useApi.js.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 19:27:24 -04:00
co-authored by Claude Sonnet 5
parent cf8e65bb8e
commit a1ffa600b3
14 changed files with 263 additions and 874 deletions
+12 -12
View File
@@ -4,7 +4,7 @@ import DistrictSearch from './components/DistrictSearch.jsx'
import LoadingAnimation from './components/LoadingAnimation.jsx'
import ChartPanel from './components/ChartPanel.jsx'
import Footer from './components/Footer.jsx'
import { searchDistricts } from './hooks/useApi.js'
import { fetchDistrictEstimates } from './hooks/useApi.js'
/**
* CRDC Arrests API Demo App — main router.
@@ -21,18 +21,18 @@ export default function App() {
const leaid = params.get('leaid')
const stateParam = params.get('state')
if (leaid && stateParam) {
// Deep link: fetch district name first, then go to loading.
// Deep link (including browser back/forward landing on this URL): resolve
// the district name via a real estimates row, keyed by LEAID. The previous
// version called searchDistricts(leaid, ...), a name/text search — passing
// an LEAID as search text never matches, so it always fell back to "Unknown
// District".
setSelectedState(stateParam)
// Fetch district name from API
searchDistricts(leaid, stateParam).then(results => {
const district = results?.find(d => d.leaid === leaid)
if (district) {
setDistrict(district)
} else {
// Fallback if district not found
setDistrict({ leaid, lea_name: 'Unknown District', state: stateParam })
}
fetchDistrictEstimates(leaid, { model: 'unified_m2_mod', year: '21-22' }).then(rows => {
const row = rows?.[0]
setDistrict(row
? { leaid: row.leaid, lea_name: row.lea_name, state: row.state }
: { leaid, lea_name: 'Unknown District', state: stateParam })
setStep('loading')
}).catch(() => {
// Fallback on error