From 4da439c3ee949fd5e7be464de35ff9462ef95c84 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Jul 2025 02:10:21 +0900 Subject: [PATCH 1/5] =?UTF-8?q?yarn.lock=20=EC=9E=84=EC=8B=9C=20=EC=BB=A4?= =?UTF-8?q?=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yarn.lock | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/yarn.lock b/yarn.lock index db57c228..7125e97f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2833,6 +2833,28 @@ __metadata: languageName: node linkType: hard +"framer-motion@npm:^12.20.1": + version: 12.20.1 + resolution: "framer-motion@npm:12.20.1" + dependencies: + motion-dom: "npm:^12.20.1" + motion-utils: "npm:^12.19.0" + tslib: "npm:^2.4.0" + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: 10c0/b029e39947331eaa2e65b9a8f5cc24fda38ef63e14235f5edb883b67d507484535752fa9b3b0a84661595533b0e09069cdddf609f0c944a7f45006adbe0c46ad + languageName: node + linkType: hard + "fs-minipass@npm:^2.0.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -3729,12 +3751,29 @@ __metadata: dependencies: "@yarnpkg/sdks": "npm:^3.2.2" clsx: "npm:^2.1.1" + framer-motion: "npm:^12.20.1" turbo: "npm:^2.5.4" typescript: "npm:^5.8.3" zustand: "npm:^5.0.6" languageName: unknown linkType: soft +"motion-dom@npm:^12.20.1": + version: 12.20.1 + resolution: "motion-dom@npm:12.20.1" + dependencies: + motion-utils: "npm:^12.19.0" + checksum: 10c0/73a21b32c80b43d1f3f499a4c0ed959f694001de073414d47bd2772a3f307a8c508ce832657dce3bbacaa48e9a1e0cc4aa5ab4ba917f50f2e179f0b6c3a31fdc + languageName: node + linkType: hard + +"motion-utils@npm:^12.19.0": + version: 12.19.0 + resolution: "motion-utils@npm:12.19.0" + checksum: 10c0/e9526e0135c5f596b2d9a242edbd5b5268922b6001d1b9fb63f2fb4b11f891ac63a186eef8dbd80a4011692d70897aa0c6d4d161fcaaaef3dd4ca7aea6263226 + languageName: node + linkType: hard + "mri@npm:^1.2.0": version: 1.2.0 resolution: "mri@npm:1.2.0" @@ -3898,6 +3937,7 @@ __metadata: eslint: "npm:^9.25.0" eslint-plugin-react-hooks: "npm:^5.2.0" eslint-plugin-react-refresh: "npm:^0.4.19" + framer-motion: "npm:^12.20.1" globals: "npm:^16.0.0" postcss: "npm:^8.5.3" react: "npm:^19.1.0" From 0270d93d70e24f7d5653f72ce0ef9b745f59916e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Jul 2025 04:22:56 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=ED=8D=BC=EB=B8=94=EB=A6=AC=EC=8B=B1=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + apps/nowait-admin/tsconfig.app.tsbuildinfo | 2 +- apps/nowait-user/src/assets/icon/minus.svg | 2 +- .../src/components/SmallActionButton.tsx | 30 +++++++++++++ .../src/components/{ => common}/MenuList.tsx | 2 +- .../components/common/QuantitySelector.tsx | 17 ++++--- .../components/common/SuccessMessagePage.tsx | 18 +++++++- .../src/components/order/EmptyCart.tsx | 10 ++--- .../src/components/order/Toast.tsx | 5 +-- .../src/components/order/TotalButton.tsx | 14 +++--- apps/nowait-user/src/global.css | 3 ++ .../src/pages/order/AddMenuPage.tsx | 14 +++--- .../src/pages/order/OrderListPage.tsx | 20 +++++++-- .../nowait-user/src/pages/order/StorePage.tsx | 45 ++++++++++++++----- .../src/pages/reserve/StoreDetailPage.tsx | 2 +- apps/nowait-user/src/stores/cartStore.ts | 20 ++++++--- apps/nowait-user/src/utils/sumUtils.ts | 4 +- package.json | 1 + 18 files changed, 152 insertions(+), 58 deletions(-) create mode 100644 apps/nowait-user/src/components/SmallActionButton.tsx rename apps/nowait-user/src/components/{ => common}/MenuList.tsx (98%) diff --git a/.gitignore b/.gitignore index f21e3db1..7ecf8651 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ dist-ssr server/dist public/dist .yarn/install-state.gz +yarn.lock .pnp .pnp.js diff --git a/apps/nowait-admin/tsconfig.app.tsbuildinfo b/apps/nowait-admin/tsconfig.app.tsbuildinfo index 695e97be..4056a50e 100644 --- a/apps/nowait-admin/tsconfig.app.tsbuildinfo +++ b/apps/nowait-admin/tsconfig.app.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AdminSidebar.tsx","./src/components/ImageBox.tsx","./src/components/MenuItem.tsx","./src/components/MobileMenuBar.tsx","./src/components/RedBadge.tsx","./src/components/closeButton.tsx","./src/hooks/usePostAdminLogin.tsx","./src/hooks/useWindowWidth.tsx","./src/layout/AdminLayout.tsx","./src/pages/AdminAnalytics/AdminAnalytics.tsx","./src/pages/AdminAuth/AdminAuth.tsx","./src/pages/AdminHome/AdminHome.tsx","./src/pages/AdminHome/components/CardBox.tsx","./src/pages/AdminHome/components/RoundTabButton.tsx","./src/pages/AdminHome/components/WaitingCard.tsx","./src/pages/AdminOrders/AdminOrders.tsx","./src/pages/AdminOrders/CookedPage.tsx","./src/pages/AdminOrders/OrderCard.tsx","./src/pages/LoingPage/LoginPage.tsx","./src/pages/NotFound/NotFound.tsx","./src/utils/UserApi.tsx"],"version":"5.8.3"} +{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AdminSidebar.tsx","./src/components/ImageBox.tsx","./src/components/MenuItem.tsx","./src/components/MobileMenuBar.tsx","./src/components/RedBadge.tsx","./src/components/closeButton.tsx","./src/hooks/useGetReservationList.tsx","./src/hooks/usePostAdminLogin.tsx","./src/hooks/useWindowWidth.tsx","./src/layout/AdminLayout.tsx","./src/pages/AdminAnalytics/AdminAnalytics.tsx","./src/pages/AdminAuth/AdminAuth.tsx","./src/pages/AdminHome/AdminHome.tsx","./src/pages/AdminHome/components/CardBox.tsx","./src/pages/AdminHome/components/RoundTabButton.tsx","./src/pages/AdminHome/components/WaitingCard.tsx","./src/pages/AdminOrders/AdminOrders.tsx","./src/pages/AdminOrders/CookedPage.tsx","./src/pages/AdminOrders/OrderCard.tsx","./src/pages/LoingPage/LoginPage.tsx","./src/pages/NotFound/NotFound.tsx","./src/utils/UserApi.tsx"],"errors":true,"version":"5.8.3"} \ No newline at end of file diff --git a/apps/nowait-user/src/assets/icon/minus.svg b/apps/nowait-user/src/assets/icon/minus.svg index 065671b3..f11159e6 100644 --- a/apps/nowait-user/src/assets/icon/minus.svg +++ b/apps/nowait-user/src/assets/icon/minus.svg @@ -1,3 +1,3 @@ - + diff --git a/apps/nowait-user/src/components/SmallActionButton.tsx b/apps/nowait-user/src/components/SmallActionButton.tsx new file mode 100644 index 00000000..4c9cc4e4 --- /dev/null +++ b/apps/nowait-user/src/components/SmallActionButton.tsx @@ -0,0 +1,30 @@ +interface PropsType { + type?: "button" | "submit" | "reset"; + ariaLabel: string; + children: React.ReactNode; + onClick: () => void; + icon?: React.ReactNode; + iconPosition?: "left" | "right"; + className?: string; +} +export const SmallActionButton = ({ + type = "button", + children, + onClick, + ariaLabel, + + className, +}: PropsType) => { + return ( + + ); +}; diff --git a/apps/nowait-user/src/components/MenuList.tsx b/apps/nowait-user/src/components/common/MenuList.tsx similarity index 98% rename from apps/nowait-user/src/components/MenuList.tsx rename to apps/nowait-user/src/components/common/MenuList.tsx index 87a32fac..54140919 100644 --- a/apps/nowait-user/src/components/MenuList.tsx +++ b/apps/nowait-user/src/components/common/MenuList.tsx @@ -1,5 +1,5 @@ import { useNavigate, useParams } from "react-router-dom"; -import type { MenuType } from "../types/order/menu"; +import type { MenuType } from "../../types/order/menu"; const dummyData: MenuType[] = [ { diff --git a/apps/nowait-user/src/components/common/QuantitySelector.tsx b/apps/nowait-user/src/components/common/QuantitySelector.tsx index ba504803..2ddfd90a 100644 --- a/apps/nowait-user/src/components/common/QuantitySelector.tsx +++ b/apps/nowait-user/src/components/common/QuantitySelector.tsx @@ -1,12 +1,13 @@ import React from "react"; -import minus from "../../assets/icon/minus.svg"; -import plus from "../../assets/icon/plus.svg"; +import Minus from "../../assets/icon/minus.svg?react"; +import Plus from "../../assets/icon/plus.svg?react"; interface stateProps { mode: "state"; quantity: number; setQuantity: React.Dispatch>; } + interface storeProps { mode: "store"; id: string; @@ -15,12 +16,16 @@ interface storeProps { increaseQuantity: (id: string, price: number) => void; decreaseQuantity: (id: string, price: number) => void; } + type PropsType = stateProps | storeProps; const QuantitySelector = (props: PropsType) => { + const increaseQuantityButton = () => { + // 전체 주문 페이지에서 수량 컨트롤(로컬 스토리지에 바로 반영) if (props.mode === "store") { props.increaseQuantity(props.id, props.price); + // 메뉴 추가 페이지에서 수량 컨트롤(메뉴 추가 페이지에서 추가하기 클릭 전까지 로컬 스토리지에 반영x) } else if (props.mode === "state") { props.setQuantity(props.quantity + 1); } @@ -36,13 +41,11 @@ const QuantitySelector = (props: PropsType) => { return (

{ className="bg-[#F2F6F9] rounded-[7px] w-[28px] h-[28px] flex items-center justify-center" onClick={increaseQuantityButton} > - 수량 마이너스 아이콘 +

); diff --git a/apps/nowait-user/src/components/common/SuccessMessagePage.tsx b/apps/nowait-user/src/components/common/SuccessMessagePage.tsx index 3e6a6fe2..f063cf20 100644 --- a/apps/nowait-user/src/components/common/SuccessMessagePage.tsx +++ b/apps/nowait-user/src/components/common/SuccessMessagePage.tsx @@ -1,5 +1,7 @@ import PageFooterButton from "../order/PageFooterButton"; import { Button } from "@repo/ui"; +import { SmallActionButton } from "../SmallActionButton"; +import { useNavigate, useParams } from "react-router-dom"; interface PropsType { imageSrc: string; @@ -18,19 +20,31 @@ const SuccessMessagePage = ({ onClick, buttonText, }: PropsType) => { + const navigate = useNavigate(); + const { storeId } = useParams(); return (
{imageAlt}

{title}

-

+

{message}

+ {storeId && ( + navigate(`/${storeId}`)} //주문 내역 페이지로 변경하기 + > + 주문내역 확인 + + )}
+ +
); }; diff --git a/apps/nowait-user/src/components/order/Toast.tsx b/apps/nowait-user/src/components/order/Toast.tsx index fec45fdc..011fb73f 100644 --- a/apps/nowait-user/src/components/order/Toast.tsx +++ b/apps/nowait-user/src/components/order/Toast.tsx @@ -1,4 +1,3 @@ -import React from "react"; import { motion } from "framer-motion"; interface PropsType { @@ -8,8 +7,8 @@ interface PropsType { const Toast = ({ message }: PropsType) => { return ( diff --git a/apps/nowait-user/src/components/order/TotalButton.tsx b/apps/nowait-user/src/components/order/TotalButton.tsx index 4e2129e2..84834ea6 100644 --- a/apps/nowait-user/src/components/order/TotalButton.tsx +++ b/apps/nowait-user/src/components/order/TotalButton.tsx @@ -1,21 +1,23 @@ import { sumQuantity, sumTotalPrice } from "../../utils/sumUtils"; import { useCartStore } from "../../stores/cartStore"; -import { useLocation, useParams } from "react-router-dom"; -const TotalButton = () => { +interface PropsType { + variant?: "default" | "orderPage"; + actionText: string; +} + +const TotalButton = ({ variant = "default", actionText }: PropsType) => { const { cart } = useCartStore(); - const { storeId } = useParams(); - const pathname = useLocation().pathname; return ( <> - {pathname !== `/${storeId}/order` && ( + {variant !== "orderPage" && ( {`${sumQuantity( cart, "quantity" )}`} )} - {`${sumTotalPrice(cart)}원 주문하기`} + {`${sumTotalPrice(cart)}원 ${actionText}`} ); }; diff --git a/apps/nowait-user/src/global.css b/apps/nowait-user/src/global.css index 4b5faff2..d9fb20fd 100644 --- a/apps/nowait-user/src/global.css +++ b/apps/nowait-user/src/global.css @@ -37,11 +37,14 @@ body { display: flex; min-width: 100vw; min-height: 100vh; + background-color: #222; + } #root { max-width: 430px; min-width: 360px; + background-color: #fff; width: 100%; margin: 0 auto; } diff --git a/apps/nowait-user/src/pages/order/AddMenuPage.tsx b/apps/nowait-user/src/pages/order/AddMenuPage.tsx index 826adf23..c6bd16bf 100644 --- a/apps/nowait-user/src/pages/order/AddMenuPage.tsx +++ b/apps/nowait-user/src/pages/order/AddMenuPage.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import QuantitySelector from "../../components/common/QuantitySelector"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useLocation, useNavigate, useParams } from "react-router-dom"; import PageFooterButton from "../../components/order/PageFooterButton"; import { Button } from "@repo/ui"; import type { CartType } from "../../types/order/cart"; @@ -10,6 +10,7 @@ import type { MenuType } from "../../types/order/menu"; const AddMenuPage = () => { const location = useLocation(); const navigate = useNavigate(); + const { storeId } = useParams(); const { id, image, name, description, price } = location.state as MenuType; const [quantity, setQuantity] = useState(1); const { addToCart } = useCartStore(); @@ -22,21 +23,22 @@ const AddMenuPage = () => { price: price * quantity, }; addToCart(item); - navigate(-1); + navigate(`/${storeId}`, { state: { added: true } }); }; return (

- 음식 메뉴 이미지 + 음식 메뉴 이미지

-

{name}

+

{name}

{description}

-
-
+ {/* 메뉴 가격 및 수량 컨트롤 */} +
+

{(price * quantity).toLocaleString()}원

diff --git a/apps/nowait-user/src/pages/order/OrderListPage.tsx b/apps/nowait-user/src/pages/order/OrderListPage.tsx index 0340e181..63e83244 100644 --- a/apps/nowait-user/src/pages/order/OrderListPage.tsx +++ b/apps/nowait-user/src/pages/order/OrderListPage.tsx @@ -8,6 +8,8 @@ import { AnimatePresence } from "framer-motion"; import EmptyCart from "../../components/order/EmptyCart"; import axios from "axios"; import { getTableId } from "../../utils/cartStorage"; +import { SmallActionButton } from "../../components/SmallActionButton"; +import Add from "../../assets/icon/Add.svg?react"; const OrderListPage = () => { const navigate = useNavigate(); @@ -48,13 +50,13 @@ const OrderListPage = () => {

총 주문 {cart.length}건

-
    +
      {cart.map((item) => { return ( { ); })} + navigate(`/${storeId}`)} + icon={} + className="py-5 border-none" + > + 메뉴 추가하기 + +
diff --git a/apps/nowait-user/src/pages/order/StorePage.tsx b/apps/nowait-user/src/pages/order/StorePage.tsx index 636f4fae..0f08f5b7 100644 --- a/apps/nowait-user/src/pages/order/StorePage.tsx +++ b/apps/nowait-user/src/pages/order/StorePage.tsx @@ -1,25 +1,40 @@ -import { useNavigate, useParams } from "react-router-dom"; +import { useLocation, useNavigate, useParams } from "react-router-dom"; import PageFooterButton from "../../components/order/PageFooterButton"; import { Button } from "@repo/ui"; import TotalButton from "../../components/order/TotalButton"; import { useCartStore } from "../../stores/cartStore"; -import MenuList from "../../components/MenuList"; +import MenuList from "../../components/common/MenuList"; import axios from "axios"; - +import { useEffect, useState } from "react"; +import Toast from "../../components/order/Toast"; const StorePage = () => { const navigate = useNavigate(); const { storeId } = useParams(); + const location = useLocation(); + const added = (location.state as { added?: boolean } | null)?.added; const { cart } = useCartStore(); -const SERVER_URI = import.meta.env.VITE_SERVER_URI; - const a = async() => { + const SERVER_URI = import.meta.env.VITE_SERVER_URI; + const [showToast, setShowToast] = useState(false); + const clipBoardDelay = 3000; + + useEffect(() => { + if (added) setShowToast(true); + const timeout = setTimeout(() => { + setShowToast(false); + }, clipBoardDelay); + navigate(location.pathname, { replace: true }); + return () => clearTimeout(timeout); + }, [added]); + + const getMyOrderList = async () => { try { - const res = await axios.get(`${SERVER_URI}/orders/items/7/1`) - console.log(res) + const res = await axios.get(`${SERVER_URI}/orders/items/7/1`); + console.log(res); } catch (error) { - console.log(error) + console.log(error); } - } + }; return (
@@ -30,7 +45,7 @@ const SERVER_URI = import.meta.env.VITE_SERVER_URI;

5번 테이블

+
+ {showToast && } +
{cart && cart.length > 0 && ( - )} diff --git a/apps/nowait-user/src/pages/reserve/StoreDetailPage.tsx b/apps/nowait-user/src/pages/reserve/StoreDetailPage.tsx index b797fe71..5e68b5f0 100644 --- a/apps/nowait-user/src/pages/reserve/StoreDetailPage.tsx +++ b/apps/nowait-user/src/pages/reserve/StoreDetailPage.tsx @@ -1,4 +1,4 @@ -import MenuList from "../../components/MenuList"; +import MenuList from "../../components/common/MenuList"; import Arrow from "../../assets/icon/arrow-right.svg?react"; import MapPin from "../../assets/icon/map-pin.svg?react"; import Clock from "../../assets/icon/clock.svg?react"; diff --git a/apps/nowait-user/src/stores/cartStore.ts b/apps/nowait-user/src/stores/cartStore.ts index 700d9fd5..77a924d0 100644 --- a/apps/nowait-user/src/stores/cartStore.ts +++ b/apps/nowait-user/src/stores/cartStore.ts @@ -1,12 +1,12 @@ import { create } from "zustand"; -import type { CartItem } from "../types/order/cart"; import { persist } from "zustand/middleware"; +import type { CartType } from "../types/order/cart"; interface CartState { - cart: CartItem[]; + cart: CartType[]; increaseQuantity: (id: string, price: number) => void; decreaseQuantity: (id: string, price: number) => void; - addToCart: (item: CartItem) => void; + addToCart: (item: CartType) => void; removeFromCart: (id: string) => void; clearCart: () => void; } @@ -15,10 +15,11 @@ export const useCartStore = create()( persist( (set) => ({ cart: [], + // 메뉴 수량 증가 increaseQuantity: (id, price) => set(({ cart }) => ({ cart: cart.map((item) => { - return item.id === id + return item.menuId === id ? { ...item, quantity: item.quantity + 1, @@ -27,10 +28,11 @@ export const useCartStore = create()( : item; }), })), + //메뉴 수량 감소 decreaseQuantity: (id, price) => set(({ cart }) => ({ cart: cart.map((item) => { - return item.id === id + return item.menuId === id ? { ...item, quantity: item.quantity - 1, @@ -39,15 +41,17 @@ export const useCartStore = create()( : item; }), })), + //메뉴 추가(같은 메뉴가 있다면 기존 수량에 합산, 없으면 새 메뉴 추가) addToCart: (item) => set(({ cart }) => { const existingIndex = cart.findIndex( - (cartItem) => cartItem.id === item.id + (cartItem) => cartItem.menuId === item.menuId ); if (existingIndex !== -1) { const updatedCart = [...cart]; updatedCart[existingIndex] = { ...updatedCart[existingIndex], + price : updatedCart[existingIndex].price + item.price, quantity: updatedCart[existingIndex].quantity + item.quantity, }; return { cart: updatedCart }; // 수량 변경 @@ -55,10 +59,12 @@ export const useCartStore = create()( return { cart: [...cart, item] }; // 새 메뉴 추가 } }), + // 메뉴 삭제 removeFromCart: (id) => set((state) => ({ - cart: state.cart.filter((item) => item.id !== id), + cart: state.cart.filter((item) => item.menuId !== id), })), + // 장바구니 전체 삭제(key는 남아있고, value만 삭제) clearCart: () => set({ cart: [] }), }), { name: "cart-storage" } diff --git a/apps/nowait-user/src/utils/sumUtils.ts b/apps/nowait-user/src/utils/sumUtils.ts index 3294ffde..50346f83 100644 --- a/apps/nowait-user/src/utils/sumUtils.ts +++ b/apps/nowait-user/src/utils/sumUtils.ts @@ -1,4 +1,4 @@ -import type { CartItem } from "../types/order/cart"; +import type { CartType } from "../types/order/cart"; export const sumQuantity = ( items: T[], @@ -7,7 +7,7 @@ export const sumQuantity = ( return items.reduce((acc, cur) => acc + Number(cur[key]), 0); }; -export const sumTotalPrice = (items: CartItem[]) => { +export const sumTotalPrice = (items: CartType[]) => { const totalPrice = items.reduce( (acc, cur) => acc + cur.price, 0 diff --git a/package.json b/package.json index 14d19b23..9be2baa4 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "clsx": "^2.1.1", + "framer-motion": "^12.20.1", "zustand": "^5.0.6" } } From 89efb27c4263e47791bf5872ca469a14f924d2ca Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Jul 2025 07:14:22 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=EC=A0=84=EC=97=AD=20toast=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/nowait-user/src/App.tsx | 2 + .../src/components/common/GlobalToast.tsx | 15 ++++++++ .../src/components/common/MenuList.tsx | 2 +- .../order/{MenuItem.tsx => CartItem.tsx} | 4 +- .../src/components/order/TotalButton.tsx | 2 +- apps/nowait-user/src/hooks/useTimeout.ts | 10 +++++ apps/nowait-user/src/lib/order.ts | 38 ++++++++++++++----- .../src/pages/order/AddMenuPage.tsx | 2 +- .../src/pages/order/OrderListPage.tsx | 23 +++++------ .../src/pages/order/RemittanceRequestPage.tsx | 14 +++---- .../nowait-user/src/pages/order/StorePage.tsx | 27 ++++++++----- apps/nowait-user/src/stores/toastStore.ts | 19 ++++++++++ apps/nowait-user/src/utils/cartStorage.ts | 16 ++++++-- apps/nowait-user/src/utils/sumUtils.ts | 2 +- 14 files changed, 128 insertions(+), 48 deletions(-) create mode 100644 apps/nowait-user/src/components/common/GlobalToast.tsx rename apps/nowait-user/src/components/order/{MenuItem.tsx => CartItem.tsx} (94%) create mode 100644 apps/nowait-user/src/hooks/useTimeout.ts create mode 100644 apps/nowait-user/src/stores/toastStore.ts diff --git a/apps/nowait-user/src/App.tsx b/apps/nowait-user/src/App.tsx index 37a97a5f..14619a84 100644 --- a/apps/nowait-user/src/App.tsx +++ b/apps/nowait-user/src/App.tsx @@ -1,6 +1,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import Router from "./routes/Router"; import { BrowserRouter } from "react-router-dom"; +import GlobalToast from "./components/common/GlobalToast"; function App() { const queryClient = new QueryClient(); @@ -9,6 +10,7 @@ function App() { + ); diff --git a/apps/nowait-user/src/components/common/GlobalToast.tsx b/apps/nowait-user/src/components/common/GlobalToast.tsx new file mode 100644 index 00000000..7539b842 --- /dev/null +++ b/apps/nowait-user/src/components/common/GlobalToast.tsx @@ -0,0 +1,15 @@ +import { useToastStore } from "../../stores/toastStore"; +import Toast from "../order/Toast"; + +const GlobalToast = () => { + const { message, isOpen } = useToastStore(); + console.log("렌더") + if (!isOpen) return null; + return ( +
+ +
+ ); +}; + +export default GlobalToast; diff --git a/apps/nowait-user/src/components/common/MenuList.tsx b/apps/nowait-user/src/components/common/MenuList.tsx index 54140919..0faeb051 100644 --- a/apps/nowait-user/src/components/common/MenuList.tsx +++ b/apps/nowait-user/src/components/common/MenuList.tsx @@ -27,7 +27,7 @@ const dummyData: MenuType[] = [ }, ]; -const MenuList = ({ mode } : { mode: string }) => { +const MenuList = ({ mode }: { mode: string }) => { const navigate = useNavigate(); const { storeId } = useParams(); return ( diff --git a/apps/nowait-user/src/components/order/MenuItem.tsx b/apps/nowait-user/src/components/order/CartItem.tsx similarity index 94% rename from apps/nowait-user/src/components/order/MenuItem.tsx rename to apps/nowait-user/src/components/order/CartItem.tsx index 75a9559b..90392667 100644 --- a/apps/nowait-user/src/components/order/MenuItem.tsx +++ b/apps/nowait-user/src/components/order/CartItem.tsx @@ -11,7 +11,7 @@ interface PropsType { quantity: number; } -const MenuItem = ({ id, name, price, quantity }: PropsType) => { +const CartItem = ({ id, name, price, quantity }: PropsType) => { const { removeFromCart, increaseQuantity, decreaseQuantity } = useCartStore(); const [isRemoving, setIsRemoving] = useState(false); return ( @@ -53,4 +53,4 @@ const MenuItem = ({ id, name, price, quantity }: PropsType) => { ); }; -export default MenuItem; +export default CartItem; diff --git a/apps/nowait-user/src/components/order/TotalButton.tsx b/apps/nowait-user/src/components/order/TotalButton.tsx index 84834ea6..1ad19b4e 100644 --- a/apps/nowait-user/src/components/order/TotalButton.tsx +++ b/apps/nowait-user/src/components/order/TotalButton.tsx @@ -17,7 +17,7 @@ const TotalButton = ({ variant = "default", actionText }: PropsType) => { "quantity" )}`} )} - {`${sumTotalPrice(cart)}원 ${actionText}`} + {`${sumTotalPrice(cart).toLocaleString()}원 ${actionText}`} ); }; diff --git a/apps/nowait-user/src/hooks/useTimeout.ts b/apps/nowait-user/src/hooks/useTimeout.ts new file mode 100644 index 00000000..3edb83bd --- /dev/null +++ b/apps/nowait-user/src/hooks/useTimeout.ts @@ -0,0 +1,10 @@ +import { useEffect } from "react"; + +const useTimeout = (delay:number) => { + useEffect(() => { + const timeOut = setTimeout(() => console.log(), delay); + return () => { + clearTimeout(timeOut); + }; + }); +}; diff --git a/apps/nowait-user/src/lib/order.ts b/apps/nowait-user/src/lib/order.ts index 834406e7..b8e368ae 100644 --- a/apps/nowait-user/src/lib/order.ts +++ b/apps/nowait-user/src/lib/order.ts @@ -8,21 +8,27 @@ interface OrderType { items: { menuId: string; quantity: number }[]; } -// interface ServerResponse { -// success: boolean; -// response: { -// hasNext: boolean; -// storeReadDtos: Store[]; -// }; -// } +interface ServerResponse { + success: boolean; + response: { + orderId: number; + storeId: number; + storeName: string; + sessionId: string; + depositorName: string; + orderItems: { menuId: string; quantity: number }[]; + status: string; + totalPrice: number; + }; +} export const createOrder = async ( - storeId: string | undefined, + storeId: string, tableId: string, payload: OrderType ) => { try { - const res = await axios.post( + const res = await axios.post( `${SERVER_URI}/orders/create/${storeId}/${tableId}`, payload ); @@ -31,3 +37,17 @@ export const createOrder = async ( console.log(error); } }; + +export const getMyOrderList = async ( + storeId: string | undefined, + tableId: string +) => { + try { + const res = await axios.get( + `${SERVER_URI}/orders/items/${storeId}/${tableId}` + ); + return res.data; + } catch (error) { + console.log(error); + } +}; diff --git a/apps/nowait-user/src/pages/order/AddMenuPage.tsx b/apps/nowait-user/src/pages/order/AddMenuPage.tsx index c6bd16bf..4d1f47d5 100644 --- a/apps/nowait-user/src/pages/order/AddMenuPage.tsx +++ b/apps/nowait-user/src/pages/order/AddMenuPage.tsx @@ -23,7 +23,7 @@ const AddMenuPage = () => { price: price * quantity, }; addToCart(item); - navigate(`/${storeId}`, { state: { added: true } }); + navigate(`/${storeId}`, { state: { added: true }, replace: true }); }; return (
diff --git a/apps/nowait-user/src/pages/order/OrderListPage.tsx b/apps/nowait-user/src/pages/order/OrderListPage.tsx index 63e83244..d8eddd29 100644 --- a/apps/nowait-user/src/pages/order/OrderListPage.tsx +++ b/apps/nowait-user/src/pages/order/OrderListPage.tsx @@ -1,4 +1,4 @@ -import MenuItem from "../../components/order/MenuItem"; +import CartItem from "../../components/order/CartItem"; import PageFooterButton from "../../components/order/PageFooterButton"; import { Button } from "@repo/ui"; import { useNavigate, useParams } from "react-router-dom"; @@ -6,10 +6,11 @@ import TotalButton from "../../components/order/TotalButton"; import { useCartStore } from "../../stores/cartStore"; import { AnimatePresence } from "framer-motion"; import EmptyCart from "../../components/order/EmptyCart"; -import axios from "axios"; -import { getTableId } from "../../utils/cartStorage"; +import { getTableId, setSessionData } from "../../utils/cartStorage"; import { SmallActionButton } from "../../components/SmallActionButton"; import Add from "../../assets/icon/Add.svg?react"; +import { sumTotalPrice } from "../../utils/sumUtils"; +import { createOrder } from "../../lib/order"; const OrderListPage = () => { const navigate = useNavigate(); @@ -17,8 +18,6 @@ const OrderListPage = () => { const tableId = getTableId(); const { cart } = useCartStore(); - const SERVER_URI = import.meta.env.VITE_SERVER_URI; - const orderHandleButton = async () => { try { const payload = { @@ -27,17 +26,15 @@ const OrderListPage = () => { menuId: item.menuId, quantity: item.quantity, })), + totalPrice: sumTotalPrice(cart), }; - const url = `${SERVER_URI}/orders/create/${storeId}/${tableId}`; - const res = await axios.post(url, payload); - if (res.status === 201 && res.data.success) { - console.log(res); - localStorage.setItem("sessionId", res.data.response.sessionId); - localStorage.setItem("depositorName", res.data.response.depositorName); + const res = await createOrder(storeId!, tableId!, payload); + if (res?.success) { + //세션 아이디, 입금자명 로컬스토리지 저장 + setSessionData(res.response.sessionId, res.response.depositorName); } else { console.log("error"); } - navigate(`/${storeId}/payer`); } catch (e) { console.log(e); @@ -54,7 +51,7 @@ const OrderListPage = () => { {cart.map((item) => { return ( - { - const [showToast, setShowToast] = useState(false); - + // const [showToast, setShowToast] = useState(false); + const { showToast } = useToastStore(); const navigate = useNavigate(); const { storeId } = useParams(); const modal = useModal(); const price = useLocation().state; const account = "기업은행 611-000202-01-010"; - const clipBoardDelay = 3000; + const clipBoardDelay = 2000; const handleCopyClipBoard = useThrottle(() => { navigator.clipboard.writeText(account); - setShowToast(true); - setTimeout(() => setShowToast(false), clipBoardDelay); + showToast("블라", 2000); }, clipBoardDelay); return ( @@ -50,9 +50,9 @@ const RemittanceRequestPage = () => {

{price}원

-
+ {/*
{showToast && } -
+
*/} {modal.isOpen && ( navigate(`/${storeId}/order/success`)} diff --git a/apps/nowait-user/src/pages/order/StorePage.tsx b/apps/nowait-user/src/pages/order/StorePage.tsx index 0f08f5b7..832028e1 100644 --- a/apps/nowait-user/src/pages/order/StorePage.tsx +++ b/apps/nowait-user/src/pages/order/StorePage.tsx @@ -1,36 +1,45 @@ -import { useLocation, useNavigate, useParams } from "react-router-dom"; +import { + useLocation, + useNavigate, + useNavigation, + useParams, +} from "react-router-dom"; import PageFooterButton from "../../components/order/PageFooterButton"; import { Button } from "@repo/ui"; import TotalButton from "../../components/order/TotalButton"; import { useCartStore } from "../../stores/cartStore"; import MenuList from "../../components/common/MenuList"; -import axios from "axios"; import { useEffect, useState } from "react"; import Toast from "../../components/order/Toast"; +import { getMyOrderList } from "../../lib/order"; const StorePage = () => { const navigate = useNavigate(); const { storeId } = useParams(); + const tableId = localStorage.getItem("tableId"); const location = useLocation(); const added = (location.state as { added?: boolean } | null)?.added; const { cart } = useCartStore(); - const SERVER_URI = import.meta.env.VITE_SERVER_URI; const [showToast, setShowToast] = useState(false); - const clipBoardDelay = 3000; + const addMenuDelay = 2000; + //메뉴 추가 시 toast 띄우기 useEffect(() => { if (added) setShowToast(true); + const timeout = setTimeout(() => { setShowToast(false); - }, clipBoardDelay); + }, addMenuDelay); + navigate(location.pathname, { replace: true }); + return () => clearTimeout(timeout); }, [added]); - const getMyOrderList = async () => { + const getMyOrderListButton = async () => { try { - const res = await axios.get(`${SERVER_URI}/orders/items/7/1`); - console.log(res); + const res = await getMyOrderList(storeId, tableId!); + navigate(`/${storeId}/myOrderList`, { state: res }); } catch (error) { console.log(error); } @@ -45,7 +54,7 @@ const StorePage = () => {

5번 테이블