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
4 changes: 4 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
55 changes: 55 additions & 0 deletions components/Card/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useState } from 'react';
import useDownloader from 'react-use-downloader';
import Link from 'next/link';
import { DownloadIcon } from '../Icons';

import {
Container,
CardBox,
Img,
CardOverlay,
DownloadBtn,
DownloadBtnMobile,
} from './styles';

export function Card(props) {
const [isHovering, setIsHovering] = useState(false);
const { download } = useDownloader();

const fileUrl = props.fileUrl;
const fileName = props.fileName;

const handleMouseOver = () => {
setIsHovering(true);
};

const handleMouseOut = () => {
setIsHovering(false);
};

const handleDownload = () => {
download(fileUrl, fileName);
};

return (
<Container>
<CardBox onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}>
<Link href={`photos/photo/${props.photoId}`}>
<Img src={props.photo} alt={props.alt} />

{isHovering && (
<CardOverlay>
<h1>{props.author}</h1>
<DownloadBtn onClick={handleDownload}>
<DownloadIcon />
</DownloadBtn>
</CardOverlay>
)}
</Link>
<DownloadBtnMobile onClick={handleDownload}>
<DownloadIcon />
</DownloadBtnMobile>
</CardBox>
</Container>
);
}
88 changes: 88 additions & 0 deletions components/Card/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import styled from 'styled-components';

export const Container = styled.div`
margin-top: 0.5rem;
position: relative;
`;

export const Img = styled.img`
width: 100%;
height: 100%;
object-fit: cover;
`;

export const CardBox = styled.div`
height: 100%;
background-color: ${(props) => props.theme.colors.background};
box-shadow: 0px 2px 2px 0px hsla(0, 0%, 0%, 0.14),
0px 3px 1px -2px hsla(0, 0%, 0%, 0.12), 0px 1px 5px 0px hsla(0, 0%, 0%, 0.2);
cursor: pointer;
`;

export const CardOverlay = styled.div`
display: flex;
justify-content: space-between;
align-content: center;
align-items: flex-end;
padding: 0 0.5rem 0.5rem;

background: linear-gradient(
180deg,
rgba(0, 0, 0, 0.25),
transparent 35%,
transparent 65%,
rgba(0, 0, 0, 0.25)
);

height: 100%;
width: 100%;

position: absolute;
bottom: 0;

color: ${(props) => props.theme.colors.text_overlay};

h1 {
font-size: ${(props) => props.theme.font_size.sm};
}
svg {
height: 1.3rem;
}
`;

export const DownloadBtn = styled.button`
display: flex;
justify-content: end;

border: none;
background: transparent;
color: ${(props) => props.theme.colors.text_overlay};
text-decoration: none;
cursor: pointer;
`;

export const DownloadBtnMobile = styled.button`
display: flex;
padding: 0 0.5rem 0.5rem;

position: absolute;
bottom: 0;
right: 0;

border: none;
background: transparent;
color: ${(props) => props.theme.colors.text_overlay};
text-decoration: none;
cursor: pointer;

svg {
height: 1.3rem;
opacity: 95%;
}

@media (min-width: 1100px) {
svg {
display: none;
}
}
`;
53 changes: 53 additions & 0 deletions components/Dropdown/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { useState } from 'react';

import { ChevronDown } from '../Icons';

import {
Main,
DropDownContainer,
DropDownHeader,
Title,
DropDownListContainer,
DropDownList,
Button,
ListItem,
} from './styles';

export default function Dropdown(props) {
return (
<Main>
<DropDownContainer>
<DropDownHeader onClick={props.toggling}>
<Title>Filter</Title>
<ChevronDown />
</DropDownHeader>
{props.isOpen && (
<DropDownListContainer>
<DropDownList>
<ListItem>
<Button onClick={props.onClick} value='People'>
People
</Button>
</ListItem>
<ListItem>
<Button onClick={props.onClick} value='Cars'>
Cars
</Button>
</ListItem>
<ListItem>
<Button onClick={props.onClick} value='Landscape'>
Landscape
</Button>
</ListItem>
<ListItem>
<Button onClick={props.onClick} value='Animals'>
Animals
</Button>
</ListItem>
</DropDownList>
</DropDownListContainer>
)}
</DropDownContainer>
</Main>
);
}
98 changes: 98 additions & 0 deletions components/Dropdown/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import styled from 'styled-components';

export const Main = styled.div`
font-family: sans-serif;
background: ${(props) => props.theme.colors.background};
color: ${(props) => props.theme.colors.text};

margin-top: 1rem;

display: flex;
justify-content: flex-end;
align-items: center;
cursor: pointer;

position: relative;
`;

export const DropDownContainer = styled.div`
width: 7rem;
margin: 0 auto;
`;

export const DropDownHeader = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
padding: 0.5rem;
box-shadow: 0px 2px 2px 0px hsla(0, 0%, 0%, 0.14),
0px 3px 1px -2px hsla(0, 0%, 0%, 0.12), 0px 1px 5px 0px hsla(0, 0%, 0%, 0.2);
font-weight: ${(props) => props.theme.font_weight.bold};
font-size: ${(props) => props.theme.font_size.sm};

border-radius: 5px;

@media (min-width: 1100px) {
margin: 0.5rem 1rem 0 0;
}
`;

export const Title = styled.span``;

export const DropDownListContainer = styled.div`
width: 30%;
`;

export const DropDownList = styled.ul`
box-shadow: 0px 2px 2px 0px hsla(0, 0%, 0%, 0.14),
0px 3px 1px -2px hsla(0, 0%, 0%, 0.12), 0px 1px 5px 0px hsla(0, 0%, 0%, 0.2);

border-radius: 5px;
position: absolute;
z-index: 1;

right: 0;
width: 13rem;

background: #ffffff;
border: 2px solid #e5e5e5;
box-sizing: border-box;
font-size: 1.3rem;
font-weight: 500;

@media (min-width: 1100px) {
margin: 0.5rem 1rem 0;
}
`;

export const ListItem = styled.li`
list-style: none;
border-bottom: 1px solid ${(props) => props.theme.colors.caption_400};
&:last-child {
border: none;
}
`;

export const Button = styled.button`
display: flex;

font-size: ${(props) => props.theme.font_size.xsm};
font-weight: ${(props) => props.theme.font_weight.black};
background-color: ${(props) => props.theme.colors.background};
color: ${(props) => props.theme.colors.text};
border: none;
outline: none;

width: 100%;

padding: 1rem 0.5rem;

cursor: pointer;

&:focus,
&:active,
&:hover {
background-color: ${(props) => props.theme.colors.background_700};
}
`;
48 changes: 48 additions & 0 deletions components/Form/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Card } from '../Card/index';
import { SearchIcon } from '../Icons';

import {
Container,
FormContainer,
Form,
Input,
Button,
ContainerResults,
Section,
T,
} from './styles';

export default function SearchBar(props) {
return (
<Container>
<FormContainer>
<Form onSubmit={props.search} key={props.photoID}>
<Input
type='text'
placeholder={`Search for free photos`}
onChange={props.onChange}
tabIndex={1}
/>
<Button>
<SearchIcon />
</Button>
</Form>
</FormContainer>
<ContainerResults>
<Section>
{props.photoData.map((photo) => (
<Card
key={photo.id}
photo={photo.src.large}
photoId={photo.id}
author={photo.photographer}
alt={photo.alt}
fileUrl={photo.src.original}
fileName={`${photo.id}.jpeg`}
/>
))}
</Section>
</ContainerResults>
</Container>
);
}
Loading