From 1431ec93665adf3dbfb1bb9df2380455456c65b8 Mon Sep 17 00:00:00 2001 From: dgKim1 Date: Fri, 25 Jul 2025 01:45:15 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=EC=83=88=EB=A1=9C=EC=9B=80=20?= =?UTF-8?q?=ED=94=BC=EA=B7=B8=EB=A7=88=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/assets/analytics/arrow_back.svg | 8 +++ .../assets/analytics/arrow_back_active.svg | 8 +++ .../src/assets/analytics/arrow_forward.svg | 8 +++ .../assets/analytics/arrow_forward_active.svg | 8 +++ .../components/BoothSalesRankingCard .tsx | 28 ++++----- .../components/HeaderStatus.tsx | 28 ++++----- .../AdminAnalytics/components/SalesCard.tsx | 58 ++++++++++++++----- .../components/TotalSalesCard.tsx | 44 ++++++++++++++ 8 files changed, 144 insertions(+), 46 deletions(-) create mode 100644 apps/nowait-admin/src/assets/analytics/arrow_back.svg create mode 100644 apps/nowait-admin/src/assets/analytics/arrow_back_active.svg create mode 100644 apps/nowait-admin/src/assets/analytics/arrow_forward.svg create mode 100644 apps/nowait-admin/src/assets/analytics/arrow_forward_active.svg create mode 100644 apps/nowait-admin/src/pages/AdminAnalytics/components/TotalSalesCard.tsx diff --git a/apps/nowait-admin/src/assets/analytics/arrow_back.svg b/apps/nowait-admin/src/assets/analytics/arrow_back.svg new file mode 100644 index 00000000..f8fc195a --- /dev/null +++ b/apps/nowait-admin/src/assets/analytics/arrow_back.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/nowait-admin/src/assets/analytics/arrow_back_active.svg b/apps/nowait-admin/src/assets/analytics/arrow_back_active.svg new file mode 100644 index 00000000..e567d047 --- /dev/null +++ b/apps/nowait-admin/src/assets/analytics/arrow_back_active.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/nowait-admin/src/assets/analytics/arrow_forward.svg b/apps/nowait-admin/src/assets/analytics/arrow_forward.svg new file mode 100644 index 00000000..e3543fb7 --- /dev/null +++ b/apps/nowait-admin/src/assets/analytics/arrow_forward.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/nowait-admin/src/assets/analytics/arrow_forward_active.svg b/apps/nowait-admin/src/assets/analytics/arrow_forward_active.svg new file mode 100644 index 00000000..76bb55df --- /dev/null +++ b/apps/nowait-admin/src/assets/analytics/arrow_forward_active.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/nowait-admin/src/pages/AdminAnalytics/components/BoothSalesRankingCard .tsx b/apps/nowait-admin/src/pages/AdminAnalytics/components/BoothSalesRankingCard .tsx index 4165074c..4f182cd8 100644 --- a/apps/nowait-admin/src/pages/AdminAnalytics/components/BoothSalesRankingCard .tsx +++ b/apps/nowait-admin/src/pages/AdminAnalytics/components/BoothSalesRankingCard .tsx @@ -20,23 +20,15 @@ const BoothSalesRankingCard: React.FC = ({ data, }) => { return ( -
+
-

- {"통계2"} -

-
-
매출 순위
- - - -
+

부스별 판매순위

{date}
-
    +
      {data.map((item) => { const isUp = item.rankChange > 0; const isDown = item.rankChange < 0; @@ -45,15 +37,17 @@ const BoothSalesRankingCard: React.FC = ({ return (
    • -
      - - {item.rank}위 +
      + + {item.rank} -
      +
      {item.name} diff --git a/apps/nowait-admin/src/pages/AdminAnalytics/components/HeaderStatus.tsx b/apps/nowait-admin/src/pages/AdminAnalytics/components/HeaderStatus.tsx index d248cd85..4523520b 100644 --- a/apps/nowait-admin/src/pages/AdminAnalytics/components/HeaderStatus.tsx +++ b/apps/nowait-admin/src/pages/AdminAnalytics/components/HeaderStatus.tsx @@ -1,9 +1,10 @@ import React from "react"; import SalesCard from "./SalesCard"; +import TotalSalesCard from "./TotalSalesCard"; const HeaderStatus = () => { return ( -
      +
      {/* 오늘 매출 */} { percent={13.6} /> {/* 누적 매출 */} -
      {/* 인기 메뉴 TOP 5 */} -
      -
      +
      +

      인기 메뉴 TOP 5

      2025.07.18 금
      -
        +
          {[1, 2, 3, 4, 5].map((rank) => ( -
        • - {rank}위 참치마요주먹밥 - 100개 +
        • + + {rank}

          참치마요주먹밥

          +
          + 100개
        • ))}
        diff --git a/apps/nowait-admin/src/pages/AdminAnalytics/components/SalesCard.tsx b/apps/nowait-admin/src/pages/AdminAnalytics/components/SalesCard.tsx index 00a0d81f..fb7ed164 100644 --- a/apps/nowait-admin/src/pages/AdminAnalytics/components/SalesCard.tsx +++ b/apps/nowait-admin/src/pages/AdminAnalytics/components/SalesCard.tsx @@ -1,3 +1,8 @@ +import backIcon from "../../../assets/analytics/arrow_back.svg"; +import forwardIcon from "../../../assets/analytics/arrow_forward.svg"; +import activeBackIcon from "../../../assets/analytics/arrow_back_active.svg"; +import activeForwardIcon from "../../../assets/analytics/arrow_forward_active.svg"; +import { useState } from "react"; interface SalesCardProps { title: string; // 예: "오늘 매출" 또는 "누적 매출" date: string; @@ -12,23 +17,44 @@ const SalesCard: React.FC = ({ amount, diffAmount, percent, -}) => ( -
        -
        -

        {title}

        -

        {date}

        -
        -
        -
        -

        - {amount.toLocaleString()}원 +}) => { + const [isHoverBack, setIsHoverBack] = useState(false); + const [isHoverForward, setIsHoverForward] = useState(false); + return ( +

        +
        + +

        {title}

        +

        {date}

        +
        + + setIsHoverBack(true)} + onMouseLeave={() => setIsHoverBack(false)} + /> + setIsHoverForward(true)} + onMouseLeave={() => setIsHoverForward(false)} + /> + +
        + +
        +
        +

        + {amount.toLocaleString()}원 +

        + +{percent}% +
        +

        + 어제보다 {diffAmount.toLocaleString()}원 더 벌었어요!

        - +{percent}%
        -

        - 어제보다 {diffAmount.toLocaleString()}원 더 벌었어요! -

        -
        -); + ); +}; export default SalesCard; diff --git a/apps/nowait-admin/src/pages/AdminAnalytics/components/TotalSalesCard.tsx b/apps/nowait-admin/src/pages/AdminAnalytics/components/TotalSalesCard.tsx new file mode 100644 index 00000000..a6e60d58 --- /dev/null +++ b/apps/nowait-admin/src/pages/AdminAnalytics/components/TotalSalesCard.tsx @@ -0,0 +1,44 @@ +import React from "react"; + +interface TotalSalesCardProps { + title: string; // 예: "누적매출" + date: string; // 예: "2025. 07.18 - 07.19" + amount: number; // 예: 1800000 + percent: number; // 예: -0.6 +} + +const TotalSalesCard: React.FC = ({ + title, + date, + amount, + percent, +}) => { + const percentColor = + percent > 0 + ? "text-[#FF5A1F]" // 상승: 주황 + : percent < 0 + ? "text-[#3A75E5]" // 하락: 파랑 + : "text-gray-500"; // 변동 없음 + + return ( +
        + {/* 상단 제목 + 날짜 */} +
        +

        {title}

        +

        {date}

        +
        + + {/* 금액 + 퍼센트 변화 */} +
        +

        + {amount.toLocaleString()}원 +

        + + {percent > 0 ? `+${percent}%` : `${percent}%`} + +
        +
        + ); +}; + +export default TotalSalesCard; From 8a77319abf0b7416ca2beb9570c89727dc6482c0 Mon Sep 17 00:00:00 2001 From: dgKim1 Date: Fri, 25 Jul 2025 02:24:06 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=ED=86=B5=EA=B3=84=20api=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=20=EA=B5=AC=EC=A1=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/hooks/analytics/useGetPopularMenu.tsx | 29 +++++++++++++++++ .../src/hooks/analytics/useGetSalesByDate.tsx | 23 ++++++++++++++ .../src/hooks/analytics/useGetTopSalse.tsx | 31 +++++++++++++++++++ .../pages/AdminAnalytics/AdminAnalytics.tsx | 1 + 4 files changed, 84 insertions(+) create mode 100644 apps/nowait-admin/src/hooks/analytics/useGetPopularMenu.tsx create mode 100644 apps/nowait-admin/src/hooks/analytics/useGetSalesByDate.tsx create mode 100644 apps/nowait-admin/src/hooks/analytics/useGetTopSalse.tsx diff --git a/apps/nowait-admin/src/hooks/analytics/useGetPopularMenu.tsx b/apps/nowait-admin/src/hooks/analytics/useGetPopularMenu.tsx new file mode 100644 index 00000000..1fc73c10 --- /dev/null +++ b/apps/nowait-admin/src/hooks/analytics/useGetPopularMenu.tsx @@ -0,0 +1,29 @@ +import { useQuery } from "@tanstack/react-query"; +import AdminApi from "../../utils/AdminApi"; + +interface PopularMenuItem { + menuId: number; + menuName: string; + totalSalesCount: number; + boothName: string; +} + +interface PopularMenuResponse { + success: boolean; + response: PopularMenuItem[]; +} + +const fetchPopularMenu = async (): Promise => { + const res = await AdminApi.get( + "/admin/statistics/popular-menu" + ); + return res.data.response; +}; + +export const useGetPopularMenu = () => { + return useQuery({ + queryKey: ["popular-menu"], + queryFn: fetchPopularMenu, + staleTime: 1000 * 60 * 5, // 5분 캐싱 + }); +}; diff --git a/apps/nowait-admin/src/hooks/analytics/useGetSalesByDate.tsx b/apps/nowait-admin/src/hooks/analytics/useGetSalesByDate.tsx new file mode 100644 index 00000000..35a5daf4 --- /dev/null +++ b/apps/nowait-admin/src/hooks/analytics/useGetSalesByDate.tsx @@ -0,0 +1,23 @@ +import { useQuery } from "@tanstack/react-query"; +import AdminApi from "../../utils/AdminApi"; + +interface SalesResponse { + success: boolean; + response: number | string; // "해당일 매출 데이터가 없습니다." 또는 숫자형 매출값 +} + +const fetchSalesByDate = async (date: string): Promise => { + const res = await AdminApi.get(`/admin/statistics/sales`, { + params: { date }, + }); + return res.data.response; +}; + +export const useGetSalesByDate = (date: string) => { + return useQuery({ + queryKey: ["sales-by-date", date], + queryFn: () => fetchSalesByDate(date), + enabled: !!date, // 날짜 있을 때만 실행 + staleTime: 1000 * 60, // 1분 캐싱 + }); +}; diff --git a/apps/nowait-admin/src/hooks/analytics/useGetTopSalse.tsx b/apps/nowait-admin/src/hooks/analytics/useGetTopSalse.tsx new file mode 100644 index 00000000..a1f68652 --- /dev/null +++ b/apps/nowait-admin/src/hooks/analytics/useGetTopSalse.tsx @@ -0,0 +1,31 @@ +import { useQuery } from "@tanstack/react-query"; +import AdminApi from "../../utils/AdminApi"; + +interface TopSalesItem { + rank: number; + name: string; + department: string; + salesCount: number; + isCurrentBooth: boolean; + rankChange: number; +} + +interface TopSalesResponse { + success: boolean; + response: TopSalesItem[]; +} + +const fetchTopSales = async (): Promise => { + const res = await AdminApi.get( + "/admin/statistics/top-sales" + ); + return res.data.response; +}; + +export const useGetTopSales = () => { + return useQuery({ + queryKey: ["top-sales"], + queryFn: fetchTopSales, + staleTime: 1000 * 60 * 5, // 5분 캐싱 + }); +}; diff --git a/apps/nowait-admin/src/pages/AdminAnalytics/AdminAnalytics.tsx b/apps/nowait-admin/src/pages/AdminAnalytics/AdminAnalytics.tsx index 431a5343..b76bde79 100644 --- a/apps/nowait-admin/src/pages/AdminAnalytics/AdminAnalytics.tsx +++ b/apps/nowait-admin/src/pages/AdminAnalytics/AdminAnalytics.tsx @@ -55,6 +55,7 @@ const boothData: BoothRanking[] = [ ]; const AdminAnalytics = () => { + // const { data, isLoading, isError } = useGetTopSales(); return (