UI improvements: responsive layout, unified panels, credit legend

- Add responsive 2-panel layout (mobile single-col, tablet/desktop grid)
- Unify specialization ranking with credit bars, status badges, and
  expandable allocation breakdowns (remove standalone ResultsDashboard)
- Inline decision tree ceiling data on course buttons with spec counts
- Add Clear All button to reset all course selections
- Add collapsible CreditLegend explaining bars, badges, and limits
- Extract ModeComparison and MutualExclusionWarnings to Notifications
- Add useMediaQuery hook with matchMedia-based breakpoint detection
This commit is contained in:
2026-02-28 21:17:50 -05:00
parent 9e00901179
commit f8bab9ee33
18 changed files with 718 additions and 369 deletions

View File

@@ -0,0 +1,34 @@
import { useState, useEffect } from 'react';
export type Breakpoint = 'mobile' | 'tablet' | 'desktop';
const mobileQuery = '(max-width: 639px)';
const tabletQuery = '(min-width: 640px) and (max-width: 1024px)';
function getBreakpoint(): Breakpoint {
if (window.matchMedia(mobileQuery).matches) return 'mobile';
if (window.matchMedia(tabletQuery).matches) return 'tablet';
return 'desktop';
}
export function useMediaQuery(): Breakpoint {
const [breakpoint, setBreakpoint] = useState<Breakpoint>(getBreakpoint);
useEffect(() => {
const mobileMql = window.matchMedia(mobileQuery);
const tabletMql = window.matchMedia(tabletQuery);
function onChange() {
setBreakpoint(getBreakpoint());
}
mobileMql.addEventListener('change', onChange);
tabletMql.addEventListener('change', onChange);
return () => {
mobileMql.removeEventListener('change', onChange);
tabletMql.removeEventListener('change', onChange);
};
}, []);
return breakpoint;
}