diff --git a/.yarn/cache/turbo-npm-2.5.5-8b364ceb83-f51ec29528.zip b/.yarn/cache/turbo-npm-2.5.5-8b364ceb83-f51ec29528.zip new file mode 100644 index 00000000..95f2703e Binary files /dev/null and b/.yarn/cache/turbo-npm-2.5.5-8b364ceb83-f51ec29528.zip differ diff --git a/.yarn/cache/turbo-windows-64-npm-2.5.5-996d83a7c5-10c0.zip b/.yarn/cache/turbo-windows-64-npm-2.5.5-996d83a7c5-10c0.zip new file mode 100644 index 00000000..79956437 Binary files /dev/null and b/.yarn/cache/turbo-windows-64-npm-2.5.5-996d83a7c5-10c0.zip differ diff --git a/apps/nowait-user/.gitignore b/apps/nowait-user/.gitignore index a547bf36..adc90cd1 100644 --- a/apps/nowait-user/.gitignore +++ b/apps/nowait-user/.gitignore @@ -11,6 +11,7 @@ node_modules dist dist-ssr *.local +yarn.lock # Editor directories and files .vscode/* diff --git a/apps/nowait-user/public/default-menu.png b/apps/nowait-user/public/default-menu.png new file mode 100644 index 00000000..9b3d7cc4 Binary files /dev/null and b/apps/nowait-user/public/default-menu.png differ diff --git a/apps/nowait-user/src/api/order.ts b/apps/nowait-user/src/api/order.ts index b937bf3c..eee0b132 100644 --- a/apps/nowait-user/src/api/order.ts +++ b/apps/nowait-user/src/api/order.ts @@ -1,54 +1,29 @@ import axios from "axios"; +import type { + CreateOrderServerResponse, + OrderDetailsServerResponse, + OrderType, +} from "../types/order/order"; -const SERVER_URI = import.meta.env.VITE_SERVER_URI; +export const api = axios.create({ + withCredentials: true, +}); -interface OrderType { - depositorName: string; - items: { menuId: string; quantity: number }[]; -} - -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, tableId: string, payload: OrderType -) => { - try { - const res = await axios.post( - `${SERVER_URI}/orders/create/${storeId}/${tableId}`, - payload - ); - return res.data; - } catch (error) { - console.log(error); - } +): Promise => { + const res = await api.post(`/orders/create/${storeId}/${tableId}`, payload); + return res.data; }; -//주문내역 가져오기 -export const getMyOrderList = async ( +//주문 내역 조회 +export const getOrderDetails = 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); - } +): Promise => { + const res = await api.get(`/orders/items/${storeId}/${tableId}`); + return res.data; }; diff --git a/apps/nowait-user/src/assets/icon/back.svg b/apps/nowait-user/src/assets/icon/back.svg new file mode 100644 index 00000000..4df0049a --- /dev/null +++ b/apps/nowait-user/src/assets/icon/back.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/nowait-user/src/assets/icon/fullfieldBookmark.svg b/apps/nowait-user/src/assets/icon/fullfieldBookmark.svg index b6015ec2..23a67172 100644 --- a/apps/nowait-user/src/assets/icon/fullfieldBookmark.svg +++ b/apps/nowait-user/src/assets/icon/fullfieldBookmark.svg @@ -1,3 +1,3 @@ - - + + diff --git a/apps/nowait-user/src/components/EmptyPage.tsx b/apps/nowait-user/src/components/EmptyPage.tsx new file mode 100644 index 00000000..9cb4bdc6 --- /dev/null +++ b/apps/nowait-user/src/components/EmptyPage.tsx @@ -0,0 +1,32 @@ +import { useNavigate, useParams } from "react-router-dom"; +import { SmallActionButton } from "./SmallActionButton"; +import Add from "../assets/icon/Add.svg?react"; + +interface PropsType { + mode: "default" | "orderDetails"; + title: string; + buttonText: string; +} + +const EmptyPage = ({ mode, title, buttonText }: PropsType) => { + const navigate = useNavigate(); + const { storeId } = useParams(); + return ( +
+

+ {title} +

+ navigate(`/${storeId}`)} + > + {buttonText} + + +
+ ); +}; + +export default EmptyPage; diff --git a/apps/nowait-user/src/components/SmallActionButton.tsx b/apps/nowait-user/src/components/SmallActionButton.tsx index 6c8512b2..4599a81a 100644 --- a/apps/nowait-user/src/components/SmallActionButton.tsx +++ b/apps/nowait-user/src/components/SmallActionButton.tsx @@ -1,4 +1,5 @@ interface PropsType { + mode? : "default" | "orderDetails" type?: "button" | "submit" | "reset"; ariaLabel: string; children: React.ReactNode; @@ -6,6 +7,7 @@ interface PropsType { className?: string; } export const SmallActionButton = ({ + mode = "default", type = "button", children, onClick, @@ -16,7 +18,7 @@ export const SmallActionButton = ({ diff --git a/apps/nowait-user/src/components/common/SuccessMessagePage.tsx b/apps/nowait-user/src/components/common/SuccessMessagePage.tsx index 87962b13..8822bd30 100644 --- a/apps/nowait-user/src/components/common/SuccessMessagePage.tsx +++ b/apps/nowait-user/src/components/common/SuccessMessagePage.tsx @@ -38,7 +38,7 @@ const SuccessMessagePage = ({ navigate(`/${storeId}`)} //주문 내역 페이지로 변경하기 + onClick={() => navigate(`/${storeId}/orderDetails`)} > 주문내역 확인 diff --git a/apps/nowait-user/src/components/order/Header.tsx b/apps/nowait-user/src/components/order/Header.tsx new file mode 100644 index 00000000..c1c61d49 --- /dev/null +++ b/apps/nowait-user/src/components/order/Header.tsx @@ -0,0 +1,21 @@ +import Back from "../../assets/icon/back.svg?react"; + +interface PropsType { + title: string; +} + +const Header = ({ title }: PropsType) => { + return ( +
+
+ +

{title}

+
+
+
+ ); +}; + +export default Header; diff --git a/apps/nowait-user/src/pages/order/addMenu/AddMenuPage.tsx b/apps/nowait-user/src/pages/order/addMenu/AddMenuPage.tsx index 60ac1230..884f1021 100644 --- a/apps/nowait-user/src/pages/order/addMenu/AddMenuPage.tsx +++ b/apps/nowait-user/src/pages/order/addMenu/AddMenuPage.tsx @@ -30,7 +30,7 @@ const AddMenuPage = () => { return (
-

+

음식 메뉴 이미지

diff --git a/apps/nowait-user/src/pages/order/home/RedirectToStorePage.tsx b/apps/nowait-user/src/pages/order/home/RedirectToStorePage.tsx index 63d4d314..a985e410 100644 --- a/apps/nowait-user/src/pages/order/home/RedirectToStorePage.tsx +++ b/apps/nowait-user/src/pages/order/home/RedirectToStorePage.tsx @@ -1,13 +1,27 @@ import { useEffect } from "react"; import { useNavigate, useParams } from "react-router-dom"; +import { useCartStore } from "../../../stores/cartStore"; const RedirectToStorePage = () => { const { storeId, tableId } = useParams(); const navigate = useNavigate(); + const { cart, clearCart } = useCartStore(); useEffect(() => { if (storeId && tableId) { - //테이블 아이디 로컬스토리지 저장(다른 방법 생각) + //장바구니에 메뉴를 담고 다른 주점이나 테이블로 이동했을 때 장바구니 초기화 + const prevStoreId = localStorage.getItem("storeId"); + const prevTableId = localStorage.getItem("tableId"); + //이전 storeId, tableId랑 비교 + const isDifferentStore = prevStoreId && prevStoreId !== storeId; + const isDifferentTable = prevTableId && prevTableId !== tableId; + //이전 storeId 또는 tableId가 변경 되었고, 장바구니에 메뉴가 담겨있을 시 장바구니 비우기 + if ((isDifferentStore || isDifferentTable) && cart.length > 0) { + localStorage.removeItem("depositorName") + clearCart(); + } + //테이블 아이디 로컬스토리지 저장 + localStorage.setItem("storeId", storeId); localStorage.setItem("tableId", tableId); navigate(`/${storeId}`, { replace: true }); } diff --git a/apps/nowait-user/src/pages/order/home/components/StoreHeader.tsx b/apps/nowait-user/src/pages/order/home/components/StoreHeader.tsx index 5be9590b..c5c7f9a6 100644 --- a/apps/nowait-user/src/pages/order/home/components/StoreHeader.tsx +++ b/apps/nowait-user/src/pages/order/home/components/StoreHeader.tsx @@ -1,19 +1,8 @@ import { useNavigate, useParams } from "react-router-dom"; -import { getMyOrderList } from "../../../../api/order"; const StoreHeader = () => { const navigate = useNavigate(); const { storeId } = useParams(); - const tableId = localStorage.getItem("tableId"); - - const getMyOrderListButton = async () => { - try { - const res = await getMyOrderList(storeId, tableId!); - navigate(`/${storeId}/myOrderList`, { state: res }); - } catch (error) { - console.log(error); - } - }; return (
@@ -22,7 +11,7 @@ const StoreHeader = () => {

5번 테이블

+
음식 메뉴 이미지 diff --git a/apps/nowait-user/src/pages/order/remittance/components/PayerInput.tsx b/apps/nowait-user/src/pages/order/remittance/components/PayerInput.tsx index 4b4e050c..fae45214 100644 --- a/apps/nowait-user/src/pages/order/remittance/components/PayerInput.tsx +++ b/apps/nowait-user/src/pages/order/remittance/components/PayerInput.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; interface PropsType { value: string; @@ -8,6 +8,14 @@ interface PropsType { } const PayerInput = ({ value, setValue, payerError, payerFocus }: PropsType) => { + const depositorName = localStorage.getItem("depositorName"); + //재주문 시 입금자명 input에 이전 입금자명 설정 + useEffect(() => { + if (depositorName !== null) { + setValue(depositorName); + } + }, []); + return (
diff --git a/apps/nowait-user/src/pages/order/remittance/components/RemitOptions.tsx b/apps/nowait-user/src/pages/order/remittance/components/RemitOptions.tsx index aaaf1812..fa37ef4e 100644 --- a/apps/nowait-user/src/pages/order/remittance/components/RemitOptions.tsx +++ b/apps/nowait-user/src/pages/order/remittance/components/RemitOptions.tsx @@ -9,10 +9,14 @@ import RadioGroup from "./RadioGroup"; import Radio from "./Radio"; import SlideToggle from "./SlideToggle"; -const RemitOptions = () => { +interface PropsType { + remitValue: string; + setRemitValue: React.Dispatch>; +} + +const RemitOptions = ({ remitValue, setRemitValue }: PropsType) => { const { showToast } = useToastStore(); const [remitDescriptionToggle, setRemitDescriptionToggle] = useState(false); - const [remitValue, setRemitValue] = useState("kakao"); const account = `카카오뱅크 3333-04-2095277`; const clipBoardDelay = 2000; diff --git a/apps/nowait-user/src/pages/order/remittenceWait/RemittanceWaitPage.tsx b/apps/nowait-user/src/pages/order/remittenceWait/RemittanceWaitPage.tsx index bd4c451d..c2a4df87 100644 --- a/apps/nowait-user/src/pages/order/remittenceWait/RemittanceWaitPage.tsx +++ b/apps/nowait-user/src/pages/order/remittenceWait/RemittanceWaitPage.tsx @@ -1,11 +1,41 @@ -import React from "react"; -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 { useCartStore } from "../../../stores/cartStore"; +import { sumTotalPrice } from "../../../utils/sumUtils"; +import { createOrder } from "../../../api/order"; const RemittanceWaitPage = () => { const navigate = useNavigate(); + const location = useLocation(); + const payer = location.state; const { storeId } = useParams(); + const tableId = localStorage.getItem("tableId"); + const { cart, clearCart } = useCartStore(); + const totalPrice = sumTotalPrice(cart); + + const orderButton = async () => { + try { + const payload = { + depositorName: payer, + items: cart.map((item) => ({ + menuId: item.menuId, + quantity: item.quantity, + })), + totalPrice, + }; + const res = await createOrder(storeId!, tableId!, payload); + if (res?.success) { + //세션 아이디, 입금자명 로컬스토리지 저장 + localStorage.setItem("depositorName", res.response.depositorName); + } + //장바구니 비우기 + clearCart(); + } catch (error) { + console.log(error); + } + navigate(`/${storeId}/order/success`); + }; return (
@@ -15,19 +45,16 @@ const RemittanceWaitPage = () => { src="" alt="이체 대기중인 이미지" /> -

- 아직 주문이 완료되지 않았어요 -

+

이체가 진행되고 있어요

+ 아직 주문이 완료되지 않았어요 +
이체를 완료하셨다면 버튼을 눌러주세요

- diff --git a/apps/nowait-user/src/pages/waiting/menuDetail/StoreMenuDetailPage.tsx b/apps/nowait-user/src/pages/waiting/menuDetail/StoreMenuDetailPage.tsx deleted file mode 100644 index 8ae1052c..00000000 --- a/apps/nowait-user/src/pages/waiting/menuDetail/StoreMenuDetailPage.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { useLocation } from "react-router-dom"; -import type { MenuType } from "../../../types/order/menu"; - -const StoreMenuDetailPage = () => { - const location = useLocation(); - const { image, name, description } = location.state as MenuType; - - return ( -
-
-

- 음식 메뉴 이미지 -

-
-

{name}

-

{description}

-
-
-
- ); -}; - -export default StoreMenuDetailPage; diff --git a/apps/nowait-user/src/pages/waiting/storeDetail/StoreDetailPage.tsx b/apps/nowait-user/src/pages/waiting/storeDetail/StoreDetailPage.tsx index cd712b26..cbd104fb 100644 --- a/apps/nowait-user/src/pages/waiting/storeDetail/StoreDetailPage.tsx +++ b/apps/nowait-user/src/pages/waiting/storeDetail/StoreDetailPage.tsx @@ -6,6 +6,7 @@ import { Button } from "@repo/ui"; import { useNavigate, useParams } from "react-router-dom"; import MenuList from "../../../components/common/MenuList"; import IsBookmark from "./components/IsBookmark"; +import { getBookmark } from "../../../api/reservation"; const TAG = [ { id: 1, type: "default", tag: "태그 추가" }, @@ -17,11 +18,20 @@ const StoreDetailPage = () => { const navigate = useNavigate(); const { id } = useParams(); + const a = async () => { + try { + const res = await getBookmark(); + console.log(res); + } catch (error) { + console.log(error) + } + }; + return (

- 음식 메뉴 이미지 + 학과 주점 대표 이미지

@@ -54,6 +64,7 @@ const StoreDetailPage = () => {
+

diff --git a/apps/nowait-user/src/pages/waiting/storeDetail/components/IsBookmark.tsx b/apps/nowait-user/src/pages/waiting/storeDetail/components/IsBookmark.tsx index 714e213a..1aacbd59 100644 --- a/apps/nowait-user/src/pages/waiting/storeDetail/components/IsBookmark.tsx +++ b/apps/nowait-user/src/pages/waiting/storeDetail/components/IsBookmark.tsx @@ -14,7 +14,6 @@ interface BookmarkType { const IsBookmark = () => { const { id } = useParams(); - const { createBookmarkMutate, deleteBookmarkMutate } = useBookmarkMutation(); const { data: isBookmark } = useQuery({ queryKey: ["bookmark", id], diff --git a/apps/nowait-user/src/routes/Router.tsx b/apps/nowait-user/src/routes/Router.tsx index 7a57a430..35e3b70c 100644 --- a/apps/nowait-user/src/routes/Router.tsx +++ b/apps/nowait-user/src/routes/Router.tsx @@ -12,9 +12,10 @@ import KakaoRedirectHandler from "../pages/login/KakaoRedirectHandler"; import AuthGuard from "../components/AuthGuard"; import PageTransitionWrapper from "../components/layout/PageTransitionWrapper"; import WaitingPartySizeForm from "../pages/waiting/waitingPartysize/WaitingPartySizeForm"; -import StoreMenuDetailPage from "../pages/waiting/menuDetail/StoreMenuDetailPage"; import WaitingSummaryPage from "../pages/waiting/WaitingSummary/WaitingSummaryPage"; import AddMenuPage from "../pages/order/addMenu/AddMenuPage"; +import RemittanceWaitPage from "../pages/order/remittenceWait/RemittanceWaitPage"; +import OrderDetailsPage from "../pages/order/orderDetails/OrderDetailsPage"; import RemittancePage from "../pages/order/remittance/RemittancePage"; // AuthGuard로 래핑하는 헬퍼 함수 @@ -32,10 +33,10 @@ const Router = () => { const location = useLocation(); return ( // - - {/* 공개 라우트 - 인증 불필요 */} - } /> - } /> + + {/* 공개 라우트 - 인증 불필요 */} + } /> + } /> {/* 보호된 라우트 - 인증 필요 (구체적인 경로 먼저) */} { path="/:storeId/remittance" element={withTransition(RemittancePage)} /> - + + {/* 보호된 라우트 - 인증 필요 */} { } /> } /> - } - /> } diff --git a/apps/nowait-user/src/types/order/cart.ts b/apps/nowait-user/src/types/order/cart.ts index eee9b3c4..9e4dc1b8 100644 --- a/apps/nowait-user/src/types/order/cart.ts +++ b/apps/nowait-user/src/types/order/cart.ts @@ -1,3 +1,4 @@ +//장바구니 메뉴 타입 export interface CartType { menuId: string; name: string; diff --git a/apps/nowait-user/src/types/order/menu.ts b/apps/nowait-user/src/types/order/menu.ts index b56ede4b..13e21ba6 100644 --- a/apps/nowait-user/src/types/order/menu.ts +++ b/apps/nowait-user/src/types/order/menu.ts @@ -1,3 +1,4 @@ +//음식 메뉴 타입 export interface MenuType { id: string; image: string; diff --git a/apps/nowait-user/src/types/order/order.ts b/apps/nowait-user/src/types/order/order.ts new file mode 100644 index 00000000..7e7f8303 --- /dev/null +++ b/apps/nowait-user/src/types/order/order.ts @@ -0,0 +1,41 @@ +//주문 생성 payload 타입 +export interface OrderType { + depositorName: string; + items: { menuId: string; quantity: number }[]; +} + +//주문 생성 요청 성공 시 오는 응답 타입 +export interface CreateOrderServerResponse { + success: boolean; + response: { + orderId: number; + storeId: number; + storeName: string; + sessionId: string; + depositorName: string; + orderItems: { menuId: string; quantity: number }[]; + status: string; + totalPrice: number; + }; +} + +//주문 내역 타입 +export interface OrderDetailsType { + orderId: string; + menuName: string; + price: number; + quantity: number; +} + +//주문 status 유니온 타입 +export type OrderStatus = "WAITING_FOR_PAYMENT" | "COOKING" | "COOKED"; + +//주문 내역 조회 시 성공 시 응답 타입 +export interface OrderDetailsServerResponse { + success: boolean; + response: { + items: OrderDetailsType[]; + status: OrderStatus; + }[]; + status: OrderStatus; +} diff --git a/apps/nowait-user/src/utils/cartStorage.ts b/apps/nowait-user/src/utils/cartStorage.ts index 8f50e87f..95ef5cc8 100644 --- a/apps/nowait-user/src/utils/cartStorage.ts +++ b/apps/nowait-user/src/utils/cartStorage.ts @@ -2,19 +2,6 @@ import type { CartType } from "../types/order/cart"; const CART_KEY = "cart"; -export const getTableId = (): string => { - const tableId = localStorage.getItem("tableId"); - return tableId || ""; -}; - - -//주문 시 세션 아이디, 입금자명 로컬스토리지에 저장 -export const setSessionData = (sessionId: string, depositorName: string) => { - localStorage.setItem("sessionId", sessionId); - localStorage.setItem("depositorName", depositorName); -}; - - export const getcart = (): CartType[] => { const cartString = localStorage.getItem(CART_KEY); try { diff --git a/apps/nowait-user/vite.config.ts b/apps/nowait-user/vite.config.ts index dcfe7827..ca840260 100644 --- a/apps/nowait-user/vite.config.ts +++ b/apps/nowait-user/vite.config.ts @@ -1,8 +1,25 @@ -import { defineConfig } from "vite"; +import { defineConfig, loadEnv } from "vite"; import react from "@vitejs/plugin-react"; import svgr from "vite-plugin-svgr"; // https://vite.dev/config/ -export default defineConfig({ - plugins: [react(), svgr()], +// export default defineConfig({ +// plugins: [react(), svgr()], +// }); + +// https://vite.dev/config/ +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd()); + return { + plugins: [react(), svgr()], + server: { + proxy: { + // /orders 로 시작하는 요청은 모두 백엔드서버 주소로 전달 + "/orders": { + target: env.VITE_SERVER_URI, + changeOrigin: true, + }, + }, + }, + }; });