<file_sep>import styled from 'styled-components'
import { Link } from 'react-router-dom'

export const Container = styled.header`
    display:flex;
    justify-content: space-between;
    padding:1em;
    align-items:center;
    color:#fff;
    background: #3c4b4d;
    margin-bottom: 0.5em;
    font-size:1rem;
`
export const Group = styled.div`      
    display:flex;
    align-items: center;
    padding:0.5em;
`

export const Title = styled.h1`
    font-size:2rem;
    text-transform: uppercase;

    @media (max-width: 720px){
        font-size:0.9rem;
    }
`

export const Text = styled.p`
   color: #e11005;
`
export const Button = styled(Link)`   
    display:flex; 
    position: relative;
    font-weight:700;
    border: 0;
    border-radius:15px;
    color:#fff;
    padding: 8px 17px;
    cursor: pointer;
    text-decoration: none;
    text-transform: uppercase;
    margin-left:1em;

    &:hover {
        transform: scale(1.2);
    }

    @media (max-width:600px){
        padding: 4px 8px;
        font-size:0.9rem;
    }
`


<file_sep>import React from 'react'
import { Container, Form, Label, Input, Text } from './styles/filter'

export default function Filter({ children, ...restProps }) {
    return (
        <Container {...restProps}>{children}</Container>
    )
}

Filter.Form = function FilterForm({ children, ...restProps }) {
    return <Form {...restProps}>{children}</Form>
}

Filter.Label = function FormLabel({ children, ...restProps }) {
    return <Label {...restProps}>{children}</Label>
}

Filter.Input = function FormInput({ ...restProps }) {
    return <Input {...restProps}/>
}

Filter.Text = function FormText({ children, ...restProps }) {
    return <Text {...restProps}>{children}</Text>
}


<file_sep>export const filterVars = {
    showAll: "",
    
    weakABV: "&abv_lt=4.6",
    mediumABV: "&abv_gt=4.5&abv_lt=7.5",
    strongABV: "&abv_gt=7.4",

    lowIBU: "&ibu=35",
    mediumIBU: "&ibu_gt=35&ibu_lt=75",
    highIBU: "&ibu_gt=75"
}<file_sep>import React, { useContext } from "react"
import { HeaderContainer } from '../containers/header'
import { CartContainer } from '../containers/cart'
import { FooterContainer } from '../containers/footer'
import { Context } from '../context/context'


export function Cart() {
    const { cartItems, setCartItems, removeFromCart, emptyCart } = useContext(Context)
    return (
        <>
            <HeaderContainer />
            <CartContainer cartItems={cartItems} setCartItems={setCartItems} removeFromCart={removeFromCart} emptyCart={emptyCart} />
            <FooterContainer />
        </>
    )
}
<file_sep>import React, { useState, useEffect } from "react"
import { HeaderContainer } from '../containers/header'
import { FooterContainer } from '../containers/footer'
import { FilterContainer } from '../containers/filter'
import { CardContainer } from '../containers/card'
import { PaginationContainer } from "../containers/pagination"

export function Store() {
    const [beers, setBeers] = useState([])
    const [optionsABV, setOptionsABV] = useState("")
    const [optionsIBU, setOptionsIBU] = useState("")
    const [page, setPage] = useState(1);

    useEffect(() => {
        getBeers()
    }, [page, optionsABV, optionsIBU])

    const getBeers = async () => {
        let API_URL = `https://api.punkapi.com/v2/beers?page=${page}&per_page=15${optionsABV}${optionsIBU}`
        try {
            const promise = await fetch(API_URL);
            const beersData = await promise.json();
            setBeers(beersData)
        }
        catch (e) {
            console.error(e)
        }
    }

    return (
        <>
            <HeaderContainer />
            <FilterContainer
                getBeers={getBeers}
                setPage={setPage}
                optionsIBU={optionsIBU}
                optionsABV={optionsABV}
                setOptionsABV={setOptionsABV}
                setOptionsIBU={setOptionsIBU} />
            <CardContainer items={beers} />
            <PaginationContainer page={page} setPage={setPage} items={beers} />
            <FooterContainer />
        </>
    )
}
<file_sep>import { createGlobalStyle } from 'styled-components';

export const GlobalStyles = createGlobalStyle`

    * {
        margin 0;
        padding: 0;
        box-sizing: border-box;
    }

    html, body {
        font-family: 'Open Sans', sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        scroll-behavior: smooth;
        color: #fff;
        background: #f2eded;
        font-size: 16px;
        margin: 0 auto;
        padding:0;
        max-width:1400px;
        letter-spacing:1px;
    }

    
`;<file_sep>import React from 'react'
import { Switch, Route } from "react-router-dom"
import { BrowserRouter as Router } from 'react-router-dom'
import { Store } from './pages/store'
import { Cart } from './pages/cart'
import { ContextProvider } from './context/context'

export default function App() {
  return (
    <ContextProvider>
      <Router>
        <Switch>
          <Route exact path="/">
            <Store />
          </Route>
          <Route path="/cart">
            <Cart />
          </Route>
        </Switch>
      </Router>
    </ContextProvider>
  );
}

<file_sep>import React from 'react'
import { Filter } from '../components/exports'
import { filterVars } from '../util/filterVars'


export function FilterContainer({ getBeers, setPage, optionsIBU, optionsABV, setOptionsABV, setOptionsIBU }) {

    const handleABVChange = (e) => {
        e.preventDefault()
        const value = e.target.value;

        switch (value) {
            case 'all':
                setOptionsABV(filterVars.showAll)
                break
            case 'weak':
                setOptionsABV(filterVars.weakABV)
                break
            case 'medium':
                setOptionsABV(filterVars.mediumABV)
                break
            case 'strong':
                setOptionsABV(filterVars.strongABV)
                break
            default: break
        }

        setPage(1)
    }

    const handleIBUChange = (e) => {
        e.preventDefault()
        const value = e.target.value;

        switch (value) {
            case 'all':
                setOptionsIBU(filterVars.showAll)
                break
            case 'low':
                setOptionsIBU(filterVars.lowIBU)
                break
            case 'medium':
                setOptionsIBU(filterVars.mediumIBU)
                break
            case 'high':
                setOptionsIBU(filterVars.highIBU)
                break
            default: break
        }

        setPage(1)
    }

    return (
        <Filter>
            <Filter.Form>
                <Filter.Text color='red'>
                    Alcohol (ABV):
                </Filter.Text>
                <Filter.Label htmlFor="abvAll">
                    <Filter.Input type="radio" value="all" name="filter-abv" checked={optionsABV === filterVars.showAll} onChange={handleABVChange} />

                    all
                </Filter.Label>

                <Filter.Label htmlFor="abvWeak">
                    <Filter.Input type="radio" value="weak" name="filter-abv" checked={optionsABV === filterVars.weakABV} onChange={handleABVChange} />
                    weak
                </Filter.Label>

                <Filter.Label htmlFor="abvMedium">
                    <Filter.Input type="radio" value="medium" name="filter-abv" checked={optionsABV === filterVars.mediumABV} onChange={handleABVChange} />
                    medium
                </Filter.Label>

                <Filter.Label htmlFor="abvStrong">
                    <Filter.Input type="radio" value="strong" name="filter-abv" checked={optionsABV === filterVars.strongABV} onChange={handleABVChange} />
                    strong
                </Filter.Label>
            </Filter.Form>

            <Filter.Form>
                <Filter.Text>
                    Hoppiness (IBU):
                </Filter.Text>

                <Filter.Label htmlFor="ibuAll">
                    <Filter.Input type="radio" value="all" name="filter-ibu" checked={optionsIBU === filterVars.showAll} onChange={handleIBUChange} />
                        all
                </Filter.Label>

                <Filter.Label htmlFor="ibuLow">
                    <Filter.Input type="radio" value="low" name="filter-ibu" checked={optionsIBU === filterVars.lowIBU} onChange={handleIBUChange} />
                    low
                </Filter.Label>

                <Filter.Label htmlFor="ibuMedium">
                    <Filter.Input type="radio" value="medium" name="filter-ibu" checked={optionsIBU === filterVars.mediumIBU} onChange={handleIBUChange} />
                    medium
                </Filter.Label>

                <Filter.Label htmlFor="ibuHigh">
                    <Filter.Input type="radio" value="high" name="filter-ibu" checked={optionsIBU === filterVars.highIBU} onChange={handleIBUChange} />
                    high
                </Filter.Label>
            </Filter.Form>
        </Filter>

    )
}
<file_sep>import styled from 'styled-components'

export const Container = styled.div`
   display: grid;
   grid-template-columns: ${({ gridType }) => (gridType === 'list' ? 'repeat(auto-fill, minmax(350px, 1fr))' : '200px 1fr')};
   grid-gap: 8px;
   padding: 1em;
   color:#333;
   background: #3c4b4d;
   margin-bottom:1em;

   @media(max-width: 620px){
      grid-template-columns: ${({ gridType }) => (gridType === 'list' ? 'repeat(auto-fill, minmax(100%, 1fr))' : '40% 1fr')};
   }
`

export const Wrapper = styled.div`
   display: ${({ display }) => (display === 'block' ? 'block' : 'flex')};
   position: relative;
   flex-direction: ${({ flexDirection }) => (flexDirection === 'row' ? 'row' : 'column')};
   justify-content: ${({ justifyContent }) => (justifyContent === 'end' ? 'flex-end' : 'space-evenly')};
   box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
   background:#ebeded;
   padding: 1em;
   text-align: ${({ textAlign }) => (textAlign === 'left' ? 'left' : 'center')};
   font-size: 1rem;
   @media(max-width: 620px){
      font-size:0.8rem;
   }
`
export const Text = styled.p`
   padding: 0.5em;
   font-size:0.9rem;
`

export const Image = styled.img`
   max-width: 100%;
   height: 200px;
   object-fit: contain;
   margin: 3em 0 1em 0;

   @media(max-width: 620px){
      height: 150px;
   }
`

export const Title = styled.h2`
   font-size: 1.2rem;
   padding: 0.5em;

   @media(max-width: 620px){
      font-size: 1rem;
   }
`

export const Tagline = styled.p`
   font-style: italic;
   padding: 0.5em;
`

export const ABV = styled.span`
   position: ${({ position }) => (position === 'relative' ? 'relative' : 'absolute')};
   color: #FF8D00;
   left:0;
   top:0;
   padding:1em;
   font-weight: 700;
`
export const IBU = styled.span`
   position: ${({ position }) => (position === 'relative' ? 'relative' : 'absolute')};
   color: #28b470 ;
   padding:1em;
   right:0;
   top:0;
   font-weight: 700;
`

export const Content = styled.div`
   position: ${({ position }) => (position === 'relative' ? 'relative' : 'absolute')};;
   top: 0;
   left: 0;
   padding: 1em;
   width: 100%;
   height: 100%;
   background: #f2eded;
   overflow: auto;
   cursor: pointer;
   border-radius:7px;
   text-align: left;
   opacity: 0;
   transition: opacity .8s ease;
      
         &: hover {
      opacity: 0.92;
   }

`

export const ContentTitle = styled.h2`
   padding: 0.5em 1em 0.5em 0.5em;
`

export const ContentTagline = styled.p`
   padding: 0.5em;
   font-style: italic;
`
export const ContentDescription = styled.p`
   padding: 0.5em;
`

export const Icon = styled.img`
   width: 40px;
   height: 40px;
   position: absolute;
   right:1em;
   top:1em;
   cursor:pointer;
   z-index:1000;

   &:hover {
      width:45px;
      height:45px;
   }

   @media (max-width:720px){
      width:30px;
      height:30px;

      &:hover {
         width:35px;
         height:35px;
      }
   }

`

export const Button = styled.button`
   display:block;
   padding: 1em 2.5em;
   background: ${({ color }) => (color === 'red' ? '#dd225b' : '#28b470')};
   margin-left:1em;
   font-family:inherit;
   text-transform: uppercase;
   font-weight: 700;
   cursor:pointer;
   color: #fff;
   border:0;
   border-radius: 15px;
   
   &:hover {
      transform: scale(1.02)
   }
   @media (max-width: 620px){
      font-size:0.8rem;
      padding: 0.8em 1.5em;
   }
`
<file_sep>import React from 'react'
import { Container, Title, Group, Button, Text } from './styles/header'

export default function Header({ children, ...restProps }) {
    return (
        <Container {...restProps}>{children}</Container>
    )
}

Header.Title = function HeaderTitle({children, ...restProps }) {
    return <Title {...restProps}>{children}</Title>
}

Header.Text = function HeaderText({children, ...restProps }) {
    return <Text {...restProps}>{children}</Text>
}

Header.Group = function HeaderGroup({children, ...restProps}){
    return <Group {...restProps}>{children}</Group>
}

Header.Button = function HeaderButton({children, ...restProps}){
    return <Button {...restProps}>{children}</Button>
}

<file_sep>import React, { useState, createContext } from 'react'

export const Context = createContext()

export function ContextProvider({ children }) {

    const [cartItems, setCartItems] = useState([])
    const [loading, setLoading] = useState(false)

    const addToCart = (item) => {
        setCartItems(prev => [...prev, item])
    }

    const removeFromCart = (id) => {
        setCartItems(prevItems => prevItems.filter(item => item.id !== id))
    }

    const emptyCart = () => {
        setCartItems([])
    }

    const checkout = () => {
        setLoading(true)
        setTimeout(() => {
            emptyCart()
            setLoading(false)
        }, 2000)
    }

    return (
        <Context.Provider value={{
            cartItems,
            setCartItems,
            addToCart,
            removeFromCart,
            emptyCart,
            checkout,
            loading
        }}>
            {children}
        </Context.Provider>
    )
}<file_sep>import React from 'react';
import { Container, Text, Image, Title, Tagline, ABV, IBU, Content, ContentTitle, ContentTagline, ContentDescription, Icon, Wrapper, Button } from './styles/card'


export default function Card({ children, ...restProps }) {
    return (
            <Container {...restProps}>{children}</Container>
    )
}
Card.Wrapper = function CardWrapper({ children, ...restProps }) {
    return <Wrapper {...restProps}>{children}</Wrapper>
}

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

Card.Tagline = function CardTagline({ children, ...restProps }) {
    return <Tagline {...restProps}>{children}</Tagline>
}

Card.Text = function CardText({ children, ...restProps }) {
    return <Text {...restProps}>{children}</Text>
}

Card.Image = function CardImage({ children, ...restProps }) {
    return <Image {...restProps} />
}

Card.ABV = function CardABV({ children, ...restProps }) {
    return <ABV {...restProps}>{children}</ABV>
}

Card.IBU = function CardABV({ children, ...restProps }) {
    return <IBU {...restProps}>{children}</IBU>
}

Card.Content = function CardContent({ children, ...restProps }) {
    return <Content {...restProps}>{children}</Content>
}

Card.ContentTitle = function CardContentTitle({ children, ...restProps }) {
    return <ContentTitle {...restProps}>{children}</ContentTitle>
}
Card.ContentTagline = function CardContentTagline({ children, ...restProps }) {
    return <ContentTagline {...restProps}>{children}</ContentTagline>
}

Card.ContentDescription = function CardContentDescription({ children, ...restProps }) {
    return <ContentDescription {...restProps}>{children}</ContentDescription>
}

Card.Icon = function CardIcon({ ...restProps }) {
    return <Icon {...restProps} />
}


Card.Button = function CardButton({ children, ...restProps }) {
    return <Button {...restProps}>{children}</Button>
}
<file_sep>export { default as Header } from './header/index'
export { default as Footer } from './footer/index'
export { default as Card} from './card/index'
export { default as Pagination} from './pagination/index'
export { default as Filter} from './filter/index'<file_sep># beerium

Beerium is an e-commerce type app built in React while following a compound component design pattern, prioritizing reusability. Styled with styled components.
Used Punk API to receive beer data.

https://beerium-haris588.netlify.app
