22
33import { useState , useEffect , useRef } from 'react' ;
44import {
5+ Check ,
56 ChevronDown ,
67 ChevronUp ,
78 Edit2 ,
89 MoreVertical ,
910 Plus ,
1011 Trash2 ,
12+ X ,
1113} from 'lucide-react' ;
1214import Card from '../home/Card' ;
1315import TaskItem from './TaskItem' ;
@@ -26,6 +28,11 @@ interface PlanSectionProps {
2628 title : string ;
2729 description ?: string ;
2830 onDeletePlan : ( planId : string , title : string ) => void ;
31+ onUpdatePlan : (
32+ planId : string ,
33+ newTitle : string ,
34+ newDescription : string
35+ ) => void ;
2936}
3037
3138export default function PlanSection ( {
@@ -34,14 +41,18 @@ export default function PlanSection({
3441 title,
3542 description,
3643 onDeletePlan,
44+ onUpdatePlan,
3745} : PlanSectionProps ) {
3846 const [ isOpen , setIsOpen ] = useState ( true ) ;
3947 const [ tasks , setTasks ] = useState < PlanItem [ ] > ( [ ] ) ;
4048 const [ isTasksLoading , setIsTasksLoading ] = useState ( true ) ;
4149 const [ isAddingTask , setIsAddingTask ] = useState ( false ) ;
4250
43- const [ showPlanMenu , setShowPlanMenu ] = useState ( false ) ;
51+ const [ isEditingPlan , setIsEditingPlan ] = useState ( false ) ;
52+ const [ editTitle , setEditTitle ] = useState ( title ) ;
53+ const [ editDesc , setEditDesc ] = useState ( description || '' ) ;
4454
55+ const [ showPlanMenu , setShowPlanMenu ] = useState ( false ) ;
4556 const menuRef = useRef < HTMLDivElement > ( null ) ;
4657
4758 // 1. 초기 데이터 로드
@@ -148,6 +159,33 @@ export default function PlanSection({
148159 }
149160 } ;
150161
162+ // 6. 플랜 수정 핸들러
163+ const handleStartEdit = ( e : React . MouseEvent ) => {
164+ e . stopPropagation ( ) ; // 아코디언 토글 방지
165+
166+ setEditTitle ( title ) ; // props로 받은 최신값으로 초기화
167+ setEditDesc ( description || '' ) ;
168+
169+ setIsEditingPlan ( true ) ;
170+ setShowPlanMenu ( false ) ; // 메뉴 닫기
171+ } ;
172+
173+ const handleSaveEdit = ( e : React . MouseEvent ) => {
174+ e . stopPropagation ( ) ;
175+
176+ // 부모 컴포넌트에게 변경된 내용 전달
177+ onUpdatePlan ( planId , editTitle , editDesc ) ;
178+
179+ setIsEditingPlan ( false ) ; // 수정 모드 종료
180+ } ;
181+
182+ // 7. 플랜 수정 취소 핸들러
183+ const handleCancelEdit = ( e : React . MouseEvent ) => {
184+ e . stopPropagation ( ) ;
185+
186+ setIsEditingPlan ( false ) ; // 수정 모드 종료
187+ } ;
188+
151189 // 완료된 할 일 개수 계산
152190 const completedCount = tasks . filter ( ( t ) => t . isChecked ) . length ;
153191 const totalCount = tasks . length ;
@@ -163,12 +201,51 @@ export default function PlanSection({
163201 { /* 헤더 영역 */ }
164202 < div
165203 className = "flex cursor-pointer items-start justify-between"
166- onClick = { ( ) => setIsOpen ( ! isOpen ) }
204+ onClick = { ( ) => ! isEditingPlan && setIsOpen ( ! isOpen ) }
167205 >
168- < div >
169- < h3 className = "text-xl font-bold text-gray-900" > { title } </ h3 >
170- < p className = "mt-1 text-sm text-gray-500" > { description } </ p >
171- </ div >
206+ { isEditingPlan ? (
207+ < div
208+ className = "flex cursor-default flex-col gap-2"
209+ onClick = { ( e ) => e . stopPropagation ( ) }
210+ >
211+ { /* 제목 입력창 */ }
212+ < input
213+ type = "text"
214+ value = { editTitle }
215+ onChange = { ( e ) => setEditTitle ( e . target . value ) }
216+ className = "w-full border-b-2 border-[#556BD6] bg-transparent text-xl font-bold text-gray-900 focus:outline-none"
217+ placeholder = "플랜 제목"
218+ autoFocus
219+ />
220+ { /* 설명 입력창 */ }
221+ < input
222+ type = "text"
223+ value = { editDesc }
224+ onChange = { ( e ) => setEditDesc ( e . target . value ) }
225+ className = "w-full border-b border-gray-300 bg-transparent text-sm text-gray-600 focus:border-[#556BD6] focus:outline-none"
226+ placeholder = "설명 (선택사항)"
227+ />
228+ < div className = "mt-1 flex gap-2" >
229+ < button
230+ onClick = { handleSaveEdit }
231+ className = "flex items-center gap-1 rounded bg-[#556BD6] px-2 py-1 text-xs text-white transition-colors hover:bg-[#4456a8]"
232+ >
233+ < Check size = { 12 } /> 저장
234+ </ button >
235+ < button
236+ onClick = { handleCancelEdit }
237+ className = "flex items-center gap-1 rounded bg-gray-200 px-2 py-1 text-xs text-gray-600 transition-colors hover:bg-gray-300"
238+ >
239+ < X size = { 12 } /> 취소
240+ </ button >
241+ </ div >
242+ </ div >
243+ ) : (
244+ < div >
245+ < h3 className = "text-xl font-bold text-gray-900" > { title } </ h3 >
246+ < p className = "mt-1 text-sm text-gray-500" > { description } </ p >
247+ </ div >
248+ ) }
172249
173250 < div className = "flex items-center gap-4" >
174251 < div className = "text-right" >
@@ -193,10 +270,7 @@ export default function PlanSection({
193270 < div className = "absolute top-8 right-0 w-32 overflow-hidden rounded-lg border border-gray-100 bg-white py-1 shadow-lg" >
194271 < button
195272 className = "flex w-full items-center gap-2 px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50"
196- onClick = { ( e ) => {
197- e . stopPropagation ( ) ;
198- alert ( '플랜 수정 기능' ) ;
199- } }
273+ onClick = { handleStartEdit }
200274 >
201275 < Edit2 size = { 14 } /> 수정
202276 </ button >
0 commit comments