Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { useMutation } from "@tanstack/react-query";
import AdminApi from "../../utils/AdminApi";

interface UpdateReservationParams {
storeId: number;
userId: number;
status: "WAITING" | "CALLING" | "CONFIRMED" | "CANCELLED" | "NO_SHOW";
}

export const useUpdateReservationStatus = () => {
return useMutation({
mutationFn: async ({
reservationId,
storeId,
userId,
status,
}: {
reservationId: number;
status: "WAITING" | "CALLING" | "CONFIRMED" | "CANCELLED" | "NO_SHOW";
}) => {
}: UpdateReservationParams) => {
const res = await AdminApi.patch(
`/reservations/admin/updates/${reservationId}`,
{ status }
`/reservations/admin/update/${storeId}/${userId}/${status}`
);
return res.data;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface PopularMenuItem {
menuName: string;
totalSalesCount: number;
boothName: string;
soldCount: number;
}

interface PopularMenuResponse {
Expand Down
14 changes: 11 additions & 3 deletions apps/nowait-admin/src/hooks/analytics/useGetSalesByDate.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { useQuery } from "@tanstack/react-query";
import AdminApi from "../../utils/AdminApi";

interface SalesData {
storeId: number;
date: string;
todaySalesSum: number;
yesterdaySalesSum: number;
cumulativeSalesBeforeYesterday: number;
ObjectallZero: boolean;
}

interface SalesResponse {
success: boolean;
response: number | string; // "해당일 매출 데이터가 없습니다." 또는 숫자형 매출값
response: SalesData | string;
}

const fetchSalesByDate = async (date: string): Promise<number | string> => {
const fetchSalesByDate = async (date: string): Promise<SalesData | string> => {
const res = await AdminApi.get<SalesResponse>(`/admin/statistics/sales`, {
params: { date },
});
Expand Down
25 changes: 21 additions & 4 deletions apps/nowait-admin/src/pages/AdminAnalytics/AdminAnalytics.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { useGetPopularMenu } from "../../hooks/analytics/useGetPopularMenu";
import { useGetSalesByDate } from "../../hooks/analytics/useGetSalesByDate";
import { useGetTopSales } from "../../hooks/analytics/useGetTopSalse";
import BoothSalesRankingCard from "./components/BoothSalesRankingCard ";
import HeaderStatus from "./components/HeaderStatus";

Expand Down Expand Up @@ -55,11 +58,25 @@ const boothData: BoothRanking[] = [
];

const AdminAnalytics = () => {
// const { data, isLoading, isError } = useGetTopSales();
const today = new Date();
const formatted = today.toISOString().slice(0, 10);
const { data: boothRank } = useGetTopSales();
const { data: sales } = useGetSalesByDate(formatted);
const { data: popularMenu } = useGetPopularMenu();
console.log(boothRank, "부스별 판매순위");
console.log(sales, "판매량");
console.log(popularMenu, "인기 메뉴");
if (typeof sales === "string") {
return <p>매출 데이터가 없습니다.</p>;
}

return (
<div className="w-full">
<HeaderStatus />
<BoothSalesRankingCard date="2025.07.18 금" data={boothData} />
<div className="w-full flex flex-col items-center justify-center ">
<HeaderStatus sales={sales} popularMenu={popularMenu} />
<BoothSalesRankingCard
date={formatted}
data={boothRank?.length === 0 ? boothData : boothRank ?? []}
/>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const BoothSalesRankingCard: React.FC<BoothSalesRankingCardProps> = ({
data,
}) => {
return (
<div className="bg-white max-h-[364px] rounded-[12px] p-6 shadow-sm w-full h-full mt-[10px]">
<div className="bg-white max-h-[364px] rounded-[12px] p-6 shadow-sm w-[754px] max-h-[50%] mt-[10px]">
<div className="flex justify-between mb-4">
<div className="flex flex-col">
<h2 className="text-title-18-bold text-navy-80">부스별 판매순위</h2>
Expand All @@ -43,27 +43,30 @@ const BoothSalesRankingCard: React.FC<BoothSalesRankingCardProps> = ({
: ""
}`}
>
<div className="flex items-center w-[710px]">
<span className="text-[14px] font-semibold text-gray-600 w-[30px] h-[23px]">
<div className="flex items-center w-1/2">
<span className="text-14-semibold text-gray-600 w-[30px] h-[23px]">
{item.rank}
</span>
<div className="w-6 h-6 rounded-full bg-[#5A6ACF] mr-[10px]" />
<div className="flex flex-col text-sm">
<span className="font-medium text-black">{item.name}</span>
<div className="w-9 h-9 rounded-full bg-[#5A6ACF] mr-[10px]" />
<div className="flex items-center text-sm gap-2">
<span className="text-16-semibold text-black">
{item.name}
</span>
<span className="text-[12px] text-gray-400">
{item.department}
</span>
</div>
</div>

<div className="flex items-center gap-3">
<span className="text-[14px] font-medium text-black">
<div className="flex items-center justify-between w-1/2 gap-3">
<div></div>
<span className="flex text-16-medium text-black">
{item.salesCount}건
</span>

{/* 랭크 변화 표시 */}
<div
className={`text-[12px] font-semibold flex items-center justify-center rounded-full w-[30px] h-[20px] ${
className={`text-14-semibold w-[40px] h-[29px] py-[5px] flex items-center justify-center rounded-[8px] ${
isUp
? "bg-[#FFF1F0] text-[#FF5A1F]"
: isDown
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,74 @@
import React from "react";
import SalesCard from "./SalesCard";
import TotalSalesCard from "./TotalSalesCard";

const HeaderStatus = () => {
interface HeaderStatusProps {
sales?: {
storeId: number;
date: string;
todaySalesSum: number;
yesterdaySalesSum: number;
cumulativeSalesBeforeYesterday: number;
ObjectallZero: boolean;
};
popularMenu?: {
menuId: number;
menuName: string;
soldCount: number;
}[];
}

const HeaderStatus: React.FC<HeaderStatusProps> = ({ sales, popularMenu }) => {
const todayAmount = sales?.todaySalesSum ?? 0;
const yesterdayAmount = sales?.yesterdaySalesSum ?? 0;
const diffAmount = todayAmount - yesterdayAmount;
const percent = yesterdayAmount
? parseFloat(((diffAmount / yesterdayAmount) * 100).toFixed(1))
: 0;

const todayDate = sales?.date ?? "오늘";
const yesterdayDate = "어제";

return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-[10px] max-h-[352px]">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-[10px] w-[754px] h-[50%]">
<div className="flex flex-col gap-[10px]">
{/* 오늘 매출 */}
<SalesCard
today={{
date: "2025.07.18 금",
amount: 920000,
diffAmount: 120000,
percent: 13.6,
date: todayDate,
amount: todayAmount,
diffAmount,
percent,
}}
previous={{
date: "2025.07.17 목",
amount: 800000,
date: yesterdayDate,
amount: yesterdayAmount,
}}
/>

{/* 누적 매출 */}
<TotalSalesCard
title="누적매출"
date="2025. 07.18 - 07.19"
amount={1800000}
percent={-0.6}
date={`${todayDate} 기준`}
amount={(sales?.cumulativeSalesBeforeYesterday ?? 0) + todayAmount}
percent={percent}
/>
</div>
{/* 인기 메뉴 TOP 5 */}
<div className="flex flex-col bg-white rounded-xl p-6 shadow max-h-[352px]">

<div className="flex flex-col bg-white rounded-xl p-6">
<div className="flex flex-col mb-[25px]">
<p className="text-title-18-bold text-navy-80">인기 메뉴 TOP 5</p>
<span className="text-13-regular text-black-60">2025.07.18 금</span>
<span className="text-13-regular text-black-60">{todayDate}</span>
</div>
<ul>
{[1, 2, 3, 4, 5].map((rank) => (
<li key={rank} className="flex justify-between h-[52px]">
{(popularMenu ?? []).slice(0, 5).map((menu, i) => (
<li key={menu.menuId} className="flex justify-between h-[52px]">
<span className="flex text-16-bold gap-[10px]">
{rank} <p className="text-16-semibold">참치마요주먹밥</p>
{i + 1} <p className="text-16-semibold">{menu.menuName}</p>
</span>
<span className="text-16-medium">100개</span>
<span className="text-16-medium">{menu.soldCount}개</span>
</li>
))}
</ul>
</div>
</div>
);
};

export default HeaderStatus;
47 changes: 31 additions & 16 deletions apps/nowait-admin/src/pages/AdminAnalytics/components/SalesCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const SalesCard: React.FC<SalesCardProps> = ({ today, previous }) => {
const [isHoverForward, setIsHoverForward] = useState(false);

return (
<div className="bg-white rounded-[12px] p-6 shadow-sm w-full h-full flex flex-col justify-between">
<div className="bg-white rounded-[12px] p-6 w-full h-full flex flex-col justify-between">
<div className="flex justify-between">
<span>
<p className="text-title-18-bold text-navy-80">
Expand All @@ -35,19 +35,24 @@ const SalesCard: React.FC<SalesCardProps> = ({ today, previous }) => {
</span>
{/* 이전,다음 이동 버튼 */}
<span className="flex">
{/* 이전 버튼: 오늘 매출일 때만 활성화 */}
<img
src={isHoverBack ? activeBackIcon : backIcon}
className="h-5 w-5 cursor-pointer"
onMouseEnter={() => setIsHoverBack(true)}
onMouseLeave={() => setIsHoverBack(false)}
onClick={() => setShowToday(false)}
src={
showToday ? activeBackIcon : backIcon // 비활성 이미지로 고정
}
className={`h-5 w-5 cursor-pointer`}
onMouseEnter={() => showToday && setIsHoverBack(true)}
onMouseLeave={() => showToday && setIsHoverBack(false)}
onClick={() => showToday && setShowToday(false)}
/>

{/* 다음 버튼: 이전 매출일 때만 활성화 */}
<img
src={isHoverForward ? activeForwardIcon : forwardIcon}
className="h-5 w-5 cursor-pointer"
onMouseEnter={() => setIsHoverForward(true)}
onMouseLeave={() => setIsHoverForward(false)}
onClick={() => setShowToday(true)}
src={!showToday ? activeForwardIcon : forwardIcon}
className={`h-5 w-5 cursor-pointer `}
onMouseEnter={() => !showToday && setIsHoverForward(true)}
onMouseLeave={() => !showToday && setIsHoverForward(false)}
onClick={() => !showToday && setShowToday(true)}
/>
</span>
</div>
Expand All @@ -59,17 +64,27 @@ const SalesCard: React.FC<SalesCardProps> = ({ today, previous }) => {

{showToday && (
<>
<span className="text-14-regular text-primary">
<span
className={`text-14-regular gap-[4px] ${
today.percent > 0
? "text-primary" // 상승
: today.percent < 0
? "text-[#3A75E5]" // 하락
: "text-gray-500" // 변동 없음
}`}
>
{today.percent >= 0 ? "+" : ""}
{today.percent}%
</span>
</>
)}
</div>
<p className="text-13-regular text-black-80">
어제보다 {today.diffAmount.toLocaleString()}원{" "}
{today.diffAmount >= 0 ? "더 벌었어요!" : "덜 벌었어요!"}
</p>
{showToday && (
<p className="text-13-regular text-black-80">
어제보다 {today.diffAmount.toLocaleString()}원{" "}
{today.diffAmount >= 0 ? "더 벌었어요!" : "덜 벌었어요!"}
</p>
)}
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion apps/nowait-admin/src/pages/AdminBooth/AdminBooth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ const MenuSection = () => {
const BoothForm = () => {
const width = useWindowWidth();
const isTablet = width >= 768 && width <= 1024;
const [activeTab, setActiveTab] = useState<"booth" | "menu">("booth");
const [activeTab, setActiveTab] = useState<"booth" | "menu">("menu");
const [boothName, setBoothName] = useState("");
const [boothIntro, setBoothIntro] = useState("");
const [isFocused, setIsFocused] = useState(false);
Expand Down
Loading