Skip to content

Commit bdc90ee

Browse files
committed
design: 신고 모달 컴포넌트 퍼블리싱
1 parent 306ff32 commit bdc90ee

File tree

5 files changed

+100
-6
lines changed

5 files changed

+100
-6
lines changed

src/components/ConfirmModal.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ interface ConfirmModalProps {
77
description: string;
88
cancelText: string;
99
confirmText: string;
10+
confirmDisabled: boolean;
1011
children?: React.ReactNode;
1112
onCancel: () => void;
1213
onConfirm: () => void;
@@ -17,6 +18,7 @@ const ConfirmModal = ({
1718
description,
1819
cancelText,
1920
confirmText,
21+
confirmDisabled,
2022
children,
2123
onCancel,
2224
onConfirm,
@@ -46,6 +48,7 @@ const ConfirmModal = ({
4648
<button
4749
type="button"
4850
className="primary-btn body-m h-10 flex-1 basis-1/2"
51+
disabled={confirmDisabled}
4952
onClick={onConfirm}
5053
>
5154
{confirmText}

src/components/ReportModal.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { useState } from 'react';
2+
import { twMerge } from 'tailwind-merge';
3+
4+
import ConfirmModal from './ConfirmModal';
5+
6+
interface ReportModalProps {
7+
onClose: () => void;
8+
}
9+
10+
const REPORT_REASON = ['욕설', '비방', '폭언', '성희롱', '기타'];
11+
12+
const ReportModal = ({ onClose }: ReportModalProps) => {
13+
const [selected, setSelected] = useState('');
14+
const [additionalReason, setAdditionalReason] = useState('');
15+
16+
const handleReasonClick = (reason: string) => {
17+
if (selected === reason) setSelected('');
18+
else setSelected(reason);
19+
};
20+
21+
const handleSubmit = () => {
22+
onClose();
23+
};
24+
25+
return (
26+
<ConfirmModal
27+
title="신고 사유를 선택해주세요"
28+
description="신고한 게시물은 관리자 검토 후 처리됩니다."
29+
cancelText="취소하기"
30+
confirmText="제출하기"
31+
confirmDisabled={selected === ''}
32+
onCancel={onClose}
33+
onConfirm={handleSubmit}
34+
>
35+
<section className="my-6 flex flex-wrap gap-x-2.5 gap-y-2">
36+
{REPORT_REASON.map((reason) => (
37+
<button
38+
type="button"
39+
className={twMerge(
40+
'body-m rounded-full bg-white px-5 py-1.5 text-black',
41+
selected === reason && 'bg-primary-2',
42+
)}
43+
onClick={() => handleReasonClick(reason)}
44+
>
45+
{reason}
46+
</button>
47+
))}
48+
</section>
49+
<textarea
50+
rows={3}
51+
placeholder="이곳을 눌러 추가 사유를 작성해주세요"
52+
className="body-m placeholder:text-gray-30 text-gray-80 w-full resize-none rounded-sm bg-white px-3 py-1.5"
53+
value={additionalReason}
54+
onChange={(e) => setAdditionalReason(e.target.value)}
55+
/>
56+
</ConfirmModal>
57+
);
58+
};
59+
60+
export default ReportModal;

src/pages/RollingPaper/components/MessageDetailModal.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,30 @@ interface MessageDetailModalProps {
88
};
99
isWriter: boolean;
1010
onClose: () => void;
11+
onReport: () => void;
12+
onDelete: () => void;
1113
}
1214

13-
const MessageDetailModal = ({ message, isWriter, onClose }: MessageDetailModalProps) => {
15+
const MessageDetailModal = ({
16+
message,
17+
isWriter,
18+
onClose,
19+
onReport,
20+
onDelete,
21+
}: MessageDetailModalProps) => {
22+
const handleButtonClick = () => {
23+
if (isWriter) {
24+
// TODO: 삭제 로직
25+
onDelete();
26+
} else {
27+
onReport();
28+
}
29+
};
30+
1431
return (
1532
<ModalOverlay closeOnOutsideClick onClose={onClose}>
1633
<>
17-
<button type="button" className="body-b ml-auto text-white">
34+
<button type="button" className="body-b ml-auto text-white" onClick={handleButtonClick}>
1835
{isWriter ? '삭제하기' : '신고하기'}
1936
</button>
2037
<article

src/pages/RollingPaper/index.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import { useState } from 'react';
44
import EnvelopeImg from '@/assets/images/envelope.png';
55
import BgItem from '@/assets/images/field-4.png';
66
import PageTitle from '@/components/PageTitle';
7+
import ReportModal from '@/components/ReportModal';
78
import Header from '@/layouts/Header';
89

910
import Message from './components/Message';
1011
import MessageDetailModal from './components/MessageDetailModal';
1112

12-
const DUMMY_USER_ZIP_CODE = '12E12';
13+
const DUMMY_USER_ZIP_CODE = '22E12';
1314
const DUMMY_TITLE = '침수 피해를 복구중인 포스코 임직원 분들에게 응원의 메시지를 보내주세요!';
1415
const DUMMY_MESSAGE_COUNT = 20;
1516
const DUMMY_MESSAGE = {
@@ -21,6 +22,16 @@ const DUMMY_MESSAGES = Array.from({ length: 10 }, () => ({ ...DUMMY_MESSAGE }));
2122

2223
const RollingPaperPage = () => {
2324
const [activeMessageIndex, setActiveMessageIndex] = useState<number | null>(null);
25+
const [activeReportModal, setActiveReportModal] = useState(false);
26+
27+
const handleReport = () => {
28+
setActiveMessageIndex(null);
29+
setActiveReportModal(true);
30+
};
31+
32+
const handleDelete = () => {
33+
setActiveMessageIndex(null);
34+
};
2435

2536
return (
2637
<>
@@ -29,12 +40,15 @@ const RollingPaperPage = () => {
2940
message={DUMMY_MESSAGES[activeMessageIndex]}
3041
isWriter={DUMMY_MESSAGES[activeMessageIndex].sender === DUMMY_USER_ZIP_CODE}
3142
onClose={() => setActiveMessageIndex(null)}
43+
onReport={handleReport}
44+
onDelete={handleDelete}
3245
/>
3346
)}
47+
{activeReportModal && <ReportModal onClose={() => setActiveReportModal(false)} />}
3448
<Header />
3549
<main className="flex grow flex-col items-center px-5 pt-4 pb-12">
3650
<PageTitle className="mb-18 max-w-73 text-center">{DUMMY_TITLE}</PageTitle>
37-
<p className="body-sb text-gray-60 w-full">등록된 편지 {DUMMY_MESSAGE_COUNT}</p>
51+
<p className="body-sb text-gray-60 mb-2 w-full">등록된 편지 {DUMMY_MESSAGE_COUNT}</p>
3852
<section className="w-full">
3953
<MasonryInfiniteGrid column={2} align="stretch" gap={16}>
4054
{DUMMY_MESSAGES.map((message, index) => (
@@ -45,7 +59,7 @@ const RollingPaperPage = () => {
4559
<button type="button" className="fixed bottom-7.5 left-5 overflow-hidden rounded-sm">
4660
<img src={EnvelopeImg} alt="편지지 이미지" className="h-12 w-auto opacity-70" />
4761
<p className="caption-sb absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 whitespace-nowrap text-white">
48-
메시지 쓰기
62+
편지 쓰기
4963
</p>
5064
</button>
5165
</main>

src/styles/components.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
@layer components {
44
.primary-btn {
5-
@apply bg-primary-3 rounded-lg text-black;
5+
@apply bg-primary-3 disabled:bg-gray-10 rounded-lg text-black disabled:text-white;
66
}
77

88
.secondary-btn {

0 commit comments

Comments
 (0)