diff --git a/nextjs-app/components/ComparisonView.tsx b/nextjs-app/components/ComparisonView.tsx index 14399b4..3ecb5f5 100644 --- a/nextjs-app/components/ComparisonView.tsx +++ b/nextjs-app/components/ComparisonView.tsx @@ -18,7 +18,7 @@ import { SchoolSearchModal } from './SchoolSearchModal'; import { EmptyState } from './EmptyState'; import { LoadingSkeleton } from './LoadingSkeleton'; import type { ComparisonData, MetricDefinition, School } from '@/lib/types'; -import { formatPercentage, formatProgress, formatAcademicYear, CHART_COLORS, schoolUrl } from '@/lib/utils'; +import { formatPercentage, formatProgress, formatAcademicYear, CHART_COLORS, CHART_TEXT_COLORS, schoolUrl } from '@/lib/utils'; import { fetchComparison } from '@/lib/api'; import { track } from '@/lib/analytics'; import styles from './ComparisonView.module.css'; @@ -58,7 +58,7 @@ export function ComparisonView({ const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); - const { selectedSchools, removeSchool, addSchool, isInitialized } = useComparison(); + const { selectedSchools, removeSchool, addSchool, replaceSchools, isInitialized } = useComparison(); const [selectedMetric, setSelectedMetric] = useState(initialMetric); const [isModalOpen, setIsModalOpen] = useState(false); @@ -69,16 +69,22 @@ export function ComparisonView({ // While true, auto-phase detection is suppressed so manual selections aren't overridden. const phaseLockedByUser = useRef(false); - // Seed context from initialData when component mounts and localStorage is empty + // Seed context from the URL on mount. An explicit ?urns=… (e.g. a link a + // parent shared with their partner) always wins over this visitor's stored + // selection — otherwise the recipient silently sees their own old schools. + // The replacement is then persisted like any other selection change. useEffect(() => { if (!isInitialized) return; - if (selectedSchools.length === 0 && initialUrns.length > 0 && initialData) { - initialUrns.forEach(urn => { - const data = initialData[String(urn)]; - if (data?.school_info) { - addSchool(data.school_info); - } - }); + if (initialUrns.length > 0 && initialData) { + const urlSchools = initialUrns + .map(urn => initialData[String(urn)]?.school_info) + .filter((info): info is NonNullable => Boolean(info)); + const sameSet = + urlSchools.length === selectedSchools.length && + urlSchools.every(s => selectedSchools.some(sel => sel.urn === s.urn)); + if (urlSchools.length > 0 && !sameSet) { + replaceSchools(urlSchools); + } } }, [isInitialized]); // eslint-disable-line react-hooks/exhaustive-deps @@ -378,7 +384,8 @@ export function ComparisonView({ {activeComparisonData[school.urn] && (
{metricLabel}
-
+ {/* Text uses the AA-dark variant; the swatch dot keeps the true series colour */} +
void; removeSchool: (urn: number) => void; + replaceSchools: (schools: School[]) => void; clearAll: () => void; isSelected: (urn: number) => boolean; canAddMore: boolean; diff --git a/nextjs-app/context/ComparisonProvider.tsx b/nextjs-app/context/ComparisonProvider.tsx index ea5cee5..27f569e 100644 --- a/nextjs-app/context/ComparisonProvider.tsx +++ b/nextjs-app/context/ComparisonProvider.tsx @@ -65,6 +65,12 @@ export function ComparisonProvider({ children }: { children: React.ReactNode }) setSelectedSchools((prev) => prev.filter((s) => s.urn !== urn)); }, []); + // Replace the whole selection — used when a shared /compare?urns=… link + // must take precedence over whatever this visitor had stored. + const replaceSchools = useCallback((schools: School[]) => { + setSelectedSchools(schools.slice(0, MAX_SCHOOLS)); + }, []); + const clearAll = useCallback(() => { setSelectedSchools([]); }, []); @@ -86,6 +92,7 @@ export function ComparisonProvider({ children }: { children: React.ReactNode }) error: null, addSchool, removeSchool, + replaceSchools, clearAll, isSelected, canAddMore: selectedSchools.length < MAX_SCHOOLS, diff --git a/nextjs-app/hooks/useComparison.ts b/nextjs-app/hooks/useComparison.ts index 7a165bc..f7ed256 100644 --- a/nextjs-app/hooks/useComparison.ts +++ b/nextjs-app/hooks/useComparison.ts @@ -15,6 +15,7 @@ export function useComparison() { selectedSchools, addSchool, removeSchool, + replaceSchools, clearAll, isSelected, canAddMore, @@ -39,6 +40,7 @@ export function useComparison() { error, addSchool, removeSchool, + replaceSchools, clearAll, isSelected, canAddMore,