feat(home): sort countdown chips by days remaining, fade in after hydration
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
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 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
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 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Chips now sort soonest-first at hydration time so the most urgent deadline always appears first. The rail is hidden (opacity 0) until the useEffect populates and sorts the chips, then fades in — avoiding any visible layout shift from the reorder. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -77,7 +77,9 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
||||
const mapParamsRef = useRef<string>('');
|
||||
const [geoState, setGeoState] = useState<'idle' | 'requesting' | 'error'>('idle');
|
||||
const [geoError, setGeoError] = useState<string | null>(null);
|
||||
const [chipDays, setChipDays] = useState<(number | null)[]>(ADMISSIONS_CHIPS.map(() => null));
|
||||
const [sortedChips, setSortedChips] = useState<Array<{ chip: CountdownChipData; days: number | null }>>(
|
||||
ADMISSIONS_CHIPS.map(c => ({ chip: c, days: null }))
|
||||
);
|
||||
|
||||
const hasSearch = searchParams.get('search') || searchParams.get('postcode');
|
||||
const isLocationSearch = !!searchParams.get('postcode');
|
||||
@@ -140,9 +142,11 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
// Compute admissions countdown days client-side to avoid SSR mismatch
|
||||
// Compute admissions countdown days client-side and sort soonest-first to avoid SSR mismatch
|
||||
useEffect(() => {
|
||||
setChipDays(ADMISSIONS_CHIPS.map(c => daysUntil(c.month, c.day)));
|
||||
const withDays = ADMISSIONS_CHIPS.map(c => ({ chip: c, days: daysUntil(c.month, c.day) }));
|
||||
withDays.sort((a, b) => (a.days ?? Infinity) - (b.days ?? Infinity));
|
||||
setSortedChips(withDays);
|
||||
}, []);
|
||||
|
||||
const handleLoadMore = async () => {
|
||||
@@ -292,9 +296,14 @@ export function HomeView({ initialSchools, filters, totalSchools }: HomeViewProp
|
||||
<span className={styles.stripLabel}>Key admissions deadlines</span>
|
||||
<a href="/admissions" className={styles.stripCta}>Full admissions guide →</a>
|
||||
</div>
|
||||
<div className={styles.countdownRail}>
|
||||
{ADMISSIONS_CHIPS.map((chip, i) => {
|
||||
const days = chipDays[i];
|
||||
<div
|
||||
className={styles.countdownRail}
|
||||
style={{
|
||||
opacity: sortedChips[0]?.days !== null ? 1 : 0,
|
||||
transition: 'opacity 0.2s ease',
|
||||
}}
|
||||
>
|
||||
{sortedChips.map(({ chip, days }) => {
|
||||
const isUrgent = days !== null && days <= 14;
|
||||
const chipClass = [
|
||||
styles.countdownChip,
|
||||
|
||||
Reference in New Issue
Block a user