diff --git a/src/assets/components/admin/yagada-rabbit.png b/src/assets/components/admin/yagada-rabbit.png
new file mode 100644
index 0000000..f6bb616
Binary files /dev/null and b/src/assets/components/admin/yagada-rabbit.png differ
diff --git a/src/commons/svgs/AdminButton.jsx b/src/commons/svgs/AdminButton.jsx
new file mode 100644
index 0000000..dcdfe6f
--- /dev/null
+++ b/src/commons/svgs/AdminButton.jsx
@@ -0,0 +1,7 @@
+export const AdminButton = () => {
+ return (
+
+ );
+};
diff --git a/src/components/admin/AdminHeader.jsx b/src/components/admin/AdminHeader.jsx
new file mode 100644
index 0000000..024ee4f
--- /dev/null
+++ b/src/components/admin/AdminHeader.jsx
@@ -0,0 +1,28 @@
+import {
+ ADMIN_ANNOUNCE_URL,
+ ADMIN_MANAGE_CUSTOMER_URL,
+ ADMIN_MANAGE_REPORT_URL,
+ ADMIN_MANAGE_USER_URL,
+ ROOT_URL,
+} from "constants/url";
+import { Link } from "react-router-dom";
+import logo from "assets/commons/home-logo.png";
+import "styles/components/admin/AdminHeader.scss";
+import Profile from "components/home/Profile";
+
+export const AdminHeader = () => {
+ return (
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/admin/AnnounceManageBar.jsx b/src/components/admin/AnnounceManageBar.jsx
new file mode 100644
index 0000000..0d8f654
--- /dev/null
+++ b/src/components/admin/AnnounceManageBar.jsx
@@ -0,0 +1,31 @@
+import { ADMIN_ANNOUNCE_URL } from "constants/url";
+import { Link, useNavigate } from "react-router-dom";
+import { eraseNotification } from "services/admin/admin";
+import "styles/components/admin/AnnounceManageBar.scss";
+
+export const AnnounceManageBar = ({ notificationId }) => {
+ const navigate = useNavigate();
+
+ const handleDelete = async () => {
+ try {
+ await eraseNotification(notificationId);
+ navigate(ADMIN_ANNOUNCE_URL);
+ } catch (error) {
+ console.error("삭제 실패:", error);
+ }
+ };
+
+ return (
+
권한이 없습니다.
;
+ if (loading) return 로딩 중...
;
+
+ return (
+
diff --git a/src/routes/admin.js b/src/routes/admin.js
new file mode 100644
index 0000000..4dc0f40
--- /dev/null
+++ b/src/routes/admin.js
@@ -0,0 +1,50 @@
+import { AdminHome } from "pages/admin/AdminHome";
+import AdminPage, { loader as adminLoader } from "pages/admin/AdminPage";
+import AnnounceEditPage from "pages/admin/AnnounceEditPage";
+import { CreateAnnouncePage } from "pages/admin/CreateAnnouncePage";
+import AnnounceDetailPage from "pages/home/AnnounceDetailPage";
+import AnnouncePage from "pages/home/AnnouncePage";
+
+const admin = [
+ {
+ path: "/admin",
+ element:
,
+ loader: adminLoader,
+ children: [
+ {
+ index: true,
+ element:
,
+ },
+ {
+ path: "announce",
+ element:
,
+ },
+ {
+ path: "announce/:id",
+ element:
,
+ },
+ {
+ path: "announce/:id/edit",
+ element:
,
+ },
+ {
+ path: "announce/create",
+ element:
,
+ },
+ {
+ path: "user-manage",
+ element: <>유저 관리>,
+ },
+ {
+ path: "report-manage",
+ element: <>신고 관리>,
+ },
+ {
+ path: "customer-center",
+ element: <>1ㄷ1 문의 관리>,
+ },
+ ],
+ },
+];
+
+export default admin;
diff --git a/src/routes/root.js b/src/routes/root.js
index ad81782..5b86c34 100644
--- a/src/routes/root.js
+++ b/src/routes/root.js
@@ -3,13 +3,14 @@ import { createBrowserRouter } from "react-router-dom";
import auth from "routes/auth";
import home from "routes/home";
import lobby from "routes/lobby";
+import admin from "routes/admin";
const router = createBrowserRouter([
{
path: "/",
element:
,
loader: rootLoader,
- children: [...auth, ...home, ...lobby],
+ children: [...auth, ...home, ...lobby, ...admin],
},
]);
diff --git a/src/services/admin/admin.js b/src/services/admin/admin.js
new file mode 100644
index 0000000..d3cc18b
--- /dev/null
+++ b/src/services/admin/admin.js
@@ -0,0 +1,32 @@
+import { ADMIN_ANNOUNCE_MANAGE_API } from "constants/api";
+import { apiInterface } from "services/axiosForm";
+
+export const eraseNotification = async (notificationId) => {
+ return await apiInterface(
+ "delete",
+ `${ADMIN_ANNOUNCE_MANAGE_API}/${notificationId}`,
+ { notificationId },
+ {},
+ true
+ );
+};
+
+export const updateAnnounceAPI = async (notification) => {
+ return await apiInterface(
+ "put",
+ `${ADMIN_ANNOUNCE_MANAGE_API}/${notification.id}`,
+ { title: notification.title, content: notification.content },
+ {},
+ true
+ );
+};
+
+export const postAnnounceAPI = async (notification) => {
+ return await apiInterface(
+ "post",
+ `${ADMIN_ANNOUNCE_MANAGE_API}`,
+ { title: notification.title, content: notification.content },
+ {},
+ true
+ );
+};
diff --git a/src/styles/components/admin/AdminHeader.scss b/src/styles/components/admin/AdminHeader.scss
new file mode 100644
index 0000000..f1b4ac0
--- /dev/null
+++ b/src/styles/components/admin/AdminHeader.scss
@@ -0,0 +1,30 @@
+.admin-page-header {
+ position: fixed;
+ z-index: 100;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 54px;
+ width: 100%;
+ height: 20%;
+ background: white;
+ img {
+ width: 366px;
+ height: 58px;
+ }
+
+ a {
+ text-decoration: none;
+ color: black;
+ font-size: 14px;
+ font-family: "SUIT-Regular";
+ }
+
+ .admin-page-nav-container {
+ display: flex;
+ justify-content: center;
+ white-space: nowrap;
+ width: 600px;
+ gap: 80px;
+ }
+}
diff --git a/src/styles/components/admin/AnnounceManageBar.scss b/src/styles/components/admin/AnnounceManageBar.scss
new file mode 100644
index 0000000..6c78b64
--- /dev/null
+++ b/src/styles/components/admin/AnnounceManageBar.scss
@@ -0,0 +1,42 @@
+.announce-manage-button-bar {
+ display: flex;
+ align-items: center;
+ gap: 138px;
+ a {
+ text-decoration: none;
+ }
+ .button--edit {
+ padding: 8px 16px;
+ height: 40px;
+ width: 194px;
+ border: none;
+ border-radius: 4px;
+ color: #fff;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 1;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ background: #F28110;
+ }
+
+ .button--delete {
+ width: 194px;
+ padding: 8px 16px;
+ height: 40px;
+ border: none;
+ border-radius: 4px;
+ color: #fff;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 1;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ background: #808080;
+ }
+
+}
\ No newline at end of file
diff --git a/src/styles/components/home/EnterAdmin.scss b/src/styles/components/home/EnterAdmin.scss
new file mode 100644
index 0000000..522c802
--- /dev/null
+++ b/src/styles/components/home/EnterAdmin.scss
@@ -0,0 +1,24 @@
+.admin-button {
+ position: fixed;
+ right: 24px;
+ bottom: 24px;
+ z-index: 1000;
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ border: none;
+ background: #1976d2;
+ color: #fff;
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2);
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0;
+
+ svg {
+ width: 24px;
+ height: 24px;
+ display: block;
+ }
+}
diff --git a/src/styles/pages/admin/AdminHome.scss b/src/styles/pages/admin/AdminHome.scss
new file mode 100644
index 0000000..c421b19
--- /dev/null
+++ b/src/styles/pages/admin/AdminHome.scss
@@ -0,0 +1,16 @@
+.admin-home-container {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-top: 300px;
+ font-size: 200px;
+ height: auto;
+ background-color: white;
+ img{
+ width: 400px;
+ height: auto;
+ }
+}
diff --git a/src/styles/pages/admin/AdminPage.scss b/src/styles/pages/admin/AdminPage.scss
new file mode 100644
index 0000000..a654765
--- /dev/null
+++ b/src/styles/pages/admin/AdminPage.scss
@@ -0,0 +1,9 @@
+.admin-page-container {
+ position: relative;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ height: auto;
+ background-color: white;
+}
diff --git a/src/styles/pages/admin/AnnounceEditPage.scss b/src/styles/pages/admin/AnnounceEditPage.scss
new file mode 100644
index 0000000..5e70254
--- /dev/null
+++ b/src/styles/pages/admin/AnnounceEditPage.scss
@@ -0,0 +1,93 @@
+.announce-edit-page-container {
+ position: relative;
+ width: 1278px;
+ min-height: 100vh;
+ padding-top: 186px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ font-family: SUIT-Regular;
+
+ .announce-edit-container {
+ width: 1278px;
+ height: calc(100vh - 244px);
+
+ position: absolute;
+ top: 244px;
+
+ background: #ffffff;
+ border-width: 1.5px 1.5px 0 1.5px;
+ border-style: solid;
+ border-color: #000;
+ border-radius: 24px 24px 0 0 ;
+ box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.25);
+
+ animation: slideUpFade 0.4s ease-out forwards;
+
+
+ .announce-edit-header {
+ position: relative;
+
+ .close-btn {
+ position: absolute;
+ right: 35px;
+ top: 29px;
+ }
+ }
+
+ .announce-edit-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding-top: 120px;
+ gap: 35px;
+
+
+ .content-title {
+ display: flex;
+ align-items: center;
+ gap: 30px;
+ width: 960px;
+
+ .edit-title-input {
+ background-color: #F2F3F6;
+ width: 960px;
+ height: 44px;
+ font-size: 20px;
+ border: 1px solid #ccc;
+ padding: 0 12px;
+ text-align: center;
+ }
+ }
+
+ .edit-content-input {
+ background-color: #F2F3F6;
+ width: 960px;
+ border: 1px solid #ccc;
+ padding: 36px 120px;
+ font-size: 18px;
+ line-height: 1.4;
+ text-align: center;
+ overflow: auto;
+ }
+
+ .save-button {
+ margin-top: 16px;
+ width: 960px;
+ height: 40px;
+ border: none;
+ border-radius: 6px;
+ font-size: 16px;
+ font-weight: 700;
+ background: #FFDA37;
+ color: black;
+ cursor: pointer;
+ transition: 0.2s;
+
+ &:hover {
+ opacity: 0.9;
+ }
+ }
+ }
+ }
+}
diff --git a/src/styles/pages/admin/CreateAnnouncePage.scss b/src/styles/pages/admin/CreateAnnouncePage.scss
new file mode 100644
index 0000000..965c7be
--- /dev/null
+++ b/src/styles/pages/admin/CreateAnnouncePage.scss
@@ -0,0 +1,53 @@
+.announce-create-container {
+position: relative;
+ width: 1278px;
+ min-height: 100vh;
+ padding-top: 186px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ font-family: SUIT-Regular;
+}
+
+.announce-create-title {
+ width: 1170px;
+ height: 50px;
+ border-radius: 20px;
+ border: 2px solid black;
+ padding: 0 20px;
+ font-size: 18px;
+ outline: none;
+ margin-bottom: 15px;
+
+ &::placeholder {
+ text-align: center;
+ color: #aaa;
+ }
+}
+
+.announce-create-content {
+ width: 1170px;
+ height: 350px;
+ border: 2px solid #ccc;
+ border-radius: 20px;
+ padding: 20px;
+ font-size: 16px;
+ outline: none;
+ resize: none;
+}
+
+.announce-submit {
+ margin-top: 19px;
+ width: 336px;
+ height: 40px;
+ background-color: #d48b43;
+ color: white;
+ border: none;
+ border-radius: 6px;
+ font-size: 17px;
+ cursor: pointer;
+
+ &:hover {
+ background-color: #bf7a38;
+ }
+}
diff --git a/src/styles/pages/home/AnnouncePage.scss b/src/styles/pages/home/AnnouncePage.scss
index fa0c4c9..17f5640 100644
--- a/src/styles/pages/home/AnnouncePage.scss
+++ b/src/styles/pages/home/AnnouncePage.scss
@@ -102,6 +102,38 @@
.empty {
margin-top: 108px;
}
+ .announce-create-button {
+ text-decoration: none;
+ position: fixed;
+ right: 24px;
+ bottom: 24px;
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ background: rgb(17, 125, 202);
+ border: 2px solid #000;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-family: YoonChild;
+ font-size: 18px;
+ color: #fff;
+ cursor: pointer;
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
+ z-index: 999;
+ user-select: none;
+ transition: transform 120ms ease, box-shadow 120ms ease;
+
+ &:hover {
+ transform: translateY(-3px);
+ }
+
+ &:active {
+ transform: translateY(0);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
+ }
+
+ }
}
/* 페이지네이션 */
diff --git a/src/utils/user.js b/src/utils/user.js
index 0ecb913..97dff89 100644
--- a/src/utils/user.js
+++ b/src/utils/user.js
@@ -1,3 +1,5 @@
+import { ADMIN_ANNOUNCE_URL, ANNOUNCE_URL } from "constants/url";
+
// src/utils/getUserInfo.js
const { default: useUserInformationStore } = require("store/userInformation");
@@ -34,4 +36,7 @@ const getUserName = () => {
return nickname;
};
-export { getUserInfo, getUserUuid, getUserName };
+const getAnnounceDetailLink = (isAdmin, id) => {
+ return isAdmin ? `${ADMIN_ANNOUNCE_URL}/${id}` : `${ANNOUNCE_URL}/${id}`;
+};
+export { getUserInfo, getUserUuid, getUserName, getAnnounceDetailLink };