Files
school_compare/nextjs-app/hooks/useComparison.ts

88 lines
2.2 KiB
TypeScript
Raw Normal View History

/**
* Custom hook for managing school comparison state
*/
'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;
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]);
// Fetch comparison data for selected schools
const urns = selectedSchools.map((s) => s.urn).join(',');
const { data, error, isLoading, mutate } = useSWR<ComparisonResponse>(
selectedSchools.length > 0 ? `/compare?urns=${urns}` : null,
fetcher,
{
revalidateOnFocus: false,
dedupingInterval: 10000, // 10 seconds
}
);
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,
isLoading,
error,
addSchool,
removeSchool,
clearAll,
isSelected,
canAddMore: selectedSchools.length < MAX_SCHOOLS,
mutate,
};
}