Flutter 캘린더 모달에서 선택한 날짜로 할 일 추가하기: 문제 해결 가이드

2024. 12. 24. 16:57같이 공부합시다 - Flutter/Flutter로 To-Do 앱 만들기

728x90
반응형

 

안녕하세요! 😊

 

지난 글에서는 캘린더에서 선택한 날짜의 상세 화면에 할 일 추가 버튼을 만들었죠.

 

2024.12.24 - [같이 공부합시다 - Flutter/Flutter로 To-Do 앱 만들기] - 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 []; // 기본적으로 빈 리스트 반환
}


코드 설명

  1. 오늘 날짜 표준화:
    • DateTime.now()를 _normalizeDate 메서드로 표준화해 오늘 날짜를 얻습니다.
    • 예: 2024-12-20 12:34:56 → 2024-12-20 00:00:00.
  2. 필터별 조건:
    • all: 오늘 날짜의 모든 할 일을 반환합니다.
    • active: 오늘 날짜 중 미완료된 할 일을 반환합니다.
    • completed: 오늘 날짜 중 완료된 할 일을 반환합니다.
  3. 결과 반환:
    • 조건에 맞는 할 일 목록을 반환해 메인 화면에서 표시되도록 합니다.

적용 결과

여전히 메인 화면에 모든 할 일이 보여져요. 왜 그럴까요? 후…

로그를 찍어서 확인해 봐야겠습니다.

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();
}

 

 

 

 


메인 화면과 캘린더 데이터 분리하기

이제 캘린더와 메인 화면은 서로 독립적으로 동작합니다:

  1. 메인 화면: _getFilteredTodos를 통해 항상 오늘 날짜의 할 일만 표시될 거예요.
  2. 캘린더 화면: 선택된 날짜에 따라 할 일을 추가하거나, 관련 데이터를 표시될 겁니다.

 

 


최종 코드 통합

수정된 _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();
}


결과

이제 캘린더 모달에서 선택한 날짜로 정확히 할 일이 추가되었습니다 ! 짝짝짝 ! 🎉🎉

여기까지 혹시 그대로 따라오신 분들은 정말 죄송합니다만, 이게 다 경험입니다. 핫핫핫.. 죄송합니다.

 

여기까지 정말 고생하셨습니다 !

추가적인 질문이나 의견이 있다면 댓글로 남겨주세요.

 

함께 더 나은 앱을 만들어봅시다! 🚀

728x90
반응형