작성일: 2026년 3월 31일 진행 단계: Phase 7 (Flutter 앱 개발) 진행 중 이전 일지: Day 5 참고 (Phase 7 ①~⑦ 완료)


✅ Phase 7 전체 진행 현황

작업 내용 상태
① 프로젝트 구조 셋업 디렉토리 구조, 테마, 상수 ✅ 완료
② Supabase 통합 + Auth Service 인증 레이어, Riverpod 상태 ✅ 완료
③ 라우팅 설정 go_router, redirect 로직 ✅ 완료
④ Splash / 온보딩 스크린 진입 흐름, 3페이지 온보딩 ✅ 완료
⑤ 로그인 / 회원가입 스크린 이메일 인증 UI, 유효성 검사 ✅ 완료
⑥ 홈 스크린 오늘의 스케줄, 복용 확인/스킵 ✅ 완료
⑦ 약 등록 스크린 약 정보 입력, 주기/시간 설정 ✅ 완료
⑧ 약 목록 / 수정 스크린 목록 조회, 수정, 삭제, 토글 ✅ 완료
⑨ 복용 히스토리 캘린더 월별 캘린더, 기록 목록 ✅ 완료
⑩ 통계 스크린 주간/월간 복용률, 바 차트 ✅ 완료
⑪ 알림 설정 스크린 알림 ON/OFF, 사전 알림 시간 ✅ 완료
⑫ 설정 스크린 프로필, 계정, 앱 정보 ✅ 완료
⑬ FCM/APNs 푸시 알림 통합 Firebase, 로컬 알림, 토큰 등록 ✅ 완료
⑭ 인터랙티브 알림 (Yes/No) 잠금화면 복용 확인/스킵 ✅ 완료
⑮ Google / Apple 소셜 로그인 🔜 다음

1. ⑧ 약 목록 / 수정 스크린

구현 파일

lib/features/medications/domain/medication.dart       ← copyWith, MedicationUpdateRequest 추가
lib/features/medications/data/medication_repository.dart ← GET, PATCH, DELETE 추가
lib/features/medications/providers/medication_provider.dart ← list, update, toggle, delete 추가
lib/features/medications/presentation/medication_list_screen.dart
lib/features/medications/presentation/medication_edit_screen.dart

핵심 구현 내용

MedicationListScreen

활성/비활성 약을 섹션으로 분리하여 표시. 각 카드에서 토글 스위치와 더보기 메뉴(수정/삭제) 제공.

final active   = medications.where((m) => m.isActive).toList();
final inactive = medications.where((m) => !m.isActive).toList();

Optimistic Toggle

토글 시 API 응답 전에 UI를 즉시 반영. 실패 시 자동 롤백.

Future<void> toggle(String id) async {
  // 즉시 UI 반영
  state = AsyncValue.data(current.map((m) {
    if (m.id == id) return m.copyWith(isActive: !m.isActive);
    return m;
  }).toList());

  try {
    await _repo.toggleMedication(id);
  } catch (_) {
    refresh(); // 실패 시 롤백
  }
}

MedicationEditScreen

기존 데이터를 initState에서 컨트롤러에 주입하여 수정 폼으로 재사용.

@override
void initState() {
  super.initState();
  final m = widget.medication;
  _nameController = TextEditingController(text: m.name);
  _times = m.scheduledTimes.map((t) {
    final parts = t.split(':');
    return TimeOfDay(hour: int.parse(parts[0]), minute: int.parse(parts[1]));
  }).toList();
}

삭제 확인 다이얼로그

실수 삭제 방지를 위해 AlertDialog로 2단계 확인.