classwork-68

parent 84c27494
This diff is collapsed.
......@@ -9,10 +9,13 @@
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^2.5.1",
"axios": "^1.7.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^7.1.1"
"react-redux": "^9.2.0",
"react-router-dom": "^7.1.1",
"redux": "^5.0.1"
},
"devDependencies": {
"@types/node": "^22.10.1",
......
import { IngredientNames, Ingredients } from '@/interfaces/Ingredients';
import { IngredientNames } from '@/interfaces/Ingredients';
import BuildControl from './BuildControl/BuildControl';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { lessHandler, moreHandler, setOpen } from '@/store/slice/burger.slice';
import './BuildControls.css';
interface Props {
price: number
purchasable: boolean
ingredients: Ingredients
lessHandler: (ingKey: IngredientNames) => void
moreHandler: (ingKey: IngredientNames) => void
setOpen: React.Dispatch<React.SetStateAction<boolean>>
}
const BuildControls = ({ingredients, purchasable, price, setOpen, lessHandler, moreHandler}: Props) => {
const BuildControls = () => {
const dispatch = useAppDispatch()
const {ingredients, totalPrice, purchasable} = useAppSelector(state => state.burger)
const ingKeys = Object.keys(ingredients)
return (
<div className='BuildControls'>
<p>Current Price: <strong>{price}</strong></p>
<p>Current Price: <strong>{totalPrice}</strong></p>
{
ingKeys.map((ingKey, index) => (
<BuildControl
key={ingKey + index}
type={ingKey as IngredientNames}
moreHandler={() => moreHandler(ingKey as IngredientNames)}
lessHandler={() => lessHandler(ingKey as IngredientNames)}
moreHandler={() => dispatch(moreHandler(ingKey as IngredientNames))}
lessHandler={() => dispatch(lessHandler(ingKey as IngredientNames))}
disabled={!Boolean(ingredients[ingKey as IngredientNames])}
/>
))
......@@ -33,7 +31,7 @@ const BuildControls = ({ingredients, purchasable, price, setOpen, lessHandler, m
<button
className="OrderButton"
disabled={!purchasable}
onClick={() => setOpen(true)}
onClick={() => dispatch(setOpen(true))}
>
ORDER NOW
</button>
......
import { ReactNode, useState } from 'react';
import { IngredientNames, Ingredients } from '@/interfaces/Ingredients';
import { ReactNode } from 'react';
import { IngredientNames } from '@/interfaces/Ingredients';
import Ingredient from './Ingredient/Ingredient';
import { useAppSelector } from '@/store/hooks';
import './Burger.css';
interface Props {
ingredients: Ingredients
}
const Burger = () => {
const {ingredients} = useAppSelector(state => state.burger)
const Burger = ({ingredients}: Props) => {
const ingredientKeys = Object.keys(ingredients)
let ingList: ReactNode[] = []
......
import { IngredientNames, Ingredients } from '@/interfaces/Ingredients';
import { IngredientNames } from '@/interfaces/Ingredients';
import { useAppSelector } from '@/store/hooks';
import { useNavigate } from 'react-router-dom';
interface Props {
ingredients: Ingredients;
price: number;
onClick: VoidFunction
}
const OrderSummary = () => {
const navigate = useNavigate()
const {ingredients, totalPrice} = useAppSelector(state => state.burger)
const OrderSummary = ({price, ingredients, onClick}: Props) => {
const ingredientSummary = Object.keys(ingredients)
.map((ingKey) => {
return (
......@@ -25,8 +25,8 @@ const OrderSummary = ({price, ingredients, onClick}: Props) => {
<ul>
{ingredientSummary}
</ul>
<p><strong>Total Price: {price}</strong></p>
<button onClick={onClick}>
<p><strong>Total Price: {totalPrice}</strong></p>
<button onClick={() => navigate('/checkout')}>
Continue
</button>
</>
......
import Burger from "@/components/Burger/Burger";
import Button from "@/components/UI/Button/Button";
import type { Ingredients } from "@/interfaces/Ingredients";
import { MouseEventHandler } from "react";
import { useNavigate } from "react-router-dom";
import "./CheckoutSummary.css";
interface Props {
ingredients: Ingredients;
checkoutContinued: MouseEventHandler<HTMLButtonElement>;
checkoutCancelled: MouseEventHandler<HTMLButtonElement>;
}
const CheckoutSummary = (props: Props) => {
const CheckoutSummary = () => {
const navigate = useNavigate();
return (
<div className="CheckoutSummary">
<h1>We hope it tastes well!</h1>
<div style={{ width: "100%", margin: "auto" }}>
<Burger ingredients={props.ingredients} />
<Burger />
</div>
<Button
btnType="Danger"
click={props.checkoutCancelled}
click={() => navigate(-1)}
>
CANCEL
</Button>
<Button
btnType="Success"
click={props.checkoutContinued}
click={() => navigate('contact-data')}
>
CONTINUE
</Button>
......
import { useAppDispatch } from '@/store/hooks'
import { setOpen } from '@/store/slice/burger.slice'
import './Backdrop.css'
interface Props {
setOpen: React.Dispatch<React.SetStateAction<boolean>>
}
const Backdrop = () => {
const dispatch = useAppDispatch()
const Backdrop = ({setOpen}: Props) => {
return (
<div className='Backdrop' onClick={() => setOpen(false)}></div>
<div className='Backdrop' onClick={() => dispatch(setOpen(false))}></div>
)
}
......
import { ReactNode } from "react"
import './Modal.css'
import Backdrop from "../Backdrop/Backdrop"
import './Modal.css'
type TProps = {
children: ReactNode
open: boolean
setOpen: React.Dispatch<React.SetStateAction<boolean>>
}
const Modal = ({open, setOpen, children}: TProps) => {
const Modal = ({open, children}: TProps) => {
return open ? (
<>
<Backdrop setOpen={setOpen}/>
<Backdrop/>
<div className="Modal">
{children}
</div>
......
......@@ -2,101 +2,19 @@ import BuildControls from '@/components/BuildControls/BuildControls';
import Burger from '@/components/Burger/Burger';
import OrderSummary from '@/components/Burger/OrderSummary/OrderSummary';
import Modal from '@/components/UI/Modal/Modal';
import axiosBase from '@/Config/axiosBase';
import { IngredientNames, IngredientPrices, Ingredients } from '@/interfaces/Ingredients';
import { useEffect, useState } from 'react';
import { createSearchParams, URLSearchParamsInit, useNavigate } from 'react-router-dom'
import { useAppSelector } from '@/store/hooks';
const BurgerBuilder = () => {
const navigate = useNavigate()
const [totalPrice, setTotalPrice] = useState<number>(IngredientPrices.bread);
const [purchasable, setPurchasable] = useState<boolean>(false);
const [open, setOpen] = useState<boolean>(false);
const [ingredients, setIngredients] = useState<Ingredients>({
salad: 0,
cheese: 0,
chicken: 0,
meat: 0
});
const fetchOrders = async () => {
const {data} = await axiosBase.delete('orders/-OGAn20Ai4QF3lYhaufa')
console.log(data)
}
useEffect(() => {
fetchOrders()
}, [])
const updatePurschasable = (ingredients: Ingredients) => {
const sum = Object.keys(ingredients)
.map(ingKey => ingredients[ingKey as IngredientNames])
.reduce((sum, el) => sum + el, 0)
setPurchasable(sum > 0)
}
const moreHandler = (ingKey: IngredientNames) => {
const oldCount = ingredients[ingKey];
const updatedCount = oldCount + 1;
const updatedIngredients = { ...ingredients };
updatedIngredients[ingKey] = updatedCount;
setIngredients(updatedIngredients);
const priceAddition = IngredientPrices[ingKey];
const newPrice = totalPrice + priceAddition;
setTotalPrice(newPrice);
updatePurschasable(updatedIngredients);
}
const lessHandler = (ingKey: IngredientNames) => {
const oldCount = ingredients[ingKey];
if (oldCount <= 0) {
return;
}
const updatedCount = oldCount - 1;
const updatedIngredients = { ...ingredients };
updatedIngredients[ingKey] = updatedCount;
setIngredients(updatedIngredients);
const priceAddition = IngredientPrices[ingKey];
const newPrice = totalPrice - priceAddition;
setTotalPrice(newPrice);
updatePurschasable(updatedIngredients);
}
const onContinueHandler = () => {
const params = createSearchParams(ingredients as unknown as URLSearchParamsInit);
navigate({
pathname: '/checkout',
search: `?${params.toString()}`
})
}
const {open} = useAppSelector(state => state.burger)
return (
<>
<Modal open={open} setOpen={setOpen}>
<OrderSummary
price={totalPrice}
ingredients={ingredients}
onClick={onContinueHandler}
/>
<Modal open={open}>
<OrderSummary/>
</Modal>
<Burger ingredients={ingredients}/>
<BuildControls
ingredients={ingredients}
lessHandler={lessHandler}
moreHandler={moreHandler}
setOpen={setOpen}
price={totalPrice}
purchasable={purchasable}
/>
<Burger/>
<BuildControls/>
</>
)
}
......
import {useRef} from 'react';
import type {Ingredients} from '@/interfaces/Ingredients';
import CheckoutSummary from '@/components/Order/CheckoutSummary/CheckoutSummary';
import { useNavigate, useSearchParams, Outlet } from 'react-router-dom';
const parseSearch = <T extends Object,>(searchParams: URLSearchParams): T => {
return Object.fromEntries(searchParams) as unknown as T;
}
import { Outlet } from 'react-router-dom';
const Checkout = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const ingredients = useRef(parseSearch<Ingredients>(searchParams));
const checkoutCancelledHandler = () => {
navigate(-1);
};
const checkoutContinuedHandler = () => {
navigate('contact-data', {state: {ingredients: ingredients.current}});
};
return (
<>
<CheckoutSummary
ingredients={ingredients.current}
checkoutCancelled={checkoutCancelledHandler}
checkoutContinued={checkoutContinuedHandler}
/>
<CheckoutSummary/>
<Outlet/>
</>
)
......
import Button from "@/components/UI/Button/Button";
import axiosBase from "@/Config/axiosBase";
import axiosBase from "@/config/axiosBase";
import { useState } from "react";
import { ICustomer } from "@/interfaces/checkout";
import { useLocation } from "react-router-dom";
......
......@@ -3,9 +3,12 @@ import { BrowserRouter, Route, Routes } from 'react-router-dom'
import BurgerBuilder from './containers/BurgerBuilder/BurgerBuilder'
import Checkout from './containers/Checkout/Checkout'
import ContactData from './containers/Checkout/ContactData/ContactData'
import { Provider } from 'react-redux'
import { store } from './store'
import './index.css'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<Provider store={store}>
<BrowserRouter>
<Routes>
<Route path='/' element={<BurgerBuilder />}/>
......@@ -14,4 +17,5 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
</Route>
</Routes>
</BrowserRouter>
</Provider>
)
import { useDispatch, useSelector } from 'react-redux'
import type { TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './index'
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
\ No newline at end of file
import { configureStore } from "@reduxjs/toolkit";
import { burgerSlice } from "./slice/burger.slice";
export const store = configureStore({
reducer: {
burger: burgerSlice.reducer
}
})
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export default store;
\ No newline at end of file
import { IngredientNames, IngredientPrices, Ingredients } from "@/interfaces/Ingredients";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface IState {
totalPrice: number
purchasable: boolean
open: boolean
ingredients: Ingredients
}
const initialState: IState = {
totalPrice: IngredientPrices.bread,
purchasable: false,
open: false,
ingredients: {
salad: 0,
cheese: 0,
chicken: 0,
meat: 0
}
}
export const burgerSlice = createSlice({
name: 'burger',
initialState,
reducers: {
setOpen(state, action: PayloadAction<boolean>) {
state.open = action.payload
},
moreHandler(state, action: PayloadAction<IngredientNames>) {
const ingKey = action.payload
const oldCount = state.ingredients[ingKey]
state.ingredients[ingKey] = oldCount + 1
const priceAddition = IngredientPrices[ingKey];
state.totalPrice += priceAddition
const sum = Object.keys(state.ingredients)
.map(ingKey => state.ingredients[ingKey as IngredientNames])
.reduce((sum, el) => sum + el, 0)
state.purchasable = sum > 0
},
lessHandler(state, action: PayloadAction<IngredientNames>) {
const ingKey = action.payload
const oldCount = state.ingredients[ingKey]
if (oldCount <= 0) return;
state.ingredients[ingKey] = oldCount - 1
const priceAddition = IngredientPrices[ingKey];
state.totalPrice -= priceAddition
const sum = Object.keys(state.ingredients)
.map(ingKey => state.ingredients[ingKey as IngredientNames])
.reduce((sum, el) => sum + el, 0)
state.purchasable = sum > 0
}
}
})
export const {setOpen, moreHandler, lessHandler} = burgerSlice.actions
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment