Skip to content

Commit

Permalink
add task solution
Browse files Browse the repository at this point in the history
  • Loading branch information
szymonpachucki committed Sep 29, 2023
1 parent 463f841 commit 43650ea
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 656 deletions.
31 changes: 21 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import { HashRouter, Route } from 'react-router-dom';
import { PeoplePage } from './components/PeoplePage';
import { Navbar } from './components/Navbar';

import './App.scss';

export const App = () => {
return (
<div data-cy="app">
<Navbar />

<div className="section">
<div className="container">
<h1 className="title">Home Page</h1>
<h1 className="title">Page not found</h1>
<PeoplePage />
<HashRouter>
<div data-cy="app">
<Navbar />
<div className="section">
<div className="container">
<Route path="#/people">
<div className="block">
<div className="box table-container">
<PeoplePage />
</div>
</div>
</Route>
<Route path="/">
<h1 className="title">Home Page</h1>
</Route>
<Route>
<h1 className="title">Page not found</h1>
</Route>
</div>
</div>
</div>
</div>
</HashRouter>
);
};
22 changes: 17 additions & 5 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { useState } from 'react';
import { Link } from 'react-router-dom';

export const Navbar = () => {
const [activePage, setActivePage] = useState('home');

return (
<nav
data-cy="nav"
Expand All @@ -8,15 +13,22 @@ export const Navbar = () => {
>
<div className="container">
<div className="navbar-brand">
<a className="navbar-item" href="#/">Home</a>
<Link
className={`navbar-item ${activePage === 'home' ? 'has-background-grey-lighter' : ''}`}
to="#/"
onClick={() => setActivePage('home')}
>
Home
</Link>

<a
<Link
aria-current="page"
className="navbar-item has-background-grey-lighter"
href="#/people"
className={`navbar-item ${activePage === 'people' ? 'has-background-grey-lighter' : ''}`}
to="#/people"
onClick={() => setActivePage('people')}
>
People
</a>
</Link>
</div>
</div>
</nav>
Expand Down
91 changes: 87 additions & 4 deletions src/components/PeopleFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,86 @@
export const PeopleFilters = () => {
/* eslint-disable max-len */
import React, { useState } from 'react';
import { Person } from '../types';

interface Props {
people: Person[];
setVisiblePeople: (visiblePeople: Person[]) => void;
visiblePeople: Person[];
}

export const PeopleFilters: React.FC<Props>
= ({ people, setVisiblePeople, visiblePeople }) => {
// const [sexFilter, setSexFilter] = useState('All');
// const [ceuntryFilter, setCeuntryFilter] = useState('All');
const [value, setValue] = useState('');

const handleSearch: React.ChangeEventHandler<HTMLInputElement> = (event) => {
const inputValue = event.target.value.toLowerCase();

setValue(inputValue);
// eslint-disable-next-line max-len
setVisiblePeople(people.filter((p) => p.name.toLowerCase().includes(inputValue)));
};

const handleSexFilterClick = (filter: string) => {
if (filter === 'M') {
setVisiblePeople(visiblePeople.filter((p) => p.sex === 'm'));
} else if (filter === 'F') {
setVisiblePeople(visiblePeople.filter((p) => p.sex === 'f'));
} else {
setVisiblePeople(people);
}
};

const handleCeuntryFilter = (ceuntry: string) => {
if (ceuntry === '16') {
setVisiblePeople(visiblePeople.filter((p) => p.born >= 1500 && p.born < 1600));
} else if (ceuntry === '17') {
setVisiblePeople(visiblePeople.filter((p) => p.born >= 1600 && p.born < 1700));
} else if (ceuntry === '18') {
setVisiblePeople(visiblePeople.filter((p) => p.born >= 1700 && p.born < 1800));
} else if (ceuntry === '19') {
setVisiblePeople(visiblePeople.filter((p) => p.born >= 1800 && p.born < 1900));
} else if (ceuntry === '20') {
setVisiblePeople(visiblePeople.filter((p) => p.born >= 1900 && p.born < 2000));
} else {
setVisiblePeople(people);
}
};

const handleResetAllFilters = () => {
// setCeuntryFilter('All');
// setSexFilter('All');
setValue('');
setVisiblePeople(people);
};

return (
<nav className="panel">
<p className="panel-heading">Filters</p>

<p className="panel-tabs" data-cy="SexFilter">
<a className="is-active" href="#/people">All</a>
<a className="" href="#/people?sex=m">Male</a>
<a className="" href="#/people?sex=f">Female</a>
<a
className="is-active"
href="#/people"
onClick={handleSexFilterClick('All')}
>
All
</a>
<a
className=""
href="#/people?sex=m"
onClick={handleSexFilterClick('M')}
>
Male
</a>
<a
className=""
href="#/people?sex=f"
onClick={handleSexFilterClick('F')}
>
Female
</a>
</p>

<div className="panel-block">
Expand All @@ -15,6 +89,8 @@ export const PeopleFilters = () => {
data-cy="NameFilter"
type="search"
className="input"
value={value}
onChange={handleSearch}
placeholder="Search"
/>

Expand All @@ -31,6 +107,7 @@ export const PeopleFilters = () => {
data-cy="century"
className="button mr-1"
href="#/people?centuries=16"
onClick={handleCeuntryFilter('16')}
>
16
</a>
Expand All @@ -39,6 +116,7 @@ export const PeopleFilters = () => {
data-cy="century"
className="button mr-1 is-info"
href="#/people?centuries=17"
onClick={handleCeuntryFilter('17')}
>
17
</a>
Expand All @@ -47,6 +125,7 @@ export const PeopleFilters = () => {
data-cy="century"
className="button mr-1 is-info"
href="#/people?centuries=18"
onClick={handleCeuntryFilter('18')}
>
18
</a>
Expand All @@ -55,6 +134,7 @@ export const PeopleFilters = () => {
data-cy="century"
className="button mr-1 is-info"
href="#/people?centuries=19"
onClick={handleCeuntryFilter('19')}
>
19
</a>
Expand All @@ -63,6 +143,7 @@ export const PeopleFilters = () => {
data-cy="century"
className="button mr-1"
href="#/people?centuries=20"
onClick={handleCeuntryFilter('20')}
>
20
</a>
Expand All @@ -73,6 +154,7 @@ export const PeopleFilters = () => {
data-cy="centuryALL"
className="button is-success is-outlined"
href="#/people"
onClick={handleCeuntryFilter('All')}
>
All
</a>
Expand All @@ -84,6 +166,7 @@ export const PeopleFilters = () => {
<a
className="button is-link is-outlined is-fullwidth"
href="#/people"
onClick={handleResetAllFilters}
>
Reset all filters
</a>
Expand Down
59 changes: 45 additions & 14 deletions src/components/PeoplePage.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,62 @@
import { PeopleFilters } from './PeopleFilters';
import React, { useEffect, useState } from 'react';
// import { PeopleFilters } from './PeopleFilters';
import { Loader } from './Loader';
import { PeopleTable } from './PeopleTable';
import { Person } from '../types';
import { getPeople } from '../api';

export const PeoplePage: React.FC = () => {
const [people, setPeople] = useState<Person[]>([]);
const [error, setError] = useState<string | null>(null);
const [visiblePeople, setVisiblePeople] = useState<Person[]>([]);

useEffect(() => {
getPeople()
.then((data) => {
setPeople(data);
if (data.length === 0) {
setError('There are no people on the server');
setVisiblePeople([]);
}
})
.catch(() => {
setError('Something went wrong while fetching data');
});
}, []);

export const PeoplePage = () => {
return (
<>
<h1 className="title">People Page</h1>

<div className="block">
<div className="columns is-desktop is-flex-direction-row-reverse">
<div className="column is-7-tablet is-narrow-desktop">
<PeopleFilters />
{/* <PeopleFilters
people={people}
setVisiblePeople={setVisiblePeople}
visiblePeople={visiblePeople}
/> */}
</div>

<div className="column">
<div className="box table-container">
<Loader />

<p data-cy="peopleLoadingError">Something went wrong</p>

<p data-cy="noPeopleMessage">
There are no people on the server
</p>

<p>There are no people matching the current search criteria</p>

<PeopleTable />
{error ? (
<p data-cy="peopleLoadingError">{error}</p>
) : (
<>
<Loader />
{visiblePeople.length === 0 ? (
<p>
There are no people matching the current search criteria
</p>
) : (
<PeopleTable
visiblePeople={visiblePeople}
people={people}
/>
)}
</>
)}
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 43650ea

Please sign in to comment.