From 0e6654337d2627e6fe001d1df70ab8d9fcfb4e38 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 17:01:38 +0900 Subject: [PATCH 01/17] =?UTF-8?q?feat=20:=20=EB=AC=B8=EC=9D=98=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/activityLog.api.ts | 16 +++++- .../inquiresPreview/InquiresPreview.styled.ts | 50 ++++++++++++++++++- .../inquiresPreview/InquiresPreview.tsx | 34 ++++++++++++- src/hooks/admin/useGetAllInquiries.ts | 12 +++++ src/hooks/queries/user/keys.ts | 1 + src/models/activityLog.ts | 11 +++- 6 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 src/hooks/admin/useGetAllInquiries.ts diff --git a/src/api/activityLog.api.ts b/src/api/activityLog.api.ts index b16adef5..e28b2a88 100644 --- a/src/api/activityLog.api.ts +++ b/src/api/activityLog.api.ts @@ -1,4 +1,8 @@ -import type { ApiMyComments, ApiMyInquiries } from './../models/activityLog'; +import type { + ApiAllInquiries, + ApiMyComments, + ApiMyInquiries, +} from './../models/activityLog'; import { httpClient } from './http.api'; export const getMyComments = async () => { @@ -22,3 +26,13 @@ export const getMyInquiries = async () => { throw e; } }; + +export const getAllInquiries = async () => { + try { + const response = await httpClient.get(`/inquiry`); + return response.data.data; + } catch (e) { + console.error('전체 문의 조회 에러', e); + throw e; + } +}; diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts index c3389834..8b143c30 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts @@ -1,3 +1,51 @@ +import { Link } from 'react-router-dom'; import styled from 'styled-components'; -export const Container = styled.div``; +export const Container = styled.div` + display: flex; + flex-direction: column; + margin-left: 10px; +`; + +export const Wrapper = styled.div` + display: flex; + align-items: center; + margin-top: 16px; +`; + +export const Inquiry = styled(Link)` + margin-left: 16px; +`; + +export const Category = styled.p` + font-size: 10px; + opacity: 50%; +`; + +export const Title = styled.span` + font-size: 14px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; + +export const StateArea = styled.div` + display: flex; + align-items: center; +`; + +export const Date = styled.p` + font-size: 10px; + opacity: 50%; +`; + +export const Divider = styled.p` + opacity: 20%; + margin-left: 3px; + margin-right: 3px; +`; + +export const InquiryState = styled.p<{ $isCompleted: boolean }>` + font-size: 10px; + color: ${({ $isCompleted }) => ($isCompleted ? `#07DE00` : `#DE1A00`)}; +`; diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx index 25aba453..6ea05c5a 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx @@ -1,8 +1,40 @@ import React from 'react'; import * as S from './InquiresPreview.styled'; +import { useGetAllInquiries } from '../../../../hooks/admin/useGetAllInquiries'; +import Avatar from '../../../common/avatar/Avatar'; +import { ADMIN_ROUTE } from '../../../../constants/routes'; +import { Link } from 'react-router-dom'; const InquiresPreview = () => { - return InquiresPreview Component; + const { allInquiriesData } = useGetAllInquiries(); + + const previewList = allInquiriesData + ? allInquiriesData.length > 6 + ? allInquiriesData.slice(-4) + : allInquiriesData + : []; + + return ( + + {previewList?.map((inquiry) => ( + + {/* + + {inquiry.category} + {inquiry.title} + + {inquiry.createdAt} + | + + {inquiry.state ? '답변 완료' : '답변 대기 중'} + + + + + ))} + + ); }; export default InquiresPreview; diff --git a/src/hooks/admin/useGetAllInquiries.ts b/src/hooks/admin/useGetAllInquiries.ts new file mode 100644 index 00000000..3cff09b3 --- /dev/null +++ b/src/hooks/admin/useGetAllInquiries.ts @@ -0,0 +1,12 @@ +import { useQuery } from '@tanstack/react-query'; +import { getAllInquiries } from '../../api/activityLog.api'; +import { ActivityLog } from '../queries/user/keys'; + +export const useGetAllInquiries = () => { + const { data: allInquiriesData, isLoading } = useQuery({ + queryKey: [ActivityLog.allInquiries], + queryFn: () => getAllInquiries(), + }); + + return { allInquiriesData, isLoading }; +}; diff --git a/src/hooks/queries/user/keys.ts b/src/hooks/queries/user/keys.ts index 60a3acbd..36a635b9 100644 --- a/src/hooks/queries/user/keys.ts +++ b/src/hooks/queries/user/keys.ts @@ -47,6 +47,7 @@ export const ProjectMemberListEval = { export const ActivityLog = { myComments: ['MyComments'], myInquiries: ['MyInquiries'], + allInquiries: ['AllInquiries'], }; export const CustomerService = { diff --git a/src/models/activityLog.ts b/src/models/activityLog.ts index 1dd69529..4c9cb521 100644 --- a/src/models/activityLog.ts +++ b/src/models/activityLog.ts @@ -1,6 +1,7 @@ -import type { ApiCommonType } from './apiCommon'; +import type { ApiCommonType, User } from './apiCommon'; export interface MyInquiries { + id: number; title: string; content: string; category: string; @@ -11,6 +12,14 @@ export interface MyInquiries { export interface ApiMyInquiries extends ApiCommonType { data: MyInquiries[]; } +export interface AllInquiries extends MyInquiries { + user: User; + createdAt: string; +} + +export interface ApiAllInquiries extends ApiCommonType { + data: AllInquiries[]; +} export interface MyComments { id: number; From 8945a90c867ce72438d67b7699b1aa406be57b1d Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 17:18:47 +0900 Subject: [PATCH 02/17] =?UTF-8?q?style=20:=20=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EA=B5=AC=EC=A1=B0=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/admin/mainItems.ts | 20 +++++++++---------- src/pages/admin/adminMain/AdminMain.styled.ts | 14 +++++++++++-- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/constants/admin/mainItems.ts b/src/constants/admin/mainItems.ts index d83a2a41..ef55ee7e 100644 --- a/src/constants/admin/mainItems.ts +++ b/src/constants/admin/mainItems.ts @@ -14,10 +14,10 @@ export interface CardItem { export const cardList: CardItem[] = [ { - key: 'notice', - title: '공지사항', - link: `${ADMIN_ROUTE.notice}`, - Component: NoticePreview, + key: 'allUsers', + title: '전체 회원 조회', + link: `${ADMIN_ROUTE.allUser}`, + Component: AllUserPreview, }, { key: 'inquires', @@ -31,15 +31,15 @@ export const cardList: CardItem[] = [ link: `${ADMIN_ROUTE.reports}`, Component: ReportsPreview, }, - { - key: 'allUsers', - title: '전체 회원 조회', - link: `${ADMIN_ROUTE.allUser}`, - Component: AllUserPreview, - }, { key: 'Graph', title: '방문자 현황', Component: GraphCard, }, + { + key: 'notice', + title: '공지사항', + link: `${ADMIN_ROUTE.notice}`, + Component: NoticePreview, + }, ]; diff --git a/src/pages/admin/adminMain/AdminMain.styled.ts b/src/pages/admin/adminMain/AdminMain.styled.ts index 39d65d55..2c311a07 100644 --- a/src/pages/admin/adminMain/AdminMain.styled.ts +++ b/src/pages/admin/adminMain/AdminMain.styled.ts @@ -1,7 +1,7 @@ import styled from 'styled-components'; export const Container = styled.div` - padding: 50px; + padding: 10px; min-height: 100vh; `; @@ -9,7 +9,17 @@ export const Wrapper = styled.div` display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: minmax(350px, auto); - gap: 20px; + gap: 10px; + + & > * { + width: 100%; + } + + & > *:nth-child(4) { + grid-column: 1 / 3; + width: 300px; + width: 100%; + } @media (max-width: 768px) { grid-template-columns: 1fr; From eef03c48f4b409a82d89650a68c1b55c205a3af8 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 17:30:33 +0900 Subject: [PATCH 03/17] =?UTF-8?q?feat=20:=20=EB=AC=B8=EC=9D=98=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=97=90=20"=EC=83=81=EC=84=B8=20=EB=B3=B4=EA=B8=B0"?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inquiresPreview/InquiresPreview.styled.ts | 27 ++++++++++++--- .../inquiresPreview/InquiresPreview.tsx | 33 +++++++++++-------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts index 8b143c30..d0b08132 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts @@ -8,6 +8,12 @@ export const Container = styled.div` `; export const Wrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; +`; + +export const Content = styled.div` display: flex; align-items: center; margin-top: 16px; @@ -18,12 +24,12 @@ export const Inquiry = styled(Link)` `; export const Category = styled.p` - font-size: 10px; + font-size: 9px; opacity: 50%; `; export const Title = styled.span` - font-size: 14px; + font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -35,7 +41,7 @@ export const StateArea = styled.div` `; export const Date = styled.p` - font-size: 10px; + font-size: 9px; opacity: 50%; `; @@ -46,6 +52,19 @@ export const Divider = styled.p` `; export const InquiryState = styled.p<{ $isCompleted: boolean }>` - font-size: 10px; + font-size: 9px; color: ${({ $isCompleted }) => ($isCompleted ? `#07DE00` : `#DE1A00`)}; `; + +export const MoveToInquiryArea = styled(Link)` + display: flex; + justify-content: center; + align-items: center; + font-size: 10px; + margin-right: 10px; + margin-top: 20px; +`; + +export const Text = styled.p``; + +export const Arrow = styled.img``; diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx index 6ea05c5a..61d6e810 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx @@ -4,6 +4,7 @@ import { useGetAllInquiries } from '../../../../hooks/admin/useGetAllInquiries'; import Avatar from '../../../common/avatar/Avatar'; import { ADMIN_ROUTE } from '../../../../constants/routes'; import { Link } from 'react-router-dom'; +import arrow_right from '../../../../assets/ArrowRight.svg'; const InquiresPreview = () => { const { allInquiriesData } = useGetAllInquiries(); @@ -18,19 +19,25 @@ const InquiresPreview = () => { {previewList?.map((inquiry) => ( - {/* - - {inquiry.category} - {inquiry.title} - - {inquiry.createdAt} - | - - {inquiry.state ? '답변 완료' : '답변 대기 중'} - - - + + {/* + + {inquiry.category} + {inquiry.title} + + {inquiry.createdAt} + | + + {inquiry.state ? '답변 완료' : '답변 대기 중'} + + + + + + 상세 보기 + + ))} From e74714cb033ecb868133da85f3843cda22198ee0 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 20:17:13 +0900 Subject: [PATCH 04/17] =?UTF-8?q?fix=20:=20mock=20=EB=AF=B8=EB=8F=99?= =?UTF-8?q?=EC=9E=91=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20=EB=B0=8F?= =?UTF-8?q?=20=EC=8B=A0=EA=B3=A0,=20=EC=9C=A0=EC=A0=80=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20mock=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mock/applicant.ts | 14 ++- src/mock/auth.ts | 2 +- src/mock/browser.ts | 10 +- src/mock/createProject.ts | 2 +- src/mock/manageProjectList.ts | 4 +- src/mock/mockReports.json | 166 +++++++++++++++++++++++++++++ src/mock/mockUsers.json | 151 ++++++++++++++++++++++++++ src/mock/mypage.ts | 12 +-- src/mock/projectDetail.ts | 10 +- src/mock/projectLists.ts | 4 +- src/mock/projectSearchFiltering.ts | 6 +- src/mock/userpage.ts | 12 ++- 12 files changed, 368 insertions(+), 25 deletions(-) create mode 100644 src/mock/mockReports.json create mode 100644 src/mock/mockUsers.json diff --git a/src/mock/applicant.ts b/src/mock/applicant.ts index c8e922b3..72fe2301 100644 --- a/src/mock/applicant.ts +++ b/src/mock/applicant.ts @@ -4,7 +4,7 @@ import mockApplicantData from './mockApplicantData.json'; import mockPassNonPassListData from './mockPassNonPassListData.json'; export const applicantList = http.get( - `${import.meta.env.VITE_API_BASE_URL}/project/:projectId/applicants`, + `${import.meta.env.VITE_APP_API_BASE_URL}project/:projectId/applicants`, () => { return HttpResponse.json(mockApplicantsData, { status: 200, @@ -13,7 +13,9 @@ export const applicantList = http.get( ); export const applicantInfo = http.get( - `${import.meta.env.VITE_API_BASE_URL}/project/:projectId/applicants/:userId`, + `${ + import.meta.env.VITE_APP_API_BASE_URL + }project/:projectId/applicants/:userId`, () => { return HttpResponse.json(mockApplicantData, { status: 200, @@ -22,7 +24,9 @@ export const applicantInfo = http.get( ); export const passNonPassList = http.get( - `${import.meta.env.VITE_API_BASE_URL}/project/:projectId/applicants/results`, + `${ + import.meta.env.VITE_APP_API_BASE_URL + }project/:projectId/applicants/results`, () => { return HttpResponse.json(mockPassNonPassListData, { status: 200, @@ -31,7 +35,7 @@ export const passNonPassList = http.get( ); export const passNonPass = http.put( - `${import.meta.env.VITE_API_BASE_URL}/project/:projectId/applicant`, + `${import.meta.env.VITE_APP_API_BASE_URL}project/:projectId/applicant`, () => { return HttpResponse.json( { message: '합/불합 상태가 수정되었습니다.' }, @@ -43,7 +47,7 @@ export const passNonPass = http.put( ); export const createApplicant = http.post( - `${import.meta.env.VITE_API_BASE_URL}/project/:projectId/applicant`, + `${import.meta.env.VITE_APP_API_BASE_URL}project/:projectId/applicant`, () => { return HttpResponse.json({ status: 200, diff --git a/src/mock/auth.ts b/src/mock/auth.ts index f47564ac..ce549ea7 100644 --- a/src/mock/auth.ts +++ b/src/mock/auth.ts @@ -1,7 +1,7 @@ import { http, HttpResponse } from 'msw'; export const login = http.post( - `${import.meta.env.VITE_API_BASE_URL}/auth/login`, + `${import.meta.env.VITE_APP_API_BASE_URL}auth/login`, () => { return HttpResponse.json({ status: 200, diff --git a/src/mock/browser.ts b/src/mock/browser.ts index ea43a146..81c8f6b3 100644 --- a/src/mock/browser.ts +++ b/src/mock/browser.ts @@ -7,7 +7,7 @@ import { passNonPass, passNonPassList, } from './applicant'; -import { projectDetail } from './projectDetail'; +import { projectDetail, reportsAll } from './projectDetail'; import { myPageAppliedProjectList, mypageEditProfile, @@ -16,7 +16,11 @@ import { myPageProfile, myPageSkillTag, } from './mypage'; -import { userPageAppliedProjectList, userPageProfile } from './userpage'; +import { + userAll, + userPageAppliedProjectList, + userPageProfile, +} from './userpage'; import { login } from './auth'; import { fetchProjectLists, fetchProjectStatistic } from './projectLists'; import { @@ -51,6 +55,8 @@ export const handlers = [ login, createApplicant, createProject, + userAll, + reportsAll, ]; export const worker = setupWorker(...handlers); diff --git a/src/mock/createProject.ts b/src/mock/createProject.ts index 1ab0fc72..d1fee78f 100644 --- a/src/mock/createProject.ts +++ b/src/mock/createProject.ts @@ -1,7 +1,7 @@ import { http, HttpResponse } from 'msw'; export const createProject = http.post( - `${import.meta.env.VITE_API_BASE_URL}/project`, + `${import.meta.env.VITE_APP_API_BASE_URL}project`, () => { return HttpResponse.json({ status: 200, diff --git a/src/mock/manageProjectList.ts b/src/mock/manageProjectList.ts index 44554fc7..a5a81006 100644 --- a/src/mock/manageProjectList.ts +++ b/src/mock/manageProjectList.ts @@ -2,7 +2,7 @@ import { HttpResponse, http } from 'msw'; import mockManageMyprojectList from './mockProjectList.json'; export const myProjectList = http.get( - `${import.meta.env.VITE_API_BASE_URL}/project/my`, + `${import.meta.env.VITE_APP_API_BASE_URL}project/my`, () => { return HttpResponse.json(mockManageMyprojectList, { status: 200, @@ -11,7 +11,7 @@ export const myProjectList = http.get( ); export const sendResult = http.put( - `${import.meta.env.VITE_API_BASE_URL}/project/:projectId/close`, + `${import.meta.env.VITE_APP_API_BASE_URL}project/:projectId/close`, () => { return HttpResponse.json( { message: '지원자들에게 결과를 전송했어요' }, diff --git a/src/mock/mockReports.json b/src/mock/mockReports.json new file mode 100644 index 00000000..e029e710 --- /dev/null +++ b/src/mock/mockReports.json @@ -0,0 +1,166 @@ +{ + "success": true, + "message": "성공적으로 처리되었습니다.", + "data": [ + { + "id": 1, + "imposedCount": 3, + "category": "스팸 신고", + "user": [ + { + "id": 301, + "nickname": "alice", + "img": "https://example.com/images/alice.png" + } + ], + "IsImposed": false, + "createdAt": "2025-05-01T10:15:00+09:00" + }, + { + "id": 2, + "imposedCount": 5, + "category": "욕설/비방", + "user": [ + { + "id": 302, + "nickname": "bob", + "img": "https://example.com/images/bob.jpg" + }, + { + "id": 303, + "nickname": "charlie", + "img": "https://example.com/images/charlie.jpeg" + } + ], + "IsImposed": true, + "createdAt": "2025-05-03T14:30:00+09:00" + }, + { + "id": 3, + "imposedCount": 2, + "category": "저작권 침해", + "user": [ + { + "id": 304, + "nickname": "daisy", + "img": "https://example.com/images/daisy.png" + } + ], + "IsImposed": false, + "createdAt": "2025-05-05T09:45:00+09:00" + }, + { + "id": 4, + "imposedCount": 7, + "category": "개인정보 노출", + "user": [ + { + "id": 305, + "nickname": "eve", + "img": "https://example.com/images/eve.jpg" + } + ], + "IsImposed": true, + "createdAt": "2025-05-07T16:20:00+09:00" + }, + { + "id": 5, + "imposedCount": 1, + "category": "음란물 게시물", + "user": [ + { + "id": 306, + "nickname": "frank", + "img": "https://example.com/images/frank.png" + }, + { + "id": 307, + "nickname": "grace", + "img": "https://example.com/images/grace.jpeg" + } + ], + "IsImposed": false, + "createdAt": "2025-05-09T11:10:00+09:00" + }, + { + "id": 6, + "imposedCount": 4, + "category": "사칭 계정", + "user": [ + { + "id": 308, + "nickname": "henry", + "img": "https://example.com/images/henry.jpg" + } + ], + "IsImposed": true, + "createdAt": "2025-05-11T13:55:00+09:00" + }, + { + "id": 7, + "imposedCount": 6, + "category": "허위 정보 유포", + "user": [ + { + "id": 309, + "nickname": "iris", + "img": "https://example.com/images/iris.png" + }, + { + "id": 310, + "nickname": "jack", + "img": "https://example.com/images/jack.jpg" + } + ], + "IsImposed": false, + "createdAt": "2025-05-13T18:05:00+09:00" + }, + { + "id": 8, + "imposedCount": 2, + "category": "불법 광고", + "user": [ + { + "id": 311, + "nickname": "kate", + "img": "https://example.com/images/kate.jpeg" + } + ], + "IsImposed": true, + "createdAt": "2025-05-15T08:25:00+09:00" + }, + { + "id": 9, + "imposedCount": 8, + "category": "명예 훼손", + "user": [ + { + "id": 312, + "nickname": "leo", + "img": "https://example.com/images/leo.png" + } + ], + "IsImposed": true, + "createdAt": "2025-05-17T12:40:00+09:00" + }, + { + "id": 10, + "imposedCount": 3, + "category": "폭력/위협", + "user": [ + { + "id": 313, + "nickname": "maria", + "img": "https://example.com/images/maria.jpg" + }, + { + "id": 314, + "nickname": "nate", + "img": "https://example.com/images/nate.png" + } + ], + "IsImposed": false, + "createdAt": "2025-05-19T20:15:00+09:00" + } + ] +} diff --git a/src/mock/mockUsers.json b/src/mock/mockUsers.json new file mode 100644 index 00000000..4c3c65f6 --- /dev/null +++ b/src/mock/mockUsers.json @@ -0,0 +1,151 @@ +{ + "success": true, + "message": "성공적으로 처리되었습니다.", + "data": [ + { + "id": 1, + "email": "alice@example.com", + "name": "Alice Kim", + "user": [ + { + "id": 201, + "nickname": "alice", + "img": "https://example.com/images/alice.png" + } + ], + "createdAt": "2025-05-15T09:30:00+09:00" + }, + { + "id": 2, + "email": "bob@example.com", + "name": "Bob Lee", + "user": [ + { + "id": 202, + "nickname": "bob", + "img": "https://example.com/images/bob.jpg" + } + ], + "createdAt": "2025-05-16T11:45:00+09:00" + }, + { + "id": 3, + "email": "charlie@example.com", + "name": "Charlie Park", + "user": [ + { + "id": 203, + "nickname": "charlie", + "img": "https://example.com/images/charlie.jpeg" + }, + { + "id": 204, + "nickname": "daisy", + "img": "https://example.com/images/daisy.png" + } + ], + "createdAt": "2025-05-17T14:20:00+09:00" + }, + { + "id": 4, + "email": "daisy@example.com", + "name": "Daisy Choi", + "user": [ + { + "id": 205, + "nickname": "daisy", + "img": "https://example.com/images/daisy.png" + } + ], + "createdAt": "2025-05-18T08:10:00+09:00" + }, + { + "id": 5, + "email": "eve@example.com", + "name": "Eve Jung", + "user": [ + { + "id": 206, + "nickname": "eve", + "img": "https://example.com/images/eve.jpg" + } + ], + "createdAt": "2025-05-19T17:50:00+09:00" + }, + { + "id": 6, + "email": "frank@example.com", + "name": "Frank Han", + "user": [ + { + "id": 207, + "nickname": "frank", + "img": "https://example.com/images/frank.png" + }, + { + "id": 208, + "nickname": "grace", + "img": "https://example.com/images/grace.jpeg" + } + ], + "createdAt": "2025-05-20T12:05:00+09:00" + }, + { + "id": 7, + "email": "grace@example.com", + "name": "Grace Yoon", + "user": [ + { + "id": 209, + "nickname": "grace", + "img": "https://example.com/images/grace.jpeg" + } + ], + "createdAt": "2025-05-21T10:15:00+09:00" + }, + { + "id": 8, + "email": "henry@example.com", + "name": "Henry Shin", + "user": [ + { + "id": 210, + "nickname": "henry", + "img": "https://example.com/images/henry.jpg" + } + ], + "createdAt": "2025-05-22T13:40:00+09:00" + }, + { + "id": 9, + "email": "iris@example.com", + "name": "Iris Lim", + "user": [ + { + "id": 211, + "nickname": "iris", + "img": "https://example.com/images/iris.png" + } + ], + "createdAt": "2025-05-23T16:25:00+09:00" + }, + { + "id": 10, + "email": "jack@example.com", + "name": "Jack Han", + "user": [ + { + "id": 212, + "nickname": "jack", + "img": "https://example.com/images/jack.jpg" + }, + { + "id": 213, + "nickname": "kate", + "img": "https://example.com/images/kate.jpeg" + } + ], + "createdAt": "2025-05-24T19:55:00+09:00" + } + ] +} diff --git a/src/mock/mypage.ts b/src/mock/mypage.ts index 74c04ed0..6adaf4f2 100644 --- a/src/mock/mypage.ts +++ b/src/mock/mypage.ts @@ -6,7 +6,7 @@ import mockMypageJoinedProjectListData from './mockMypageJoinedProjectListData.j import mockMypageAppliedProjectListData from './mockMypageAppliedProjectListData.json'; export const myPageProfile = http.get( - `${import.meta.env.VITE_API_BASE_URL}/user/me`, + `${import.meta.env.VITE_APP_API_BASE_URL}user/me`, () => { return HttpResponse.json(mockMypageProfileData, { status: 200, @@ -15,7 +15,7 @@ export const myPageProfile = http.get( ); export const myPagePositionTag = http.get( - `${import.meta.env.VITE_API_BASE_URL}/position-tag`, + `${import.meta.env.VITE_APP_API_BASE_URL}position-tag`, () => { return HttpResponse.json(mockPositionTagData, { status: 200, @@ -24,7 +24,7 @@ export const myPagePositionTag = http.get( ); export const myPageSkillTag = http.get( - `${import.meta.env.VITE_API_BASE_URL}/skill-tag`, + `${import.meta.env.VITE_APP_API_BASE_URL}skill-tag`, () => { return HttpResponse.json(mockSkillTagData, { status: 200, @@ -33,7 +33,7 @@ export const myPageSkillTag = http.get( ); export const myPageJoinedProjectList = http.get( - `${import.meta.env.VITE_API_BASE_URL}/user/me/project`, + `${import.meta.env.VITE_APP_API_BASE_URL}user/me/project`, () => { return HttpResponse.json(mockMypageJoinedProjectListData, { status: 200, @@ -42,7 +42,7 @@ export const myPageJoinedProjectList = http.get( ); export const myPageAppliedProjectList = http.get( - `${import.meta.env.VITE_API_BASE_URL}/user/me/applications`, + `${import.meta.env.VITE_APP_API_BASE_URL}user/me/applications`, () => { return HttpResponse.json(mockMypageAppliedProjectListData, { status: 200, @@ -51,7 +51,7 @@ export const myPageAppliedProjectList = http.get( ); export const mypageEditProfile = http.put( - `${import.meta.env.VITE_API_BASE_URL}/user/me`, + `${import.meta.env.VITE_APP_API_BASE_URL}user/me`, () => { return HttpResponse.json({ status: 200, diff --git a/src/mock/projectDetail.ts b/src/mock/projectDetail.ts index 9ac8c983..a22d7fc4 100644 --- a/src/mock/projectDetail.ts +++ b/src/mock/projectDetail.ts @@ -1,11 +1,19 @@ import { http, HttpResponse } from 'msw'; import mockPrjectDetail from './mockProjectDetail.json'; +import mockReports from './mockReports.json'; export const projectDetail = http.get( - `${import.meta.env.VITE_API_BASE_URL}/project/:projectId`, + `${import.meta.env.VITE_APP_API_BASE_URL}/project/:projectId`, () => { return HttpResponse.json(mockPrjectDetail, { status: 200, }); } ); + +export const reportsAll = http.get( + `${import.meta.env.VITE_APP_API_BASE_URL}reports`, + () => { + return HttpResponse.json(mockReports, { status: 200 }); + } +); diff --git a/src/mock/projectLists.ts b/src/mock/projectLists.ts index 394b7cf6..c9db9c1c 100644 --- a/src/mock/projectLists.ts +++ b/src/mock/projectLists.ts @@ -3,7 +3,7 @@ import count from './mockCount.json'; import project from './mockProject.json'; export const fetchProjectLists = http.get( - `${import.meta.env.VITE_API_BASE_URL}/project`, + `${import.meta.env.VITE_APP_API_BASE_URL}project`, () => { return HttpResponse.json(project, { status: 200, @@ -12,7 +12,7 @@ export const fetchProjectLists = http.get( ); export const fetchProjectStatistic = http.get( - `${import.meta.env.VITE_API_BASE_URL}/project/count`, + `${import.meta.env.VITE_APP_API_BASE_URL}project/count`, () => { return HttpResponse.json(count, { status: 200, diff --git a/src/mock/projectSearchFiltering.ts b/src/mock/projectSearchFiltering.ts index e97bda84..1a86df73 100644 --- a/src/mock/projectSearchFiltering.ts +++ b/src/mock/projectSearchFiltering.ts @@ -4,7 +4,7 @@ import position from './mockPosition.json'; import method from './mockMethod.json'; export const fetchSkillTag = http.get( - `${import.meta.env.VITE_API_BASE_URL}/skill-tag`, + `${import.meta.env.VITE_APP_API_BASE_URL}skill-tag`, () => { return HttpResponse.json(skill, { status: 200, @@ -12,7 +12,7 @@ export const fetchSkillTag = http.get( } ); export const fetchPositionTag = http.get( - `${import.meta.env.VITE_API_BASE_URL}/position-tag`, + `${import.meta.env.VITE_APP_API_BASE_URL}position-tag`, () => { return HttpResponse.json(position, { status: 200, @@ -21,7 +21,7 @@ export const fetchPositionTag = http.get( ); export const fetchMethodTag = http.get( - `${import.meta.env.VITE_API_BASE_URL}/method`, + `${import.meta.env.VITE_APP_API_BASE_URL}method`, () => { return HttpResponse.json(method, { status: 200, diff --git a/src/mock/userpage.ts b/src/mock/userpage.ts index 65f443d1..21090fff 100644 --- a/src/mock/userpage.ts +++ b/src/mock/userpage.ts @@ -1,9 +1,10 @@ import { http, HttpResponse } from 'msw'; import mockUserpageProfileData from './mockUserpageProfileData.json'; import mockUserpageAppliedProjectListData from './mockUserpageAppliedProjectListData.json'; +import mockUsers from './mockUsers.json'; export const userPageProfile = http.get( - `${import.meta.env.VITE_API_BASE_URL}/user/:id`, + `${import.meta.env.VITE_APP_API_BASE_URL}user/:id`, () => { return HttpResponse.json(mockUserpageProfileData, { status: 200, @@ -12,10 +13,17 @@ export const userPageProfile = http.get( ); export const userPageAppliedProjectList = http.get( - `${import.meta.env.VITE_API_BASE_URL}/user/:id/project`, + `${import.meta.env.VITE_APP_API_BASE_URL}user/:id/project`, () => { return HttpResponse.json(mockUserpageAppliedProjectListData, { status: 200, }); } ); + +export const userAll = http.get( + `${import.meta.env.VITE_APP_API_BASE_URL}users`, + () => { + return HttpResponse.json(mockUsers, { status: 200 }); + } +); From b222ea367e4db243914bd0bbcdd26fee82b74e8c Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 20:34:01 +0900 Subject: [PATCH 05/17] =?UTF-8?q?style=20:=20"=EB=AC=B8=EC=9D=98=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0"=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inquiresPreview/InquiresPreview.styled.ts | 23 +++++++++---------- .../inquiresPreview/InquiresPreview.tsx | 6 ++--- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts index d0b08132..b5ef0b12 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts @@ -4,19 +4,17 @@ import styled from 'styled-components'; export const Container = styled.div` display: flex; flex-direction: column; - margin-left: 10px; `; export const Wrapper = styled.div` display: flex; justify-content: space-between; align-items: center; + padding: 10px; `; export const Content = styled.div` display: flex; - align-items: center; - margin-top: 16px; `; export const Inquiry = styled(Link)` @@ -28,7 +26,7 @@ export const Category = styled.p` opacity: 50%; `; -export const Title = styled.span` +export const Title = styled.p` font-size: 13px; white-space: nowrap; overflow: hidden; @@ -37,7 +35,6 @@ export const Title = styled.span` export const StateArea = styled.div` display: flex; - align-items: center; `; export const Date = styled.p` @@ -46,6 +43,7 @@ export const Date = styled.p` `; export const Divider = styled.p` + font-size: 9px; opacity: 20%; margin-left: 3px; margin-right: 3px; @@ -58,13 +56,14 @@ export const InquiryState = styled.p<{ $isCompleted: boolean }>` export const MoveToInquiryArea = styled(Link)` display: flex; - justify-content: center; - align-items: center; - font-size: 10px; - margin-right: 10px; - margin-top: 20px; + font-size: 9px; `; -export const Text = styled.p``; +export const Text = styled.p` + font-size: 9px; +`; -export const Arrow = styled.img``; +export const Arrow = styled.img` + width: 11px; + height: 11px; +`; diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx index 61d6e810..ea62c3f5 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx @@ -1,9 +1,7 @@ -import React from 'react'; import * as S from './InquiresPreview.styled'; import { useGetAllInquiries } from '../../../../hooks/admin/useGetAllInquiries'; import Avatar from '../../../common/avatar/Avatar'; import { ADMIN_ROUTE } from '../../../../constants/routes'; -import { Link } from 'react-router-dom'; import arrow_right from '../../../../assets/ArrowRight.svg'; const InquiresPreview = () => { @@ -11,7 +9,7 @@ const InquiresPreview = () => { const previewList = allInquiriesData ? allInquiriesData.length > 6 - ? allInquiriesData.slice(-4) + ? allInquiriesData.slice(0, 4) : allInquiriesData : []; @@ -21,7 +19,7 @@ const InquiresPreview = () => { {/* + {inquiry.category} {inquiry.title} From 722cc8a2eb22ec0b13d794a30c3dc5b72bd966aa Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 20:34:50 +0900 Subject: [PATCH 06/17] =?UTF-8?q?feat=20:=20"=EC=8B=A0=EA=B3=A0=20?= =?UTF-8?q?=EA=B2=80=ED=86=A0"=20=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reportsPreview/ReportsPreview.styled.ts | 67 ++++++++++++++++++- .../reportsPreview/ReportsPreview.tsx | 40 ++++++++++- src/hooks/admin/useGetAllReports.ts | 12 ++++ src/hooks/queries/user/keys.ts | 4 ++ src/mock/mockReports.json | 20 +++--- src/models/report.ts | 15 +++++ 6 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 src/hooks/admin/useGetAllReports.ts diff --git a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts index c3389834..65820764 100644 --- a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts +++ b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts @@ -1,3 +1,68 @@ +import { Link } from 'react-router-dom'; import styled from 'styled-components'; -export const Container = styled.div``; +export const Container = styled.div` + display: flex; + flex-direction: column; +`; + +export const Wrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; +`; + +export const ReportArea = styled(Link)` + display: flex; +`; + +export const ContentArea = styled.div` + margin-left: 16px; +`; + +export const ImposedCount = styled.div` + font-size: 9px; + opacity: 50%; +`; + +export const Category = styled.p` + font-size: 13px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; + +export const StateArea = styled.div` + display: flex; +`; + +export const Date = styled.p` + font-size: 9px; + opacity: 50%; +`; + +export const Divider = styled.p` + font-size: 9px; + opacity: 20%; + margin-left: 3px; + margin-right: 3px; +`; + +export const IsImposed = styled.p<{ $isImposed: boolean }>` + font-size: 9px; + color: ${({ $isImposed }) => ($isImposed ? `#07DE00` : `#DE1A00`)}; +`; + +export const MoveToReportsArea = styled(Link)` + display: flex; +`; + +export const Text = styled.p` + font-size: 9px; +`; + +export const Arrow = styled.img` + width: 11px; + height: 11px; +`; diff --git a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx index d3964ed7..5e6c0502 100644 --- a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx +++ b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx @@ -1,8 +1,44 @@ -import React from 'react'; import * as S from './ReportsPreview.styled'; +import { useGetAllReports } from '../../../../hooks/admin/useGetAllReports'; +import Avatar from '../../../common/avatar/Avatar'; +import arrow_right from '../../../../assets/ArrowRight.svg'; +import { ADMIN_ROUTE } from '../../../../constants/routes'; const ReportsPreview = () => { - return ReportsPreview Component; + const { allReportsData } = useGetAllReports(); + + const previewList = allReportsData + ? allReportsData.length > 6 + ? allReportsData.slice(0, 4) + : allReportsData + : []; + + return ( + + {previewList?.map((report) => ( + + + + + {report.imposedCount} 번 + {report.category} + + {report.createdAt} + | + + {report.IsImposed ? '검토 완료' : '검토 미완료'} + + + + + + 신고 상세 보기 + + + + ))} + + ); }; export default ReportsPreview; diff --git a/src/hooks/admin/useGetAllReports.ts b/src/hooks/admin/useGetAllReports.ts new file mode 100644 index 00000000..ab7c1f31 --- /dev/null +++ b/src/hooks/admin/useGetAllReports.ts @@ -0,0 +1,12 @@ +import { useQuery } from '@tanstack/react-query'; +import { ReportData } from '../queries/user/keys'; +import { getAllReports } from '../../api/report.api'; + +export const useGetAllReports = () => { + const { data: allReportsData, isLoading } = useQuery({ + queryKey: [ReportData.allReports], + queryFn: () => getAllReports(), + }); + + return { allReportsData, isLoading }; +}; diff --git a/src/hooks/queries/user/keys.ts b/src/hooks/queries/user/keys.ts index 36a635b9..13cee296 100644 --- a/src/hooks/queries/user/keys.ts +++ b/src/hooks/queries/user/keys.ts @@ -55,3 +55,7 @@ export const CustomerService = { notice: 'notice', noticeDetail: 'noticeDetail', }; + +export const ReportData = { + allReports: ['AllReports'], +}; diff --git a/src/mock/mockReports.json b/src/mock/mockReports.json index e029e710..7e85a209 100644 --- a/src/mock/mockReports.json +++ b/src/mock/mockReports.json @@ -14,7 +14,7 @@ } ], "IsImposed": false, - "createdAt": "2025-05-01T10:15:00+09:00" + "createdAt": "2025-05-01" }, { "id": 2, @@ -33,7 +33,7 @@ } ], "IsImposed": true, - "createdAt": "2025-05-03T14:30:00+09:00" + "createdAt": "2025-05-03" }, { "id": 3, @@ -47,7 +47,7 @@ } ], "IsImposed": false, - "createdAt": "2025-05-05T09:45:00+09:00" + "createdAt": "2025-05-05" }, { "id": 4, @@ -61,7 +61,7 @@ } ], "IsImposed": true, - "createdAt": "2025-05-07T16:20:00+09:00" + "createdAt": "2025-05-07" }, { "id": 5, @@ -80,7 +80,7 @@ } ], "IsImposed": false, - "createdAt": "2025-05-09T11:10:00+09:00" + "createdAt": "2025-05-09" }, { "id": 6, @@ -94,7 +94,7 @@ } ], "IsImposed": true, - "createdAt": "2025-05-11T13:55:00+09:00" + "createdAt": "2025-05-11" }, { "id": 7, @@ -113,7 +113,7 @@ } ], "IsImposed": false, - "createdAt": "2025-05-13T18:05:00+09:00" + "createdAt": "2025-05-13" }, { "id": 8, @@ -127,7 +127,7 @@ } ], "IsImposed": true, - "createdAt": "2025-05-15T08:25:00+09:00" + "createdAt": "2025-05-15" }, { "id": 9, @@ -141,7 +141,7 @@ } ], "IsImposed": true, - "createdAt": "2025-05-17T12:40:00+09:00" + "createdAt": "2025-05-17" }, { "id": 10, @@ -160,7 +160,7 @@ } ], "IsImposed": false, - "createdAt": "2025-05-19T20:15:00+09:00" + "createdAt": "2025-05-19" } ] } diff --git a/src/models/report.ts b/src/models/report.ts index 16fa8720..da44cd9b 100644 --- a/src/models/report.ts +++ b/src/models/report.ts @@ -1,6 +1,21 @@ +import { ApiCommonType, User } from './apiCommon'; + export interface ApiPostContent { reportTargetId: number; reportFilter: number; reason: string[]; detail: string; } + +export interface ApiAllReports extends ApiCommonType { + data: AllReports[]; +} + +export interface AllReports { + id: number; + imposedCount: number; + category: string; + user: User; + IsImposed: boolean; + createdAt: string; +} From c9bda6dc69ce51a91ac5fae0ef88ea10966cc6b1 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 21:20:05 +0900 Subject: [PATCH 07/17] =?UTF-8?q?feat=20:=20"=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A1=B0=ED=9A=8C"=20=EB=AF=B8=EB=A6=AC?= =?UTF-8?q?=20=EB=B3=B4=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allUserPreview/AllUserPreview.styled.ts | 43 ++++++++++++++++++- .../allUserPreview/AllUserPreview.tsx | 32 +++++++++++++- src/hooks/admin/useGetAllUsers.ts | 12 ++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/hooks/admin/useGetAllUsers.ts diff --git a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts index c3389834..5a2a4058 100644 --- a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts +++ b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts @@ -1,3 +1,44 @@ +import { Link } from 'react-router-dom'; import styled from 'styled-components'; -export const Container = styled.div``; +export const Container = styled.div` + display: flex; + flex-direction: column; +`; + +export const Wrapper = styled.div` + display: flex; + justify-content: space-between; + padding: 10px; +`; + +export const UserArea = styled.div` + display: flex; +`; + +export const ContentArea = styled(Link)` + margin-left: 16px; +`; + +export const NickName = styled.p` + font-size: 14px; +`; + +export const Email = styled.p` + font-size: 9px; + opacity: 50%; +`; + +export const MoveToUsersArea = styled(Link)` + display: flex; + align-items: center; +`; + +export const Text = styled.p` + font-size: 9px; +`; + +export const Arrow = styled.img` + width: 10px; + height: 10px; +`; diff --git a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx index fba6c2f3..4967bafe 100644 --- a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx +++ b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx @@ -1,8 +1,38 @@ import React from 'react'; import * as S from './AllUserPreview.styled'; +import { useGetAllUsers } from '../../../../hooks/admin/useGetAllUsers'; +import Avatar from '../../../common/avatar/Avatar'; +import { ADMIN_ROUTE } from '../../../../constants/routes'; +import arrow_right from '../../../../assets/ArrowRight.svg'; const AllUserPreview = () => { - return AllUserPreview Component; + const { allUserData, isLoading } = useGetAllUsers(); + + const previewList = allUserData + ? allUserData.length > 6 + ? allUserData.slice(0, 4) + : allUserData + : []; + + return ( + + {previewList?.map((user) => ( + + + + + {user.user.nickname} + {user.email} + + + + 상세 보기 + + + + ))} + + ); }; export default AllUserPreview; diff --git a/src/hooks/admin/useGetAllUsers.ts b/src/hooks/admin/useGetAllUsers.ts new file mode 100644 index 00000000..a9c9e7a8 --- /dev/null +++ b/src/hooks/admin/useGetAllUsers.ts @@ -0,0 +1,12 @@ +import { useQuery } from '@tanstack/react-query'; +import { ReportData } from '../queries/user/keys'; +import { getAllUsers } from '../../api/auth.api'; + +export const useGetAllUsers = () => { + const { data: allUserData, isLoading } = useQuery({ + queryKey: [ReportData.allReports], + queryFn: () => getAllUsers(), + }); + + return { allUserData, isLoading }; +}; From 6fcbc1dd170fd50dbbfdc09baf74ff4e6a1f3813 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 21:20:24 +0900 Subject: [PATCH 08/17] =?UTF-8?q?feat=20:=20"=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A1=B0=ED=9A=8C"=20=EB=AF=B8=EB=A6=AC?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth.api.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/api/auth.api.ts b/src/api/auth.api.ts index 0bc320ea..b866b37c 100644 --- a/src/api/auth.api.ts +++ b/src/api/auth.api.ts @@ -1,4 +1,9 @@ -import type { ApiOauth, ApiVerifyNickname, VerifyEmail } from '../models/auth'; +import { + ApiGetAllUsers, + type ApiOauth, + type ApiVerifyNickname, + type VerifyEmail, +} from '../models/auth'; import { httpClient } from './http.api'; import { loginFormValues } from '../pages/login/Login'; import { registerFormValues } from '../pages/user/register/Register'; @@ -100,3 +105,13 @@ export const getOauthLogin = async (oauthAccessToken: string) => { throw e; } }; + +export const getAllUsers = async () => { + try { + const response = await httpClient.get(`/users`); + return response.data.data; + } catch (e) { + console.error(e); + throw e; + } +}; From eb775406bb7a33cdbfbc5151b2cd134bc16ef9cb Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 21:20:48 +0900 Subject: [PATCH 09/17] =?UTF-8?q?feat=20:=20mock=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mock/browser.ts | 2 +- src/mock/mockReports.json | 142 +++++++++++++--------------------- src/mock/mockUsers.json | 156 +++++++++++++++----------------------- src/mock/projectDetail.ts | 2 +- 4 files changed, 115 insertions(+), 187 deletions(-) diff --git a/src/mock/browser.ts b/src/mock/browser.ts index 81c8f6b3..2c4da947 100644 --- a/src/mock/browser.ts +++ b/src/mock/browser.ts @@ -55,8 +55,8 @@ export const handlers = [ login, createApplicant, createProject, - userAll, reportsAll, + userAll, ]; export const worker = setupWorker(...handlers); diff --git a/src/mock/mockReports.json b/src/mock/mockReports.json index 7e85a209..bd73ad0b 100644 --- a/src/mock/mockReports.json +++ b/src/mock/mockReports.json @@ -6,13 +6,11 @@ "id": 1, "imposedCount": 3, "category": "스팸 신고", - "user": [ - { - "id": 301, - "nickname": "alice", - "img": "https://example.com/images/alice.png" - } - ], + "user": { + "id": 301, + "nickname": "alice", + "img": "https://example.com/images/alice.png" + }, "IsImposed": false, "createdAt": "2025-05-01" }, @@ -20,18 +18,11 @@ "id": 2, "imposedCount": 5, "category": "욕설/비방", - "user": [ - { - "id": 302, - "nickname": "bob", - "img": "https://example.com/images/bob.jpg" - }, - { - "id": 303, - "nickname": "charlie", - "img": "https://example.com/images/charlie.jpeg" - } - ], + "user": { + "id": 303, + "nickname": "charlie", + "img": "https://example.com/images/charlie.jpeg" + }, "IsImposed": true, "createdAt": "2025-05-03" }, @@ -39,13 +30,11 @@ "id": 3, "imposedCount": 2, "category": "저작권 침해", - "user": [ - { - "id": 304, - "nickname": "daisy", - "img": "https://example.com/images/daisy.png" - } - ], + "user": { + "id": 304, + "nickname": "daisy", + "img": "https://example.com/images/daisy.png" + }, "IsImposed": false, "createdAt": "2025-05-05" }, @@ -53,13 +42,11 @@ "id": 4, "imposedCount": 7, "category": "개인정보 노출", - "user": [ - { - "id": 305, - "nickname": "eve", - "img": "https://example.com/images/eve.jpg" - } - ], + "user": { + "id": 305, + "nickname": "eve", + "img": "https://example.com/images/eve.jpg" + }, "IsImposed": true, "createdAt": "2025-05-07" }, @@ -67,18 +54,12 @@ "id": 5, "imposedCount": 1, "category": "음란물 게시물", - "user": [ - { - "id": 306, - "nickname": "frank", - "img": "https://example.com/images/frank.png" - }, - { - "id": 307, - "nickname": "grace", - "img": "https://example.com/images/grace.jpeg" - } - ], + "user": { + "id": 306, + "nickname": "frank", + "img": "https://example.com/images/frank.png" + }, + "IsImposed": false, "createdAt": "2025-05-09" }, @@ -86,13 +67,11 @@ "id": 6, "imposedCount": 4, "category": "사칭 계정", - "user": [ - { - "id": 308, - "nickname": "henry", - "img": "https://example.com/images/henry.jpg" - } - ], + "user": { + "id": 308, + "nickname": "henry", + "img": "https://example.com/images/henry.jpg" + }, "IsImposed": true, "createdAt": "2025-05-11" }, @@ -100,18 +79,12 @@ "id": 7, "imposedCount": 6, "category": "허위 정보 유포", - "user": [ - { - "id": 309, - "nickname": "iris", - "img": "https://example.com/images/iris.png" - }, - { - "id": 310, - "nickname": "jack", - "img": "https://example.com/images/jack.jpg" - } - ], + "user": { + "id": 309, + "nickname": "iris", + "img": "https://example.com/images/iris.png" + }, + "IsImposed": false, "createdAt": "2025-05-13" }, @@ -119,13 +92,11 @@ "id": 8, "imposedCount": 2, "category": "불법 광고", - "user": [ - { - "id": 311, - "nickname": "kate", - "img": "https://example.com/images/kate.jpeg" - } - ], + "user": { + "id": 311, + "nickname": "kate", + "img": "https://example.com/images/kate.jpeg" + }, "IsImposed": true, "createdAt": "2025-05-15" }, @@ -133,13 +104,11 @@ "id": 9, "imposedCount": 8, "category": "명예 훼손", - "user": [ - { - "id": 312, - "nickname": "leo", - "img": "https://example.com/images/leo.png" - } - ], + "user": { + "id": 312, + "nickname": "leo", + "img": "https://example.com/images/leo.png" + }, "IsImposed": true, "createdAt": "2025-05-17" }, @@ -147,18 +116,11 @@ "id": 10, "imposedCount": 3, "category": "폭력/위협", - "user": [ - { - "id": 313, - "nickname": "maria", - "img": "https://example.com/images/maria.jpg" - }, - { - "id": 314, - "nickname": "nate", - "img": "https://example.com/images/nate.png" - } - ], + "user": { + "id": 314, + "nickname": "nate", + "img": "https://example.com/images/nate.png" + }, "IsImposed": false, "createdAt": "2025-05-19" } diff --git a/src/mock/mockUsers.json b/src/mock/mockUsers.json index 4c3c65f6..29036373 100644 --- a/src/mock/mockUsers.json +++ b/src/mock/mockUsers.json @@ -6,146 +6,112 @@ "id": 1, "email": "alice@example.com", "name": "Alice Kim", - "user": [ - { - "id": 201, - "nickname": "alice", - "img": "https://example.com/images/alice.png" - } - ], - "createdAt": "2025-05-15T09:30:00+09:00" + "user": { + "id": 201, + "nickname": "alice", + "img": "" + }, + "createdAt": "2025-05-15" }, { "id": 2, "email": "bob@example.com", "name": "Bob Lee", - "user": [ - { - "id": 202, - "nickname": "bob", - "img": "https://example.com/images/bob.jpg" - } - ], - "createdAt": "2025-05-16T11:45:00+09:00" + "user": { + "id": 202, + "nickname": "bob", + "img": "" + }, + "createdAt": "2025-05-16" }, { "id": 3, "email": "charlie@example.com", "name": "Charlie Park", - "user": [ - { - "id": 203, - "nickname": "charlie", - "img": "https://example.com/images/charlie.jpeg" - }, - { - "id": 204, - "nickname": "daisy", - "img": "https://example.com/images/daisy.png" - } - ], - "createdAt": "2025-05-17T14:20:00+09:00" + "user": { + "id": 204, + "nickname": "daisy", + "img": "" + }, + "createdAt": "2025-05-17" }, { "id": 4, "email": "daisy@example.com", "name": "Daisy Choi", - "user": [ - { - "id": 205, - "nickname": "daisy", - "img": "https://example.com/images/daisy.png" - } - ], - "createdAt": "2025-05-18T08:10:00+09:00" + "user": { + "id": 205, + "nickname": "daisy", + "img": "" + }, + "createdAt": "2025-05-18" }, { "id": 5, "email": "eve@example.com", "name": "Eve Jung", - "user": [ - { - "id": 206, - "nickname": "eve", - "img": "https://example.com/images/eve.jpg" - } - ], - "createdAt": "2025-05-19T17:50:00+09:00" + "user": { + "id": 206, + "nickname": "eve", + "img": "" + }, + "createdAt": "2025-05-19" }, { "id": 6, "email": "frank@example.com", "name": "Frank Han", - "user": [ - { - "id": 207, - "nickname": "frank", - "img": "https://example.com/images/frank.png" - }, - { - "id": 208, - "nickname": "grace", - "img": "https://example.com/images/grace.jpeg" - } - ], - "createdAt": "2025-05-20T12:05:00+09:00" + "user": { + "id": 208, + "nickname": "grace", + "img": "" + }, + "createdAt": "2025-05-20" }, { "id": 7, "email": "grace@example.com", "name": "Grace Yoon", - "user": [ - { - "id": 209, - "nickname": "grace", - "img": "https://example.com/images/grace.jpeg" - } - ], - "createdAt": "2025-05-21T10:15:00+09:00" + "user": { + "id": 209, + "nickname": "grace", + "img": "" + }, + "createdAt": "2025-05-21" }, { "id": 8, "email": "henry@example.com", "name": "Henry Shin", - "user": [ - { - "id": 210, - "nickname": "henry", - "img": "https://example.com/images/henry.jpg" - } - ], - "createdAt": "2025-05-22T13:40:00+09:00" + "user": { + "id": 210, + "nickname": "henry", + "img": "" + }, + "createdAt": "2025-05-22" }, { "id": 9, "email": "iris@example.com", "name": "Iris Lim", - "user": [ - { - "id": 211, - "nickname": "iris", - "img": "https://example.com/images/iris.png" - } - ], - "createdAt": "2025-05-23T16:25:00+09:00" + "user": { + "id": 211, + "nickname": "iris", + "img": "" + }, + "createdAt": "2025-05-23" }, { "id": 10, "email": "jack@example.com", "name": "Jack Han", - "user": [ - { - "id": 212, - "nickname": "jack", - "img": "https://example.com/images/jack.jpg" - }, - { - "id": 213, - "nickname": "kate", - "img": "https://example.com/images/kate.jpeg" - } - ], - "createdAt": "2025-05-24T19:55:00+09:00" + "user": { + "id": 212, + "nickname": "jack", + "img": "" + }, + + "createdAt": "2025-05-24" } ] } diff --git a/src/mock/projectDetail.ts b/src/mock/projectDetail.ts index a22d7fc4..bf6c51ea 100644 --- a/src/mock/projectDetail.ts +++ b/src/mock/projectDetail.ts @@ -3,7 +3,7 @@ import mockPrjectDetail from './mockProjectDetail.json'; import mockReports from './mockReports.json'; export const projectDetail = http.get( - `${import.meta.env.VITE_APP_API_BASE_URL}/project/:projectId`, + `${import.meta.env.VITE_APP_API_BASE_URL}project/:projectId`, () => { return HttpResponse.json(mockPrjectDetail, { status: 200, From 90e5e329e5f8c9e5ce6affb8d34d12ddd0aae377 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 21:21:06 +0900 Subject: [PATCH 10/17] =?UTF-8?q?feat=20:=20"=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A1=B0=ED=9A=8C"=20=EB=AF=B8=EB=A6=AC?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/models/auth.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/models/auth.ts b/src/models/auth.ts index bd5787a2..67370ae4 100644 --- a/src/models/auth.ts +++ b/src/models/auth.ts @@ -1,5 +1,5 @@ //model -import { ApiCommonType } from './apiCommon'; +import { ApiCommonType, User } from './apiCommon'; export interface VerifyEmail { email: string; @@ -27,3 +27,15 @@ export interface ApiOauth extends ApiCommonType { data: Pick; user: UserData; } + +export interface ApiGetAllUsers extends ApiCommonType { + data: AllUser[]; +} + +export interface AllUser { + id: number; + email: string; + name: string; + user: User; + createdAt: string; +} From b32707602fec5057c8985d5005311667bf66c062 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 21:21:24 +0900 Subject: [PATCH 11/17] =?UTF-8?q?feat=20:=20"=EC=8B=A0=EA=B3=A0=20?= =?UTF-8?q?=ED=95=AD=EB=AA=A9"=20=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0=20ap?= =?UTF-8?q?i=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/report.api.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/api/report.api.ts b/src/api/report.api.ts index 111ef186..27911f2b 100644 --- a/src/api/report.api.ts +++ b/src/api/report.api.ts @@ -1,4 +1,4 @@ -import type { ApiPostContent } from '../models/report'; +import { ApiAllReports, type ApiPostContent } from '../models/report'; import { httpClient } from './http.api'; export const postReport = async (formData: ApiPostContent) => { @@ -13,3 +13,13 @@ export const postReport = async (formData: ApiPostContent) => { throw error; } }; + +export const getAllReports = async () => { + try { + const response = await httpClient.get(`/reports`); + return response.data.data; + } catch (e) { + console.error(e); + throw e; + } +}; From 31a4c935faaf0aabbb07358d4705c8d66f3e7aad Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 22:02:47 +0900 Subject: [PATCH 12/17] =?UTF-8?q?feat=20:=20=EB=A9=94=EC=9D=B8=20=EA=B7=B8?= =?UTF-8?q?=EB=9E=98=ED=94=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mainCard/graphCard/GraphCard.styled.ts | 4 +- .../admin/mainCard/graphCard/GraphCard.tsx | 91 ++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/components/admin/mainCard/graphCard/GraphCard.styled.ts b/src/components/admin/mainCard/graphCard/GraphCard.styled.ts index c3389834..bd91c4e2 100644 --- a/src/components/admin/mainCard/graphCard/GraphCard.styled.ts +++ b/src/components/admin/mainCard/graphCard/GraphCard.styled.ts @@ -1,3 +1,5 @@ import styled from 'styled-components'; -export const Container = styled.div``; +export const Container = styled.div` + height: 350px; +`; diff --git a/src/components/admin/mainCard/graphCard/GraphCard.tsx b/src/components/admin/mainCard/graphCard/GraphCard.tsx index 0ceef919..576a1cab 100644 --- a/src/components/admin/mainCard/graphCard/GraphCard.tsx +++ b/src/components/admin/mainCard/graphCard/GraphCard.tsx @@ -1,8 +1,97 @@ import React from 'react'; import * as S from './GraphCard.styled'; +import { Line } from 'react-chartjs-2'; +import 'chart.js/auto'; +import { ChartData, ChartOptions } from 'chart.js'; const GraphCard = () => { - return GraphCard Component; + return ( + + + + ); +}; + +const data: ChartData<'line'> = { + labels: [ + '월요일', + '화요일', + '수요일', + '목요일', + '금요일', + '토요일', + '일요일', + ], + datasets: [ + { + label: '방문자 수', + data: [8, 6, 4, 0, 7, 5, 3], + fill: true, + backgroundColor: 'rgba(54, 162, 235, 0.2)', + borderColor: 'rgba(54, 162, 235, 1)', + borderWidth: 2, + tension: 0.3, + pointRadius: 5, + pointBackgroundColor: '#ffffff', + pointBorderColor: 'rgba(54, 162, 235, 1)', + pointBorderWidth: 2, + pointHoverRadius: 6, + }, + ], +}; + +const options: ChartOptions<'line'> = { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + display: false, + }, + tooltip: { + enabled: true, + }, + title: { + display: false, + }, + }, + scales: { + x: { + grid: { + display: true, + borderDash: [5, 5], + color: 'rgba(0,0,0,0.1)', + }, + ticks: { + font: { + size: 14, + }, + color: '#333', + }, + }, + y: { + grid: { + display: true, + drawBorder: false, + + borderDash: [5, 5], + color: 'rgba(0,0,0,0.1)', + }, + ticks: { + stepSize: 2, + font: { + size: 14, + }, + color: '#333', + callback: (value) => `${value}`, + }, + beginAtZero: true, + suggestedMax: 8, + }, + }, + animation: { + duration: 800, + easing: 'easeOutQuart', + }, }; export default GraphCard; From 3a5e87c94c2950f39ff3acbfc739cf0175883995 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 23:15:53 +0900 Subject: [PATCH 13/17] =?UTF-8?q?feat=20:=20=ED=86=A0=ED=81=B0=EC=9D=B4=20?= =?UTF-8?q?=EC=9E=88=EC=9D=84=20=EB=95=8C=EB=A7=8C=20testAlarm=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/alarm.api.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/api/alarm.api.ts b/src/api/alarm.api.ts index 3ec22180..14e9d94d 100644 --- a/src/api/alarm.api.ts +++ b/src/api/alarm.api.ts @@ -1,4 +1,5 @@ import type { ApiAlarmList } from '../models/alarm'; +import useAuthStore from '../store/authStore'; import { httpClient } from './http.api'; export const getAlarmList = async () => { @@ -36,14 +37,19 @@ export const patchAlarm = async (id: number) => { }; export const testLiveAlarm = async () => { - try { - const response = await httpClient.get( - `/user/send-alarm?alarmFilter=0` - ); + const { accessToken } = useAuthStore.getState(); + if (accessToken) { + try { + const response = await httpClient.get( + `/user/send-alarm?alarmFilter=0` + ); - return response; - } catch (e) { - console.error(e); - throw e; + return response; + } catch (e) { + console.error(e); + throw e; + } + } else { + return; } }; From 7b09a7c55eaa868c7fdf71c49795eabc27389e82 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Sun, 1 Jun 2025 23:46:38 +0900 Subject: [PATCH 14/17] =?UTF-8?q?fix=20:=20=EB=B8=8C=EB=9E=9C=EC=B9=98?= =?UTF-8?q?=EA=B0=80=20=EA=BC=AC=EC=97=AC=20=EB=9D=BC=EC=9A=B0=ED=8C=85=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=EB=82=9C=20=EB=B6=80=EB=B6=84=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/AppRoutes.tsx | 22 ++-------------------- src/routes/MergeRoutes.tsx | 11 ++++++++--- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/routes/AppRoutes.tsx b/src/routes/AppRoutes.tsx index 35cc2f98..b65e2c7a 100644 --- a/src/routes/AppRoutes.tsx +++ b/src/routes/AppRoutes.tsx @@ -5,10 +5,7 @@ import useAuthStore from '../store/authStore'; import ProtectRoute from '../components/common/ProtectRoute'; import NotFoundPage from '../pages/notFoundPage/NotFoundPage'; import QueryErrorBoundary from '../components/common/error/QueryErrorBoundary'; -import { ToastProvider } from '../components/common/Toast/ToastProvider'; -import NotificationInitializer from '../components/user/notificationLive/NotificationInitializer'; -import { NotificationProvider } from '../components/user/notificationLive/NotificationProvider'; -import { ADMIN_ROUTE, ROUTES } from '../constants/routes'; +import { ROUTES } from '../constants/routes'; const Login = lazy(() => import('../pages/login/Login')); const LoginSuccess = lazy(() => import('../pages/login/LoginSuccess')); const LoginApi = lazy(() => import('../pages/login/LoginApi')); @@ -379,22 +376,7 @@ export const AppRoutes = () => { }; }); - const router = createBrowserRouter([ - { - element: ( - - - - - - - ), - - children: [...newRouteList, { path: '*', element: }], - }, - ]); - - return ; + return newRouteList; }; export default AppRoutes; diff --git a/src/routes/MergeRoutes.tsx b/src/routes/MergeRoutes.tsx index dd084465..421c2895 100644 --- a/src/routes/MergeRoutes.tsx +++ b/src/routes/MergeRoutes.tsx @@ -4,14 +4,19 @@ import AppRoutes from './AppRoutes'; import NotFoundPage from '../pages/notFoundPage/NotFoundPage'; import { ToastProvider } from '../components/common/Toast/ToastProvider'; import ProtectAdminRoute from './ProtectAdminRoute'; +import { NotificationProvider } from '../components/user/notificationLive/NotificationProvider'; +import NotificationInitializer from '../components/user/notificationLive/NotificationInitializer'; export default function MergeRoutes() { const router = createBrowserRouter([ { element: ( - - - + + + + + + ), children: [...AppRoutes()], }, From e2c113d9a431eb383a41affe3a4220b7aca4edcb Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Mon, 2 Jun 2025 15:44:24 +0900 Subject: [PATCH 15/17] =?UTF-8?q?review=20:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/alarm.api.ts | 2 +- .../allUserPreview/AllUserPreview.styled.ts | 4 ++-- .../allUserPreview/AllUserPreview.tsx | 13 ++++++++++-- .../inquiresPreview/InquiresPreview.styled.ts | 8 ++++---- .../inquiresPreview/InquiresPreview.tsx | 13 ++++++++++-- .../noticePreview/NoticePreview.tsx | 16 +++++++++++++-- .../reportsPreview/ReportsPreview.styled.ts | 8 ++++---- .../reportsPreview/ReportsPreview.tsx | 8 ++++---- src/constants/admin/mainItems.ts | 2 +- src/hooks/admin/useGetAllInquiries.ts | 8 ++++++-- src/hooks/admin/useGetAllUsers.ts | 12 +++++++---- src/hooks/queries/user/keys.ts | 4 ++++ src/hooks/user/useGetNotice.ts | 8 ++++++-- src/mock/mockReports.json | 20 +++++++++---------- src/models/auth.ts | 1 - src/models/report.ts | 2 +- 16 files changed, 87 insertions(+), 42 deletions(-) diff --git a/src/api/alarm.api.ts b/src/api/alarm.api.ts index 14e9d94d..55e3b1a5 100644 --- a/src/api/alarm.api.ts +++ b/src/api/alarm.api.ts @@ -50,6 +50,6 @@ export const testLiveAlarm = async () => { throw e; } } else { - return; + throw new Error('인증 토큰이 없습니다.'); } }; diff --git a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts index 5a2a4058..d316a7bf 100644 --- a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts +++ b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts @@ -39,6 +39,6 @@ export const Text = styled.p` `; export const Arrow = styled.img` - width: 10px; - height: 10px; + width: 11px; + height: 11px; `; diff --git a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx index 4967bafe..9131fd10 100644 --- a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx +++ b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx @@ -4,9 +4,18 @@ import { useGetAllUsers } from '../../../../hooks/admin/useGetAllUsers'; import Avatar from '../../../common/avatar/Avatar'; import { ADMIN_ROUTE } from '../../../../constants/routes'; import arrow_right from '../../../../assets/ArrowRight.svg'; +import LoadingSpinner from '../../../common/loadingSpinner/LoadingSpinner'; const AllUserPreview = () => { - const { allUserData, isLoading } = useGetAllUsers(); + const { allUserData, isLoading, isFetching } = useGetAllUsers(); + + if (isLoading || isFetching) { + return ; + } + + if (!allUserData || allUserData.length === 0) { + return 가입된 회원이 없습니다.; + } const previewList = allUserData ? allUserData.length > 6 @@ -19,7 +28,7 @@ const AllUserPreview = () => { {previewList?.map((user) => ( - + {user.user.nickname} {user.email} diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts index b5ef0b12..0fa5c181 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.styled.ts @@ -23,7 +23,7 @@ export const Inquiry = styled(Link)` export const Category = styled.p` font-size: 9px; - opacity: 50%; + opacity: 0.5; `; export const Title = styled.p` @@ -37,14 +37,14 @@ export const StateArea = styled.div` display: flex; `; -export const Date = styled.p` +export const InquiriesDate = styled.p` font-size: 9px; - opacity: 50%; + opacity: 0.5; `; export const Divider = styled.p` font-size: 9px; - opacity: 20%; + opacity: 0.2; margin-left: 3px; margin-right: 3px; `; diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx index ea62c3f5..e448b731 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx @@ -3,9 +3,18 @@ import { useGetAllInquiries } from '../../../../hooks/admin/useGetAllInquiries'; import Avatar from '../../../common/avatar/Avatar'; import { ADMIN_ROUTE } from '../../../../constants/routes'; import arrow_right from '../../../../assets/ArrowRight.svg'; +import LoadingSpinner from '../../../common/loadingSpinner/LoadingSpinner'; const InquiresPreview = () => { - const { allInquiriesData } = useGetAllInquiries(); + const { allInquiriesData, isLoading, isFetching } = useGetAllInquiries(); + + if (isLoading || isFetching) { + return ; + } + + if (!allInquiriesData || allInquiriesData.length === 0) { + return 등록된 공지사항이 없습니다.; + } const previewList = allInquiriesData ? allInquiriesData.length > 6 @@ -24,7 +33,7 @@ const InquiresPreview = () => { {inquiry.category} {inquiry.title} - {inquiry.createdAt} + {inquiry.createdAt} | {inquiry.state ? '답변 완료' : '답변 대기 중'} diff --git a/src/components/admin/previewComponent/noticePreview/NoticePreview.tsx b/src/components/admin/previewComponent/noticePreview/NoticePreview.tsx index a5efc202..8337563d 100644 --- a/src/components/admin/previewComponent/noticePreview/NoticePreview.tsx +++ b/src/components/admin/previewComponent/noticePreview/NoticePreview.tsx @@ -2,13 +2,25 @@ import React from 'react'; import * as S from './NoticePreview.styled'; import { useGetNotice } from '../../../../hooks/user/useGetNotice'; import line from '../../../../assets/line.svg'; +import LoadingSpinner from '../../../common/loadingSpinner/LoadingSpinner'; const NoticePreview = () => { - const { noticeData } = useGetNotice({ keyword: '', page: 1 }); + const { noticeData, isLoading, isFetching } = useGetNotice({ + keyword: '', + page: 1, + }); + + if (isLoading || isFetching) { + return ; + } + + if (!noticeData?.notices || noticeData.notices.length === 0) { + return 공지사힝이 없습니다.; + } return ( - {noticeData?.notices.map((notice) => ( + {noticeData.notices.map((notice) => ( {notice.title} diff --git a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts index 65820764..5514ca39 100644 --- a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts +++ b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.styled.ts @@ -23,7 +23,7 @@ export const ContentArea = styled.div` export const ImposedCount = styled.div` font-size: 9px; - opacity: 50%; + opacity: 0.5; `; export const Category = styled.p` @@ -37,14 +37,14 @@ export const StateArea = styled.div` display: flex; `; -export const Date = styled.p` +export const ReportDate = styled.p` font-size: 9px; - opacity: 50%; + opacity: 0.5; `; export const Divider = styled.p` font-size: 9px; - opacity: 20%; + opacity: 0.2; margin-left: 3px; margin-right: 3px; `; diff --git a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx index 5e6c0502..0f7f4d21 100644 --- a/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx +++ b/src/components/admin/previewComponent/reportsPreview/ReportsPreview.tsx @@ -16,17 +16,17 @@ const ReportsPreview = () => { return ( {previewList?.map((report) => ( - + {report.imposedCount} 번 {report.category} - {report.createdAt} + {report.createdAt} | - - {report.IsImposed ? '검토 완료' : '검토 미완료'} + + {report.isImposed ? '검토 완료' : '검토 미완료'} diff --git a/src/constants/admin/mainItems.ts b/src/constants/admin/mainItems.ts index ef55ee7e..74c17c8d 100644 --- a/src/constants/admin/mainItems.ts +++ b/src/constants/admin/mainItems.ts @@ -20,7 +20,7 @@ export const cardList: CardItem[] = [ Component: AllUserPreview, }, { - key: 'inquires', + key: 'inquiries', title: '문의 확인', link: `${ADMIN_ROUTE.inquiries}`, Component: InquiresPreview, diff --git a/src/hooks/admin/useGetAllInquiries.ts b/src/hooks/admin/useGetAllInquiries.ts index 3cff09b3..1eed7d49 100644 --- a/src/hooks/admin/useGetAllInquiries.ts +++ b/src/hooks/admin/useGetAllInquiries.ts @@ -3,10 +3,14 @@ import { getAllInquiries } from '../../api/activityLog.api'; import { ActivityLog } from '../queries/user/keys'; export const useGetAllInquiries = () => { - const { data: allInquiriesData, isLoading } = useQuery({ + const { + data: allInquiriesData, + isLoading, + isFetching, + } = useQuery({ queryKey: [ActivityLog.allInquiries], queryFn: () => getAllInquiries(), }); - return { allInquiriesData, isLoading }; + return { allInquiriesData, isLoading, isFetching }; }; diff --git a/src/hooks/admin/useGetAllUsers.ts b/src/hooks/admin/useGetAllUsers.ts index a9c9e7a8..769cfea7 100644 --- a/src/hooks/admin/useGetAllUsers.ts +++ b/src/hooks/admin/useGetAllUsers.ts @@ -1,12 +1,16 @@ import { useQuery } from '@tanstack/react-query'; -import { ReportData } from '../queries/user/keys'; +import { UserData } from '../queries/user/keys'; import { getAllUsers } from '../../api/auth.api'; export const useGetAllUsers = () => { - const { data: allUserData, isLoading } = useQuery({ - queryKey: [ReportData.allReports], + const { + data: allUserData, + isLoading, + isFetching, + } = useQuery({ + queryKey: [UserData.allUser], queryFn: () => getAllUsers(), }); - return { allUserData, isLoading }; + return { allUserData, isLoading, isFetching }; }; diff --git a/src/hooks/queries/user/keys.ts b/src/hooks/queries/user/keys.ts index 13cee296..22708439 100644 --- a/src/hooks/queries/user/keys.ts +++ b/src/hooks/queries/user/keys.ts @@ -59,3 +59,7 @@ export const CustomerService = { export const ReportData = { allReports: ['AllReports'], }; + +export const UserData = { + allUser: ['AllUser'], +}; diff --git a/src/hooks/user/useGetNotice.ts b/src/hooks/user/useGetNotice.ts index 16cd3df3..f367e266 100644 --- a/src/hooks/user/useGetNotice.ts +++ b/src/hooks/user/useGetNotice.ts @@ -6,12 +6,16 @@ import { CustomerService } from '../queries/user/keys'; export const useGetNotice = (searchProperty: NoticeSearch) => { const { keyword, page } = searchProperty; - const { data: noticeData, isLoading } = useQuery({ + const { + data: noticeData, + isLoading, + isFetching, + } = useQuery({ queryKey: [CustomerService.notice, keyword, page], queryFn: () => getNotice(searchProperty), staleTime: Infinity, gcTime: Infinity, }); - return { noticeData, isLoading }; + return { noticeData, isLoading, isFetching }; }; diff --git a/src/mock/mockReports.json b/src/mock/mockReports.json index bd73ad0b..5d9e4f00 100644 --- a/src/mock/mockReports.json +++ b/src/mock/mockReports.json @@ -11,7 +11,7 @@ "nickname": "alice", "img": "https://example.com/images/alice.png" }, - "IsImposed": false, + "isImposed": false, "createdAt": "2025-05-01" }, { @@ -23,7 +23,7 @@ "nickname": "charlie", "img": "https://example.com/images/charlie.jpeg" }, - "IsImposed": true, + "isImposed": true, "createdAt": "2025-05-03" }, { @@ -35,7 +35,7 @@ "nickname": "daisy", "img": "https://example.com/images/daisy.png" }, - "IsImposed": false, + "isImposed": false, "createdAt": "2025-05-05" }, { @@ -47,7 +47,7 @@ "nickname": "eve", "img": "https://example.com/images/eve.jpg" }, - "IsImposed": true, + "isImposed": true, "createdAt": "2025-05-07" }, { @@ -60,7 +60,7 @@ "img": "https://example.com/images/frank.png" }, - "IsImposed": false, + "isImposed": false, "createdAt": "2025-05-09" }, { @@ -72,7 +72,7 @@ "nickname": "henry", "img": "https://example.com/images/henry.jpg" }, - "IsImposed": true, + "isImposed": true, "createdAt": "2025-05-11" }, { @@ -85,7 +85,7 @@ "img": "https://example.com/images/iris.png" }, - "IsImposed": false, + "isImposed": false, "createdAt": "2025-05-13" }, { @@ -97,7 +97,7 @@ "nickname": "kate", "img": "https://example.com/images/kate.jpeg" }, - "IsImposed": true, + "isImposed": true, "createdAt": "2025-05-15" }, { @@ -109,7 +109,7 @@ "nickname": "leo", "img": "https://example.com/images/leo.png" }, - "IsImposed": true, + "isImposed": true, "createdAt": "2025-05-17" }, { @@ -121,7 +121,7 @@ "nickname": "nate", "img": "https://example.com/images/nate.png" }, - "IsImposed": false, + "isImposed": false, "createdAt": "2025-05-19" } ] diff --git a/src/models/auth.ts b/src/models/auth.ts index 67370ae4..ae4d1fb9 100644 --- a/src/models/auth.ts +++ b/src/models/auth.ts @@ -35,7 +35,6 @@ export interface ApiGetAllUsers extends ApiCommonType { export interface AllUser { id: number; email: string; - name: string; user: User; createdAt: string; } diff --git a/src/models/report.ts b/src/models/report.ts index da44cd9b..4ace69eb 100644 --- a/src/models/report.ts +++ b/src/models/report.ts @@ -16,6 +16,6 @@ export interface AllReports { imposedCount: number; category: string; user: User; - IsImposed: boolean; + isImposed: boolean; createdAt: string; } From d667d0b8bac8bb36638cfd220471b065b1d6d2ca Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:39:27 +0900 Subject: [PATCH 16/17] =?UTF-8?q?review=20:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../previewComponent/allUserPreview/AllUserPreview.styled.ts | 2 +- .../admin/previewComponent/inquiresPreview/InquiresPreview.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts index d316a7bf..a68e5081 100644 --- a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts +++ b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.styled.ts @@ -26,7 +26,7 @@ export const NickName = styled.p` export const Email = styled.p` font-size: 9px; - opacity: 50%; + opacity: 0.5; `; export const MoveToUsersArea = styled(Link)` diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx index e448b731..3b4968b4 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx @@ -13,7 +13,7 @@ const InquiresPreview = () => { } if (!allInquiriesData || allInquiriesData.length === 0) { - return 등록된 공지사항이 없습니다.; + return 등록된 문의가 없습니다.; } const previewList = allInquiriesData From 9b42294a354fd63aaa1dab240c6910f35f54a85d Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Mon, 2 Jun 2025 23:52:23 +0900 Subject: [PATCH 17/17] =?UTF-8?q?review=20:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/activityLog.api.ts | 7 ++----- src/api/report.api.ts | 2 +- src/hooks/admin/useGetAllInquiries.ts | 4 ++-- src/hooks/queries/user/keys.ts | 3 +++ src/models/activityLog.ts | 10 +--------- src/models/admin/mainPreview.ts | 11 +++++++++++ src/models/auth.ts | 3 +-- src/models/report.ts | 2 +- 8 files changed, 22 insertions(+), 20 deletions(-) create mode 100644 src/models/admin/mainPreview.ts diff --git a/src/api/activityLog.api.ts b/src/api/activityLog.api.ts index e28b2a88..e5a2c5fa 100644 --- a/src/api/activityLog.api.ts +++ b/src/api/activityLog.api.ts @@ -1,8 +1,5 @@ -import type { - ApiAllInquiries, - ApiMyComments, - ApiMyInquiries, -} from './../models/activityLog'; +import { ApiAllInquiries } from '../models/admin/mainPreview'; +import type { ApiMyComments, ApiMyInquiries } from './../models/activityLog'; import { httpClient } from './http.api'; export const getMyComments = async () => { diff --git a/src/api/report.api.ts b/src/api/report.api.ts index 27911f2b..0b0d24dd 100644 --- a/src/api/report.api.ts +++ b/src/api/report.api.ts @@ -1,4 +1,4 @@ -import { ApiAllReports, type ApiPostContent } from '../models/report'; +import { type ApiAllReports, type ApiPostContent } from '../models/report'; import { httpClient } from './http.api'; export const postReport = async (formData: ApiPostContent) => { diff --git a/src/hooks/admin/useGetAllInquiries.ts b/src/hooks/admin/useGetAllInquiries.ts index 1eed7d49..b4b7b797 100644 --- a/src/hooks/admin/useGetAllInquiries.ts +++ b/src/hooks/admin/useGetAllInquiries.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query'; import { getAllInquiries } from '../../api/activityLog.api'; -import { ActivityLog } from '../queries/user/keys'; +import { Inquiries } from '../queries/user/keys'; export const useGetAllInquiries = () => { const { @@ -8,7 +8,7 @@ export const useGetAllInquiries = () => { isLoading, isFetching, } = useQuery({ - queryKey: [ActivityLog.allInquiries], + queryKey: [Inquiries.allInquiries], queryFn: () => getAllInquiries(), }); diff --git a/src/hooks/queries/user/keys.ts b/src/hooks/queries/user/keys.ts index 22708439..ae2f244a 100644 --- a/src/hooks/queries/user/keys.ts +++ b/src/hooks/queries/user/keys.ts @@ -47,6 +47,9 @@ export const ProjectMemberListEval = { export const ActivityLog = { myComments: ['MyComments'], myInquiries: ['MyInquiries'], +}; + +export const Inquiries = { allInquiries: ['AllInquiries'], }; diff --git a/src/models/activityLog.ts b/src/models/activityLog.ts index 4c9cb521..d264daa1 100644 --- a/src/models/activityLog.ts +++ b/src/models/activityLog.ts @@ -1,4 +1,4 @@ -import type { ApiCommonType, User } from './apiCommon'; +import type { ApiCommonType } from './apiCommon'; export interface MyInquiries { id: number; @@ -12,14 +12,6 @@ export interface MyInquiries { export interface ApiMyInquiries extends ApiCommonType { data: MyInquiries[]; } -export interface AllInquiries extends MyInquiries { - user: User; - createdAt: string; -} - -export interface ApiAllInquiries extends ApiCommonType { - data: AllInquiries[]; -} export interface MyComments { id: number; diff --git a/src/models/admin/mainPreview.ts b/src/models/admin/mainPreview.ts new file mode 100644 index 00000000..892b1ee9 --- /dev/null +++ b/src/models/admin/mainPreview.ts @@ -0,0 +1,11 @@ +import type { MyInquiries } from '../activityLog'; +import type { ApiCommonType, User } from '../apiCommon'; + +export interface AllInquiries extends MyInquiries { + user: User; + createdAt: string; +} + +export interface ApiAllInquiries extends ApiCommonType { + data: AllInquiries[]; +} diff --git a/src/models/auth.ts b/src/models/auth.ts index ae4d1fb9..f663c1aa 100644 --- a/src/models/auth.ts +++ b/src/models/auth.ts @@ -1,5 +1,4 @@ -//model -import { ApiCommonType, User } from './apiCommon'; +import { type ApiCommonType, type User } from './apiCommon'; export interface VerifyEmail { email: string; diff --git a/src/models/report.ts b/src/models/report.ts index 4ace69eb..0c24868e 100644 --- a/src/models/report.ts +++ b/src/models/report.ts @@ -1,4 +1,4 @@ -import { ApiCommonType, User } from './apiCommon'; +import { type ApiCommonType, type User } from './apiCommon'; export interface ApiPostContent { reportTargetId: number;