Skip to content

Commit bebd539

Browse files
authored
fix(fe): add error handling and toast notifications for question and reply improvements (#118)
feat: add error handling and toast notifications for question and reply improvements
1 parent 43872ca commit bebd539

File tree

10 files changed

+109
-23
lines changed

10 files changed

+109
-23
lines changed

apps/client/src/features/create-update-question/api/improve-question-retry.api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ export const postRetryQuestionImprovement = async (
2121
headers: { 'Content-Type': 'application/json' },
2222
body: JSON.stringify(RetryImproveQuestionRequestSchema.parse(body)),
2323
});
24+
25+
if (response.status === 403) {
26+
if (onError) onError(new Error('Forbidden'));
27+
return;
28+
}
29+
2430
if (!response.body) throw new Error('ReadableStream not supported');
2531

2632
const reader = response.body.getReader();

apps/client/src/features/create-update-question/api/improve-question.api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ export const postQuestionImprovementStream = async (
1919
headers: { 'Content-Type': 'application/json' },
2020
body: JSON.stringify(QuestionImprovementRequestSchema.parse(body)),
2121
});
22+
23+
if (response.status === 403) {
24+
if (onError) onError(new Error('Forbidden'));
25+
return;
26+
}
27+
2228
if (!response.body) throw new Error('ReadableStream not supported');
2329

2430
const reader = response.body.getReader();

apps/client/src/features/create-update-question/model/useQuestionWritingSupport.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
QuestionImprovementRequest,
1111
} from '@/features/create-update-question/api/improve-question.api';
1212

13+
import { useToastStore } from '@/shared/ui/toast';
14+
1315
export const useQuestionWritingSupport = ({
1416
body,
1517
handleAccept,
@@ -22,20 +24,32 @@ export const useQuestionWritingSupport = ({
2224

2325
const [isPending, setIsPending] = useState(false);
2426

25-
const questionImprovement = (body: QuestionImprovementRequest) => {
27+
const addToast = useToastStore((state) => state.addToast);
28+
29+
const questionImprovement = (body: QuestionImprovementRequest, onComplete: () => void) => {
2630
setIsPending(true);
2731
postQuestionImprovementStream(
2832
body,
2933
({ content }) => {
3034
setSupportResult((prev) => (prev ?? '') + content);
3135
},
3236
() => {
37+
onComplete();
38+
setIsPending(false);
39+
},
40+
() => {
41+
onComplete();
3342
setIsPending(false);
43+
addToast({
44+
type: 'ERROR',
45+
message: '3초 뒤에 다시 시도해주세요.',
46+
duration: 3000,
47+
});
3448
},
3549
);
3650
};
3751

38-
const retryQuestionImprovement = (body: RetryImproveQuestionRequest) => {
52+
const retryQuestionImprovement = (body: RetryImproveQuestionRequest, onComplete: () => void) => {
3953
setSupportResult(null);
4054
setIsPending(true);
4155
postRetryQuestionImprovement(
@@ -44,7 +58,17 @@ export const useQuestionWritingSupport = ({
4458
setSupportResult((prev) => (prev ?? '') + content);
4559
},
4660
() => {
61+
onComplete();
62+
setIsPending(false);
63+
},
64+
() => {
65+
onComplete();
4766
setIsPending(false);
67+
addToast({
68+
type: 'ERROR',
69+
message: '3초 뒤에 다시 시도해주세요.',
70+
duration: 3000,
71+
});
4872
},
4973
);
5074
};

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,23 @@ function CreateQuestionModal({ question }: Readonly<CreateQuestionModalProps>) {
5050
if (buttonEnabled && isValidLength && sessionId && token) {
5151
setSupportType('IMPROVE_QUESTION');
5252
setIsAnimationComplete(false);
53-
questionImprovement({ token, sessionId, body });
53+
questionImprovement({ token, sessionId, body }, () => setIsAnimationComplete(true));
5454
}
5555
};
5656

5757
const handleRetry = (requirements: string) => {
5858
if (sessionId && token && supportResult && supportType) {
5959
setIsAnimationComplete(false);
60-
retryQuestionImprovement({
61-
token,
62-
sessionId,
63-
original: body,
64-
received: supportResult,
65-
retryMessage: requirements,
66-
});
60+
retryQuestionImprovement(
61+
{
62+
token,
63+
sessionId,
64+
original: body,
65+
received: supportResult,
66+
retryMessage: requirements,
67+
},
68+
() => setIsAnimationComplete(true),
69+
);
6770
}
6871
};
6972

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,11 @@ export default function CreateQuestionModalFooter({
131131
<div className='text-sm font-bold text-white'>질문 개선하기</div>
132132
</Button>
133133
<div className='flex flex-row gap-2'>
134-
<Button className='bg-gray-500' onClick={closeModal}>
134+
<Button
135+
className={`${buttonEnabled ? 'bg-gray-500' : 'cursor-not-allowed bg-gray-300'}`}
136+
onClick={closeModal}
137+
disabled={!buttonEnabled}
138+
>
135139
<div className='text-sm font-bold text-white'>취소하기</div>
136140
</Button>
137141
<Button

apps/client/src/features/create-update-reply/api/improve-reply-retry.api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ export const postRetryReplyImprovement = async (
2222
headers: { 'Content-Type': 'application/json' },
2323
body: JSON.stringify(RetryReplyImprovementRequestSchema.parse(body)),
2424
});
25+
26+
if (response.status === 403) {
27+
if (onError) onError(new Error('Forbidden'));
28+
return;
29+
}
30+
2531
if (!response.body) throw new Error('ReadableStream not supported');
2632

2733
const reader = response.body.getReader();

apps/client/src/features/create-update-reply/api/improve-reply.api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ export const postReplyImprovementStream = async (
2020
headers: { 'Content-Type': 'application/json' },
2121
body: JSON.stringify(ReplyImprovementRequestSchema.parse(body)),
2222
});
23+
24+
if (response.status === 403) {
25+
if (onError) onError(new Error('Forbidden'));
26+
return;
27+
}
28+
2329
if (!response.body) throw new Error('ReadableStream not supported');
2430

2531
const reader = response.body.getReader();

apps/client/src/features/create-update-reply/model/useReplyWritingSupport.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
ReplyImprovementRequest,
1111
} from '@/features/create-update-reply/api/improve-reply.api';
1212

13+
import { useToastStore } from '@/shared/ui/toast';
14+
1315
export const useReplyWritingSupport = ({
1416
questionBody,
1517
body,
@@ -24,20 +26,32 @@ export const useReplyWritingSupport = ({
2426

2527
const [isPending, setIsPending] = useState(false);
2628

27-
const replyImprovement = (body: ReplyImprovementRequest) => {
29+
const addToast = useToastStore((state) => state.addToast);
30+
31+
const replyImprovement = (body: ReplyImprovementRequest, onComplete: () => void) => {
2832
setIsPending(true);
2933
postReplyImprovementStream(
3034
body,
3135
({ content }) => {
3236
setSupportResult((prev) => (prev ?? '') + content);
3337
},
3438
() => {
39+
onComplete();
40+
setIsPending(false);
41+
},
42+
() => {
43+
onComplete();
3544
setIsPending(false);
45+
addToast({
46+
type: 'ERROR',
47+
message: '3초 뒤에 다시 시도해주세요.',
48+
duration: 3000,
49+
});
3650
},
3751
);
3852
};
3953

40-
const retryReplyImprovement = (body: RetryReplyImprovementRequest) => {
54+
const retryReplyImprovement = (body: RetryReplyImprovementRequest, onComplete: () => void) => {
4155
setSupportResult(null);
4256
setIsPending(true);
4357
postRetryReplyImprovement(
@@ -46,7 +60,17 @@ export const useReplyWritingSupport = ({
4660
setSupportResult((prev) => (prev ?? '') + content);
4761
},
4862
() => {
63+
onComplete();
64+
setIsPending(false);
65+
},
66+
() => {
67+
onComplete();
4968
setIsPending(false);
69+
addToast({
70+
type: 'ERROR',
71+
message: '3초 뒤에 다시 시도해주세요.',
72+
duration: 3000,
73+
});
5074
},
5175
);
5276
};

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,24 @@ function CreateReplyModal({ question, reply }: Readonly<CreateReplyModalProps>)
4949
if (buttonEnabled && isValidLength && question && sessionId && token) {
5050
setSupportType('IMPROVE_REPLY');
5151
setIsAnimationComplete(false);
52-
replyImprovement({ token, sessionId, body, originalQuestion: question.body });
52+
replyImprovement({ token, sessionId, body, originalQuestion: question.body }, () => setIsAnimationComplete(true));
5353
}
5454
};
5555

5656
const handleRetry = (requirements: string) => {
5757
if (sessionId && token && question && supportResult && supportType) {
5858
setIsAnimationComplete(false);
59-
retryReplyImprovement({
60-
token,
61-
sessionId,
62-
originalQuestion: question.body,
63-
original: body,
64-
received: supportResult,
65-
retryMessage: requirements,
66-
});
59+
retryReplyImprovement(
60+
{
61+
token,
62+
sessionId,
63+
originalQuestion: question.body,
64+
original: body,
65+
received: supportResult,
66+
retryMessage: requirements,
67+
},
68+
() => setIsAnimationComplete(true),
69+
);
6770
}
6871
};
6972

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ export default function CreateReplyModalFooter({
116116
<div className='text-sm font-bold text-white'>답변 개선하기</div>
117117
</Button>
118118
<div className='flex flex-row gap-2'>
119-
<Button className='bg-gray-500' onClick={closeModal}>
119+
<Button
120+
className={`${buttonEnabled ? 'bg-gray-500' : 'cursor-not-allowed bg-gray-300'}`}
121+
onClick={closeModal}
122+
disabled={!buttonEnabled}
123+
>
120124
<div className='text-sm font-bold text-white'>취소하기</div>
121125
</Button>
122126
<Button

0 commit comments

Comments
 (0)