diff --git a/client/src/pages/AllPerks.jsx b/client/src/pages/AllPerks.jsx index c35e719..383c91b 100644 --- a/client/src/pages/AllPerks.jsx +++ b/client/src/pages/AllPerks.jsx @@ -3,58 +3,73 @@ import { Link } from 'react-router-dom' import { api } from '../api' export default function AllPerks() { - - + + const [perks, setPerks] = useState([]) const [searchQuery, setSearchQuery] = useState('') - + const [merchantFilter, setMerchantFilter] = useState('') - + const [uniqueMerchants, setUniqueMerchants] = useState([]) - + const [loading, setLoading] = useState(true) - + const [error, setError] = useState('') // ==================== SIDE EFFECTS WITH useEffect HOOK ==================== - /* - TODO: HOOKS TO IMPLEMENT - * useEffect Hook #1: Initial Data Loading - * useEffect Hook #2: Auto-search on Input Change + /* + TODO: HOOKS TO IMPLEMENT + * useEffect Hook #1: Initial Data Loading + * useEffect Hook #2: Auto-search on Input Change + + */ + + // useEffect Hook #1: Initial Data Loading - Load all perks on component mount + useEffect(() => { + loadAllPerks() + }, []) + + // useEffect Hook #2: Auto-search on Input Change - Reload perks when search or filter changes + useEffect(() => { + // Only auto-search if at least one filter has changed (after initial load) + const timer = setTimeout(() => { + loadAllPerks() + }, 500) // 500ms debounce to avoid too many API calls + + return () => clearTimeout(timer) // Cleanup timer on dependency change + }, [searchQuery, merchantFilter]) -*/ - useEffect(() => { // Extract all merchant names from perks array const merchants = perks .map(perk => perk.merchant) // Get merchant from each perk .filter(merchant => merchant && merchant.trim()) // Remove empty/null values - + // Create array of unique merchants using Set // Set automatically removes duplicates, then we convert back to array const unique = [...new Set(merchants)] - + // Update state with unique merchants setUniqueMerchants(unique) - + // This effect depends on [perks], so it re-runs whenever perks changes }, [perks]) // Dependency: re-run when perks array changes - + async function loadAllPerks() { // Reset error state before new request setError('') - + // Show loading indicator setLoading(true) - + try { // Make GET request to /api/perks/all with query parameters const res = await api.get('/perks/all', { @@ -65,15 +80,15 @@ export default function AllPerks() { merchant: merchantFilter.trim() || undefined } }) - + // Update perks state with response data setPerks(res.data.perks) - + } catch (err) { // Handle errors (network failure, server error, etc.) console.error('Failed to load perks:', err) setError(err?.response?.data?.message || 'Failed to load perks') - + } finally { // This block runs whether try succeeds or catch handles error // Always stop loading indicator @@ -83,17 +98,17 @@ export default function AllPerks() { // ==================== EVENT HANDLERS ==================== - + function handleSearch(e) { // Prevent default form submission behavior (page reload) e.preventDefault() - + // Immediately reload perks with current search and filter values // This bypasses the debounce delay for instant results loadAllPerks() } - + function handleReset() { // Reset search and filter states to empty // The useEffect with [searchQuery, merchantFilter] dependencies @@ -102,8 +117,8 @@ export default function AllPerks() { setMerchantFilter('') } - - + + return ( /* TODO: HTML INPUT HANDLERS @@ -111,7 +126,7 @@ export default function AllPerks() { * update state when user selects filter */
- + {/* Page Title */}

All Perks

@@ -123,10 +138,10 @@ export default function AllPerks() { {/* Search and Filter Form */}
- +
- - + +