-
Notifications
You must be signed in to change notification settings - Fork 2
design, feat, chore : 편지 작성 페이지 추가 퍼블리싱 + 기능구현 + API연결 + 관리자페이지 퍼블리싱 #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2341700
83500ef
b585b4a
eed708a
4e709cc
f3180fc
0a4f949
38757ae
a181914
45b0434
dce8d2e
b0d7161
45bdda0
6227d93
29a67a9
c3135aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { client } from './client'; | ||
|
|
||
| const getLetter = async ( | ||
| letterId: string, | ||
| setLetterState: React.Dispatch<React.SetStateAction<LetterDetail | null>>, | ||
| ) => { | ||
| try { | ||
| const res = await client.get(`/api/letters/${letterId}`); | ||
| setLetterState(res.data.data); | ||
| console.log(res); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| const deleteLetter = async (letterId: string) => { | ||
| try { | ||
| console.log(`/api/letters/${letterId}`); | ||
| const res = await client.delete(`/api/letters/${letterId}`); | ||
| console.log(res); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| export { getLetter, deleteLetter }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { client } from './client'; | ||
|
|
||
| const postLetter = async ( | ||
| data: LetterRequest, | ||
| setState?: React.Dispatch<React.SetStateAction<boolean>>, | ||
| ) => { | ||
| try { | ||
| const res = await client.post('/api/letters', data); | ||
| if (setState) setState(true); | ||
| console.log(res); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| const getPrevLetter = async ( | ||
| setPrevLetterState: React.Dispatch<React.SetStateAction<PrevLetter[]>>, | ||
| letterId: string, | ||
| ) => { | ||
| try { | ||
| const res = await client.get(`/api/letters/${letterId}/previous`); | ||
| setPrevLetterState(res.data.data); | ||
| console.log(res); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| export { postLetter, getPrevLetter }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { useNavigate } from 'react-router'; | ||
|
|
||
| import { ArrowLeftIcon } from '@/assets/icons'; | ||
|
|
||
| export default function BackButton() { | ||
| const navigate = useNavigate(); | ||
| return ( | ||
| <button onClick={() => navigate(-1)} aria-label="뒤로 가기"> | ||
| <ArrowLeftIcon className="text-primary-1 h-6 w-6" /> | ||
| </button> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { Outlet } from 'react-router'; | ||
|
|
||
| const MobileLayout = () => { | ||
| return ( | ||
| <div className="mobile-bg"> | ||
| <div className="mobile-layout"> | ||
| <Outlet /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
| export default MobileLayout; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| import { useEffect, useState } from 'react'; | ||
|
|
||
| import { client } from '@/apis/client'; | ||
| import { AlarmIcon } from '@/assets/icons'; | ||
|
|
||
| import DetailFrame from './components/DetailFrame'; | ||
| import ListItem from './components/ListItem'; | ||
| import WrapperFrame from './components/WrapperFrame'; | ||
|
|
||
| export default function ReportManage() { | ||
| const [detailModalOpen, setDetailModalOpen] = useState<boolean>(false); | ||
| // { | ||
| // id: '001', | ||
| // reporterEmail: '[email protected]', | ||
| // targetEmail: '[email protected]', | ||
| // reportedAt: new Date(2025, 1, 20), | ||
| // letterId:2001, | ||
| // sharePostId:null, | ||
| // eventId:null, | ||
| // reportType:'LETTER', | ||
| // reason:"ABUSE", | ||
| // reasonDetail:null, | ||
| // status: 'PENDING', | ||
| // }, | ||
| const DUMMY = [ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 어떤 더미 데이터인지 적어주시는 게 직관적일 것 같아요 ex) DUMMY_REPORTS |
||
| { | ||
| id: '001', | ||
| reporterEmail: '[email protected]', | ||
| targetEmail: '[email protected]', | ||
| reportedAt: new Date(2020, 12, 4), | ||
| reason: '욕설', | ||
| }, | ||
| { | ||
| id: '002', | ||
| reporterEmail: '[email protected]', | ||
| targetEmail: '[email protected]', | ||
| reportedAt: new Date(2020, 12, 4), | ||
| reason: '욕설', | ||
| }, | ||
| { | ||
| id: '003', | ||
| reporterEmail: '[email protected]', | ||
| targetEmail: '[email protected]', | ||
| reportedAt: new Date(2000, 6, 23), | ||
| reason: '욕설', | ||
| }, | ||
| { | ||
| id: '004', | ||
| reporterEmail: '[email protected]', | ||
| targetEmail: '[email protected]', | ||
| reportedAt: new Date(1080, 11, 5), | ||
| reason: '욕설', | ||
| }, | ||
| { | ||
| id: '005', | ||
| reporterEmail: '[email protected]', | ||
| targetEmail: '[email protected]', | ||
| reportedAt: new Date(2040, 1, 2), | ||
| reason: '욕설', | ||
| }, | ||
| { | ||
| id: '006', | ||
| reporterEmail: '[email protected]', | ||
| targetEmail: '[email protected]', | ||
| reportedAt: new Date(2025, 1, 23), | ||
| reason: '욕설', | ||
| }, | ||
| ]; | ||
| const modalContents = [ | ||
| { | ||
| title: '신고 목록 삭제', | ||
| onClick: () => { | ||
| console.log('삭제'); | ||
| }, | ||
| }, | ||
| { | ||
| title: '작성자 활동 정지', | ||
| onClick: () => { | ||
| console.log('정지'); | ||
| }, | ||
| }, | ||
| ]; | ||
| // const [allReports, setAllReports] = useState(); | ||
| useEffect(() => { | ||
| const getAllReports = async () => { | ||
| const res = await client.get('/api/reports'); | ||
| console.log(res); | ||
| }; | ||
| getAllReports(); | ||
| const getReportDetail = async () => { | ||
| const res = await client.get('/api/reports/2'); | ||
| console.log(res); | ||
| }; | ||
| getReportDetail(); | ||
| const postReport = async () => { | ||
| const res = await client.post('/api/reports', { | ||
| letterId: 2010, | ||
| reportType: 'POST', | ||
| reason: 'HARASSMENT', | ||
| reasonDetail: '테스트용', | ||
| }); | ||
| console.log(res); | ||
| }; | ||
| postReport(); | ||
| }, []); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| return ( | ||
| <WrapperFrame> | ||
| <span className="h3-sb flex items-center gap-4.5"> | ||
| <AlarmIcon className="h-9 w-9"></AlarmIcon> 신고 편지 목록 | ||
| </span> | ||
| <section className="mt-5 flex flex-col"> | ||
| <div className="bg-primary-3 flex w-full border-b px-6 py-4"> | ||
| <div className="flex w-[80%] items-center"> | ||
| <span className="ml-4 flex basis-1/10 overflow-ellipsis">ID</span> | ||
| <span className="ml-4 flex basis-2/10">제보자 이메일</span> | ||
| <span className="ml-4 flex basis-2/10">작성자 이메일</span> | ||
| <span className="ml-4 flex basis-2/10">제보 일자</span> | ||
| <span className="ml-4 flex basis-3/10">제보 사유</span> | ||
| </div> | ||
| </div> | ||
| {DUMMY.map((data, idx) => ( | ||
| <ListItem | ||
| data={data} | ||
| modalContents={modalContents} | ||
| key={idx} | ||
| setDetailModalOpen={setDetailModalOpen} | ||
| /> | ||
| ))} | ||
| </section> | ||
| {detailModalOpen && ( | ||
| <DetailFrame closeEvent={setDetailModalOpen}> | ||
| <> | ||
| <span className="h2-sb">제보 편지 상세 조회</span> | ||
| </> | ||
| </DetailFrame> | ||
| )} | ||
| </WrapperFrame> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| interface Report { | ||
| id: number; | ||
| reporterEmail: string; | ||
| targetEmail: string; | ||
| reportedAt: Date; | ||
| letterId: number | null; | ||
| comment: string | null; | ||
| sharePostId: number | null; | ||
| reportType: 'LETTER' | 'POST' | 'COMMENT'; | ||
| reason: 'ABUSE' | 'DEFAMATION' | 'HARASSMENT' | 'THREATS' | 'ETC'; | ||
| reasonDetail: string | null; | ||
| status: 'PENDING' | 'RESOLVED' | 'REJECTED'; | ||
| } | ||
|
|
||
| interface ReportDetail { | ||
| id: number; | ||
| memberId: number | null; | ||
| letterId: number | null; | ||
| sharePostId: number | null; | ||
| eventId: number | null; | ||
| reportType: 'LETTER' | 'POST' | 'COMMENT' | 'EVENT'; | ||
| reason: 'ABUSE' | 'DEFAMATION' | 'HARASSMENT' | 'THREATS' | 'ETC'; | ||
| reasonDetail: string | null; | ||
| status: 'PENDING' | 'RESOLVED' | 'REJECTED'; | ||
| reportedAt: Date; | ||
| createdAt: Date; | ||
| letterDetail: { | ||
| title: string; | ||
| content: string; | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
address는 prop으로 전달해야겠네요!