Skip to content

Commit

Permalink
Merge pull request #105 from cesarhenrq/qa
Browse files Browse the repository at this point in the history
Feat/pagination
  • Loading branch information
cesarhenrq authored Oct 20, 2023
2 parents e197597 + 02579a2 commit 374f06d
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 24 deletions.
94 changes: 94 additions & 0 deletions src/assets/db.icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,96 @@ function Circle({ fill, width, height }: IconProps) {
);
}

function ArrowRight() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="none"
viewBox="0 0 24 24"
transform="rotate(180)"
>
<path
fill="var(--dark-gray)"
fillRule="evenodd"
d="M12.53 5.47a.75.75 0 010 1.06L7.06 12l5.47 5.47a.75.75 0 11-1.06 1.06l-6-6a.75.75 0 010-1.06l6-6a.75.75 0 011.06 0z"
clipRule="evenodd"
/>
</svg>
);
}

function ArrowDoubleRight() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="none"
viewBox="0 0 24 24"
transform="rotate(180)"
>
<path
fill="var(--dark-gray)"
fillRule="evenodd"
d="M12.53 5.47a.75.75 0 010 1.06L7.06 12l5.47 5.47a.75.75 0 11-1.06 1.06l-6-6a.75.75 0 010-1.06l6-6a.75.75 0 011.06 0z"
clipRule="evenodd"
/>
<path
fill="var(--dark-gray)"
fillRule="evenodd"
d="M16.53 5.47a.75.75 0 010 1.06L11.06 12l5.47 5.47a.75.75 0 11-1.06 1.06l-6-6a.75.75 0 010-1.06l6-6a.75.75 0 011.06 0z"
clipRule="evenodd"
/>
</svg>
);
}

const ArrowLeft = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="none"
viewBox="0 0 24 24"
>
<path
fill="var(--dark-gray)"
fillRule="evenodd"
d="M12.53 5.47a.75.75 0 010 1.06L7.06 12l5.47 5.47a.75.75 0 11-1.06 1.06l-6-6a.75.75 0 010-1.06l6-6a.75.75 0 011.06 0z"
clipRule="evenodd"
/>
</svg>
);
};

const ArrowDoubleLeft = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="none"
viewBox="0 0 24 24"
>
<path
fill="var(--dark-gray)"
fillRule="evenodd"
d="M12.53 5.47a.75.75 0 010 1.06L7.06 12l5.47 5.47a.75.75 0 11-1.06 1.06l-6-6a.75.75 0 010-1.06l6-6a.75.75 0 011.06 0z"
clipRule="evenodd"
/>
<path
fill="var(--dark-gray)"
fillRule="evenodd"
d="M16.53 5.47a.75.75 0 010 1.06L11.06 12l5.47 5.47a.75.75 0 11-1.06 1.06l-6-6a.75.75 0 010-1.06l6-6a.75.75 0 011.06 0z"
clipRule="evenodd"
/>
</svg>
);
};

export {
Magnifier,
Location,
Expand All @@ -375,4 +465,8 @@ export {
DownArrow,
SideArrow,
Circle,
ArrowRight,
ArrowLeft,
ArrowDoubleLeft,
ArrowDoubleRight,
};
86 changes: 86 additions & 0 deletions src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';

import * as S from './styles';

import * as I from '@assets/db.icons';

type IProps = {
quantity: number;
currentPage: number;
setCurrentPage: React.Dispatch<React.SetStateAction<number>>;
};

const Pagination = ({ currentPage, setCurrentPage, quantity }: IProps) => {
const pagesToShow = 5; // Número de botões de página a serem exibidos

const previousPage = () => {
if (currentPage > 1) setCurrentPage(currentPage - 1);
};

const nextPage = () => {
if (currentPage < Math.ceil(quantity / pagesToShow)) {
setCurrentPage(currentPage + 1);
}
};

const firstPage = () => {
setCurrentPage(1);
};

const lastPage = () => {
setCurrentPage(Math.ceil(quantity / pagesToShow));
};

const getPageNumbers = () => {
const totalPages = Math.ceil(quantity / pagesToShow);
const pageNumbers = [];
for (let i = 1; i <= totalPages; i++) {
pageNumbers.push(i);
}
return pageNumbers;
};

const pageNumbers = getPageNumbers();

// Calcula o índice inicial para renderizar os botões da página
const startIndex = Math.max(0, currentPage - 3);
const endIndex = Math.min(startIndex + 5, pageNumbers.length);

const visiblePageNumbers = pageNumbers.slice(startIndex, endIndex);

return (
<S.WrapperPagination>
<S.TextPagination>
{`${Math.min(currentPage * 5, quantity)
.toString()
.padStart(2, '0')} de ${quantity.toString().padStart(2, '0')} itens`}
</S.TextPagination>
<S.WrapperPaginationButtons>
<S.IconWrapper onClick={firstPage}>
<I.ArrowDoubleLeft />
</S.IconWrapper>
<S.IconWrapper onClick={previousPage}>
<I.ArrowLeft />
</S.IconWrapper>

{visiblePageNumbers.map(page => (
<S.ButtonPagination
key={`button-pagination-${page}`}
onClick={() => setCurrentPage(page)}
isActive={currentPage === page}
>
{page}
</S.ButtonPagination>
))}
<S.IconWrapper onClick={nextPage}>
<I.ArrowRight />
</S.IconWrapper>
<S.IconWrapper onClick={lastPage}>
<I.ArrowDoubleRight />
</S.IconWrapper>
</S.WrapperPaginationButtons>
</S.WrapperPagination>
);
};

export default Pagination;
1 change: 1 addition & 0 deletions src/components/Pagination/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Pagination';
44 changes: 44 additions & 0 deletions src/components/Pagination/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import styled from 'styled-components';

export const WrapperPagination = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`;

export const TextPagination = styled.span`
font-size: var(--font-size-xsmall);
font-weight: 500;
color: 'var(--dark-gray)';
`;

export const WrapperPaginationButtons = styled.div`
display: flex;
align-items: center;
gap: 5px;
`;

type IButtonPaginationProps = {
isActive: boolean;
};

export const ButtonPagination = styled.button<IButtonPaginationProps>`
border: none;
background-color: ${({ isActive }) =>
isActive ? 'var(--purple-dark-secondary)' : 'transparent'};
cursor: pointer;
font-size: var(--font-size-xsmall);
font-weight: ${({ isActive }) => (isActive ? '500' : '400')};
color: ${({ isActive }) => (isActive ? 'var(--white)' : 'var(--dark-gray)')};
width: 24px;
height: 24px;
border-radius: 8px;
`;
export const IconWrapper = styled.div`
width: 24px;
height: 24px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
`;
4 changes: 3 additions & 1 deletion src/components/VacanciesFound/VacanciesFound.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ describe('VacanciesFound component', () => {
let container: HTMLElement;

beforeEach(() => {
container = render(<VacanciesFound allVacancies={'255'} />).container;
container = render(
<VacanciesFound allVacancies={255} technology="React" />,
).container;
});

it('should be defined', () => {
Expand Down
26 changes: 15 additions & 11 deletions src/components/VacanciesFound/VacanciesFound.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,25 @@ import Text from '@components/Text';
import * as S from './styles';

type props = {
allVacancies: string;
allVacancies: number;
technology: string;
};

const VacanciesFound = ({ allVacancies }: props) => {
const VacanciesFound = ({ allVacancies, technology }: props) => {
return (
<S.Container>
<Text
label={
<p>
Vagas em <b>React</b>
</p>
}
fontSize="large"
fontColor="purple-dark"
/>
{technology && (
<Text
label={
<p>
Vagas em <b>{technology}</b>
</p>
}
fontSize="large"
fontColor="purple-dark"
/>
)}

<Text
label={`${allVacancies} vagas encontradas`}
fontSize="medium"
Expand Down
19 changes: 15 additions & 4 deletions src/hooks/useResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@ import { useState } from 'react';
import httpClient from '@services/httpClient';
import { AxiosError } from 'axios';

const useResource = <T>(resouceUrl: string): [T[], Service<T>] => {
type ResourceResponse<T> = T extends Vacancy
? { vacancies: T[]; count: number }
: T[];

const useResource = <T>(resouceUrl: string): [T[], Service<T>, number] => {
const [resources, setResources] = useState<T[]>([]);
const [count, setCount] = useState<number>(0);

const get = async () => {
try {
const response = await httpClient.get<T[]>(resouceUrl);
setResources(response.data);
const response = await httpClient.get<ResourceResponse<T>>(resouceUrl);

if ('vacancies' in response.data) {
setResources(response.data.vacancies);
setCount(response.data.count);
} else {
setResources(response.data);
}
} catch (error: unknown) {
if (error instanceof AxiosError) {
console.error('Failed to get resource', error);
Expand Down Expand Up @@ -38,7 +49,7 @@ const useResource = <T>(resouceUrl: string): [T[], Service<T>] => {
post,
};

return [resources, service];
return [resources, service, count];
};

export default useResource;
41 changes: 33 additions & 8 deletions src/pages/VacanciesPage/VacanciesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,53 @@
import { useContext } from 'react';
import { useState, useEffect } from 'react';

import SearchBar from '@components/SearchBar';
import CountryTechTrends from '@components/CountryTechTrends';
import CityTechTrendsChart from '@components/CityTechTrendsChart';
import Filter from '@components/Filter';
import VacancyInfoCard from '@components/VacancyInfoCard';
import LoadingSpinner from '@components/LoadingSpinner';

import { queryContext } from '@contexts/query';
import Pagination from '@components/Pagination';

import useResource from '@hooks/useResource';
import useFetchResource from '@hooks/useFetchResource';
import useFilters from '@hooks/useFilters';
import useQuery from '@hooks/useQuery';

import * as S from './styles';
import VacanciesFound from '@components/VacanciesFound';

const VacanciesPage = () => {
const { query } = useContext(queryContext);
const [currentPage, setCurrentPage] = useState(1);

const { filters } = useFilters();

const { query } = useQuery();

const url = query
? `vacancies${query && '?' + query}&page=${currentPage}`
: `vacancies?page=${currentPage}`;

console.log('url', url);

const url = `vacancies${query && '?' + query}`;
const [vacancies, vacancyService, vacanciesCount] = useResource<Vacancy>(url);

const [vacancies, vacancyService] = useResource<Vacancy>(url);
const isLoaded = useFetchResource(vacancyService, [
query,
currentPage,
filters,
]);

const isLoaded = useFetchResource(vacancyService, [query]);
useEffect(() => {
setCurrentPage(1);
}, [query]);

return (
<S.VacanciesPage data-cy="vacancies-page">
<SearchBar />
<VacanciesFound allVacancies={'255'} />
<VacanciesFound
allVacancies={vacanciesCount}
technology={filters.technologies.join(', ')}
/>
<S.Content>
<Filter />
<S.VacancyChartContainer>
Expand All @@ -52,6 +72,11 @@ const VacanciesPage = () => {
),
)}
</S.Vacancies>
<Pagination
quantity={vacanciesCount}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
/>
</S.VacancyChartContainer>
</S.Content>
</S.VacanciesPage>
Expand Down

0 comments on commit 374f06d

Please sign in to comment.