Skip to content

Commit

Permalink
fix: 충돓해결 #23
Browse files Browse the repository at this point in the history
  • Loading branch information
sunhyeongpp committed Feb 17, 2025
2 parents 847e910 + 09a38ba commit c62dea0
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
"@tailwindcss/vite": "^4.0.6",
"@tanstack/react-query": "^5.66.0",
"axios": "^1.7.9",
"chart.js": "^4.4.7",
"dayjs": "^1.11.13",
"react": "^19.0.0",
"react-chartjs-2": "^5.3.0",
"react-dom": "^19.0.0",
"react-router": "^7.1.5",
"tailwind-merge": "^3.0.1",
Expand Down
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import HeaderLayout from "./components/layout/HeaderLayout";
import ProjectRoomDetail from "./pages/ProjectRoom/ProjectRoomDetail";
import MyPage from "./pages/MyPage";
import MeetingRoom from "./pages/MeetingRoom/MeetingRoom";
import Admin from "./pages/Admin";

const App = () => {
return (
Expand All @@ -25,6 +26,7 @@ const App = () => {
<Route element={<Layout />}>
<Route path="/" element={<MainPage />} />
<Route path="/projectRoom/:projectId" element={<ProjectRoomDetail />} />
<Route path="/admin" element={<Admin />} />
</Route>

{/* 헤더만 있는 페이지 */}
Expand Down
13 changes: 13 additions & 0 deletions src/assets/icons/dashboard/accountIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/assets/icons/dashboard/dashboardIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions src/assets/icons/dashboard/payIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/icons/dashboard/projectIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/assets/icons/dashboard/tagIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/assets/icons/dashboard/taskIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions src/components/Admin/Chart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Tooltip,
Legend,
ChartOptions,
ChartData,
Filler,
} from "chart.js";
import { Line } from "react-chartjs-2";

ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Tooltip,
Legend,
Filler
);

interface ChartProps {
data: number[];
labelTitle: string;
label: string[];
}

const Chart = ({ data, labelTitle, label }: ChartProps) => {
const chartData: ChartData<"line"> = {
labels: label,
datasets: [
{
label: labelTitle,
data: data,
borderColor: labelTitle !== "매출액" ? "#FF6854" : "#657166",
backgroundColor: labelTitle !== "매출액" ? "#ff68546a" : "#6571666a",
fill: true,
pointRadius: 6,
pointHoverRadius: 8, // 마우스 올릴 때 점 크기
pointBackgroundColor: labelTitle !== "매출액" ? "#FF6854" : "#657166", // 점 내부 색상
pointBorderColor: labelTitle !== "매출액" ? "#FF6854" : "#657166", // 점 테두리 색상
pointBorderWidth: 2, // 점 테두리 두께
},
],
};

const options: ChartOptions<"line"> = {
responsive: true,
plugins: {
legend: {
display: true,
position: "bottom",
},
},
scales: {
y: {
beginAtZero: true,
max: Math.max(...data) + 30,
},
},
};

return (
<div className="">
<Line data={chartData} options={options} height={50} />
</div>
);
};

export default Chart;
70 changes: 70 additions & 0 deletions src/components/Admin/DashBoard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { twMerge } from "tailwind-merge";
import Chart from "./Chart";
import { useState } from "react";

const PAY_DATA_FILTER = ["일일 매출", "월간 매출", "연간 매출"];

const DashBoard = () => {
const [payDataTab, setPayDataTab] = useState("일일 매출");

return (
<div className="pl-[150px] pr-5 min-h-[calc(100vh-50px)] bg-gradient-to-t from-white/0 via-[#BFCDB7]/30 to-white/0">
<h1 className="font-bold text-[27px] mb-4">회원 데이터</h1>
<div className=" px-2">
<p className="text-main-green font-bold mb-2">누적 회원 수</p>
<div
className="border border-main-green02 w-[170px] h-[50px] flex gap-2
items-center justify-center text-main-green01 font-bold rounded-[10px]"
>
총 구독 회원 <p className="text-[25px] text-header-red">127명</p>
</div>
<Chart
data={[60, 80, 120, 120, 140]}
labelTitle="누적 회원 수"
label={["4주전", "3주전", "2주전", "1주전", "오늘"]}
/>
<div className="mt-10">
<p className="font-bold mb-5">신규 회원 수</p>
<Chart
data={[30, 20, 40, 0, 15]}
labelTitle="신규 회원 수"
label={["4주전", "3주전", "2주전", "1주전", "오늘"]}
/>
</div>

{/* 결제 데이터 */}
<div className="mt-10">
<p className="font-bold text-[20px] mb-5">결제 데이터</p>

<ul className="flex gap-5 font-bold mb-5">
{PAY_DATA_FILTER.map((payData, idx) => {
return (
<li
key={idx}
className={twMerge(
`w-[80px] h-[30px] bg-white flex items-center justify-center
border border-header-green rounded-[3px] text-header-green cursor-pointer
${
payDataTab === payData &&
"text-main-beige01 bg-header-green border-none"
}`
)}
onClick={() => setPayDataTab(payData)}
>
{payData}
</li>
);
})}
</ul>
<Chart
labelTitle="매출액"
data={[15, 13, 20, 0, 10]}
label={["1/17", "1/22", "2/1", "2/11", "오늘"]}
/>
</div>
</div>
</div>
);
};

export default DashBoard;
2 changes: 1 addition & 1 deletion src/components/layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const Layout = () => {
const [sidebarToggle, setSidebarToggle] = useState<boolean>(false);

return (
<div>
<div className="relative">
<Header />
<div className="absolute">
<Sidebar
Expand Down
54 changes: 54 additions & 0 deletions src/components/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,29 @@ import sidebarMeetIcon from "../../assets/icons/sidebarMeetIcon.svg";
import { twMerge } from "tailwind-merge";
import sideLeftArrow from "../../assets/icons/sideLeftArrow.svg";
import sideRightArrow from "../../assets/icons/sideRightArrow.svg";
import accountIcon from "../../assets/icons/dashboard/accountIcon.svg";
import dashboardIcon from "../../assets/icons/dashboard/dashboardIcon.svg";
import payIcon from "../../assets/icons/dashboard/payIcon.svg";
import projectIcon from "../../assets/icons/dashboard/projectIcon.svg";
import tagIcon from "../../assets/icons/dashboard/tagIcon.svg";
import taskIcon from "../../assets/icons/dashboard/taskIcon.svg";

const SideMenuList = [
// 프로젝트룸
{ title: "전체 업무", icon: sidebarAllicon, src: "all" },
{ title: "담당자", icon: sidebarManagerIcon, src: "manager" },
{ title: "미팅룸", icon: sidebarMeetIcon, src: "meeting" },
];

const ADMIN_SIDE_MENU_LIST = [
{ title: "대시보드", icon: dashboardIcon, src: "dashboard" },
{ title: "계정 관리", icon: accountIcon, src: "account" },
{ title: "프로젝트 관리", icon: projectIcon, src: "project" },
{ title: "업무 관리", icon: taskIcon, src: "task" },
{ title: "결제 내역 관리", icon: payIcon, src: "pay" },
{ title: "태그 관리", icon: tagIcon, src: "tag" },
];

interface SidebarProps {
sidebarToggle: boolean;
setSidebarToggle: React.Dispatch<React.SetStateAction<boolean>>;
Expand All @@ -22,6 +38,8 @@ interface SidebarProps {
const Sidebar = ({ sidebarToggle, setSidebarToggle }: SidebarProps) => {
const { pathname } = useLocation();

const [adminSideMenu, setAdminSideMenu] = useState("대시보드");

if (pathname.startsWith("/projectRoom")) {
return (
<div
Expand Down Expand Up @@ -54,6 +72,42 @@ const Sidebar = ({ sidebarToggle, setSidebarToggle }: SidebarProps) => {
</ul>
</div>
);
} else if (pathname.startsWith("/admin")) {
return (
<div className="w-[130px] bg-white min-h-[calc(100vh-50px)] font-bold flex flex-col items-center pt-5 text-main-green01">
<p className="pb-7 border-b border-header-green w-[110px] text-center ">
관리자 메뉴
</p>

<ul className="flex flex-col gap-5 mt-7 text-[15px]">
{ADMIN_SIDE_MENU_LIST.map((adminMenu, idx) => {
return (
<li
key={idx}
className={twMerge(
`bg-white w-full h-[35px] ${
adminSideMenu === adminMenu.title && "bg-main-green03"
}`
)}
onClick={() => setAdminSideMenu(adminMenu.title)}
>
<Link
to={`${pathname}?tab=${adminMenu.src}`}
className="flex gap-2 w-full h-full items-center px-2"
>
<img
src={adminMenu.icon}
alt="관리자 메뉴 아이콘"
className="w-5 h-5"
/>
<p>{adminMenu.title}</p>
</Link>
</li>
);
})}
</ul>
</div>
);
}

return (
Expand Down
16 changes: 16 additions & 0 deletions src/pages/Admin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useSearchParams } from "react-router";
import DashBoard from "../components/Admin/DashBoard";

const Admin = () => {
const [tabName] = useSearchParams();
console.log(tabName.get("tab"));
return (
<div>
{(tabName.get("tab") === "dashboard" || !tabName.get("tab")) && (
<DashBoard />
)}
</div>
);
};

export default Admin;

0 comments on commit c62dea0

Please sign in to comment.