Skip to content

Commit

Permalink
ADD: Filter logic
Browse files Browse the repository at this point in the history
  • Loading branch information
GGalina committed May 14, 2024
1 parent ffe0fbe commit 47b7791
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 157 deletions.
23 changes: 17 additions & 6 deletions src/components/Filter/Filter.jsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
import React, { useEffect,useState, useCallback } from 'react';
import React, { useState } from 'react';
import { useColor } from '../../context/ColorContext';
import { Label, CustomSelect, FilterContainer, FilterItemWrapper } from './Filter.styled';

export const Filter = ({ onFilterChange }) => {
const { selectedColor } = useColor();
const [selectedLanguage, setSelectedLanguage] = useState('');
const [selectedLevel, setSelectedLevel] = useState('');
const [selectedPrice, setSelectedPrice] = useState('');
const [selectedLanguage, setSelectedLanguage] = useState('');

const handleLanguageChange = (selectedOption) => {
setSelectedLanguage(selectedOption);
onFilterChange({ language: selectedOption.value, level: selectedLevel, price: selectedPrice });
onFilterChange({
language: selectedOption.value,
level: selectedLevel.value,
price: selectedPrice.value
});
};

const handleLevelChange = (selectedOption) => {
setSelectedLevel(selectedOption);
onFilterChange({ language: selectedLanguage, level: selectedOption.value, price: selectedPrice });
onFilterChange({
language: selectedLanguage.value,
level: selectedOption.value,
price: selectedPrice.value
});
};

const handlePriceChange = (selectedOption) => {
setSelectedPrice(selectedOption);
onFilterChange({ language: selectedLanguage, level: selectedLevel, price: selectedOption.value });
console.log(selectedOption)
onFilterChange({
language: selectedLanguage.value,
level: selectedLevel.value,
price: selectedOption.value
});
};

const languageOptions = [
Expand Down
157 changes: 65 additions & 92 deletions src/components/Teachers/Teachers.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ import { useEffect, useState } from 'react';
import { Loader } from '../Loader/Loader';
import { useMediaQuery } from 'react-responsive';
import { useColor } from '../../context/ColorContext';
import { fetchTeachersAPI, fetchFilteredTeachersAPI } from '../../services/firebaseAPI';
import { fetchTeachersAPI, fetchAllTeachersAPI } from '../../services/firebaseAPI';
import { Filter } from '../Filter/Filter';
import { TeachersList } from '../TeachersList/TeachersList';
import {
LoadMore,
TeachersContainer
NoResults,
TeachersContainer,
} from './Teachers.styled';

export const Teachers = () => {
const batchSize = 4;
const [page, setPage] = useState(1);
const { selectedColor } = useColor();
const [teachers, setTeachers] = useState([]);
const [hasMore, setHasMore] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [lastFetched, setLastFetched] = useState(null);
const isDesktop = useMediaQuery({ query: '(min-width: 1280px)' });

const [filteredTeachers, setFilteredTeachers] = useState([]);
const [filters, setFilters] = useState({
language: '',
level: '',
Expand Down Expand Up @@ -63,7 +66,6 @@ export const Teachers = () => {
setTeachers((prevTeachers) => [...prevTeachers, ...newTeachers]);
setLastFetched(newTeachers[newTeachers.length - 1].id);
} else {
// No more teachers to load
setHasMore(false);
}
} catch (error) {
Expand All @@ -72,101 +74,69 @@ export const Teachers = () => {
setIsLoading(false);
}
};

const handleFilterChange = async (filters) => {
try {
setPage(1);
setIsLoading(true);
setFilters(filters);
setTeachers([]); // Reset teachers array
setHasMore(true); // Reset hasMore flag
setLastFetched(null); // Reset lastFetched value

const allTeachers = await fetchAllTeachersAPI();

const filteredTeachers = allTeachers.filter((teacher) => {
let match = true;

if (filters.language !== undefined && !teacher.languages.includes(filters.language)) {
match = false;
}

if (filters.level !== undefined && filters.level !== '' && !teacher.levels.includes(filters.level)) {
match = false;
}

if (filters.price !== undefined && filters.price !== '') {
const priceRange = parseInt(filters.price);
const teacherPrice = parseInt(teacher.price_per_hour);

if (teacherPrice < priceRange || teacherPrice >= priceRange + 10) {
match = false;
}
}

const handleFilterChange = async (newFilters) => {
try {
setFilters(newFilters);
setTeachers([]); // Reset teachers array
setHasMore(true); // Reset hasMore flag
setLastFetched(null); // Reset lastFetched value

const filteredTeachers = await fetchFilteredTeachersAPI(4, newFilters);

if (filteredTeachers.length > 0) {
setTeachers(filteredTeachers);
setLastFetched(filteredTeachers[filteredTeachers.length - 1].id);
} else {
setHasMore(false);
}
} catch (error) {
console.error('Error handling filter change:', error);
// Handle error as needed
}
};


// const handleFilterChange = async (newFilters) => {
// setFilters(newFilters);
// setTeachers([]); // Reset teachers array
// setHasMore(true); // Reset hasMore flag
// setLastFetched(null); // Reset lastFetched value

// let allTeachers;
// // Fetch initial set of data
// allTeachers = await fetchFilteredTeachersAPI(null, 4); // Fetch a larger set initially

// // Apply first filter
// if (newFilters.language) {
// allTeachers = allTeachers.filter((teacher) => teacher.languages.includes(newFilters.language));
// }

// // Apply second filter
// if (newFilters.level) {
// allTeachers = allTeachers.filter((teacher) => teacher.levels.includes(newFilters.level));
// }

// if (newFilters.price) {
// // Define price categories
// const priceCategories = {
// '10': [0, 19],
// '20': [20, 29],
// '30': [30, 39],
// '40': [40, 49]
// // Add more categories as needed
// };

// // Filter based on price categories
// const [minPrice, maxPrice] = priceCategories[newFilters.price];
// allTeachers = allTeachers.filter(
// (teacher) => teacher.price_per_hour >= minPrice && teacher.price_per_hour <= maxPrice
// );
// }

// // Update state with the filtered data
// setTeachers((prevTeachers) => [...prevTeachers, ...allTeachers.slice(0, 4)]);
// setLastFetched(allTeachers[allTeachers.length - 1]?.id);
// }




return match;
});

const loadMoreFilteredTeachers = async () => {
try {
setIsLoading(true);
setFilteredTeachers(filteredTeachers);

if (lastFetched === null || lastFetched === undefined) {
console.error('Error fetching teachers: lastFetched is null or undefined');
return;
if (filteredTeachers.length > 0 && filteredTeachers.length > 4) {
setTeachers(filteredTeachers.slice(0, batchSize));
} else if (filteredTeachers.length > 0 && filteredTeachers.length <= 4) {
setTeachers(filteredTeachers);
setHasMore(false);
} else if (filteredTeachers.length === 0) {
setHasMore(false);
}
} catch (error) {
console.error('Error handling filter change:', error);
} finally {
setIsLoading(false);
}
};

const loadMoreFilteredTeachers = () => {
const nextPage = page + 1;

const newTeachers = await fetchTeachersAPI(teachers[teachers.length - 1].id);

if (newTeachers.length > 0) {
setTeachers((prevTeachers) => [...prevTeachers, ...newTeachers]);
setLastFetched(newTeachers[newTeachers.length - 1].id);
if (filteredTeachers.length > nextPage * batchSize) {
setTeachers(filteredTeachers.slice(0, nextPage * batchSize));
setPage(nextPage);
} else {
// No more teachers to load
setHasMore(false);
setHasMore(false);
}
} catch (error) {
console.error('Error fetching teachers:', error);
} finally {
setIsLoading(false);
}
};


};

return (
<TeachersContainer>
<Filter onFilterChange={handleFilterChange} />
Expand All @@ -177,6 +147,9 @@ const loadMoreFilteredTeachers = async () => {
</LoadMore>
)}
{isLoading && <Loader />}
{filteredTeachers.length === 0 && teachers.length === 0 && (
<NoResults>Sorry, no teachers found matching the selected criteria</NoResults>
)}
</TeachersContainer>
);
};
10 changes: 10 additions & 0 deletions src/components/Teachers/Teachers.styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import styled from 'styled-components';

export const TeachersContainer = styled.div`
width: 100%;
min-height: 100vh;
margin-right: auto;
margin-left: auto;
background-color: #EEEEEE;
Expand Down Expand Up @@ -48,4 +49,13 @@ export const LoadMore = styled.button`
&:hover {
transform: scale(1.1);
}
`;

export const NoResults = styled.p`
font-family: 'Roboto-Bold', sans-serif;
font-size: 24px;
line-height: 28px;
color: #121417;
text-align: center;
padding-top: 30px;
`;
67 changes: 8 additions & 59 deletions src/services/firebaseAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { firebaseConfig } from './firebaseConfig';
import {
getDatabase, ref, get, set,
query, orderByChild, orderByKey,
startAfter, limitToFirst, equalTo
startAfter, limitToFirst, equalTo,
} from 'firebase/database';

// Initialize Firebase
Expand Down Expand Up @@ -211,76 +211,25 @@ export const getFavoriteTeachersAPI = async () => {
}
};

//----------------------------------------------Filters-------------------------------------------












export const fetchFilteredTeachersAPI = async (batchSize = 4, filters = {}, lastFetched) => {
export const fetchAllTeachersAPI = async () => {
try {
const teachersRef = ref(db, 'teachers');
let teachersQuery = query(teachersRef, orderByChild('id'));

const applyLanguageFilter = (query, language) => query(teachersQuery, equalTo('languages', language));
const applyLevelFilter = (query, level) => query(teachersQuery, equalTo('levels', level));
// Add more helper functions as needed for different filters

// Apply pagination logic
if (lastFetched) {
teachersQuery = query(teachersQuery, startAfter(lastFetched));
}
const teachersQuery = query(teachersRef, orderByChild('id'));

teachersQuery = query(teachersQuery, limitToFirst(batchSize));

// Apply additional filters based on conditions
switch (true) {
case filters.language && filters.level:
// Apply language and level filters
teachersQuery = applyLanguageFilter(teachersQuery, filters.language);
teachersQuery = applyLevelFilter(teachersQuery, filters.level);
break;

case filters.language:
// Apply language filter
teachersQuery = applyLanguageFilter(teachersQuery, filters.language);
break;

case filters.level:
// Apply level filter
teachersQuery = applyLevelFilter(teachersQuery, filters.level);
break;

// Add more cases as needed for different combinations

default:
// No specific combination, apply default logic
}

// Fetch the data based on the modified query
const snapshot = await get(teachersQuery);

// Process the snapshot and get the results
const response = [];

snapshot.forEach((childSnapshot) => {
const data = childSnapshot.val();
response.push({ id: childSnapshot.key, ...data });
const id = data.id;
response.push({ id, ...data });
});

console.log('response', response);
return response;
} catch (error) {
console.log('Error fetching teachers:', error);
toast.error('Error fetching teachers:');
throw new Error('Error fetching teachers:', error);
}
};



};

0 comments on commit 47b7791

Please sign in to comment.