forked from wesbos/Advanced-React
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
338 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import React from 'react'; | ||
import { Query, Mutation } from 'react-apollo'; | ||
import gql from 'graphql-tag'; | ||
import { adopt } from 'react-adopt'; | ||
import User from './User'; | ||
import CartStyles from './styles/CartStyles'; | ||
import Supreme from './styles/Supreme'; | ||
import CloseButton from './styles/CloseButton'; | ||
import SickButton from './styles/SickButton'; | ||
import CartItem from './CartItem'; | ||
import calcTotalPrice from '../lib/calcTotalPrice'; | ||
import formatMoney from '../lib/formatMoney'; | ||
|
||
const LOCAL_STATE_QUERY = gql` | ||
query { | ||
cartOpen @client | ||
} | ||
`; | ||
|
||
const TOGGLE_CART_MUTATION = gql` | ||
mutation { | ||
toggleCart @client | ||
} | ||
`; | ||
/* eslint-disable */ | ||
const Composed = adopt({ | ||
user: ({ render }) => <User>{render}</User>, | ||
toggleCart: ({ render }) => <Mutation mutation={TOGGLE_CART_MUTATION}>{render}</Mutation>, | ||
localState: ({ render }) => <Query query={LOCAL_STATE_QUERY}>{render}</Query>, | ||
}); | ||
/* eslint-enable */ | ||
|
||
const Cart = () => ( | ||
<Composed> | ||
{({ user, toggleCart, localState }) => { | ||
const me = user.data.me; | ||
if (!me) return null; | ||
return ( | ||
<CartStyles open={localState.data.cartOpen}> | ||
<header> | ||
<CloseButton onClick={toggleCart} title="close"> | ||
× | ||
</CloseButton> | ||
<Supreme>{me.name}'s Cart</Supreme> | ||
<p> | ||
You Have {me.cart.length} Item{me.cart.length === 1 ? '' : 's'} in your cart. | ||
</p> | ||
</header> | ||
<ul>{me.cart.map(cartItem => <CartItem key={cartItem.id} cartItem={cartItem} />)}</ul> | ||
<footer> | ||
<p>{formatMoney(calcTotalPrice(me.cart))}</p> | ||
<SickButton>Checkout</SickButton> | ||
</footer> | ||
</CartStyles> | ||
); | ||
}} | ||
</Composed> | ||
); | ||
|
||
export default Cart; | ||
export { LOCAL_STATE_QUERY, TOGGLE_CART_MUTATION }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import Link from 'next/link'; | ||
import styled from 'styled-components'; | ||
import NProgress from 'nprogress'; | ||
import Router from 'next/router'; | ||
import Nav from './Nav'; | ||
import Cart from './Cart'; | ||
import Search from './Search'; | ||
|
||
Router.onRouteChangeStart = () => { | ||
NProgress.start(); | ||
}; | ||
Router.onRouteChangeComplete = () => { | ||
NProgress.done(); | ||
}; | ||
|
||
Router.onRouteChangeError = () => { | ||
NProgress.done(); | ||
}; | ||
|
||
const Logo = styled.h1` | ||
font-size: 4rem; | ||
margin-left: 2rem; | ||
position: relative; | ||
z-index: 2; | ||
transform: skew(-7deg); | ||
a { | ||
padding: 0.5rem 1rem; | ||
background: ${props => props.theme.red}; | ||
color: white; | ||
text-transform: uppercase; | ||
text-decoration: none; | ||
} | ||
@media (max-width: 1300px) { | ||
margin: 0; | ||
text-align: center; | ||
} | ||
`; | ||
|
||
const StyledHeader = styled.header` | ||
.bar { | ||
border-bottom: 10px solid ${props => props.theme.black}; | ||
display: grid; | ||
grid-template-columns: auto 1fr; | ||
justify-content: space-between; | ||
align-items: stretch; | ||
@media (max-width: 1300px) { | ||
grid-template-columns: 1fr; | ||
justify-content: center; | ||
} | ||
} | ||
.sub-bar { | ||
display: grid; | ||
grid-template-columns: 1fr auto; | ||
border-bottom: 1px solid ${props => props.theme.lightgrey}; | ||
} | ||
`; | ||
|
||
const Header = () => ( | ||
<StyledHeader> | ||
<div className="bar"> | ||
<Logo> | ||
<Link href="/"> | ||
<a>Sick Fits</a> | ||
</Link> | ||
</Logo> | ||
<Nav /> | ||
</div> | ||
<div className="sub-bar"> | ||
<Search /> | ||
</div> | ||
<Cart /> | ||
</StyledHeader> | ||
); | ||
|
||
export default Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import React from 'react'; | ||
import Downshift from 'downshift'; | ||
import Router from 'next/router'; | ||
import { ApolloConsumer } from 'react-apollo'; | ||
import gql from 'graphql-tag'; | ||
import debounce from 'lodash.debounce'; | ||
import { DropDown, DropDownItem, SearchStyles } from './styles/DropDown'; | ||
|
||
const SEARCH_ITEMS_QUERY = gql` | ||
query SEARCH_ITEMS_QUERY($searchTerm: String!) { | ||
items(where: { OR: [{ title_contains: $searchTerm }, { description_contains: $searchTerm }] }) { | ||
id | ||
image | ||
title | ||
} | ||
} | ||
`; | ||
|
||
class AutoComplete extends React.Component { | ||
state = { | ||
items: [], | ||
loading: false, | ||
}; | ||
onChange = debounce(async (e, client) => { | ||
console.log('Searching...'); | ||
// turn loading on | ||
this.setState({ loading: true }); | ||
// Manually query apollo client | ||
const res = await client.query({ | ||
query: SEARCH_ITEMS_QUERY, | ||
variables: { searchTerm: e.target.value }, | ||
}); | ||
this.setState({ | ||
items: res.data.items, | ||
loading: false, | ||
}); | ||
}, 350); | ||
render() { | ||
return ( | ||
<SearchStyles> | ||
<div> | ||
<ApolloConsumer> | ||
{client => ( | ||
<input | ||
type="search" | ||
onChange={e => { | ||
e.persist(); | ||
this.onChange(e, client); | ||
}} | ||
/> | ||
)} | ||
</ApolloConsumer> | ||
<DropDown> | ||
{this.state.items.map(item => ( | ||
<DropDownItem key={item.id}> | ||
<img width="50" src={item.image} alt={item.title} /> | ||
{item.title} | ||
</DropDownItem> | ||
))} | ||
</DropDown> | ||
</div> | ||
</SearchStyles> | ||
); | ||
} | ||
} | ||
|
||
export default AutoComplete; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import React from 'react'; | ||
import Downshift from 'downshift'; | ||
import Router from 'next/router'; | ||
import { ApolloConsumer } from 'react-apollo'; | ||
import gql from 'graphql-tag'; | ||
import debounce from 'lodash.debounce'; | ||
import { DropDown, DropDownItem, SearchStyles } from './styles/DropDown'; | ||
|
||
const SEARCH_ITEMS_QUERY = gql` | ||
query SEARCH_ITEMS_QUERY($searchTerm: String!) { | ||
items(where: { OR: [{ title_contains: $searchTerm }, { description_contains: $searchTerm }] }) { | ||
id | ||
image | ||
title | ||
} | ||
} | ||
`; | ||
|
||
function routeToItem(item) { | ||
Router.push({ | ||
pathname: '/item', | ||
query: { | ||
id: item.id, | ||
}, | ||
}); | ||
} | ||
|
||
class AutoComplete extends React.Component { | ||
state = { | ||
items: [], | ||
loading: false, | ||
}; | ||
onChange = debounce(async (e, client) => { | ||
console.log('Searching...'); | ||
// turn loading on | ||
this.setState({ loading: true }); | ||
// Manually query apollo client | ||
const res = await client.query({ | ||
query: SEARCH_ITEMS_QUERY, | ||
variables: { searchTerm: e.target.value }, | ||
}); | ||
this.setState({ | ||
items: res.data.items, | ||
loading: false, | ||
}); | ||
}, 350); | ||
render() { | ||
return ( | ||
<SearchStyles> | ||
<Downshift onChange={routeToItem} itemToString={item => (item === null ? '' : item.title)}> | ||
{({ getInputProps, getItemProps, isOpen, inputValue, highlightedIndex }) => ( | ||
<div> | ||
<ApolloConsumer> | ||
{client => ( | ||
<input | ||
{...getInputProps({ | ||
type: 'search', | ||
placeholder: 'Search For An Item', | ||
id: 'search', | ||
className: this.state.loading ? 'loading' : '', | ||
onChange: e => { | ||
e.persist(); | ||
this.onChange(e, client); | ||
}, | ||
})} | ||
/> | ||
)} | ||
</ApolloConsumer> | ||
{isOpen && ( | ||
<DropDown> | ||
{this.state.items.map((item, index) => ( | ||
<DropDownItem | ||
{...getItemProps({ item })} | ||
key={item.id} | ||
highlighted={index === highlightedIndex} | ||
> | ||
<img width="50" src={item.image} alt={item.title} /> | ||
{item.title} | ||
</DropDownItem> | ||
))} | ||
{!this.state.items.length && | ||
!this.state.loading && <DropDownItem> Nothing Found {inputValue}</DropDownItem>} | ||
</DropDown> | ||
)} | ||
</div> | ||
)} | ||
</Downshift> | ||
</SearchStyles> | ||
); | ||
} | ||
} | ||
|
||
export default AutoComplete; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import withApollo from 'next-with-apollo'; | ||
import ApolloClient from 'apollo-boost'; | ||
import { endpoint } from '../config'; | ||
import { LOCAL_STATE_QUERY } from '../components/Cart'; | ||
|
||
function createClient({ headers }) { | ||
return new ApolloClient({ | ||
uri: process.env.NODE_ENV === 'development' ? endpoint : endpoint, | ||
request: operation => { | ||
operation.setContext({ | ||
fetchOptions: { | ||
credentials: 'include', | ||
}, | ||
headers, | ||
}); | ||
}, | ||
// local data | ||
clientState: { | ||
resolvers: { | ||
Mutation: { | ||
toggleCart(_, variables, { cache }) { | ||
// read the cartOpen value from the cache | ||
const { cartOpen } = cache.readQuery({ | ||
query: LOCAL_STATE_QUERY, | ||
}); | ||
// Write the cart State to the opposite | ||
const data = { | ||
data: { cartOpen: !cartOpen }, | ||
}; | ||
cache.writeData(data); | ||
return data; | ||
}, | ||
}, | ||
}, | ||
defaults: { | ||
cartOpen: false, | ||
}, | ||
}, | ||
}); | ||
} | ||
|
||
export default withApollo(createClient); |