@@ -29,6 +29,8 @@ export default function PeriodSelectionScreen({
2929
3030 const [ currentMonth , setCurrentMonth ] = useState ( new Date ( ) . getMonth ( ) ) ;
3131 const [ currentYear , setCurrentYear ] = useState ( new Date ( ) . getFullYear ( ) ) ;
32+ const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
33+ const [ isNavigating , setIsNavigating ] = useState ( false ) ;
3234
3335 const months = [
3436 "1월" ,
@@ -54,6 +56,16 @@ export default function PeriodSelectionScreen({
5456 return new Date ( year , month , 1 ) . getDay ( ) ;
5557 } ;
5658
59+ const handleDateSelect = ( day : number ) => {
60+ if ( isSubmitting ) return ;
61+ setTargetDate ( new Date ( currentYear , currentMonth , day ) ) ;
62+ } ;
63+
64+ const handlePeriodTypeSelect = ( type : "months" | "date" ) => {
65+ if ( isSubmitting ) return ;
66+ setPeriodType ( type ) ;
67+ } ;
68+
5769 const renderCalendar = ( ) => {
5870 const daysInMonth = getDaysInMonth ( currentMonth , currentYear ) ;
5971 const firstDay = getFirstDayOfMonth ( currentMonth , currentYear ) ;
@@ -95,10 +107,8 @@ export default function PeriodSelectionScreen({
95107 days . push (
96108 < button
97109 key = { day }
98- onClick = { ( ) =>
99- ! isPast && setTargetDate ( new Date ( currentYear , currentMonth , day ) )
100- }
101- disabled = { isPast }
110+ onClick = { ( ) => ! isPast && handleDateSelect ( day ) }
111+ disabled = { isPast || isSubmitting }
102112 className = { `h-10 w-10 rounded flex items-center justify-center text-xs font-medium ${ isSelected
103113 ? "bg-label-primary text-background-alternative"
104114 : isPast
@@ -115,6 +125,10 @@ export default function PeriodSelectionScreen({
115125 } ;
116126
117127 const navigateMonth = ( direction : "prev" | "next" ) => {
128+ if ( isNavigating || isSubmitting ) return ;
129+
130+ setIsNavigating ( true ) ;
131+ setTimeout ( ( ) => setIsNavigating ( false ) , 200 ) ;
118132 if ( direction === "prev" ) {
119133 if ( currentMonth === 0 ) {
120134 setCurrentMonth ( 11 ) ;
@@ -132,7 +146,7 @@ export default function PeriodSelectionScreen({
132146 }
133147 } ;
134148
135- const isNextEnabled = periodType === "months" || targetDate !== null ;
149+ const isNextEnabled = ( periodType === "months" || targetDate !== null ) && ! isSubmitting ;
136150
137151 return (
138152 < div className = "min-h-screen bg-background-alternative flex flex-col" >
@@ -154,20 +168,22 @@ export default function PeriodSelectionScreen({
154168 < div className = "bg-background-normal rounded-full p-1 mb-8" >
155169 < div className = "flex" >
156170 < button
157- onClick = { ( ) => setPeriodType ( "months" ) }
171+ onClick = { ( ) => handlePeriodTypeSelect ( "months" ) }
172+ disabled = { isSubmitting }
158173 className = { `flex-1 py-2 px-4 rounded-full font-bold text-sm ${ periodType === "months"
159174 ? "bg-label-primary text-background-alternative"
160175 : "text-label-alternative"
161- } `}
176+ } ${ isSubmitting ? "opacity-50 cursor-not-allowed" : "" } `}
162177 >
163178 개월 수로 설정
164179 </ button >
165180 < button
166- onClick = { ( ) => setPeriodType ( "date" ) }
181+ onClick = { ( ) => handlePeriodTypeSelect ( "date" ) }
182+ disabled = { isSubmitting }
167183 className = { `flex-1 py-2 px-4 rounded-full font-bold text-sm ${ periodType === "date"
168184 ? "bg-label-primary text-background-alternative"
169185 : "text-label-alternative"
170- } `}
186+ } ${ isSubmitting ? "opacity-50 cursor-not-allowed" : "" } `}
171187 >
172188 완료 날짜로 설정
173189 </ button >
@@ -201,6 +217,8 @@ export default function PeriodSelectionScreen({
201217 onClick = { ( ) => navigateMonth ( "prev" ) }
202218 className = "w-8 h-8 flex items-center justify-center"
203219 disabled = {
220+ isNavigating ||
221+ isSubmitting ||
204222 currentMonth === new Date ( ) . getMonth ( ) &&
205223 currentYear === new Date ( ) . getFullYear ( )
206224 }
@@ -210,6 +228,7 @@ export default function PeriodSelectionScreen({
210228 < button
211229 onClick = { ( ) => navigateMonth ( "next" ) }
212230 className = "w-8 h-8 flex items-center justify-center"
231+ disabled = { isNavigating || isSubmitting }
213232 >
214233 < ChevronLeftIcon className = "w-4 h-4 text-label-normal rotate-180" />
215234 </ button >
@@ -240,6 +259,9 @@ export default function PeriodSelectionScreen({
240259 < div className = "px-4 pb-14" >
241260 < ButtonRound
242261 onClick = { async ( ) => {
262+ if ( isSubmitting ) return ;
263+
264+ setIsSubmitting ( true ) ;
243265 const isPeriodByMonth = periodType === "months" ;
244266 const dueDate = targetDate
245267 ? targetDate . toISOString ( ) . split ( "T" ) [ 0 ]
@@ -260,12 +282,13 @@ export default function PeriodSelectionScreen({
260282 onNext ( ) ;
261283 } catch ( error ) {
262284 console . error ( 'Failed to create goal:' , error ) ;
285+ setIsSubmitting ( false ) ;
263286 // Handle error appropriately (show toast, etc.)
264287 }
265288 } }
266289 disabled = { ! isNextEnabled }
267290 >
268- 다음
291+ { isSubmitting ? "처리 중..." : "다음" }
269292 </ ButtonRound >
270293 </ div >
271294 </ div >
0 commit comments