fitst commit
This commit is contained in:
91
components/ui/FilterContext.tsx
Normal file
91
components/ui/FilterContext.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import { FilterData } from '@/types';
|
||||
import { cities, companies, countries, industries, states } from '@/types/data';
|
||||
import createContextHook from '@nkzw/create-context-hook';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
export const [FilterProvider, useFilter] = createContextHook(() => {
|
||||
const [filterData, setFilterDataState] = useState<FilterData>({
|
||||
country: { name: '', iso: 'all' },
|
||||
state: { name: '', iso: 'all' },
|
||||
city: { name: '', iso: 'all' },
|
||||
industries: [],
|
||||
});
|
||||
|
||||
const [step, setStep] = useState<'filter' | 'items'>('filter');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const itemsPerPage = 10;
|
||||
|
||||
const setFilterData = (updates: Partial<FilterData>) => {
|
||||
setFilterDataState((prev) => ({ ...prev, ...updates }));
|
||||
};
|
||||
|
||||
const availableStates = useMemo(() => {
|
||||
if (filterData.country.iso === 'all' || !filterData.country.iso) {
|
||||
return states;
|
||||
}
|
||||
return states.filter((s) => s.country_iso === filterData.country.iso);
|
||||
}, [filterData.country.iso]);
|
||||
|
||||
const availableCities = useMemo(() => {
|
||||
if (filterData.state.iso === 'all' || !filterData.state.iso) {
|
||||
return cities;
|
||||
}
|
||||
return cities.filter((c) => c.state_iso === filterData.state.iso);
|
||||
}, [filterData.state.iso]);
|
||||
|
||||
const filteredCompanies = useMemo(() => {
|
||||
return companies.filter((company) => {
|
||||
const countryMatch =
|
||||
!filterData.country.iso ||
|
||||
filterData.country.iso === 'all' ||
|
||||
company.country === filterData.country.iso;
|
||||
const industryMatch =
|
||||
filterData.industries.length === 0 ||
|
||||
(company.industry && filterData.industries.includes(company.industry));
|
||||
return countryMatch && industryMatch;
|
||||
});
|
||||
}, [filterData]);
|
||||
|
||||
const totalItems = filteredCompanies.length;
|
||||
const totalPages = Math.ceil(totalItems / itemsPerPage);
|
||||
|
||||
const paginatedData = useMemo(() => {
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
const endIndex = startIndex + itemsPerPage;
|
||||
return filteredCompanies.slice(startIndex, endIndex);
|
||||
}, [filteredCompanies, currentPage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (filterData.country.iso !== 'all') {
|
||||
const hasState = availableStates.some((s) => s.iso === filterData.state.iso);
|
||||
if (!hasState) {
|
||||
setFilterData({ state: { name: '', iso: 'all' }, city: { name: '', iso: 'all' } });
|
||||
}
|
||||
}
|
||||
}, [filterData.country.iso, availableStates]);
|
||||
|
||||
useEffect(() => {
|
||||
if (filterData.state.iso !== 'all') {
|
||||
const hasCity = availableCities.some((c) => c.iso === filterData.city.iso);
|
||||
if (!hasCity) {
|
||||
setFilterData({ city: { name: '', iso: 'all' } });
|
||||
}
|
||||
}
|
||||
}, [filterData.state.iso, availableCities]);
|
||||
|
||||
return {
|
||||
filterData,
|
||||
setFilterData,
|
||||
countries,
|
||||
states: availableStates,
|
||||
cities: availableCities,
|
||||
industries,
|
||||
totalItems,
|
||||
step,
|
||||
setStep,
|
||||
allData: paginatedData,
|
||||
currentPage,
|
||||
setCurrentPage,
|
||||
totalPages,
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user