Skip to content

Commit 54be6d0

Browse files
authored
fix(fe): enhance UX by adding new features during question/reply creation (#66)
* feat: add preventCloseFromBackground option to modal context * feat: enable modal to prevent closing from background in question and reply components * feat: enhance body length display and update button labels in question/reply modals
1 parent 279a55b commit 54be6d0

File tree

9 files changed

+38
-12
lines changed

9 files changed

+38
-12
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function CreateQuestionModal({ question }: Readonly<CreateQuestionModalProps>) {
2828

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

31-
const bodyLength = getContentBodyLength(body);
31+
const bodyLength = getContentBodyLength(supportResult ?? body);
3232

3333
const buttonEnabled = !submitDisabled && requestEnable && isValidBodyLength(body);
3434

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export default function CreateQuestionModalFooter({
6565
<div className='text-sm font-bold text-white'>취소하기</div>
6666
</Button>
6767
<Button className='bg-gray-500' onClick={handleRetry}>
68-
<div className='text-sm font-bold text-white'>다시 작성하기</div>
68+
<div className='text-sm font-bold text-white'>다시 요청하기</div>
6969
</Button>
7070
<Button className='bg-indigo-600' onClick={accept}>
7171
<div className='text-sm font-bold text-white'>사용하기</div>

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,31 @@ interface CreateQuestionModalSideProps {
66
setOpenPreview: (openPreview: boolean) => void;
77
}
88

9+
const textSize = (bodyLength: number) => {
10+
if (bodyLength >= 10000) {
11+
return 'text-[0.5rem] leading-3';
12+
} else if (bodyLength >= 1000) {
13+
return 'text-xs';
14+
}
15+
return 'text-sm';
16+
};
17+
918
export default function CreateQuestionModalSide({
1019
bodyLength,
1120
openPreview,
1221
setOpenPreview,
1322
}: Readonly<CreateQuestionModalSideProps>) {
1423
return (
15-
<div className='absolute right-8 flex h-[calc(100%-5rem)] flex-col items-center justify-between py-4'>
24+
<div className='absolute right-8 flex h-[calc(100%-5rem)] w-12 flex-col items-center justify-between py-4'>
1625
<button
1726
className='flex h-10 w-10 items-center justify-center rounded-full border p-2 shadow-md'
1827
onClick={() => setOpenPreview(!openPreview)}
1928
>
2029
{openPreview ? <VscEdit size={32} /> : <VscMarkdown size={32} />}
2130
</button>
22-
<span className={`text-xs ${bodyLength > 500 ? 'text-red-600' : 'text-slate-400'}`}>{bodyLength}/500</span>
31+
<span className={`${bodyLength > 500 ? 'text-red-600' : 'text-slate-400'} ${textSize(bodyLength)}`}>
32+
{bodyLength}/500
33+
</span>
2334
</div>
2435
);
2536
}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,22 @@ interface CreateReplyModalSideProps {
1010
setContentType: (contentType: ContentType) => void;
1111
}
1212

13+
const textSize = (bodyLength: number) => {
14+
if (bodyLength >= 10000) {
15+
return 'text-[0.5rem] leading-3';
16+
} else if (bodyLength >= 1000) {
17+
return 'text-xs';
18+
}
19+
return 'text-sm';
20+
};
21+
1322
export default function CreateReplyModalSide({
1423
bodyLength,
1524
contentType,
1625
setContentType,
1726
}: Readonly<CreateReplyModalSideProps>) {
1827
return (
19-
<div className='absolute right-8 flex h-[calc(100%-5rem)] flex-col items-center justify-between py-4'>
28+
<div className='absolute right-8 flex h-[calc(100%-5rem)] w-12 flex-col items-center justify-between py-4'>
2029
<div className='flex flex-col items-center gap-2'>
2130
{(contentType === 'reply' || contentType === 'question') && (
2231
<button
@@ -35,7 +44,9 @@ export default function CreateReplyModalSide({
3544
</button>
3645
)}
3746
</div>
38-
<span className={`text-xs ${bodyLength > 500 ? 'text-red-600' : 'text-slate-400'}`}>{bodyLength}/500</span>
47+
<span className={`${bodyLength > 500 ? 'text-red-600' : 'text-slate-400'} ${textSize(bodyLength)}`}>
48+
{bodyLength}/500
49+
</span>
3950
</div>
4051
);
4152
}

apps/client/src/shared/ui/modal/useModal.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ import {
1111
import { createPortal } from 'react-dom';
1212

1313
export interface ModalContextProps {
14+
preventCloseFromBackground: boolean;
1415
openModal: () => void;
1516
closeModal: () => void;
1617
}
1718

1819
export const ModalContext = createContext<ModalContextProps | undefined>(undefined);
1920

2021
function Background({ children }: Readonly<PropsWithChildren>) {
21-
const { closeModal } = useModalContext();
22+
const { closeModal, preventCloseFromBackground } = useModalContext();
2223

2324
useEffect(() => {
2425
const handleEsc = (e: KeyboardEvent) => {
@@ -37,6 +38,7 @@ function Background({ children }: Readonly<PropsWithChildren>) {
3738
role='dialog'
3839
onClick={(e) => {
3940
e.stopPropagation();
41+
if (window.getSelection()?.toString() || preventCloseFromBackground) return;
4042
if (e.target === e.currentTarget) closeModal();
4143
}}
4244
onKeyDown={(e) => e.stopPropagation()}
@@ -49,7 +51,7 @@ function Background({ children }: Readonly<PropsWithChildren>) {
4951
);
5052
}
5153

52-
export const useModal = (children: ReactNode) => {
54+
export const useModal = (children: ReactNode, preventCloseFromBackground: boolean = false) => {
5355
const [isOpen, setIsOpen] = useState(false);
5456
const [isClosing, setIsClosing] = useState(false);
5557

@@ -66,14 +68,14 @@ export const useModal = (children: ReactNode) => {
6668
const Modal = useMemo(() => {
6769
if (!isOpen) return null;
6870
return createPortal(
69-
<ModalContext.Provider value={{ openModal, closeModal }}>
71+
<ModalContext.Provider value={{ openModal, closeModal, preventCloseFromBackground }}>
7072
<Background>
7173
<div className={`modal-content ${isClosing ? 'animate-modalClose' : 'animate-modalOpen'}`}>{children}</div>
7274
</Background>
7375
</ModalContext.Provider>,
7476
document.body,
7577
);
76-
}, [isOpen, openModal, closeModal, isClosing, children]);
78+
}, [isOpen, openModal, closeModal, preventCloseFromBackground, isClosing, children]);
7779

7880
return useMemo(
7981
() => ({

apps/client/src/widgets/question-list/ui/QuestionItem.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function QuestionItem({ question, onQuestionSelect }: Readonly<QuestionItemProps
2020

2121
const { Modal: CreateQuestion, openModal: openCreateQuestionModal } = useModal(
2222
<CreateQuestionModal question={question} />,
23+
true,
2324
);
2425

2526
const { Modal: DeleteConfirm, openModal: openDeleteConfirmModal } = useModal(

apps/client/src/widgets/question-list/ui/QuestionList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function QuestionList() {
3939

4040
const socket = useSocket();
4141

42-
const { Modal: CreateQuestion, openModal: openCreateQuestionModal } = useModal(<CreateQuestionModal />);
42+
const { Modal: CreateQuestion, openModal: openCreateQuestionModal } = useModal(<CreateQuestionModal />, true);
4343

4444
const { Modal: SessionParticipants, openModal: openSessionParticipantsModal } = useModal(
4545
<SessionParticipantsModal />,

apps/client/src/widgets/reply-list/ui/ReplyItem.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function ReplyItem({ question, reply }: Readonly<ReplyItemProps>) {
2020

2121
const { Modal: CreateReply, openModal: openCreateReplyModal } = useModal(
2222
<CreateReplyModal question={question} reply={reply} />,
23+
true,
2324
);
2425

2526
const { Modal: DeleteModal, openModal: openDeleteModal } = useModal(<DeleteConfirmModal onConfirm={handleDelete} />);

apps/client/src/widgets/reply-list/ui/ReplyList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function QuestionDetail() {
2626

2727
const question = questions.find((q) => q.questionId === selectedQuestionId);
2828

29-
const { Modal, openModal } = useModal(<CreateReplyModal question={question} />);
29+
const { Modal, openModal } = useModal(<CreateReplyModal question={question} />, true);
3030

3131
if (!question) {
3232
return null;

0 commit comments

Comments
 (0)