├── README.md
├── src
├── index.js
├── components
│ ├── Cards
│ │ ├── Cards.module.css
│ │ ├── index.jsx
│ │ └── Card
│ │ │ ├── index.jsx
│ │ │ └── Card.module.css
│ └── Search
│ │ ├── index.jsx
│ │ └── Search.module.css
├── containers
│ ├── App.module.css
│ └── App.js
├── constants
│ └── cards-constant.js
└── index.css
├── .gitignore
├── public
├── assets
│ └── icons
│ │ ├── search.svg
│ │ ├── property.svg
│ │ ├── bike.svg
│ │ ├── cars.svg
│ │ ├── economy.svg
│ │ ├── ticket.svg
│ │ └── boat.svg
└── index.html
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 | ## preview
2 |
3 | 
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './containers/App';
4 | import './index.css';
5 |
6 | ReactDOM.render(, document.getElementById('root'));
7 |
--------------------------------------------------------------------------------
/src/components/Cards/Cards.module.css:
--------------------------------------------------------------------------------
1 | .Cards {
2 | display: grid;
3 | width: 100%;
4 | grid-template-columns: repeat(2, 1fr);
5 | grid-template-rows: 1fr;
6 | justify-content: space-between;
7 | margin-top: 3rem;
8 | gap: 1rem;
9 | }
10 |
11 | @media (min-width: 768px) {
12 | .Cards {
13 | grid-template-columns: repeat(3, 1fr);
14 |
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/containers/App.module.css:
--------------------------------------------------------------------------------
1 | .App {
2 | background-color: var(--search_background);
3 | padding: 4rem 2rem;
4 | width: 22rem;
5 | border-radius: 1rem;
6 | }
7 |
8 | @media (min-width: 499px) {
9 | .App {
10 | width: 27rem;
11 | }
12 | }
13 |
14 | @media (min-width: 768px) {
15 | .App {
16 | width: 35rem;
17 | padding: 4rem;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/components/Cards/index.jsx:
--------------------------------------------------------------------------------
1 | import Card from './Card';
2 | import classes from './Cards.module.css';
3 |
4 | const Cards = ({ cards }) => {
5 | let card = cards.map(card => (
6 |
12 | ));
13 |
14 | return {card};
15 | };
16 |
17 | export default Cards;
18 |
--------------------------------------------------------------------------------
/public/assets/icons/search.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/constants/cards-constant.js:
--------------------------------------------------------------------------------
1 | export const CARDS_DETAILS = [
2 | { title: 'Boat', image: 'assets/icons/boat.svg', themeColor: '#ff8faa' },
3 | { title: 'Cars', image: 'assets/icons/cars.svg', themeColor: '#8fbcff' },
4 | { title: 'Bike', image: 'assets/icons/bike.svg', themeColor: '#a6cd74' },
5 | {
6 | title: 'Property',
7 | image: 'assets/icons/property.svg',
8 | themeColor: '#a68fff'
9 | },
10 | { title: 'Ticket', image: 'assets/icons/ticket.svg', themeColor: '#fcc18a' },
11 | { title: 'Economy', image: 'assets/icons/economy.svg', themeColor: '#6edddd' }
12 | ];
13 |
--------------------------------------------------------------------------------
/src/components/Cards/Card/index.jsx:
--------------------------------------------------------------------------------
1 | import classes from './Card.module.css';
2 |
3 | const Card = props => {
4 | const { title, image, color } = props;
5 | return (
6 |
7 |
8 |
9 |

10 |
{title}
11 |
12 |
13 | );
14 | };
15 |
16 | export default Card;
17 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | outline: 0;
4 | margin: 0;
5 | }
6 |
7 | :root {
8 | --main_background: #f2f0ff;
9 | --search_background: #ffffff;
10 | --economy_color: #6edddd;
11 | --ticket_color: #fcc18a;
12 | --bike_color: #a6cd74;
13 | --property_color: #a68fff;
14 | --cars_color: #8fbcff;
15 | --boat_color: #ff8faa;
16 | --search_color: #2b417b;
17 | }
18 |
19 | body {
20 | margin: 0;
21 | padding: 0;
22 | height: 100vh;
23 | background: var(--main_background);
24 | display: flex;
25 | justify-content: center;
26 | align-items: center;
27 | font-family: 'Open Sans', sans-serif;
28 | }
29 |
--------------------------------------------------------------------------------
/src/components/Cards/Card/Card.module.css:
--------------------------------------------------------------------------------
1 | .Card {
2 | position: relative;
3 | border-radius: 0.6rem;
4 | text-align: center;
5 | display: flex;
6 | align-items: center;
7 | flex-direction: column;
8 | }
9 | .Card:hover {
10 | box-shadow: 1px 1px 15px inherit;
11 | }
12 | .CardDivider {
13 | width: 65%;
14 | height: 10px;
15 | border-bottom-left-radius: 5px;
16 | border-bottom-right-radius: 5px;
17 | }
18 | .CardImage {
19 | max-height: 3rem;
20 | margin-bottom: 0.5rem;
21 | }
22 |
23 | .CardTitle {
24 | color: var(--search_color);
25 | text-align: center;
26 | font-weight: 500;
27 | }
28 |
29 | .CardDetails {
30 | display: flex;
31 | flex-direction: column;
32 | padding: 1.5rem 1rem;
33 | }
34 |
--------------------------------------------------------------------------------
/src/components/Search/index.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import classes from './Search.module.css';
3 |
4 | const Search = ({ onSearch }) => {
5 | const [inputValue, setInputValue] = useState('');
6 |
7 | const filterHandler = e => {
8 | setInputValue(e.target.value);
9 | onSearch(e);
10 | };
11 | return (
12 |
13 |
filterHandler(e)}
16 | value={inputValue}
17 | className={classes.SearchInput}
18 | placeholder='Search'
19 | />
20 |

25 |
26 | );
27 | };
28 |
29 | export default Search;
30 |
--------------------------------------------------------------------------------
/src/components/Search/Search.module.css:
--------------------------------------------------------------------------------
1 | .Search {
2 | border-bottom: 1px solid var(--main_background);
3 | position: relative;
4 | padding-bottom: 0.3rem;
5 | }
6 |
7 | .SearchInput {
8 | border: 0;
9 | padding: 0.8rem 2rem;
10 | color: var(--search_color);
11 | width: 100%;
12 | }
13 |
14 | .SearchInput::placeholder {
15 | color: var(--search_color);
16 | }
17 |
18 | .SearchIcon {
19 | max-width: 1.5rem;
20 | position: absolute;
21 | left: 0rem;
22 | top: 0.5rem;
23 | }
24 |
25 | @media (min-width: 768px) {
26 | .SearchInput {
27 | border: 0;
28 | padding: 0.8rem 2.5rem;
29 | color: var(--search_color);
30 | width: 100%;
31 | font-size: 1rem;
32 | }
33 |
34 |
35 | .SearchIcon {
36 | max-width: 1.8rem;
37 | position: absolute;
38 | left: 0rem;
39 | top: 0.4rem;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/public/assets/icons/property.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/containers/App.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import Cards from '../components/Cards';
3 | import Search from '../components/Search';
4 | import { CARDS_DETAILS } from '../constants/cards-constant';
5 | import classes from './App.module.css';
6 |
7 | function App() {
8 | const [cards, setCards] = useState([...CARDS_DETAILS]);
9 |
10 | const searchHandler = ({ target }) => {
11 | const cards = [...CARDS_DETAILS];
12 | const filtredCards = cards.filter(card => {
13 | return card.title.toLowerCase().includes(target.value.toLowerCase());
14 | });
15 |
16 | setCards(prevCards => {
17 | prevCards.length = 0;
18 | return filtredCards;
19 | });
20 | };
21 | return (
22 |
23 |
24 |
25 |
26 | );
27 | }
28 |
29 | export default App;
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "search-ui",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.11.4",
7 | "@testing-library/react": "^11.1.0",
8 | "@testing-library/user-event": "^12.1.10",
9 | "react": "^17.0.2",
10 | "react-dom": "^17.0.2",
11 | "react-scripts": "4.0.3",
12 | "web-vitals": "^1.0.1"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/public/assets/icons/bike.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/assets/icons/cars.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/assets/icons/economy.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
16 |
31 | Search-UI
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/public/assets/icons/ticket.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/assets/icons/boat.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------