feat(admissions): replace bar + metric cards with Q&A tile
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 50s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 1m4s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 13s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 50s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 1m4s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
The "How Hard to Get Into This School" tile mixed a progress bar (places vs first-choice) with three text metric cards, making the data feel fragmented and hiding the real narrative. The progress bar also broke visually when undersubscribed and didn't scale to different school sizes. Replace with a typographic Q&A list that answers the questions parents actually ask — "How many places were offered?", "How many families wanted this school first?", "How many got their first choice?", "How many applied in total?" — with a verdict footer (Oversubscribed / Not oversubscribed + one-sentence explanation). The third row now uses first_preference_offers (already in the API response) to show "27 of 42 (64.3%)" instead of just the percentage, giving the raw count parents actually want. Each row is independently null-gated; rows stack vertically under 480px so the Playfair numeral stays legible. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -787,46 +787,55 @@ export function SchoolDetailView({
|
||||
{admissions && (
|
||||
<section id="admissions" className={styles.card}>
|
||||
<h2 className={styles.sectionTitle}>How Hard to Get Into This School ({formatAcademicYear(admissions.year)})</h2>
|
||||
{admissions.first_preference_applications != null && admissions.places_offered != null && (
|
||||
<div className={styles.admissionsBarWrap}>
|
||||
<div className={styles.admissionsBarLabel}>
|
||||
<strong>{admissions.places_offered}</strong> places offered for <strong>{admissions.first_preference_applications}</strong> first-choice applications
|
||||
</div>
|
||||
<div className={styles.admissionsBarTrack}>
|
||||
<div
|
||||
className={`${styles.admissionsBarFill} ${admissions.oversubscribed ? styles.admissionsBarOversubscribed : styles.admissionsBarUndersubscribed}`}
|
||||
style={{ width: `${Math.min(100, (admissions.places_offered / admissions.first_preference_applications) * 100)}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{admissions.first_preference_applications == null && admissions.oversubscribed != null && (
|
||||
<div className={`${styles.admissionsBadge} ${admissions.oversubscribed ? styles.statusWarn : styles.statusGood}`}>
|
||||
{admissions.oversubscribed
|
||||
? '⚠ Oversubscribed'
|
||||
: '✓ Not Oversubscribed'}
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.metricsGrid}>
|
||||
|
||||
<dl className={styles.admissionsQa}>
|
||||
{admissions.places_offered != null && (
|
||||
<div className={styles.metricCard}>
|
||||
<div className={styles.metricLabel}>{isSecondary ? 'Year 7' : 'Reception'} places offered</div>
|
||||
<div className={styles.metricValue}>{admissions.places_offered}</div>
|
||||
<div className={styles.admissionsQaRow}>
|
||||
<dt className={styles.admissionsQaQuestion}>How many places were offered?</dt>
|
||||
<dd className={styles.admissionsQaAnswer}>{admissions.places_offered}</dd>
|
||||
</div>
|
||||
)}
|
||||
{admissions.total_applications != null && (
|
||||
<div className={styles.metricCard}>
|
||||
<div className={styles.metricLabel}>Applications received</div>
|
||||
<div className={styles.metricValue}>{admissions.total_applications.toLocaleString()}</div>
|
||||
{admissions.first_preference_applications != null && (
|
||||
<div className={styles.admissionsQaRow}>
|
||||
<dt className={styles.admissionsQaQuestion}>How many families wanted this school first?</dt>
|
||||
<dd className={styles.admissionsQaAnswer}>{admissions.first_preference_applications}</dd>
|
||||
</div>
|
||||
)}
|
||||
{admissions.first_preference_offer_pct != null && (
|
||||
<div className={styles.metricCard}>
|
||||
<div className={styles.metricLabel}>Families who got their first-choice</div>
|
||||
<div className={styles.metricValue}>{formatPercentage(admissions.first_preference_offer_pct)}</div>
|
||||
<div className={styles.admissionsQaRow}>
|
||||
<dt className={styles.admissionsQaQuestion}>How many got their first choice?</dt>
|
||||
<dd className={styles.admissionsQaAnswer}>
|
||||
{admissions.first_preference_offers != null && admissions.first_preference_applications != null ? (
|
||||
<>
|
||||
{admissions.first_preference_offers}
|
||||
<span className={styles.admissionsQaAnswerSub}>
|
||||
of {admissions.first_preference_applications} ({formatPercentage(admissions.first_preference_offer_pct)})
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
formatPercentage(admissions.first_preference_offer_pct)
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{admissions.total_applications != null && (
|
||||
<div className={styles.admissionsQaRow}>
|
||||
<dt className={styles.admissionsQaQuestion}>How many applied in total?</dt>
|
||||
<dd className={styles.admissionsQaAnswer}>{admissions.total_applications.toLocaleString()}</dd>
|
||||
</div>
|
||||
)}
|
||||
</dl>
|
||||
|
||||
{admissions.oversubscribed != null && (
|
||||
<div className={styles.admissionsVerdict}>
|
||||
<span className={`${styles.admissionsBadge} ${admissions.oversubscribed ? styles.statusWarn : styles.statusGood}`}>
|
||||
{admissions.oversubscribed ? 'Oversubscribed' : 'Not oversubscribed'}
|
||||
</span>
|
||||
<span className={styles.admissionsVerdictText}>
|
||||
{admissions.oversubscribed ? 'Demand exceeds capacity.' : 'Supply meets demand.'}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user