Skip to content
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

fix(fe): modify modal UI that create question and reply #57

Merged
merged 3 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useState } from 'react';
import Markdown from 'react-markdown';

import { useQuestionMutation } from '@/features/create-update-question/model/useQuestionMutation';
import QuestionContentEditor from '@/features/create-update-question/ui/QuestionContentEditor';
import QuestionModalFooter from '@/features/create-update-question/ui/QuestionModalFooter';
import QuestionModalHeader from '@/features/create-update-question/ui/QuestionModalHeader';

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

import { Button } from '@/shared/ui/button';
import { useModalContext } from '@/shared/ui/modal';

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

const [openPreview, setOpenPreview] = useState(false);

return (
<div className='flex h-[50dvh] w-[50dvw] flex-col gap-2 rounded-lg bg-gray-50 p-8'>
<QuestionModalHeader />
<hr className='my-1 border-gray-200' />
<QuestionContentEditor body={body} setBody={setBody} />
<QuestionModalFooter
onClose={closeModal}
onSubmit={handleSubmit}
submitDisabled={submitDisabled}
submitText={question ? '수정하기' : '생성하기'}
/>
<div className='flex h-[20rem] w-[40rem] flex-col gap-2 rounded-lg bg-gray-50 p-4'>
{openPreview ? (
<div className='flex-1 overflow-y-auto rounded border bg-white p-4'>
<Markdown className='prose prose-stone'>{body}</Markdown>
</div>
) : (
<textarea
className='flex-1 resize-none rounded border p-4 focus:outline-none'
value={body}
onChange={(e) => setBody(e.target.value)}
placeholder='질문을 남겨주세요.'
/>
)}
<footer className='flex h-[3rem] flex-row items-end justify-between'>
<div className='flex flex-row gap-2'>
<Button className='bg-indigo-600'>
<div className='text-sm font-bold text-white'>질문 개선하기</div>
</Button>
<Button className='bg-indigo-600'>
<div className='text-sm font-bold text-white'>질문 축약하기</div>
</Button>
<Button className='bg-gray-500' onClick={() => setOpenPreview(!openPreview)}>
<div className='text-sm font-bold text-white'>{openPreview ? '작성하기' : '미리보기'}</div>
</Button>
</div>
<div className='flex flex-row gap-2'>
<Button className='bg-gray-500' onClick={closeModal}>
<div className='text-sm font-bold text-white'>취소하기</div>
</Button>
<Button
className={`${!submitDisabled ? 'bg-indigo-600' : 'cursor-not-allowed bg-indigo-300'}`}
onClick={handleSubmit}
>
<div className='text-sm font-bold text-white'>{question ? '수정하기' : '생성하기'}</div>
</Button>
</div>
</footer>
</div>
);
}
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ContentType = 'question' | 'reply' | 'preview';
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useState } from 'react';

import { ContentType } from '@/features/create-update-reply/model/reply-modal.type';
import { useReplyMutation } from '@/features/create-update-reply/model/useReplyMutation';
import QuestionPreview from '@/features/create-update-reply/ui/QuestionPreview';
import ReplyContentEditor from '@/features/create-update-reply/ui/ReplyContentEditor';
import ReplyModalFooter from '@/features/create-update-reply/ui/ReplyModalFooter';
import ReplyModalHeader from '@/features/create-update-reply/ui/ReplyModalHeader';
import ReplyContentView from '@/features/create-update-reply/ui/ReplyContentView';

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

import { Button } from '@/shared/ui/button';
import { useModalContext } from '@/shared/ui/modal';

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

const [contentType, setContentType] = useState<ContentType>('reply');

return (
<div className='flex h-[50dvh] w-[50dvw] flex-col gap-2 rounded-lg bg-gray-50 p-8'>
<ReplyModalHeader />
<hr className='my-1 border-gray-200' />
<QuestionPreview question={question} />
<hr className='my-1 border-gray-200' />
<ReplyContentEditor body={body} setBody={setBody} />
<ReplyModalFooter
onClose={closeModal}
onSubmit={handleSubmit}
submitDisabled={submitDisabled}
submitText={reply ? '수정하기' : '생성하기'}
<div className='flex h-[20rem] w-[40rem] flex-col gap-2 rounded-lg bg-gray-50 p-4'>
<ReplyContentView
contentType={contentType}
questionBody={question?.body ?? '질문을 찾을 수 없습니다.'}
replyBody={body}
onChange={setBody}
/>
<footer className='flex h-[3rem] flex-row items-end justify-between'>
<div className='flex flex-row gap-2'>
<Button className='bg-indigo-600'>
<div className='text-sm font-bold text-white'>답변 개선하기</div>
</Button>
<Button className='bg-indigo-600'>
<div className='text-sm font-bold text-white'>답변 축약하기</div>
</Button>
{(contentType === 'reply' || contentType === 'question') && (
<Button
className='bg-gray-500'
onClick={() => setContentType((prev) => (prev !== 'question' ? 'question' : 'reply'))}
>
<div className='text-sm font-bold text-white'>{contentType === 'reply' ? '질문보기' : '답변하기'}</div>
</Button>
)}
{(contentType === 'reply' || contentType === 'preview') && (
<Button
className='bg-gray-500'
onClick={() => setContentType((prev) => (prev !== 'preview' ? 'preview' : 'reply'))}
>
<div className='text-sm font-bold text-white'>{contentType === 'reply' ? '미리보기' : '답변하기'}</div>
</Button>
)}
</div>
<div className='flex flex-row gap-2'>
<Button className='bg-gray-500' onClick={closeModal}>
<div className='text-sm font-bold text-white'>취소하기</div>
</Button>
<Button
className={`${!submitDisabled ? 'bg-indigo-600' : 'cursor-not-allowed bg-indigo-300'}`}
onClick={handleSubmit}
>
<div className='text-sm font-bold text-white'>{reply ? '수정하기' : '생성하기'}</div>
</Button>
</div>
</footer>
</div>
);
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Markdown from 'react-markdown';

import { ContentType } from '@/features/create-update-reply/model/reply-modal.type';

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

interface ReplyContentViewProps {
contentType: ContentType;
questionBody: Question['body'];
replyBody: Reply['body'];
onChange: (body: string) => void;
}

export default function ReplyContentView({
contentType,
questionBody,
replyBody,
onChange,
}: Readonly<ReplyContentViewProps>) {
if (contentType === 'preview') {
return (
<div className='flex-1 overflow-y-auto rounded border bg-white p-4'>
<Markdown className='prose prose-stone'>{replyBody}</Markdown>
</div>
);
}

if (contentType === 'question') {
return (
<div className='flex-1 overflow-y-auto rounded border bg-white p-4'>
<Markdown className='prose prose-stone'>{questionBody}</Markdown>
</div>
);
}

return (
<textarea
className='flex-1 resize-none rounded border p-4 focus:outline-none'
value={replyBody}
onChange={(e) => onChange(e.target.value)}
placeholder='답변을 남겨주세요.'
/>
);
}

This file was deleted.

This file was deleted.

5 changes: 3 additions & 2 deletions apps/client/src/shared/ui/modal/useModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ function Background({ children }: Readonly<PropsWithChildren>) {
}, [closeModal]);

return (
<button
<div
role='dialog'
onClick={(e) => {
e.stopPropagation();
if (e.target === e.currentTarget) closeModal();
Expand All @@ -44,7 +45,7 @@ function Background({ children }: Readonly<PropsWithChildren>) {
className='fixed left-0 top-0 z-10 flex h-dvh w-dvw cursor-auto items-center justify-center bg-[#808080]/20 backdrop-blur-sm'
>
{children}
</button>
</div>
);
}

Expand Down
Loading