Skip to content

Commit 820da81

Browse files
authored
Merge pull request #78 from GTable/feature/user/order-style
feat: 주문 페이지 모달 및 아이템 삭제 애니메이션 적용
2 parents 7a3b5ff + 4ced190 commit 820da81

File tree

5 files changed

+93
-40
lines changed

5 files changed

+93
-40
lines changed

apps/nowait-user/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@tanstack/react-query": "^5.80.10",
1515
"@tanstack/react-virtual": "^3.13.11",
1616
"axios": "^1.10.0",
17+
"framer-motion": "^12.20.1",
1718
"react": "^19.1.0",
1819
"react-dom": "^19.1.0",
1920
"react-router-dom": "^7.6.2",

apps/nowait-user/src/components/order/ConfirmModal.tsx

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,67 @@
1-
import React from "react";
1+
import React, { useState } from "react";
22
import { Button } from "@repo/ui";
33
import Portal from "../common/modal/Portal";
4+
import { AnimatePresence, motion } from "framer-motion";
45

56
interface PropsType {
67
open: () => void;
78
close: () => void;
89
}
910

1011
const ConfirmModal = ({ open, close }: PropsType) => {
12+
// const [isVisible, setIsVisible] = useState(true);
13+
14+
// const handleClose = () => {
15+
// setIsVisible(false);
16+
// };
17+
18+
19+
// const handleExitComplete = () => {
20+
// if (!isVisible) close();
21+
// };
22+
1123
return (
1224
<Portal>
13-
<div
14-
onClick={close}
15-
className="fixed inset-0 z-50 bg-black/30"
16-
>
17-
<div className="absolute left-1/2 bottom-8 -translate-x-1/2 w-[calc(100%-20px)] max-w-[430px] bg-white rounded-[20px] px-5 pt-9">
18-
<h1 className="text-headline-22-bold mb-2">이체 완료 하셨나요?</h1>
19-
<h2 className="text-16-regular text-black-70 mb-12">
20-
아직 이체하지 않으셨다면 주문이
21-
<br /> 정상적으로 접수되지 않을 수 있어요.
22-
<br />
23-
계좌로 송금을 마치셨다면 버튼을 눌러주세요.
24-
</h2>
25-
<Button fullWidth={true} textColor="#ffffff" onClick={open}>
26-
이체했어요
27-
</Button>
28-
<Button
29-
fullWidth={true}
30-
backgroundColor="transparent"
31-
textColor="#888888"
25+
<AnimatePresence onExitComplete={close}>
26+
{/* {isVisible && ( */}
27+
<motion.div
28+
initial={{ opacity: 0 }}
29+
animate={{ opacity: 1 }}
30+
exit={{ opacity: 0 }}
3231
onClick={close}
32+
className="fixed inset-0 z-50 bg-black/30"
3333
>
34-
아직 안했어요
35-
</Button>
36-
</div>
37-
</div>
34+
<motion.div
35+
initial={{ y: "100%" }}
36+
animate={{ y: 0 }}
37+
exit={{ y: "100%" }}
38+
transition={{ duration: 0.3, ease: "easeInOut" }}
39+
className="absolute left-1/2 bottom-8 -translate-x-1/2 w-[calc(100%-20px)] max-w-[430px] bg-white rounded-[20px] px-5 pt-9"
40+
>
41+
<h1 className="text-headline-22-bold mb-2">
42+
이체 완료 하셨나요?
43+
</h1>
44+
<h2 className="text-16-regular text-black-70 mb-12">
45+
아직 이체하지 않으셨다면 주문이
46+
<br /> 정상적으로 접수되지 않을 수 있어요.
47+
<br />
48+
계좌로 송금을 마치셨다면 버튼을 눌러주세요.
49+
</h2>
50+
<Button fullWidth={true} textColor="#ffffff" onClick={open}>
51+
이체했어요
52+
</Button>
53+
<Button
54+
fullWidth={true}
55+
backgroundColor="transparent"
56+
textColor="#888888"
57+
onClick={close}
58+
>
59+
아직 안했어요
60+
</Button>
61+
</motion.div>
62+
</motion.div>
63+
{/* )} */}
64+
</AnimatePresence>
3865
</Portal>
3966
);
4067
};

apps/nowait-user/src/components/order/MenuItem.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import QuantitySelector from "../common/QuantitySelector";
22
import close from "../../assets/icon/close.svg";
33
import { useCartStore } from "../../stores/cartStore";
4+
import { motion } from "framer-motion";
5+
import { useState } from "react";
46

57
interface PropsType {
68
id: string;
@@ -11,8 +13,16 @@ interface PropsType {
1113

1214
const MenuItem = ({ id, name, price, quantity }: PropsType) => {
1315
const { removeFromCart, increaseQuantity, decreaseQuantity } = useCartStore();
16+
const [isRemoving, setIsRemoving] = useState(false);
1417
return (
15-
<li className="-mx-5 border-b border-[#ececec]">
18+
<motion.li
19+
layout
20+
initial={{ opacity: 1, x: 0 }}
21+
animate={{ opacity: 1, x: 0 }}
22+
exit={{ opacity: 0, x: -100 }}
23+
transition={{ duration: 0.3 }}
24+
className="-mx-5 border-b border-[#ececec]"
25+
>
1626
<div className="w-full p-5">
1727
<div className="flex justify-between items-start">
1828
<div className="max-w-[12.5rem]">
@@ -21,7 +31,12 @@ const MenuItem = ({ id, name, price, quantity }: PropsType) => {
2131
</h1>
2232
<h2 className="text-title-18-bold">{price.toLocaleString()}</h2>
2333
</div>
24-
<button onClick={() => removeFromCart(id)}>
34+
<button
35+
onClick={() => {
36+
setIsRemoving(true);
37+
setTimeout(() => removeFromCart(id), 300);
38+
}}
39+
>
2540
<img className="text-black-50" src={close} alt="메뉴 삭제 아이콘" />
2641
</button>
2742
</div>
@@ -34,7 +49,7 @@ const MenuItem = ({ id, name, price, quantity }: PropsType) => {
3449
decreaseQuantity={decreaseQuantity}
3550
/>
3651
</div>
37-
</li>
52+
</motion.li>
3853
);
3954
};
4055

apps/nowait-user/src/components/order/Toast.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import React from "react";
2+
import { motion } from "framer-motion";
23

34
interface PropsType {
45
message: string;
56
}
67

78
const Toast = ({ message }: PropsType) => {
89
return (
9-
<div className="flex justify-center items-center px-4 py-2.5 rounded-[999px] bg-[#F2F6F9] fade-in">
10+
<motion.div
11+
initial={{ y: "100%" }}
12+
animate={{ y: 0 }}
13+
transition={{ duration: 0.4, ease: "easeInOut" }}
14+
className="flex justify-center items-center px-4 py-2.5 rounded-[999px] bg-[#F2F6F9]"
15+
>
1016
<p className="text-14-medium text-navy-70">{message}</p>
11-
</div>
17+
</motion.div>
1218
);
1319
};
1420

apps/nowait-user/src/pages/order/OrderListPage.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import { Button } from "@repo/ui";
44
import { useNavigate, useParams } from "react-router-dom";
55
import TotalButton from "../../components/order/TotalButton";
66
import { useCartStore } from "../../stores/cartStore";
7+
import { AnimatePresence } from "framer-motion";
78
import EmptyCart from "../../components/order/EmptyCart";
89
import { sumTotalPrice } from "../../utils/sumUtils";
910
import axios from "axios";
1011
import { getTableId } from "../../utils/cartStorage";
1112

13+
1214
const OrderListPage = () => {
1315
const navigate = useNavigate();
1416
const { storeId } = useParams();
@@ -46,17 +48,19 @@ const OrderListPage = () => {
4648
<div className="flex-1 overflow-y-auto pt-7 px-5">
4749
<h1 className="text-headline-24-bold mb-5">총 주문 {cart.length}</h1>
4850
<ul>
49-
{cart.map((item) => {
50-
return (
51-
<MenuItem
52-
key={item.id}
53-
id={item.id}
54-
name={item.name}
55-
price={item.price}
56-
quantity={item.quantity}
57-
/>
58-
);
59-
})}
51+
<AnimatePresence mode="sync">
52+
{cart.map((item) => {
53+
return (
54+
<MenuItem
55+
key={item.id}
56+
id={item.id}
57+
name={item.name}
58+
price={item.price}
59+
quantity={item.quantity}
60+
/>
61+
);
62+
})}
63+
</AnimatePresence>
6064
</ul>
6165
</div>
6266
<PageFooterButton>

0 commit comments

Comments
 (0)