Skip to content

Commit a3d6a2f

Browse files
authored
fix(fe): modify modal UI that create question and reply (#57)
* feat: refactor reply and question modal components * fix: change button to div for modal background and add role attribute * feat: update button text in modals to reflect creation or editing state
1 parent fa6b01d commit a3d6a2f

File tree

12 files changed

+141
-171
lines changed

12 files changed

+141
-171
lines changed

apps/client/src/features/create-update-question/ui/CreateQuestionModal.tsx

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import { useState } from 'react';
2+
import Markdown from 'react-markdown';
3+
14
import { useQuestionMutation } from '@/features/create-update-question/model/useQuestionMutation';
2-
import QuestionContentEditor from '@/features/create-update-question/ui/QuestionContentEditor';
3-
import QuestionModalFooter from '@/features/create-update-question/ui/QuestionModalFooter';
4-
import QuestionModalHeader from '@/features/create-update-question/ui/QuestionModalHeader';
55

66
import { Question } from '@/entities/session';
77

8+
import { Button } from '@/shared/ui/button';
89
import { useModalContext } from '@/shared/ui/modal';
910

1011
interface CreateQuestionModalProps {
@@ -15,17 +16,46 @@ function CreateQuestionModal({ question }: Readonly<CreateQuestionModalProps>) {
1516
const { closeModal } = useModalContext();
1617
const { body, setBody, handleSubmit, submitDisabled } = useQuestionMutation(question);
1718

19+
const [openPreview, setOpenPreview] = useState(false);
20+
1821
return (
19-
<div className='flex h-[50dvh] w-[50dvw] flex-col gap-2 rounded-lg bg-gray-50 p-8'>
20-
<QuestionModalHeader />
21-
<hr className='my-1 border-gray-200' />
22-
<QuestionContentEditor body={body} setBody={setBody} />
23-
<QuestionModalFooter
24-
onClose={closeModal}
25-
onSubmit={handleSubmit}
26-
submitDisabled={submitDisabled}
27-
submitText={question ? '수정하기' : '생성하기'}
28-
/>
22+
<div className='flex h-[20rem] w-[40rem] flex-col gap-2 rounded-lg bg-gray-50 p-4'>
23+
{openPreview ? (
24+
<div className='flex-1 overflow-y-auto rounded border bg-white p-4'>
25+
<Markdown className='prose prose-stone'>{body}</Markdown>
26+
</div>
27+
) : (
28+
<textarea
29+
className='flex-1 resize-none rounded border p-4 focus:outline-none'
30+
value={body}
31+
onChange={(e) => setBody(e.target.value)}
32+
placeholder='질문을 남겨주세요.'
33+
/>
34+
)}
35+
<footer className='flex h-[3rem] flex-row items-end justify-between'>
36+
<div className='flex flex-row gap-2'>
37+
<Button className='bg-indigo-600'>
38+
<div className='text-sm font-bold text-white'>질문 개선하기</div>
39+
</Button>
40+
<Button className='bg-indigo-600'>
41+
<div className='text-sm font-bold text-white'>질문 축약하기</div>
42+
</Button>
43+
<Button className='bg-gray-500' onClick={() => setOpenPreview(!openPreview)}>
44+
<div className='text-sm font-bold text-white'>{openPreview ? '작성하기' : '미리보기'}</div>
45+
</Button>
46+
</div>
47+
<div className='flex flex-row gap-2'>
48+
<Button className='bg-gray-500' onClick={closeModal}>
49+
<div className='text-sm font-bold text-white'>취소하기</div>
50+
</Button>
51+
<Button
52+
className={`${!submitDisabled ? 'bg-indigo-600' : 'cursor-not-allowed bg-indigo-300'}`}
53+
onClick={handleSubmit}
54+
>
55+
<div className='text-sm font-bold text-white'>{question ? '수정하기' : '생성하기'}</div>
56+
</Button>
57+
</div>
58+
</footer>
2959
</div>
3060
);
3161
}

apps/client/src/features/create-update-question/ui/QuestionContentEditor.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

apps/client/src/features/create-update-question/ui/QuestionModalFooter.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

apps/client/src/features/create-update-question/ui/QuestionModalHeader.tsx

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type ContentType = 'question' | 'reply' | 'preview';

apps/client/src/features/create-update-reply/ui/CreateReplyModal.tsx

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import { useState } from 'react';
2+
3+
import { ContentType } from '@/features/create-update-reply/model/reply-modal.type';
14
import { useReplyMutation } from '@/features/create-update-reply/model/useReplyMutation';
2-
import QuestionPreview from '@/features/create-update-reply/ui/QuestionPreview';
3-
import ReplyContentEditor from '@/features/create-update-reply/ui/ReplyContentEditor';
4-
import ReplyModalFooter from '@/features/create-update-reply/ui/ReplyModalFooter';
5-
import ReplyModalHeader from '@/features/create-update-reply/ui/ReplyModalHeader';
5+
import ReplyContentView from '@/features/create-update-reply/ui/ReplyContentView';
66

77
import { Question, Reply } from '@/entities/session';
88

9+
import { Button } from '@/shared/ui/button';
910
import { useModalContext } from '@/shared/ui/modal';
1011

1112
interface CreateReplyModalProps {
@@ -17,19 +18,53 @@ function CreateReplyModal({ question, reply }: Readonly<CreateReplyModalProps>)
1718
const { closeModal } = useModalContext();
1819
const { body, setBody, handleSubmit, submitDisabled } = useReplyMutation(question, reply);
1920

21+
const [contentType, setContentType] = useState<ContentType>('reply');
22+
2023
return (
21-
<div className='flex h-[50dvh] w-[50dvw] flex-col gap-2 rounded-lg bg-gray-50 p-8'>
22-
<ReplyModalHeader />
23-
<hr className='my-1 border-gray-200' />
24-
<QuestionPreview question={question} />
25-
<hr className='my-1 border-gray-200' />
26-
<ReplyContentEditor body={body} setBody={setBody} />
27-
<ReplyModalFooter
28-
onClose={closeModal}
29-
onSubmit={handleSubmit}
30-
submitDisabled={submitDisabled}
31-
submitText={reply ? '수정하기' : '생성하기'}
24+
<div className='flex h-[20rem] w-[40rem] flex-col gap-2 rounded-lg bg-gray-50 p-4'>
25+
<ReplyContentView
26+
contentType={contentType}
27+
questionBody={question?.body ?? '질문을 찾을 수 없습니다.'}
28+
replyBody={body}
29+
onChange={setBody}
3230
/>
31+
<footer className='flex h-[3rem] flex-row items-end justify-between'>
32+
<div className='flex flex-row gap-2'>
33+
<Button className='bg-indigo-600'>
34+
<div className='text-sm font-bold text-white'>답변 개선하기</div>
35+
</Button>
36+
<Button className='bg-indigo-600'>
37+
<div className='text-sm font-bold text-white'>답변 축약하기</div>
38+
</Button>
39+
{(contentType === 'reply' || contentType === 'question') && (
40+
<Button
41+
className='bg-gray-500'
42+
onClick={() => setContentType((prev) => (prev !== 'question' ? 'question' : 'reply'))}
43+
>
44+
<div className='text-sm font-bold text-white'>{contentType === 'reply' ? '질문보기' : '답변하기'}</div>
45+
</Button>
46+
)}
47+
{(contentType === 'reply' || contentType === 'preview') && (
48+
<Button
49+
className='bg-gray-500'
50+
onClick={() => setContentType((prev) => (prev !== 'preview' ? 'preview' : 'reply'))}
51+
>
52+
<div className='text-sm font-bold text-white'>{contentType === 'reply' ? '미리보기' : '답변하기'}</div>
53+
</Button>
54+
)}
55+
</div>
56+
<div className='flex flex-row gap-2'>
57+
<Button className='bg-gray-500' onClick={closeModal}>
58+
<div className='text-sm font-bold text-white'>취소하기</div>
59+
</Button>
60+
<Button
61+
className={`${!submitDisabled ? 'bg-indigo-600' : 'cursor-not-allowed bg-indigo-300'}`}
62+
onClick={handleSubmit}
63+
>
64+
<div className='text-sm font-bold text-white'>{reply ? '수정하기' : '생성하기'}</div>
65+
</Button>
66+
</div>
67+
</footer>
3368
</div>
3469
);
3570
}

apps/client/src/features/create-update-reply/ui/QuestionPreview.tsx

Lines changed: 0 additions & 19 deletions
This file was deleted.

apps/client/src/features/create-update-reply/ui/ReplyContentEditor.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Markdown from 'react-markdown';
2+
3+
import { ContentType } from '@/features/create-update-reply/model/reply-modal.type';
4+
5+
import { Question, Reply } from '@/entities/session';
6+
7+
interface ReplyContentViewProps {
8+
contentType: ContentType;
9+
questionBody: Question['body'];
10+
replyBody: Reply['body'];
11+
onChange: (body: string) => void;
12+
}
13+
14+
export default function ReplyContentView({
15+
contentType,
16+
questionBody,
17+
replyBody,
18+
onChange,
19+
}: Readonly<ReplyContentViewProps>) {
20+
if (contentType === 'preview') {
21+
return (
22+
<div className='flex-1 overflow-y-auto rounded border bg-white p-4'>
23+
<Markdown className='prose prose-stone'>{replyBody}</Markdown>
24+
</div>
25+
);
26+
}
27+
28+
if (contentType === 'question') {
29+
return (
30+
<div className='flex-1 overflow-y-auto rounded border bg-white p-4'>
31+
<Markdown className='prose prose-stone'>{questionBody}</Markdown>
32+
</div>
33+
);
34+
}
35+
36+
return (
37+
<textarea
38+
className='flex-1 resize-none rounded border p-4 focus:outline-none'
39+
value={replyBody}
40+
onChange={(e) => onChange(e.target.value)}
41+
placeholder='답변을 남겨주세요.'
42+
/>
43+
);
44+
}

apps/client/src/features/create-update-reply/ui/ReplyModalFooter.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)