GithubHelp home page GithubHelp logo

erhantezer / cart-reducer Goto Github PK

View Code? Open in Web Editor NEW
0.0 1.0 0.0 80 KB

Home Page: https://cart-reducer-xi.vercel.app

JavaScript 62.49% HTML 2.38% CSS 35.13%
api-data context html-css-javascript loading mock-data reactjs reducer svg-images vitejs

cart-reducer's Introduction

CART

App.jsx

import Home from "./pages/Home";

function App() {
  return (
    <>
      <Home/>
    </>
  )
}

export default App;

Home:jsx

import Navbar from '../components/Navbar';
import CarContainer from '../components/cart/CarContainer';
import { useGlobalContext } from '../context';

const Home = () => {
    const { loading } = useGlobalContext();

    return (
        <>
            {loading ?
                (<div className='loading' >
                    <h1>Loading...</h1>
                </div >) : (
                    <main>
                        <Navbar />
                        <CarContainer />
                    </main>
                )
            }
        </>
    )
}

export default Home;

Navbar.jsx

import { useGlobalContext } from "../context";

const Navbar = () => {
 const {amount} = useGlobalContext()
    
    return (
        <nav>
            <div className='nav-center'>
                <h3>useReducer</h3>
                <div className='nav-container'>
                    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
                        <path d='M16 6v2h2l2 12H0L2 8h2V6a6 6 0 1 1 12 0zm-2 0a4 4 0 1 0-8 0v2h8V6zM4 10v2h2v-2H4zm10 0v2h2v-2h-2z' />
                    </svg>
                    <div className='amount-container'>
                        <p className='total-amount'>{amount}</p>
                    </div>
                </div>
            </div>
        </nav>
    )
}

export default Navbar;

CartContainer.jsx

import { useGlobalContext } from "../../context"
import CartItem from "./CartItem"

const CarContainer = () => {
    const { cart, total, clearCart, fetchData } = useGlobalContext()

    if (cart.length === 0) {
        return (
            <section className='cart'>
                <header>
                    <h2>your bag</h2>
                    <h4 className='empty-cart'>is currently empty</h4>
                    <button className="btn reloaded-btn" onClick={() => fetchData()}>
                        reloaded
                    </button>
                </header>
            </section>
        )
    }

    return (
        <section className="cart">
            <header>
                <h2>your bag</h2>
            </header>
            <div>
                {cart.map((item) => {
                    return <CartItem key={item.id} {...item} />
                })}
            </div>
            <footer>
                <hr />
                <div className="cart-total">
                    <h4>
                        total <span>${total}</span>
                    </h4>
                </div>
                <button className="btn clear-btn" onClick={() => clearCart()}>
                    clear cart
                </button>

            </footer>
        </section>
    )
}

export default CarContainer

import { useGlobalContext } from "../../context"


const CartItem = ({ id, img, title, price, amount }) => {
    const {remove, increase, decrease, toggleAmount} = useGlobalContext();

    return (
        <article className="cart-item">
            <img src={img} alt={title} />
            <div>
                <h4>{title}</h4>
                <h4 className="item-price">${price}</h4>
                <button className="remove-btn" onClick={() => remove(id)}>
                    remove
                </button>
            </div>
            <div>
                <button className="amount-btn" onClick={() => toggleAmount(id, 'inc')}>
                    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
                        <path d='M10.707 7.05L10 6.343 4.343 12l1.414 1.414L10 9.172l4.243 4.242L15.657 12z' />
                    </svg>
                </button>
                <p className="amount">{amount}</p>
                <button className='amount-btn' onClick={() => toggleAmount(id, 'dec')}>
                    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
                        <path d='M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z' />
                    </svg>
                </button>
            </div>
        </article>
    )
}

export default CartItem;

context.jsx

import { createContext, useContext, useEffect, useReducer } from "react";
import reducer from './reducer';
// import cartItems from "./helper/data";
import axios from "axios";

const AppContext = createContext();

export const useGlobalContext = () => {
    return useContext(AppContext);
};


const initialState = {
    loading: false,
    cart: [],
    total: 0,
    amount: 0,
}

const url = 'https://course-api.com/react-useReducer-cart-project';

export const AppProvider = ({ children }) => {
    // const [loading, setLoading] = useState(false);
    const [state, dispatch] = useReducer(reducer, initialState);

    const clearCart = () => {
        dispatch({ type: "CLEAR_CART" })
    };

    const remove = (id) => {
        dispatch({ type: "REMOVE_CART", payload: id })
    };

    const increase = (id) => {
        dispatch({ type: "INCREASE", payload: id })
    };

    const decrease = (id) => {
        dispatch({ type: "DECREASE", payload: id })
    };

    const toggleAmount = (id, type) => {
        dispatch({ type: "TOGGLE_AMOUNT", payload: { id, type } })
    };


    const fetchData = async () => {
        dispatch({ type: "LOADING" });
        const { data } = await axios(url)
        dispatch({ type: "DISPLAY_ITEMS", payload: data })
    };

    useEffect(() => {
        fetchData();
    }, [])


    useEffect(() => {
        dispatch({ type: "GET_TOTALS" })
    }, [state.cart]);

    return (
        <AppContext.Provider value={{
            ...state,
            clearCart,
            remove,
            increase,
            decrease,
            toggleAmount,
            fetchData,
        }}>
            {children}
        </AppContext.Provider>
    )
};

reducer.jsx

export default (state, action) => {
    
    if (action.type === "LOADING") {
        return { ...state, loading: true }
    };

    if (action.type === "CLEAR_CART") {
        return { ...state, cart:[] }
    };

    if (action.type === 'REMOVE_CART') {
        return { ...state, cart: state.cart.filter((cartItem) => cartItem.id !== action.payload)}
    };

    if (action.type === 'DISPLAY_ITEMS') {
        return { ...state, cart: action.payload, loading: false}
    };


    if (action.type === 'GET_TOTALS') {
        let { total, amount } = state.cart.reduce(
            (cartTotal, cartItem) => {
                const { price, amount } = cartItem
                const itemTotal = price * amount

                cartTotal.total += itemTotal
                cartTotal.amount += amount
                return cartTotal
            },
            {
                total: 0,
                amount: 0,
            }
        )
        total = parseFloat(total.toFixed(2))

        return { ...state, total, amount }
    }

    if (action.type === 'INCREASE') {
        let tempCart = state.cart.map((cartItem) => {
            if (cartItem.id === action.payload) {
                return { ...cartItem, amount: cartItem.amount + 1 }
            }
            return cartItem
        })
        return { ...state, cart: tempCart }
    }

    if (action.type === 'DECREASE') {
        let tempCart = state.cart
            .map((cartItem) => {
                if (cartItem.id === action.payload) {
                    return { ...cartItem, amount: cartItem.amount - 1 }
                }
                return cartItem
            })
            .filter((cartItem) => cartItem.amount !== 0)
        return { ...state, cart: tempCart }
    }

    if (action.type === 'TOGGLE_AMOUNT') {
        let tempCart = state.cart
            .map((cartItem) => {
                if (cartItem.id === action.payload.id) {
                    if (action.payload.type === 'inc') {
                        return { ...cartItem, amount: cartItem.amount + 1 }
                    }
                    if (action.payload.type === 'dec') {
                        return { ...cartItem, amount: cartItem.amount - 1 }
                    }
                }
                return cartItem
            })
            .filter((cartItem) => cartItem.amount !== 0)
        return { ...state, cart: tempCart }
    }
    throw new Error('no matching action type')

}
│   App.jsx
│   context.jsx
│   index.css
│   main.jsx
│   reducer.jsx
│
├───assets
│       react.svg
│
├───components
│   │   Navbar.jsx
│   │
│   └───cart
│           CarContainer.jsx
│           CartItem.jsx
│
├───helper
│       data.jsx
│
└───pages
        Home.jsx

cart-reducer's People

Contributors

erhantezer avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.