Skip to content

Commit

Permalink
feat: search functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
karlhadwen committed Apr 25, 2020
1 parent e3dc6d1 commit cdfba78
Show file tree
Hide file tree
Showing 37 changed files with 119 additions and 53 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"firebase": "^7.14.0",
"fuse.js": "^5.2.3",
"normalize.css": "^8.0.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
Expand Down Expand Up @@ -36,6 +37,7 @@
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"babel-plugin-macros": "^2.8.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.1.0",
"eslint-config-prettier": "^6.10.1",
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed public/images-backup/misc/home-bg.jpg
Binary file not shown.
Binary file removed public/images-backup/misc/home-imac.jpg
Binary file not shown.
Binary file removed public/images-backup/misc/home-mobile.jpg
Binary file not shown.
Binary file removed public/images-backup/misc/home-tv.jpg
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion src/components/accordion/styles/accordion.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';

export const Container = styled.div`
display: flex;
Expand Down
25 changes: 16 additions & 9 deletions src/components/card/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { useState, useContext, createContext } from 'react';
import CancelIcon from '@material-ui/icons/Cancel';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';

import {
Container,
Group,
Expand All @@ -15,6 +17,7 @@ import {
Entities,
Item,
Image,
PlayButton,
} from './styles/card';

export const FeatureContext = createContext();
Expand All @@ -25,7 +28,7 @@ export default function Card({ children, ...restProps }) {

return (
<FeatureContext.Provider value={{ showFeature, setShowFeature, itemFeature, setItemFeature }}>
<Container {...restProps}>{children}</Container>;
<Container {...restProps}>{children}</Container>
</FeatureContext.Provider>
);
}
Expand All @@ -38,10 +41,6 @@ Card.Title = function CardTitle({ children, ...restProps }) {
return <Title {...restProps}>{children}</Title>;
};

Card.Title = function CardTitle({ children, ...restProps }) {
return <Title {...restProps}>{children}</Title>;
};

Card.SubTitle = function CardSubTitle({ children, ...restProps }) {
return <SubTitle {...restProps}>{children}</SubTitle>;
};
Expand Down Expand Up @@ -78,22 +77,30 @@ Card.Image = function CardImage({ ...restProps }) {
return <Image {...restProps} />;
};

Card.Feature = function CardFeature({ selectionType, ...restProps }) {
Card.PlayButton = function CardPlayButton({ children, ...restProps }) {
return <PlayButton>{children}</PlayButton>;
};

Card.Feature = function CardFeature({ category, ...restProps }) {
const { showFeature, itemFeature, setShowFeature } = useContext(FeatureContext);

return showFeature ? (
<Feature src={`/images/${selectionType}/${itemFeature.genre}/${itemFeature.slug}/large.jpg`}>
<Feature src={`/images/${category}/${itemFeature.genre}/${itemFeature.slug}/large.jpg`}>
<Content>
<FeatureTitle>{itemFeature.title}</FeatureTitle>
<FeatureText>{itemFeature.description}</FeatureText>
<CancelIcon fontSize="large" onClick={() => setShowFeature(false)} />
<CancelIcon className="cancel" fontSize="large" onClick={() => setShowFeature(false)} />

<Group margin="30px 0" flexDirection="row" alignItems="center">
<Maturity rating={itemFeature.maturity}>{itemFeature.maturity}</Maturity>
<Maturity rating={itemFeature.maturity}>{itemFeature.maturity < 12 ? 'PG' : itemFeature.maturity}</Maturity>
<FeatureText fontWeight="bold">
{itemFeature.genre.charAt(0).toUpperCase() + itemFeature.genre.slice(1)}
</FeatureText>
</Group>
<PlayButton>
<PlayArrowIcon className="play" />
Play
</PlayButton>
</Content>
</Feature>
) : null;
Expand Down
41 changes: 33 additions & 8 deletions src/components/card/styles/card.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';

export const Container = styled.div`
display: flex;
Expand Down Expand Up @@ -103,7 +103,7 @@ export const Feature = styled.div`
background: url(${({ src }) => src});
background-size: contain;
position: relative;
height: 500px;
height: 360px;
background-position-x: right;
background-repeat: no-repeat;
background-color: black;
Expand All @@ -115,19 +115,17 @@ export const FeatureTitle = styled(Title)`

export const FeatureText = styled.p`
font-size: 18px;
color: #999;
color: white;
font-weight: ${({ fontWeight }) => (fontWeight === 'bold' ? 'bold' : 'normal')};
margin: 0;
`;

export const Content = styled.div`
margin-left: 56px;
margin-right: 56px;
margin-top: 56px;
margin: 56px;
max-width: 500px;
line-height: normal;
svg {
svg.cancel {
color: white;
position: absolute;
right: 20px;
Expand All @@ -136,6 +134,32 @@ export const Content = styled.div`
}
`;

export const PlayButton = styled.button`
background-color: #e50914;
border-color: #ff0a16;
width: 115px;
height: 45px;
text-transform: uppercase;
font-weight: bold;
color: white;
font-size: 18px;
height: 45px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding-left: 0;
&:hover {
transform: scale(1.05);
background-color: #ff0a16;
}
svg.play {
margin-right: 5px;
}
`;

export const Maturity = styled.div`
background-color: ${({ rating }) => (rating >= 15 ? 'red' : 'green')};
border-radius: 15px;
Expand All @@ -144,6 +168,7 @@ export const Maturity = styled.div`
text-align: center;
color: white;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.45);
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
margin-right: 10px;
font-size: 12px;
`;
2 changes: 1 addition & 1 deletion src/components/feature/styles/feature.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';

export const Container = styled.div`
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion src/components/footer/styles/footer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';

export const Container = styled.div`
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion src/components/form/styles/form.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';
import { Link as ReachRouterLink } from 'react-router-dom';

export const Container = styled.div`
Expand Down
9 changes: 7 additions & 2 deletions src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,18 @@ Header.Logo = function HeaderLogo({ to, ...restProps }) {
);
};

Header.Search = function HeaderSearch({ ...restProps }) {
Header.Search = function HeaderSearch({ searchTerm, setSearchTerm, ...restProps }) {
const [searchActive, setSearchActive] = useState(false);

return (
<Search {...restProps}>
<SearchIcon onClick={() => setSearchActive(!searchActive)} />
<SearchInput placeholder="Search films and series" active={searchActive} />
<SearchInput
value={searchTerm}
onChange={({ target }) => setSearchTerm(target.value)}
placeholder="Search films and series"
active={searchActive}
/>
</Search>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/header/styles/header.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';
import { Link as ReachRouterLink } from 'react-router-dom';

export const Background = styled.div`
Expand Down
2 changes: 1 addition & 1 deletion src/components/jumbotron/styles/jumbotron.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';

export const Container = styled.div`
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion src/components/opt-form/styles/opt-form.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';

export const Container = styled.div`
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion src/components/profiles/styles/profiles.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled from 'styled-components';
import styled from 'styled-components/macro';

export const Container = styled.div`
display: flex;
Expand Down
45 changes: 34 additions & 11 deletions src/containers/browse.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
import React, { useState, useEffect, useContext } from 'react';
import Fuse from 'fuse.js';
import { Card, Header, Loading } from '../components';
import * as ROUTES from '../constants/routes';
import logo from '../logo.svg';
import { FirebaseContext } from '../context/firebase';
import { SelectProfileContainer, FooterContainer } from '.';
import { SelectProfileContainer } from './profiles';
import { FooterContainer } from './footer';

export default function BrowseContainer({ slides }) {
const [selection, setSelection] = useState('series');
export function BrowseContainer({ slides }) {
const [category, setCategory] = useState('series');
const [profile, setProfile] = useState({});
const [loading, setLoading] = useState(true);
const [searchTerm, setSearchTerm] = useState('');
const [slideRows, setSlideRows] = useState([]);

const { firebase } = useContext(FirebaseContext);
const user = firebase.auth().currentUser || {};
const [loading, setLoading] = useState(true);

useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 3000);
}, [profile.displayName]);

useEffect(() => {
setSlideRows(slides[category]);
}, [slides, category]);

useEffect(() => {
const fuse = new Fuse(slideRows, { keys: ['data.description', 'data.title', 'data.genre'] });
const results = fuse.search(searchTerm).map(({ item }) => item);

if (slideRows.length > 0 && searchTerm.length > 3 && results.length > 0) {
setSlideRows(results);
} else {
setSlideRows(slides[category]);
}
}, [searchTerm]);

return profile.displayName ? (
<>
{loading ? <Loading src={`/images/users/${user.photoURL}.png`} /> : <Loading.ReleaseBody />}
Expand All @@ -26,22 +46,25 @@ export default function BrowseContainer({ slides }) {
<Header.Frame>
<Header.Group>
<Header.Logo to={ROUTES.HOME} src={logo} alt="Netflix" />
<Header.TextLink active={selection === 'series' ? 'true' : 'false'} onClick={() => setSelection('series')}>
<Header.TextLink active={category === 'series' ? 'true' : 'false'} onClick={() => setCategory('series')}>
Series
</Header.TextLink>
<Header.TextLink active={selection === 'films' ? 'true' : 'false'} onClick={() => setSelection('films')}>
<Header.TextLink active={category === 'films' ? 'true' : 'false'} onClick={() => setCategory('films')}>
Films
</Header.TextLink>
</Header.Group>
<Header.Group>
<Header.Search />
<Header.Search searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
<Header.Profile>
<Header.Picture src={`/images/users/${user.photoURL}.png`} />
<Header.Dropdown>
<Header.Group>
<Header.Picture src={`/images/users/${user.photoURL}.png`} />
<Header.TextLink>{user.displayName}</Header.TextLink>
</Header.Group>
<Header.Group>
<Header.TextLink onClick={() => console.log('favourites')}>Favourites</Header.TextLink>
</Header.Group>
<Header.Group>
<Header.TextLink onClick={() => firebase.auth().signOut()}>Sign out</Header.TextLink>
</Header.Group>
Expand All @@ -62,21 +85,21 @@ export default function BrowseContainer({ slides }) {
</Header>

<Card.Group style={{ marginTop: '-150px' }}>
{slides[selection].map((slideItem) => (
<Card key={`${selection}-${slideItem.title.toLowerCase()}`}>
{slideRows.map((slideItem) => (
<Card key={`${category}-${slideItem.title.toLowerCase()}`}>
<Card.Title>{slideItem.title}</Card.Title>
<Card.Entities>
{slideItem.data.map((item) => (
<Card.Item key={item.docId} item={item}>
<Card.Image src={`/images/${selection}/${item.genre}/${item.slug}/small.jpg`} />
<Card.Image src={`/images/${category}/${item.genre}/${item.slug}/small.jpg`} />
<Card.Meta>
<Card.SubTitle>{item.title}</Card.SubTitle>
<Card.Text>{item.description}</Card.Text>
</Card.Meta>
</Card.Item>
))}
</Card.Entities>
<Card.Feature selectionType={selection} />
<Card.Feature category={category} />
</Card>
))}
</Card.Group>
Expand Down
2 changes: 1 addition & 1 deletion src/containers/faqs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { Accordion, OptForm } from '../components';
import faqsData from '../fixtures/faqs';

export default function FaqsContainer() {
export function FaqsContainer() {
return (
<Accordion>
<Accordion.Title>Frequently Asked Questions</Accordion.Title>
Expand Down
2 changes: 1 addition & 1 deletion src/containers/footer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Footer } from '../components';

export default function FooterContainer() {
export function FooterContainer() {
return (
<Footer>
<Footer.Title>Questions? Contact us.</Footer.Title>
Expand Down
2 changes: 1 addition & 1 deletion src/containers/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Header } from '../components';
import * as ROUTES from '../constants/routes';
import logo from '../logo.svg';

export default function HeaderContainer({ children }) {
export function HeaderContainer({ children }) {
return (
<Header>
<Header.Frame>
Expand Down
5 changes: 0 additions & 5 deletions src/containers/index.js

This file was deleted.

2 changes: 1 addition & 1 deletion src/containers/profiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Header, Profiles } from '../components';
import * as ROUTES from '../constants/routes';
import logo from '../logo.svg';

export default function SelectProfileContainer({ user, setProfile }) {
export function SelectProfileContainer({ user, setProfile }) {
return (
<>
<Header bg={false}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/browse.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { BrowseContainer } from '../containers';
import { BrowseContainer } from '../containers/browse';
import { useContent } from '../hooks';
import { selectionMap } from '../utils';

Expand Down
Loading

0 comments on commit cdfba78

Please sign in to comment.