import { useEffect, useState } from 'react' import ItemCard from '../../components/ItemCard/ItemCard.jsx' import { inventoryApi, locationsApi, searchApi, } from '../../api/client.js' import { useAuth } from '../../context/AuthContext.jsx' import { filterInventoryItems, formatAmount, formatDate, getExpiryStatus, } from '../../utils/searchUtils.js' import { getPaginatedResults } from '../../utils/paginationUtils.js' import './SearchPage.css' function ExpiryBadge({ expiryDate }) { const status = getExpiryStatus(expiryDate) const badgeClass = status.status === 'Expired' ? 'expiry-expired' : (status.status === 'Soon' || status.status === 'Today') ? 'expiry-soon' : 'expiry-fresh' return (
{formatDate(expiryDate) || 'No expiry date'}
) } function SearchPage() { const { isAuthenticated } = useAuth() const [searchName, setSearchName] = useState('') const [locationId, setLocationId] = useState('') const [minAmount, setMinAmount] = useState('0') const [maxAmount, setMaxAmount] = useState('999') const [minExpiryDate, setMinExpiryDate] = useState('') const [maxExpiryDate, setMaxExpiryDate] = useState('') const [currentPage, setCurrentPage] = useState(1) const [pageSize, setPageSize] = useState(15) const [locations, setLocations] = useState([]) const [matchingLocations, setMatchingLocations] = useState([]) const [results, setResults] = useState([]) const [loading, setLoading] = useState(false) const [errorMessage, setErrorMessage] = useState('') useEffect(() => { let cancelled = false async function loadInitialData() { if (!isAuthenticated) { setLocations([]) setMatchingLocations([]) setResults([]) setErrorMessage('') return } setLoading(true) setErrorMessage('') try { const [nextLocations, nextItems] = await Promise.all([ locationsApi.getLocations(), inventoryApi.getInventoryItems(), ]) if (!cancelled) { setLocations(nextLocations) setMatchingLocations([]) setResults(nextItems) } } catch (error) { if (!cancelled) { setErrorMessage(error.message) } } finally { if (!cancelled) { setLoading(false) } } } loadInitialData() return () => { cancelled = true } }, [isAuthenticated]) async function performSearch() { const parsedMinAmount = minAmount === '' ? 0 : Number(minAmount) const parsedMaxAmount = maxAmount === '' ? Infinity : Number(maxAmount) const safeMinAmount = Number.isFinite(parsedMinAmount) ? parsedMinAmount : 0 const safeMaxAmount = maxAmount === '' || !Number.isFinite(parsedMaxAmount) ? Infinity : parsedMaxAmount if (minExpiryDate && maxExpiryDate && minExpiryDate > maxExpiryDate) { alert('Start date cannot be after end date') return } if (safeMinAmount > safeMaxAmount) { alert('Minimum amount cannot be greater than maximum amount') return } setLoading(true) setErrorMessage('') try { const trimmedQuery = searchName.trim() const [nextItems, nextMatchingLocations] = trimmedQuery ? await Promise.all([ searchApi.searchItems(trimmedQuery), searchApi.searchLocations(trimmedQuery), ]) : await Promise.all([ inventoryApi.getInventoryItems(), Promise.resolve([]), ]) const filteredItems = filterInventoryItems(nextItems, { locationId, minAmount: safeMinAmount, maxAmount: safeMaxAmount, minExpiryDate, maxExpiryDate, }) setCurrentPage(1) setResults(filteredItems) setMatchingLocations(nextMatchingLocations) } catch (error) { setErrorMessage(error.message) } finally { setLoading(false) } } async function resetForm() { setSearchName('') setLocationId('') setMinAmount('0') setMaxAmount('999') setMinExpiryDate('') setMaxExpiryDate('') setCurrentPage(1) setPageSize(15) setMatchingLocations([]) setErrorMessage('') if (!isAuthenticated) { setResults([]) return } setLoading(true) try { const [nextLocations, nextItems] = await Promise.all([ locationsApi.getLocations(), inventoryApi.getInventoryItems(), ]) setLocations(nextLocations) setResults(nextItems) } catch (error) { setErrorMessage(error.message) } finally { setLoading(false) } } const paginationData = getPaginatedResults(results, currentPage, pageSize) return ( <>

Search Inventory


{!isAuthenticated ? (
Sign in on the dashboard before using the protected item and location search endpoints.
) : ( <> {errorMessage &&
{errorMessage}
} {loading &&
Searching the API...
}
setSearchName(event.target.value)} onKeyDown={event => { if (event.key === 'Enter') { event.preventDefault() performSearch() } }} />
setMinAmount(event.target.value)} />
setMaxAmount(event.target.value)} />
setMinExpiryDate(event.target.value)} />
setMaxExpiryDate(event.target.value)} />
{searchName.trim() && (

Matching Locations

{matchingLocations.length === 0 ? (
No locations matched that query.
) : (
{matchingLocations.map(location => (
{location.name}
{location.description || 'No description provided.'}
))}
)}
)}
{results.length === 0 ? 'No results' : `Found ${results.length} item${results.length !== 1 ? 's' : ''} (showing ${paginationData.startIndex}-${paginationData.endIndex})` }
Page {paginationData.currentPage} of {paginationData.totalPages}
{results.length === 0 ? (
No items found matching your search criteria.
) : (
{paginationData.items.map(item => ( ))}
)}
)} ) } export default SearchPage