Fix comparison badge to update in real-time across components
- Move comparison state from hook to shared context provider - All components now share the same state instance - Badge count updates immediately when schools are added/removed - Add key prop to badge to re-trigger animation on count change - Add storage event listener for cross-tab synchronization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,35 +1,25 @@
|
||||
/**
|
||||
* Custom hook for managing school comparison state
|
||||
* Uses shared context for real-time updates across components
|
||||
*/
|
||||
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import useSWR from 'swr';
|
||||
import { fetcher } from '@/lib/api';
|
||||
import { getFromLocalStorage, setToLocalStorage } from '@/lib/utils';
|
||||
import type { School, ComparisonResponse } from '@/lib/types';
|
||||
|
||||
const STORAGE_KEY = 'selectedSchools';
|
||||
const MAX_SCHOOLS = 5;
|
||||
import { useComparisonContext } from '@/context/ComparisonContext';
|
||||
import type { ComparisonResponse } from '@/lib/types';
|
||||
|
||||
export function useComparison() {
|
||||
const [selectedSchools, setSelectedSchools] = useState<School[]>([]);
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
|
||||
// Load from localStorage on mount
|
||||
useEffect(() => {
|
||||
const stored = getFromLocalStorage<School[]>(STORAGE_KEY, []);
|
||||
setSelectedSchools(stored);
|
||||
setIsInitialized(true);
|
||||
}, []);
|
||||
|
||||
// Save to localStorage when schools change
|
||||
useEffect(() => {
|
||||
if (isInitialized) {
|
||||
setToLocalStorage(STORAGE_KEY, selectedSchools);
|
||||
}
|
||||
}, [selectedSchools, isInitialized]);
|
||||
const {
|
||||
selectedSchools,
|
||||
addSchool,
|
||||
removeSchool,
|
||||
clearAll,
|
||||
isSelected,
|
||||
canAddMore,
|
||||
isInitialized,
|
||||
} = useComparisonContext();
|
||||
|
||||
// Fetch comparison data for selected schools
|
||||
const urns = selectedSchools.map((s) => s.urn).join(',');
|
||||
@@ -38,40 +28,10 @@ export function useComparison() {
|
||||
fetcher,
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
dedupingInterval: 10000, // 10 seconds
|
||||
dedupingInterval: 10000,
|
||||
}
|
||||
);
|
||||
|
||||
const addSchool = useCallback((school: School) => {
|
||||
setSelectedSchools((prev) => {
|
||||
// Check if already selected
|
||||
if (prev.some((s) => s.urn === school.urn)) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
// Check max limit
|
||||
if (prev.length >= MAX_SCHOOLS) {
|
||||
alert(`Maximum ${MAX_SCHOOLS} schools can be compared`);
|
||||
return prev;
|
||||
}
|
||||
|
||||
return [...prev, school];
|
||||
});
|
||||
}, []);
|
||||
|
||||
const removeSchool = useCallback((urn: number) => {
|
||||
setSelectedSchools((prev) => prev.filter((s) => s.urn !== urn));
|
||||
}, []);
|
||||
|
||||
const clearAll = useCallback(() => {
|
||||
setSelectedSchools([]);
|
||||
}, []);
|
||||
|
||||
const isSelected = useCallback(
|
||||
(urn: number) => selectedSchools.some((s) => s.urn === urn),
|
||||
[selectedSchools]
|
||||
);
|
||||
|
||||
return {
|
||||
selectedSchools,
|
||||
comparisonData: data?.comparison,
|
||||
@@ -81,7 +41,8 @@ export function useComparison() {
|
||||
removeSchool,
|
||||
clearAll,
|
||||
isSelected,
|
||||
canAddMore: selectedSchools.length < MAX_SCHOOLS,
|
||||
canAddMore,
|
||||
isInitialized,
|
||||
mutate,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user