Skip to content

Commit

Permalink
ADD: Backend teachers, Teachers cards
Browse files Browse the repository at this point in the history
  • Loading branch information
GGalina committed Feb 15, 2024
1 parent 2f6ddb3 commit e88152b
Show file tree
Hide file tree
Showing 9 changed files with 501 additions and 32 deletions.
4 changes: 4 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Layout } from './components/Layout/Layout';

const HomePage = lazy(() => import('./pages/HomePage').then(module => ({ default: module.HomePage })));
const TeachersPage = lazy(() => import('./pages/TeachersPage').then(module => ({ default: module.TeachersPage })));
const FavoritesPage = lazy(() => import('./pages/FavoritesPage').then(module => ({ default: module.FavoritesPage })));

const App = () => {

Expand All @@ -15,6 +16,9 @@ const App = () => {
<Route path="/teachers" element={<Layout />}>
<Route index element={<TeachersPage />} />
</Route>
<Route path="/favorites" element={<Layout />}>
<Route index element={<FavoritesPage />} />
</Route>
</Routes>
);
};
Expand Down
8 changes: 8 additions & 0 deletions src/components/Filter/Filter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const Filter = () => {

return (
<>

</>
);
};
23 changes: 23 additions & 0 deletions src/components/Filter/Filter.styled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import styled from 'styled-components';

export const HomeContainer = styled.div`
width: 100%;
margin-left: auto;
margin-right: auto;
@media (min-width: 768px) {
width: 768px;
}
@media (min-width: 1280px) {
width: 1280px;
padding: 0 64px;
}
`;

export const HeroWrapper = styled.div`
width: 100%;
display: flex;
justify-content: center;
gap: 24px;
`;
44 changes: 21 additions & 23 deletions src/components/Layout/Layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,28 @@ const RegistrationModal = lazy(() => import('../RegistrationModal/RegistrationMo

export const Layout = ({ children }) => (
<AuthProvider>

<ColorProvider>
<ColorProvider>
<ModalProvider>
<Header />
<Suspense fallback={<Loader />}>
{children}
<Outlet />
<ModalRenderer />

</Suspense>
</ModalProvider>
</ColorProvider>
<ToastContainer
position="top-right"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme="light"
/>
<Header />
<Suspense fallback={<Loader />}>
{children}
<Outlet />
<ModalRenderer />
</Suspense>
</ModalProvider>
</ColorProvider>
<ToastContainer
position="top-right"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme="light"
/>
</AuthProvider>
);

Expand Down
164 changes: 164 additions & 0 deletions src/components/Teachers/Teachers.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import React, { useEffect, useState } from 'react';
import { IoBookOutline } from "react-icons/io5";
import { FaStar, FaRegHeart } from "react-icons/fa";
import { fetchTeachers } from '../../services/firebaseAPI';
import { useMediaQuery } from 'react-responsive';
import { Loader } from '../Loader/Loader';
import {
TeachersContainer,
TeacherCardsWrapper,
ImgContainer,
ProfilePhoto,
TopInfoContainer,
MainInfoContainer,
LessonsContainer,
Text, Name, TextWrapper,
Accent, GreyAccent,
LessonsWrapper,
TeacherCard, UnderlinedText,
NameContainer, ReadMoreBtn,
LoadMore
} from './Teachers.styled';

export const Teachers = () => {
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 loadMoreTeachers = async () => {
try {
setIsLoading(true);

if (lastFetched === null || lastFetched === undefined) {
console.error('Error fetching teachers: lastFetched is null or undefined');
return;
}

const newTeachers = await fetchTeachers(lastFetched);

if (newTeachers.length > 0) {
setTeachers((prevTeachers) => [...prevTeachers, ...newTeachers]);
setLastFetched(newTeachers[newTeachers.length - 1].id);
} else {
setHasMore(false);
}
} catch (error) {
throw new Error(error);
} finally {
setIsLoading(false);
}
};


useEffect(() => {
const fetchInitialTeachers = async () => {
try {
setIsLoading(true);
const initialTeachers = await fetchTeachers(null);
setTeachers(initialTeachers);

if (initialTeachers.length > 0) {
const lastFetchedValue = initialTeachers[initialTeachers.length - 1].id;
setLastFetched(lastFetchedValue);
} else {
setHasMore(false);
}
} catch (error) {
throw new Error(error)
} finally {
setIsLoading(false);
}
};
fetchInitialTeachers();
}, []);

return (
<TeachersContainer>
<TeacherCardsWrapper>
{teachers.map((teacher) => (
<TeacherCard key={teacher.id}>
<ImgContainer>
<ProfilePhoto src={teacher.avatar_url} alt="User profile photo"/>
</ImgContainer>
<TopInfoContainer>
<LessonsWrapper>
<LessonsContainer>
<IoBookOutline stroke='#121417' width='16' height='16'/>
<Text>Lessons online</Text>
</LessonsContainer>
<LessonsContainer>
<Text>Lessons done: {teacher.lessons_done}</Text>
</LessonsContainer>
<LessonsContainer>
<FaStar fill='#FFC531'/>
<Text>Rating: {teacher.rating}</Text>
</LessonsContainer>
<LessonsContainer>
<Text>Price / 1 hour: <Accent>{teacher.price_per_hour}$</Accent></Text>
</LessonsContainer>
</LessonsWrapper>
<FaRegHeart width='26' height='26' fill='#121417'/>
</TopInfoContainer>
{!isDesktop &&
<>
<NameContainer>
<GreyAccent>Languages</GreyAccent>
<Name>{teacher.name + ' ' + teacher.surname}</Name>
</NameContainer>
<MainInfoContainer>
<TextWrapper>
<GreyAccent>Speaks: </GreyAccent>
<UnderlinedText>{teacher.languages.join(', ')}</UnderlinedText>
</TextWrapper>
<TextWrapper>
<GreyAccent>Lesson Info: </GreyAccent>
<Text>{teacher.lesson_info}</Text>
</TextWrapper>
<TextWrapper>
<GreyAccent>Conditions: </GreyAccent>
<Text>{teacher.conditions.join(' ')}</Text>
</TextWrapper>
<ReadMoreBtn>Read More</ReadMoreBtn>
</MainInfoContainer>
</>
}

{isDesktop &&
<>
<MainInfoContainer>
<NameContainer>
<GreyAccent>Languages</GreyAccent>
<Name>{teacher.name + ' ' + teacher.surname}</Name>
</NameContainer>
<TextWrapper>
<GreyAccent>Speaks: </GreyAccent>
<UnderlinedText>{teacher.languages.join(', ')}</UnderlinedText>
</TextWrapper>
<TextWrapper>
<GreyAccent>Lesson Info: </GreyAccent>
<Text>{teacher.lesson_info}</Text>
</TextWrapper>
<TextWrapper>
<GreyAccent>Conditions: </GreyAccent>
<Text>{teacher.conditions.join(' ')}</Text>
</TextWrapper>
<ReadMoreBtn>Read More</ReadMoreBtn>
</MainInfoContainer>
</>
}
</TeacherCard>
))}
</TeacherCardsWrapper>

{hasMore && (
<LoadMore type='button' onClick={loadMoreTeachers}>
Load more
</LoadMore>
)}

{isLoading && <Loader/>}
</TeachersContainer>
);
};
Loading

0 comments on commit e88152b

Please sign in to comment.