diff --git a/apps/nowait-admin/src/hooks/useGetOrderList.tsx b/apps/nowait-admin/src/hooks/useGetOrderList.tsx new file mode 100644 index 00000000..160a6a30 --- /dev/null +++ b/apps/nowait-admin/src/hooks/useGetOrderList.tsx @@ -0,0 +1,51 @@ +import { useQuery } from "@tanstack/react-query"; +import adminApi from "../utils/AdminApi"; + +// 주문 데이터 인터페이스 +export interface Order { + id: number; + tableId: number; + depositorName: string; + totalPrice: number | null; + status: "WAITING_FOR_PAYMENT" | "COOKING" | "COOKED"; + createdAt: string; +} + +interface OrderResponse { + success: boolean; + response: Order[]; + error: null; +} + +// 주문 목록을 가져오는 함수 +const fetchOrders = async (): Promise => { + try { + const token = localStorage.getItem("adminToken"); + const res = await adminApi.get(`/admin/orders/1`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + // 응답 데이터가 유효한지 확인 + if (res.data && res.data.success && Array.isArray(res.data.response)) { + return res.data.response; + } + + // 응답이 유효하지 않으면 빈 배열 반환 + return []; + } catch (error) { + console.error("주문 목록 조회 실패:", error); + // 에러가 발생해도 빈 배열을 반환하여 undefined 방지 + return []; + } +}; + +// 주문 목록을 가져오는 hook +export const useGetOrderList = () => { + return useQuery({ + queryKey: ["orders"], + queryFn: fetchOrders, + refetchInterval: 30000, // 30초마다 자동 새로고침 + }); +}; diff --git a/apps/nowait-admin/src/pages/AdminOrders/AdminOrders.tsx b/apps/nowait-admin/src/pages/AdminOrders/AdminOrders.tsx index e4ee32d1..84de4a3d 100644 --- a/apps/nowait-admin/src/pages/AdminOrders/AdminOrders.tsx +++ b/apps/nowait-admin/src/pages/AdminOrders/AdminOrders.tsx @@ -2,93 +2,53 @@ import { useState } from "react"; import { PaymentCard, CookCard } from "./OrderCard"; import RefreshIcon from "../../assets/refresh.svg?react"; import CookedPage from "./CookedPage"; +import { useGetOrderList } from "../../hooks/useGetOrderList"; const AdminOrders = () => { const [activeTab, setActiveTab] = useState<"전체" | "조리 완료">("전체"); - // 통합 주문 데이터 - const ordersData = [ - { - id: 1, - tableNumber: 5, - minutesAgo: 10, - status: "payment_waiting", // 입금 대기 - menus: [ - { name: "김치찌개", quantity: 2 }, - { name: "된장찌개", quantity: 1 }, - ], - totalAmount: 26000, - createdAt: "오후 6:50", - }, - { - id: 2, - tableNumber: 2, - minutesAgo: 5, - status: "payment_waiting", // 입금 대기 - menus: [ - { name: "비빔밥", quantity: 1 }, - { name: "된장국", quantity: 1 }, - ], - totalAmount: 18000, - createdAt: "오후 6:55", - }, - { - id: 3, - tableNumber: 7, - minutesAgo: 15, - status: "payment_waiting", // 입금 대기 - menus: [ - { name: "불고기", quantity: 2 }, - { name: "냉면", quantity: 1 }, - { name: "공기밥", quantity: 1 }, - ], - totalAmount: 35000, - createdAt: "오후 6:45", - }, - { - id: 4, - tableNumber: 3, - minutesAgo: 20, - status: "cooking", // 조리 중 - menus: [ - { name: "메뉴명한줄로떨어져야야야야피피피피", quantity: 1 }, - { name: "된장된장찌개", quantity: 1 }, - { name: "계란후라이", quantity: 1 }, - { name: "달달한 쏘야볶음", quantity: 1 }, - ], - totalAmount: 28000, - createdAt: "오후 7:24", - }, - { - id: 5, - tableNumber: 6, - minutesAgo: 30, - status: "cooked", // 조리 완료 - menus: [ - { name: "묵은지 삼겹 김치 말이찜", quantity: 2 }, - { name: "공기밥", quantity: 2 }, - { name: "된장국", quantity: 1 }, - ], - totalAmount: 23000, - createdAt: "오후 7:24", - }, - { - id: 6, - tableNumber: 1, - minutesAgo: 25, - status: "cooked", // 조리 완료 - menus: [{ name: "김치볶음밥", quantity: 1 }], - totalAmount: 8000, - createdAt: "오후 19:24", - }, - ]; + // API에서 주문 데이터 가져오기 + const { data: orders = [], isLoading, error, refetch } = useGetOrderList(); + + // 시간 포맷팅 함수 (17:30 형식) + const getFormattedTime = (createdAt: string) => { + const date = new Date(createdAt); + const hours = date.getHours().toString().padStart(2, "0"); + const minutes = date.getMinutes().toString().padStart(2, "0"); + return `${hours}:${minutes}`; + }; + + // 시간 포맷팅 함수 + const formatTime = (createdAt: string) => { + const date = new Date(createdAt); + const hours = date.getHours(); + const minutes = date.getMinutes(); + const period = hours >= 12 ? "오후" : "오전"; + const displayHours = hours > 12 ? hours - 12 : hours === 0 ? 12 : hours; + return `${period} ${displayHours}:${minutes.toString().padStart(2, "0")}`; + }; + + // 테스트를 위해 일부 주문을 다른 상태로 변경 + const testOrders = orders.map((order, index) => { + if (index % 3 === 1) { + return { ...order, status: "COOKING" as const }; + } else if (index % 3 === 2) { + return { ...order, status: "COOKED" as const }; + } + return order; + }); // 상태별 데이터 필터링 - const paymentWaitingData = ordersData.filter( - (order) => order.status === "payment_waiting" + const paymentWaitingData = testOrders.filter( + (order) => order.status === "WAITING_FOR_PAYMENT" ); - const cookingData = ordersData.filter((order) => order.status === "cooking"); - const cookedData = ordersData.filter((order) => order.status === "cooked"); + const cookingData = testOrders.filter((order) => order.status === "COOKING"); + const cookedData = testOrders.filter((order) => order.status === "COOKED"); + + // 새로고침 핸들러 + const handleRefresh = () => { + refetch(); + }; return (
@@ -117,7 +77,10 @@ const AdminOrders = () => {
-
+
@@ -128,26 +91,39 @@ const AdminOrders = () => {
입금 대기
-
5
+
+ {paymentWaitingData.length} +
-
+
테이블
입금 내역
- {paymentWaitingData.map((payment) => ( - total + menu.quantity, - 0 - )} - totalAmount={payment.totalAmount} - /> - ))} + {isLoading ? ( +
+
로딩 중...
+
+ ) : paymentWaitingData.length > 0 ? ( + paymentWaitingData.map((payment) => ( + + )) + ) : ( +
+
+ {error + ? "데이터를 불러오지 못했습니다." + : "아직 입금 대기 중인 주문이 없어요!"} +
+
+ )}
@@ -155,10 +131,12 @@ const AdminOrders = () => {
조리 중
-
3
+
+ {cookingData.length} +
-
+
테이블
메뉴 @@ -166,18 +144,50 @@ const AdminOrders = () => {
수량
- {cookingData.map((cooking) => ( - - ))} + {isLoading ? ( +
+
로딩 중...
+
+ ) : cookingData.length > 0 ? ( + cookingData.map((cooking) => ( + + )) + ) : ( +
+
+ {error + ? "데이터를 불러오지 못했습니다." + : "조리 중인 주문이 없어요!"} +
+
+ )}
) : ( - + ({ + id: order.id, + tableNumber: order.tableId, + depositorName: order.depositorName, + menus: + index % 2 === 0 + ? [{ name: "김치찌개", quantity: 1 }] + : [ + { name: "김치찌개", quantity: 1 }, + { name: "된장찌개", quantity: 2 }, + { name: "불고기", quantity: 1 }, + ], + totalAmount: order.totalPrice || 0, + createdAt: getFormattedTime(order.createdAt), + }))} + isLoading={isLoading} + error={error} + /> )}
); diff --git a/apps/nowait-admin/src/pages/AdminOrders/CookedPage.tsx b/apps/nowait-admin/src/pages/AdminOrders/CookedPage.tsx index 8fd8f3aa..98b72d78 100644 --- a/apps/nowait-admin/src/pages/AdminOrders/CookedPage.tsx +++ b/apps/nowait-admin/src/pages/AdminOrders/CookedPage.tsx @@ -4,13 +4,16 @@ interface CookedPageProps { cookedOrders: Array<{ id: number; tableNumber: number; + depositorName: string; menus: Array<{ name: string; quantity: number }>; totalAmount: number; createdAt: string; }>; + isLoading?: boolean; + error?: unknown; } -const CookedPage = ({ cookedOrders }: CookedPageProps) => { +const CookedPage = ({ cookedOrders, isLoading, error }: CookedPageProps) => { return (
{/* 조리 완료 블럭 */} @@ -24,26 +27,49 @@ const CookedPage = ({ cookedOrders }: CookedPageProps) => {
{/* 조리 완료 헤더 */} -
-
테이블
-
메뉴명
-
개수
-
금액
-
+
+
+ 테이블 +
+
+ 입금자 +
+
+ 메뉴 +
+
+ 금액 +
+
주문 시간
-
+
- {cookedOrders.map((order) => ( - - ))} + {isLoading ? ( +
+
로딩 중...
+
+ ) : cookedOrders.length > 0 ? ( + cookedOrders.map((order) => ( + + )) + ) : ( +
+
+ {error + ? "데이터를 불러오지 못했습니다." + : "조리 완료된 주문이 없어요!"} +
+
+ )}
diff --git a/apps/nowait-admin/src/pages/AdminOrders/OrderCard.tsx b/apps/nowait-admin/src/pages/AdminOrders/OrderCard.tsx index f7baeb1f..d7799d20 100644 --- a/apps/nowait-admin/src/pages/AdminOrders/OrderCard.tsx +++ b/apps/nowait-admin/src/pages/AdminOrders/OrderCard.tsx @@ -1,14 +1,14 @@ interface PaymentCardProps { tableNumber: number; - minutesAgo: number; - menuCount: number; + timeText: string; + depositorName: string; totalAmount: number; } const PaymentCard = ({ tableNumber, - minutesAgo, - menuCount, + timeText, + depositorName, totalAmount, }: PaymentCardProps) => { return ( @@ -19,12 +19,10 @@ const PaymentCard = ({
-
- {minutesAgo}분 전 -
+
{timeText}
- 메뉴 {menuCount}개 + {depositorName}
@@ -81,6 +79,7 @@ const CookCard = ({ tableNumber, menus }: CookCardProps) => { interface CookedCardProps { tableNumber: number; + depositorName: string; menus: Array<{ name: string; quantity: number }>; totalAmount: number; createdAt: string; @@ -88,6 +87,7 @@ interface CookedCardProps { const CookedCard = ({ tableNumber, + depositorName, menus, totalAmount, createdAt, @@ -96,33 +96,29 @@ const CookedCard = ({ const firstMenuName = menus[0]?.name || ""; const remainingMenuCount = menus.length - 1; const menuDisplayText = - remainingMenuCount > 0 + menus.length > 1 ? `${firstMenuName} 외 ${remainingMenuCount}개` : firstMenuName; - // 총 메뉴 개수 계산 - const totalMenuCount = menus.reduce( - (total, menu) => total + menu.quantity, - 0 - ); - return ( -
-
+
+
{tableNumber}번
-
- {menuDisplayText} +
+ {depositorName}
-
- {totalMenuCount}개 +
+ {menuDisplayText}
-
+
{totalAmount.toLocaleString()}원
-
{createdAt}
-
-
+
+ {createdAt} +
+
+
주문 복구