Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
31 changes: 31 additions & 0 deletions App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import './App.css';
import { Header } from "./components/Header/Header";
import { Home } from "./components/Home/Home";
import { Footer } from "./components/Footer/Footer";
import { Catalog } from './components/Catalog/Catalog';
import {BrowserRouter, Switch, Route,} from "react-router-dom";
import { Filter } from "./components/Filter/Filter";

function App() {
return (
<BrowserRouter>
<div>
<Switch>
<Route exact path="/">
<Header/>
<Home/>
</Route>
<Route path="/catalog">
<Catalog/>
</Route>
<Route path="/cart">
<Header/>
</Route>
</Switch>
<Footer/>
</div>
</BrowserRouter>
);
}

export default App;
8 changes: 8 additions & 0 deletions App.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
# React_Labs
# React.js: Item page
## Description: Continue work on your React App by adding a page for your
Item (see the link to wireframe of Item page above). Also, now, you have to
make all your previous pages (Home & Catalog) more interactive.
### Variants - (products that you are ‘selling’) the same as for previous works.
(see the description to 3rd work)
## Requirements:
- All of the requirements for previous React.js works should be kept.
### Code style:
- Your items should be stored inside the state or context (your
choice) of your page
https://uk.reactjs.org/docs/hooks-state.html
https://uk.reactjs.org/docs/hooks-reference.html#usecontext
- For your state management use useState() inside Functional
Component instead of this.state and Class component
- If you decided to use context, use useContext() hook instead of
Context.Consumer
https://www.robinwieruch.de/react-usecontext-hook
## Functionality (IMPORTANT):
- Home page: “View more” button should display more elements
on the same page Tip: Elements can be just random paragraph
& heading, use your imagination ;)
- Catalog page: You should be able to filter your items list, by
applying different filters by item's properties (i.e size/color/type)
- Catalog page: Search by any text property option should also
work
- Catalog & Item pages: “View more” action on every item
should refer to corresponding Item page, with correct
information about item (get the info from your state/context)
71 changes: 71 additions & 0 deletions components/Catalog/Catalog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { CatalogItem } from "../CatalogItem/CatalogItem";
import { Wrapper } from "./Catalog.styles";
import GoldCreekPond from "../../icons/GoldCreekPond.jpg";
import AppenzellDistrict from "../../icons/AppenzellDistrict.jpg";
import Uttarakhand from "../../icons/Uttarakhand.jpg";
import Algeria from "../../icons/Algeria.jpg";
import { useState } from "react";
import { Filter } from "../Filter/Filter";


export const Catalog = () => {
const catalogItems = [
{
name: "Gold Creek Pond",
price: 1200,
image: GoldCreekPond
},
{
name: "Appenzell District",
price: 700,
image: AppenzellDistrict
},
{
name: "Uttarakhand",
price: 890,
image: Uttarakhand
},
{
name: "Algeria",
price: 2500,
image: Algeria
}
];
const [items, update] = useState(catalogItems);

function updateItems(name, order, price, input) {
let resultArray = catalogItems;
if (price == 1)
resultArray = catalogItems.filter(item => item.price <= 1500);
else if (price == 2)
resultArray = catalogItems.filter(item => item.price > 1500);
if (name == "name")
resultArray.sort((a, b) => a.name.localeCompare(b.name));
else if (name == "price")
resultArray.sort((a, b) => a.price - b.price)
sortByOrder(resultArray, order, input);
}

function sortByOrder(array, order, input) {
let resultArray;
if (order == 2)
resultArray = Array.from(array).reverse();
else
resultArray = Array.from(array);
filterInput(resultArray, input);
}

function filterInput(array, input) {
update(array.filter(item => item.name.search(input.value) !== -1));
}

return (
<>
<Filter function={updateItems}/>
<Wrapper>
{items.map(item =>
<CatalogItem key={item.name.toString()} name={item.name} price={item.price} image={item.image}/>)}
</Wrapper>
</>
);
}
8 changes: 8 additions & 0 deletions components/Catalog/Catalog.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from 'styled-components';

export const Wrapper = styled.div`
display: flex;
justify-content: space-around;
padding: 20px 50px;
flex-wrap: wrap;
`
14 changes: 14 additions & 0 deletions components/CatalogItem/CatalogItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {Image, Wrapper, Label, SmallText, TextWrapper, Button} from './CatalogItem.styles'

export function CatalogItem(props) {
return (
<Wrapper>
<Image src={props.image}/>
<TextWrapper>
<Label>{props.name}</Label>
<SmallText>Price: {props.price}$</SmallText>
</TextWrapper>
<Button>View more</Button>
</Wrapper>
);
}
46 changes: 46 additions & 0 deletions components/CatalogItem/CatalogItem.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import styled from 'styled-components';

export const Wrapper = styled.div`
display: flex;
flex-direction: column;
background-color: #f3f3f3;
border-radius: 25px;
padding: 10px;
text-align: center;
margin: 10px;
`

export const TextWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 20px;
`

export const Image = styled.img`
width: 400px;
height: 300px;
border-radius: 15px;
`

export const Label = styled.h2`
margin: 10px;
`
export const SmallText = styled.h3`
font-weight: 400;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
align-self: center;
`

export const Button = styled.button`
padding: 10px 6px;
left: 50%;
background-color: #f3f3f3;
border: solid #c4c4c4 1px;
border-radius: 10px;
width: 30%;
transform: translate(120%, 0);
&:hover {
box-shadow: 0 0 8px #777676;
}
`
80 changes: 80 additions & 0 deletions components/Filter/Filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useState } from "react";
import { Logo, Nav, Search, NavItem, NavWrapper, Wrapper } from "../Header/Header.styles";
import {
ApplyButton,
FilterSelector,
FilterWrapper,
HorLine,
LabelText,
OuterWrapper
} from "./Filter.styles";
import SearchIcon from "../../icons/search.png";
import { Link } from "react-router-dom";


export const Filter = (props) => {
const [name, changeName] = useState("DEFAULT");
const [order, changeOrder] = useState("DEFAULT");
const [price, changePrice] = useState("DEFAULT");
const input = document.getElementById("search_input");

function setName(nameSelector) {
changeName(nameSelector.target.value);
}

function setOrder(orderSelector) {
changeOrder(orderSelector.target.value);
}

function setPrice(priceSelector) {
changePrice(priceSelector.target.value);
}

function updateItems() {
props.function(name, order, price, input);
}

return (
<>
<Wrapper>
<Logo>Voucher</Logo>
<Nav>
<Link to="/" style={{textDecoration: 'none', color: 'black'}}><NavItem>Home</NavItem></Link>
<Link to="/catalog" style={{textDecoration: 'none', color: 'black'}}><NavItem>Catalog</NavItem></Link>
<Link to="/cart" style={{textDecoration: 'none', color: 'black'}}><NavItem>Cart</NavItem></Link>
</Nav>
<NavWrapper>
<div style={{display: "flex", alignItems: "center"}}>
<Search id={"search_input"}/>
<img src={SearchIcon} alt={"search"} style={{width: '20px', height: '20px', padding:'5px'}}/>
</div>
</NavWrapper>
</Wrapper>
<HorLine/>
<OuterWrapper>
<FilterWrapper>
<LabelText>Sort by:</LabelText>
<FilterSelector id="name" onChange={setName}>
<option value="DEFAULT">Choose filter:</option>
<option value="price">Price</option>
<option value="name">Name</option>
</FilterSelector>
<LabelText>Order by:</LabelText>
<FilterSelector id="order" onChange={setOrder}>
<option value="DEFAULT">Choose order:</option>
<option value="1">Ascending</option>
<option value="2">Descending</option>
</FilterSelector>
<LabelText>Price:</LabelText>
<FilterSelector id="price" onChange={setPrice}>
<option value="DEFAULT">Choose price:</option>
<option value="1">&lt;1500</option>
<option value="2">&gt;1500</option>
</FilterSelector>
</FilterWrapper>
<ApplyButton onClick={updateItems}>Apply</ApplyButton>
</OuterWrapper>
<HorLine style={{marginTop: '10px'}}/>
</>
);
}
44 changes: 44 additions & 0 deletions components/Filter/Filter.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import styled from "styled-components";

export const OuterWrapper = styled.div`
display: flex;
padding: 5px 80px;
`

export const Wrapper = styled.div`
display: flex;
padding: 5px 80px;
`

export const FilterWrapper = styled.div`
display: flex;
flex: 10;
`

export const FilterSelector = styled.div`
margin-right: 40px;
padding: 10px 32px;
border-radius: 10px;
border: solid #c4c4c4 1px;
`

export const LabelText = styled.h4`
margin: 0 30px;
align-self: center;
`

export const ApplyButton = styled.button`
padding: 18px 32px;
background-color: #f3f3f3;
flex: 1;
border: solid #c4c4c4 1px;
border-radius: 10px;
&:hover {
box-shadow: 0 0 8px #777676;
}
`

export const HorLine = styled.hr`
margin-top: 0;
`

Loading