2024. 12. 24. 16:57ㆍ같이 공부합시다 - Flutter/Flutter로 To-Do 앱 만들기
안녕하세요! 😊
지난 글에서는 캘린더에서 선택한 날짜의 상세 화면에 할 일 추가 버튼을 만들었죠.
Flutter 캘린더 모달에서 할 일을 추가하는 방법: 편리한 To-Do 관리 기능 구현하기
안녕하세요! 😊 이번 글에서는 Flutter로 캘린더 모달 창에서 새로운 할 일을 바로 추가할 수 있는 기능을 구현하는 방법을 적용해 보겠습니다. 기존에는 캘린더를 보고 선택한 날짜의 할 일을 확
steadybuilder.tistory.com
하지만 여기에서 심각한 문제가 발견되었어요.
바로, 캘린더 모달 날짜 상세 보기 화면에서
할 일을 추가하면 메인 화면에 전부 추가되는 문제죠.
😱😱😱😱😱
메인 화면은 오늘 날짜만 보여줄 수 있도록 합시다.
문제점
캘린더 기능이 있는 To-Do 리스트 앱에서
메인 화면에 모든 할 일이 표시되면,
굳이 캘린더에서 추가한 이유가 없어지겠죠.
사용자에게 혼란을 줄 수도 있을 것 같습니다.
오늘 날짜의 할 일만 표시하면 이런 장점이 있어요:
- 더 빠른 확인: 오늘 해야 할 일만 보기 때문에 하루의 작업 관리가 더 쉬워져요.
- UI 깔끔: 모든 할 일이 아닌, 필요한 정보만 표시되어 화면이 더 정돈된 느낌을 줍니다.
- 캘린더와 분리된 역할: 캘린더는 날짜별 작업 관리에, 메인 화면은 하루의 작업 관리에 집중할 수 있어요.
오늘 날짜 필터링 구현 방법
핵심 메서드: _getFilteredTodos 수정
_getFilteredTodos는 현재 필터 상태(all, active, completed)에 따라 할 일 목록을 반환하는 메서드입니다.
현재 개발 진행중인 To-Do 앱은 필터 상태 기준으로 메인 화면에 할 일을 보여주도록 되어 있죠.
여기에 오늘 날짜 필터링 로직을 추가해 오늘 날짜의 할 일만 표시하도록 수정하면 될 것 같습니다.
수정된 코드
// 현재 필터에 따라 리스트 필터링
List<Map<String, dynamic>> _getFilteredTodos() {
final today = _normalizeDate(DateTime.now()); // 오늘 날짜를 표준화
// 'all' 필터인 경우 오늘 날짜의 할 일만 필터링
if (_filter == 'all') {
return _todoList.where((item) {
final itemDate = _normalizeDate(DateTime.parse(item['date']));
return itemDate == today; // 오늘 날짜와 동일한 할 일만 반환
}).toList();
}
// 'active' 필터인 경우 미완료된 오늘 날짜의 할 일만 필터링
if (_filter == 'active') {
return _todoList.where((item) {
final itemDate = _normalizeDate(DateTime.parse(item['date']));
return itemDate == today && !item['isCompleted'];
}).toList();
}
// 'completed' 필터인 경우 완료된 오늘 날짜의 할 일만 필터링
if (_filter == 'completed') {
return _todoList.where((item) {
final itemDate = _normalizeDate(DateTime.parse(item['date']));
return itemDate == today && item['isCompleted'];
}).toList();
}
return []; // 기본적으로 빈 리스트 반환
}
코드 설명
- 오늘 날짜 표준화:
- DateTime.now()를 _normalizeDate 메서드로 표준화해 오늘 날짜를 얻습니다.
- 예: 2024-12-20 12:34:56 → 2024-12-20 00:00:00.
- 필터별 조건:
- all: 오늘 날짜의 모든 할 일을 반환합니다.
- active: 오늘 날짜 중 미완료된 할 일을 반환합니다.
- completed: 오늘 날짜 중 완료된 할 일을 반환합니다.
- 결과 반환:
- 조건에 맞는 할 일 목록을 반환해 메인 화면에서 표시되도록 합니다.
적용 결과
여전히 메인 화면에 모든 할 일이 보여져요. 왜 그럴까요? 후…
로그를 찍어서 확인해 봐야겠습니다.
flutter: {task: 이브!, isCompleted: false, date: 2024-12-23T15:34:10.917843}
flutter: 할 일을 추가했어요 !
flutter: 캘린더 이벤트: {2024-12-20 00:00:00.000: [청소하기, 빨래하기], 2024-12-23 00:00:00.000: [강아지 산책, 크리스마스 케잌 준비하기], 2024-12-24 00:00:00.000: [이브!]}
아닛 !? 로그를 봐도 모르겠어요.
캘린더 모달 내 상세 보기에서
24일(현재 23일) 일자의 할 일을 추가했는데,
여전히 메인 화면에도 추가되는 것을 확인했습니다.
도대체 문제가 뭘까요 ?
다시 문제 파악
To-Do 앱의 메인 화면과 캘린더는 동일한 데이터 소스(_todoList)를 사용합니다.
- _addTodoItem 메서드는 할 일을 추가하면서 모든 데이터를 _todoList에 저장합니다.
- 메인 화면에서는 _todoList의 데이터를 필터링 없이 표시하다 보니, 다른 날짜의 할 일도 포함됩니다.
- 필터링 로직을 추가했지만, 추가된 할 일의 날짜를 제대로 구분하지 못해 여전히 문제가 발생하는 것으로 보여져요.
문제 해결을 위한 코드 수정
이 문제를 해결하려면 다음 두 가지를 수정해 봅시다.
1) _addTodoItem 수정
할 일을 추가할 때, 오늘 날짜 또는 선택된 날짜를 명확히 구분하여 저장합니다.
void _addTodoItem(String task) {
final today = _normalizeDate(DateTime.now()); // 오늘 날짜
final dateKey = _normalizeDate(_selectedDay ?? today); // 선택된 날짜 또는 오늘 날짜
setState(() {
// 새로운 할 일 추가
_todoList.add({
'task': task,
'isCompleted': false,
'date': dateKey.toIso8601String(), // 선택된 날짜 사용
});
// 캘린더 이벤트 업데이트
_calendarEvents[dateKey] = _calendarEvents[dateKey] ?? [];
_calendarEvents[dateKey]!.add(task);
});
print("할 일을 추가했어요!");
print("캘린더 이벤트: $_calendarEvents");
// 로컬 저장
_saveTodoList();
_saveCalendarEvents();
}
2) _getFilteredTodos 수정
이제 메인 화면에서 오늘 날짜에 해당하는 할 일만 필터링하도록 _getFilteredTodos를 수정합니다.
List<Map<String, dynamic>> _getFilteredTodos() {
final today = _normalizeDate(DateTime.now()); // 오늘 날짜 표준화
// 오늘 날짜에 해당하는 할 일만 필터링
return _todoList.where((item) {
final itemDate = _normalizeDate(DateTime.parse(item['date']));
return itemDate == today; // 오늘 날짜와 동일한 할 일만 반환
}).toList();
}
메인 화면과 캘린더 데이터 분리하기
이제 캘린더와 메인 화면은 서로 독립적으로 동작합니다:
- 메인 화면: _getFilteredTodos를 통해 항상 오늘 날짜의 할 일만 표시될 거예요.
- 캘린더 화면: 선택된 날짜에 따라 할 일을 추가하거나, 관련 데이터를 표시될 겁니다.
최종 코드 통합
수정된 _addTodoItem
void _addTodoItem(String task) {
final today = _normalizeDate(DateTime.now());
final dateKey = _normalizeDate(_selectedDay ?? today); // 선택된 날짜 또는 오늘 날짜
setState(() {
_todoList.add({
'task': task,
'isCompleted': false,
'date': dateKey.toIso8601String(),
});
_calendarEvents[dateKey] = _calendarEvents[dateKey] ?? [];
_calendarEvents[dateKey]!.add(task);
});
_saveTodoList();
_saveCalendarEvents();
}
수정된 _getFilteredTodos
List<Map<String, dynamic>> _getFilteredTodos() {
final today = _normalizeDate(DateTime.now());
return _todoList.where((item) {
final itemDate = _normalizeDate(DateTime.parse(item['date']));
return itemDate == today; // 오늘 날짜의 할 일만 반환
}).toList();
}
결과
문제가 해결되지 않네요… 😱😱😱💢💢💢
여기서 포기할 수는 없습니다.
어느 현명한 개발자님이 하신 말씀이 있죠.
“로그를 찍어보거라. 모든 것을 확인할 수 있나니.”
찍어 봅시다.
- _todoList와 _calendarEvents 상태 확인:
- _getFilteredTodos에 추가하면 메뉴의 전체 보기로 빠르게 콘솔 확인이 가능합니다.
- _addTodoItem 호출 후 _todoList와 _calendarEvents의 상태를 출력해 데이터가 정확히 업데이트되었는지 확인합시다.
- print('_todoList: $_todoList'); print('_calendarEvents: $_calendarEvents');
문제 발견
flutter: _todoList: [{task: 이브 테스트, isCompleted: false, date: 2024-12-23T15:45:00.461059}]
flutter: _calendarEvents: {2024-12-24 00:00:00.000: [이브!]}
flutter: _todoList: [{task: 이브 테스트, isCompleted: false, date: 2024-12-23T15:45:00.461059}]
flutter: _calendarEvents: {2024-12-24 00:00:00.000: [이브!]}
와우 ! _todoList 에 2024-12-23 에 추가된 것이 문제인 것 같네요. (24일 날짜를 찍고 추가했습니다.)
캘린더 모달에서 추가된 일자가 무조건 오늘 일자로 추가되는 것으로 보입니다.
당장 고쳐봅시다 !
문제 해결
이 문제는 할 일을 추가하는 메서드(_addTodoItem)에서 항상 오늘 날짜를 기준으로 저장하기 때문이었군요.
final today = DateTime.now();
위 코드처럼 오늘 날짜를 고정으로 사용하니, 캘린더에서 다른 날짜를 선택하더라도 그 값이 반영되지 않았던 거죠. 맙소사.
원인 정리
- 캘린더 모달에서 선택한 날짜(_selectedDay)를 저장하지 않고, 기본적으로 오늘 날짜(DateTime.now())를 사용하고 있었어요.
- _addTodoItem 메서드가 선택된 날짜와 상관없이 무조건 오늘 날짜를 기준으로 데이터를 처리했어요.
코드 수정: 선택한 날짜 저장하기
- 선택한 날짜 사용: 캘린더 모달에서 선택된 날짜(_selectedDay)를 기반으로 할 일을 추가하겠습니다.
- 기본값 처리: 선택된 날짜가 없을 경우에만 오늘 날짜를 기본값으로 사용합니다.
수정된 _addTodoItem 코드
void _addTodoItem(String task) {
// 선택한 날짜가 있으면 사용, 없으면 오늘 날짜를 기본값으로 설정
final selectedDate = _normalizeDate(_selectedDay ?? DateTime.now());
setState(() {
// 새로운 할 일을 todoList에 추가
_todoList.add({
'task': task,
'isCompleted': false,
'date': selectedDate.toIso8601String(), // 선택된 날짜 사용
});
// 캘린더 이벤트 업데이트
_calendarEvents[selectedDate] = _calendarEvents[selectedDate] ?? [];
_calendarEvents[selectedDate]!.add(task);
});
// 디버깅 로그 출력
print('_todoList: $_todoList');
print('_calendarEvents: $_calendarEvents');
// 데이터 저장
_saveTodoList();
_saveCalendarEvents();
}
캘린더 모달의 날짜 선택과 연동
_showCalendar 메서드에서 날짜를 선택하면, 선택된 날짜가 _selectedDay에 저장됩니다. 이제 이 값이 _addTodoItem에서 사용되도록 연결됩니다.
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay; // 선택한 날짜 저장
_focusedDay = focusedDay;
});
_showTasksForSelectedDay(); // 선택한 날짜의 할 일 표시
},
문제 해결 후 동작 확인
1) 캘린더에서 2024-12-24를 선택 후 할 일 추가
- _selectedDay가 2024-12-24로 설정됩니다.
- 새로운 할 일이 다음과 같이 저장됩니다:
- _todoList: [{'task': '이브 준비하기', 'isCompleted': false, 'date': '2024-12-24T00:00:00.000'}]
- 캘린더 마커도 업데이트됩니다:
- _calendarEvents: {2024-12-24 00:00:00.000: ['이브 준비하기']}
2) 메인 화면과 캘린더의 동작
- 메인 화면:
- 오늘 날짜(2024-12-23)의 할 일만 표시됩니다.
- 다른 날짜(2024-12-24)의 할 일은 표시되지 않습니다.
- 캘린더:
- 선택한 날짜(2024-12-24)에 할 일이 추가되고, 해당 날짜에 마커가 표시됩니다.
코드 통합
_addTodoItem 최종 코드
void _addTodoItem(String task) {
final selectedDate = _normalizeDate(_selectedDay ?? DateTime.now());
setState(() {
_todoList.add({
'task': task,
'isCompleted': false,
'date': selectedDate.toIso8601String(),
});
_calendarEvents[selectedDate] = _calendarEvents[selectedDate] ?? [];
_calendarEvents[selectedDate]!.add(task);
});
print('_todoList: $_todoList');
print('_calendarEvents: $_calendarEvents');
_saveTodoList();
_saveCalendarEvents();
}
결과
이제 캘린더 모달에서 선택한 날짜로 정확히 할 일이 추가되었습니다 ! 짝짝짝 ! 🎉🎉
여기까지 혹시 그대로 따라오신 분들은 정말 죄송합니다만, 이게 다 경험입니다. 핫핫핫.. 죄송합니다.
여기까지 정말 고생하셨습니다 !
추가적인 질문이나 의견이 있다면 댓글로 남겨주세요.
함께 더 나은 앱을 만들어봅시다! 🚀
'같이 공부합시다 - Flutter > Flutter로 To-Do 앱 만들기' 카테고리의 다른 글
Flutter 캘린더 모달에서 안전한 할 일 삭제: 오류 해결 및 UI 개선 가이드 (11) | 2024.12.27 |
---|---|
Flutter 캘린더 모달 중첩 문제 해결: 깔끔한 할 일 추가 기능 구현하기 (4) | 2024.12.26 |
Flutter 캘린더 모달에서 할 일을 추가하는 방법: 편리한 To-Do 관리 기능 구현하기 (5) | 2024.12.24 |
Flutter로 캘린더에서 선택한 날짜의 할 일 상세 보기 구현하기 (81) | 2024.12.23 |
Flutter로 To-Do 리스트 앱의 캘린더 이벤트 동기화 문제 해결하기 (앱 재실행 시 캘린더 일자에 마커 표시가 안되는 오류 개선) (3) | 2024.12.23 |