Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions 자이-백병재/9주차/src/components/CartList.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,57 @@
import { useEffect } from "react";

import CartItem from "./CartItem";
import Modal from "./Modal";
import { useAppDispatch, useSelector } from "../hooks/useCustomRedux";
import { calculateTotals } from "../slices/cartSlice";
import { openModal } from "../slices/modalSlice";

const CartList = () => {
const { cartItems } = useSelector((state) => state.cart);
const { cartItems, total } = useSelector((state) => state.cart);
const { isOpen } = useSelector((state) => state.modal);
const dispatch = useAppDispatch();

useEffect(() => {
dispatch(calculateTotals());
}, [cartItems, dispatch]);

if (cartItems.length < 1) {
return (
<section className='text-center mt-10'>
<header>
<h2 className='text-2xl font-bold'>장바구니</h2>
<h4 className='text-gray-500 mt-4'>장바구니가 비어있습니다.</h4>
</header>
</section>
);
}

return (
<div className="flex flex-col items-center justify-center mb-10">
<ul className="w-full">
<section className="flex flex-col items-center justify-center mb-10 relative">
{isOpen && <Modal />}
<header className="w-full max-w-2xl flex justify-between items-end mb-8 px-2">
<h2 className="text-3xl font-bold">장바구니</h2>

<button
className="text-sm px-3 py-1 text-red-500 border border-red-400 rounded-md hover:bg-red-50 transition cursor-pointer font-medium"
onClick={() => dispatch(openModal())}
>
장바구니 비우기
</button>
</header>

<ul className="w-full max-w-2xl">
{cartItems.map((item) => (
<CartItem key={item.id} lp={item} />
))}
</ul>
</div>

<footer className="w-full max-w-2xl mt-8 border-t border-gray-300 pt-4">
<div className="flex justify-between text-xl font-bold mb-6 px-2">
<h4>총 가격</h4>
<span>{Number(total).toLocaleString()} 원</span>
</div>
</footer>
</section>
);
};

Expand Down
41 changes: 41 additions & 0 deletions 자이-백병재/9주차/src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useAppDispatch } from '../hooks/useCustomRedux';
import { clearCart } from '../slices/cartSlice';
import { closeModal } from '../slices/modalSlice';

const Modal = () => {
const dispatch = useAppDispatch();

return (
<aside className='fixed inset-0 z-50 flex items-center justify-center bg-black/50'>
<div className='bg-white w-80 p-6 rounded shadow-lg text-center'>
<h4 className='font-bold text-lg mb-4'>
장바구니의 모든 상품을 <br /> 삭제하시겠습니까?
</h4>
<div className='flex justify-center gap-4 mt-6'>
<button
type='button'
className='px-4 py-2 border border-red-500 text-red-500 rounded hover:bg-red-50 transition'
onClick={() => {
dispatch(clearCart());
dispatch(closeModal());
}}
>
</button>

<button
type='button'
className='px-4 py-2 border border-gray-400 text-gray-700 rounded hover:bg-gray-50 transition'
onClick={() => {
dispatch(closeModal());
}}
>
아니요
</button>
</div>
</div>
</aside>
);
};

export default Modal;
25 changes: 25 additions & 0 deletions 자이-백병재/9주차/src/slices/modalSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createSlice } from '@reduxjs/toolkit';

interface ModalState {
isOpen: boolean;
}

const initialState: ModalState = {
isOpen: false,
};

const modalSlice = createSlice({
name: 'modal',
initialState,
reducers: {
openModal: (state) => {
state.isOpen = true;
},
closeModal: (state) => {
state.isOpen = false;
},
},
});

export const { openModal, closeModal } = modalSlice.actions;
export default modalSlice.reducer;
2 changes: 2 additions & 0 deletions 자이-백병재/9주차/src/stores/store.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { configureStore } from '@reduxjs/toolkit';
import cartReducer from '../slices/cartSlice';
import modalReducer from '../slices/modalSlice';

export const store = configureStore({
reducer: {
cart: cartReducer,
modal: modalReducer,
},
});

Expand Down