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
8 changes: 8 additions & 0 deletions apps/nowait-admin/src/assets/keyboard_arrow_down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 62 additions & 1 deletion apps/nowait-admin/src/pages/AdminAnalytics/AdminAnalytics.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,66 @@
import BoothSalesRankingCard from "./components/BoothSalesRankingCard ";
import HeaderStatus from "./components/HeaderStatus";

interface BoothRanking {
rank: number;
name: string;
department: string;
salesCount: number;
rankChange: number;
isCurrentBooth?: boolean;
}

// fakeData
const boothData: BoothRanking[] = [
{
rank: 1,
name: "불타는닭발부스",
department: "컴퓨터공학과",
salesCount: 52,
rankChange: 1,
isCurrentBooth: false,
},
{
rank: 2,
name: "하이볼의집",
department: "식품영양학과",
salesCount: 52,
rankChange: -1,
isCurrentBooth: false,
},
{
rank: 3,
name: "치즈폭탄존",
department: "관광경영학과",
salesCount: 52,
rankChange: 0,
isCurrentBooth: false,
},
{
rank: 4,
name: "치킨사교클럽",
department: "치위생학과",
salesCount: 52,
rankChange: 3,
isCurrentBooth: false,
},
{
rank: 27,
name: "스페이시스",
department: "경찰행정학과",
salesCount: 52,
rankChange: 3,
isCurrentBooth: true,
},
];

const AdminAnalytics = () => {
return <div>AdminAnalytics AdminAnalytics</div>;
return (
<div className="w-full">
<HeaderStatus />
<BoothSalesRankingCard date="2025.07.18 금" data={boothData} />
</div>
);
};

export default AdminAnalytics;
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from "react";
import arrowIcon from "../../../assets/keyboard_arrow_down.svg";

interface BoothRanking {
rank: number;
name: string;
department: string;
salesCount: number;
rankChange: number;
isCurrentBooth?: boolean;
}

interface BoothSalesRankingCardProps {
date: string;
data: BoothRanking[];
}

const BoothSalesRankingCard: React.FC<BoothSalesRankingCardProps> = ({
date,
data,
}) => {
return (
<div className="bg-white rounded-[12px] p-6 shadow-sm w-full h-full mt-[10px]">
<div className="flex justify-between mb-4">
<div className="flex flex-col">
<h2 className="text-13-regular font-semibold text-black-60">
{"통계2"}
</h2>
<div className="flex">
<h5>매출 순위</h5>
<span>
<img src={arrowIcon} />
</span>
</div>
</div>
<span className="text-[12px] text-gray-400">{date}</span>
</div>

<ul className="space-y-3">
{data.map((item) => {
const isUp = item.rankChange > 0;
const isDown = item.rankChange < 0;
const isSame = item.rankChange === 0;

return (
<li
key={item.rank + item.name}
className={`flex justify-between items-center p-2 rounded ${
item.isCurrentBooth ? "bg-[#F5F8FA]" : ""
}`}
>
<div className="flex items-center gap-3">
<span className="text-[14px] font-semibold text-gray-600">
{item.rank}위
</span>
<div className="w-6 h-6 rounded-full bg-[#5A6ACF]" />
<div className="flex flex-col text-sm">
<span className="font-medium 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">
{item.salesCount}건
</span>

{/* 랭크 변화 표시 */}
<div
className={`text-[12px] font-semibold flex items-center justify-center rounded-full w-[30px] h-[20px] ${
isUp
? "bg-[#FFF1F0] text-[#FF5A1F]"
: isDown
? "bg-[#EDF4FF] text-[#3A75E5]"
: "bg-[#F2F2F2] text-[#7E7E7E]"
}`}
>
{isUp && <span>{item.rankChange} ↑</span>}
{isDown && <span>{Math.abs(item.rankChange)} ↓</span>}
{isSame && <span>0 -</span>}
</div>
</div>
</li>
);
})}
</ul>
</div>
);
};

export default BoothSalesRankingCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";
import SalesCard from "./SalesCard";

const HeaderStatus = () => {
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-[10px] h-[352px]">
<div className="flex flex-col gap-[10px]">
{/* 오늘 매출 */}
<SalesCard
title="오늘 매출"
date="2025.07.18 금"
amount={800000}
diffAmount={12000}
percent={13.6}
/>
{/* 누적 매출 */}
<SalesCard
title="누적 매출"
date="2025.07.18 금"
amount={6400000}
diffAmount={40000}
percent={0.63}
/>
</div>
{/* 인기 메뉴 TOP 5 */}
<div className="flex flex-col justify-between bg-white rounded-xl p-6 shadow h-full">
<div className="flex flex-col mb-2">
<p className="text-title-18-bold text-navy-80">인기 메뉴 TOP 5</p>
<span className="text-13-regular text-black-60">2025.07.18 금</span>
</div>
<ul className="space-y-2">
{[1, 2, 3, 4, 5].map((rank) => (
<li key={rank} className="flex justify-between">
<span>{rank}위 참치마요주먹밥</span>
<span className="font-medium">100개</span>
</li>
))}
</ul>
</div>
</div>
);
};

export default HeaderStatus;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
interface SalesCardProps {
title: string; // 예: "오늘 매출" 또는 "누적 매출"
date: string;
amount: number;
diffAmount: number;
percent: number;
}

const SalesCard: React.FC<SalesCardProps> = ({
title,
date,
amount,
diffAmount,
percent,
}) => (
<div className="bg-white rounded-[12px] p-6 shadow-sm w-full h-full flex flex-col justify-between">
<div>
<p className="text-title-18-bold text-navy-80">{title}</p>
<p className="text-13-regular text-black-60 mt-1">{date}</p>
</div>
<div>
<div className="flex items-baseline gap-2">
<p className="text-headline-22-bold text-navy-80">
{amount.toLocaleString()}원
</p>
<span className="text-14-regular text-primary">+{percent}%</span>
</div>
<p className="text-13-regular text-black-80 mt-1">
어제보다 {diffAmount.toLocaleString()}원 더 벌었어요!
</p>
</div>
</div>
);
export default SalesCard;