11import { useState } from 'react' ;
2- import { isAxiosError } from 'axios' ;
32
43import { extractTitles , updateSubGoalsWithAiResponse } from '../utils/goal' ;
5- import { ALERT , GOAL_COUNT } from '../constants' ;
4+ import { GOAL_COUNT } from '../constants' ;
65
76import AiRecommendModal from '@/common/component/AiRecommendModal/AiRecommendModal' ;
7+ import AiFailModal from '@/common/component/AiFailModal/AiFailModal' ;
88import { useOverlayModal } from '@/common/hook/useOverlayModal' ;
99import {
1010 usePostAiRecommendCoreGoal ,
@@ -19,6 +19,8 @@ interface UseUpperTodoAIParams {
1919 refetch : ( ) => void ;
2020 refetchCoreGoalIds : ( ) => void ;
2121 setIsTooltipOpen : ( open : boolean ) => void ;
22+ hasAiBeenUsed : boolean ;
23+ markAiUsed : ( ) => void ;
2224}
2325
2426interface CoreGoalResponse {
@@ -27,22 +29,6 @@ interface CoreGoalResponse {
2729 title : string ;
2830}
2931
30- interface ApiErrorResponse {
31- message ?: string ;
32- }
33-
34- const getServerMessage = ( error : unknown , fallback : string ) => {
35- if ( isAxiosError < ApiErrorResponse > ( error ) ) {
36- return error . response ?. data ?. message ?? fallback ;
37- }
38-
39- if ( error instanceof Error && error . message ) {
40- return error . message ;
41- }
42-
43- return fallback ;
44- } ;
45-
4632export const useUpperTodoAI = ( {
4733 mandalartId,
4834 mainGoal,
@@ -51,41 +37,64 @@ export const useUpperTodoAI = ({
5137 refetch,
5238 refetchCoreGoalIds,
5339 setIsTooltipOpen,
40+ hasAiBeenUsed,
41+ markAiUsed,
5442} : UseUpperTodoAIParams ) => {
5543 const { openModal, closeModal } = useOverlayModal ( ) ;
5644 const postAiRecommend = usePostAiRecommendCoreGoal ( ) ;
5745 const postRecommendToCore = usePostAiRecommendToCoreGoals ( ) ;
5846
59- const [ isAiUsed , setIsAiUsed ] = useState ( false ) ;
47+ const [ isLoading , setIsLoading ] = useState ( false ) ;
6048
61- const handleAiSubmit = ( goals : { title : string } [ ] ) => {
49+ const openFailModal = ( retry ?: ( ) => void ) => {
50+ openModal ( < AiFailModal onClose = { closeModal } onRetry = { retry } /> ) ;
51+ } ;
52+
53+ const runSubmitMutation = ( titles : string [ ] ) => {
54+ if ( titles . length === 0 ) {
55+ return ;
56+ }
57+
58+ setIsLoading ( true ) ;
6259 postRecommendToCore . mutate (
63- { mandalartId, goals : goals . map ( ( g ) => g . title ) } ,
60+ { mandalartId, goals : titles } ,
6461 {
6562 onSuccess : ( response ) => {
6663 const responseData : CoreGoalResponse [ ] = response . coreGoals ;
6764 setSubGoals ( ( prev ) => updateSubGoalsWithAiResponse ( prev , responseData ) ) ;
6865 refetchCoreGoalIds ( ) ;
6966 refetch ( ) ;
67+ setIsLoading ( false ) ;
7068 } ,
71- onError : ( error ) => {
72- const message = getServerMessage ( error , ALERT . aiSaveFail ) ;
73- alert ( message ) ;
69+ onError : ( ) => {
70+ openFailModal ( ( ) => {
71+ runSubmitMutation ( titles ) ;
72+ } ) ;
73+ setIsLoading ( false ) ;
7474 } ,
7575 } ,
7676 ) ;
7777 } ;
7878
79+ const handleAiSubmit = ( goals : { title : string } [ ] ) => {
80+ const titles = goals . map ( ( goal ) => goal . title ) ;
81+ runSubmitMutation ( titles ) ;
82+ } ;
83+
7984 const handleOpenAiModal = async ( ) => {
8085 const currentFilledCount = subGoals . filter ( ( v ) => v . trim ( ) !== '' ) . length ;
8186 const maxGoals = GOAL_COUNT ;
8287
8388 if ( currentFilledCount >= maxGoals ) {
84- alert ( ALERT . goalsAlreadyFilled ) ;
89+ openFailModal ( ) ;
90+ return ;
91+ }
92+
93+ if ( hasAiBeenUsed || isLoading ) {
8594 return ;
8695 }
8796
88- setIsAiUsed ( true ) ;
97+ setIsLoading ( true ) ;
8998 setIsTooltipOpen ( false ) ;
9099
91100 try {
@@ -102,20 +111,20 @@ export const useUpperTodoAI = ({
102111 const aiModalContent = (
103112 < AiRecommendModal
104113 onClose = { closeModal }
114+ onBeforeClose = { markAiUsed }
105115 onSubmit = { handleAiSubmit }
106116 values = { subGoals }
107117 options = { titles }
108118 />
109119 ) ;
110120
111121 openModal ( aiModalContent ) ;
112- } catch ( error ) {
113- const message = getServerMessage ( error , ALERT . aiFetchFail ) ;
114- alert ( message ) ;
122+ } catch {
123+ openFailModal ( handleOpenAiModal ) ;
115124 } finally {
116- setIsAiUsed ( false ) ;
125+ setIsLoading ( false ) ;
117126 }
118127 } ;
119128
120- return { isAiUsed , handleOpenAiModal } as const ;
129+ return { isLoading , handleOpenAiModal } as const ;
121130} ;
0 commit comments