day_plan_app 수정 지시서

day_plan_app · Windows / Claude Code 작업용

day_plan_app 수정 지시서

애플 버전(day_plan_appl_app)에서 확인·수정한 문제들을 안드로이드 원본 day_plan_app에도 적용하기 위한 지시서입니다. 묶음 A · 빠른 기록(고정 필터·오버플로우)과 묶음 B · 달력 높이 자동 조절(5/6주 마지막 주 가림) 두 부분입니다.

✏️ 대상 · lib/widgets/todo_edit_sheet.dart  ·  lib/screens/calendar_tab.dart
프로젝트day_plan_app (Android)
기준 DBv9 (tb_record_template)
검증flutter analyze
A 수정 여부아직 미적용 (이 문서대로 적용)
!

문제

빠른 기록 버튼(편집기 신규 → 유형칩 「기록」 옆)을 누르면, 설정에서 만든 기록 종류가 고정(is_fixed) 여부와 상관없이 전부 나옵니다. 고정한 항목만 나와야 합니다.

원인: _openQuickRecordDialog() 가 필터 없이 전체 목록 _recTemplates 를 그대로 렌더링합니다.

1

고정 항목만 표시 필수

메서드: _openQuickRecordDialog() — 세 군데를 바꿉니다. listRecordTemplates() 는 각 항목에 is_fixed(bool)를 넣어 반환하므로 그대로 필터에 씁니다.

① showDialog 호출 직전에 고정 목록 계산 추가

todo_edit_sheet.dart · _openQuickRecordDialog추가
    if (!mounted) return;
+   // 빠른 기록에는 '고정(is_fixed)'한 기록 종류만 표시.
+   final fixed =
+       _recTemplates.where((t) => t['is_fixed'] == true).toList();
    final opt = await showDialog<String>(

② 빈 조건과 안내 문구 교체

todo_edit_sheet.dart · content변경
          child: _recTemplates.isEmpty
              ? const Text('설정 › 기록 종류에서 먼저 만들어 주세요.',
                  style: TextStyle(color: Colors.grey))
↓ 이렇게변경 후
          child: fixed.isEmpty
              ? const Text(
                  '고정된 기록 종류가 없습니다.\n설정 › 기록 종류에서 고정(체크)해 주세요.',
                  style: TextStyle(color: Colors.grey))

③ 반복 대상 목록 교체

todo_edit_sheet.dart · for 루프변경
                      for (final tpl in _recTemplates)
                        Padding( … )
↓ 이렇게변경 후
                      for (final tpl in fixed)
                        Padding( … )
⚠
주의 — is_fixed 컬럼·동기화 코드는 그대로 둡니다. 이 수정은 표시 로직만 바꾸며 DB·스키마 변경이 없습니다.
2

유형칩 줄 오버플로우 방지 선택

메서드: _typeSelector(). 좁은 화면에서 할일 / 일정 / 기록 + 빠른 기록 줄이 오른쪽으로 넘칠 수 있습니다(iOS에서 RIGHT OVERFLOWED 확인). Row 를 FittedBox(scaleDown) 로 감싸고 Spacer 를 SizedBox 로 바꿉니다.

todo_edit_sheet.dart · _typeSelector 의 return변경 후
    return Padding(
      padding: const EdgeInsets.only(bottom: 10),
      // 좁은 폭에서 넘치지 않게 필요 시 축소.
      child: FittedBox(
        fit: BoxFit.scaleDown,
        alignment: Alignment.centerLeft,
        child: Row(children: [
          chip('todo', '할일'),
          chip('event', '일정'),
          chip('record', '기록'),
          if (kind == 'record') ...[
            const SizedBox(width: 12),   // (기존 const Spacer())
            _quickRecordButton(),
          ],
        ]),
      ),
    );
i

이모지(📝)는 A에서 손대지 않아도 됨 참고

애플 버전에서는 iOS 시뮬레이터가 이모지를 “?”(두부)로 렌더링해서, 📝 를 Icon(Icons.note_add_outlined) 로 교체했습니다. A(안드로이드)는 이모지가 정상 렌더링되므로 바꿀 필요가 없습니다. (통일하고 싶으면 버튼 아이콘·다이얼로그 제목의 Text('📝') 를 동일하게 아이콘으로 교체 가능 — 선택.)

B

달력 5/6주 높이 자동 조절 (마지막 주 가림 수정) 필수

파일: lib/screens/calendar_tab.dart · build() 의 LayoutBuilder.

문제 — A 달력은 행 높이가 고정(calRowHeight=80)이고 Positioned(top:0)(bottom 없음) + 하단 시트가 겹치는 구조입니다. 짧은 폰에서 calH(=110+주수×80) 가 화면보다 커지면 6주째 마지막 줄이 시트에 가려지거나 잘립니다. 폰 크기·주 수에 맞춰 자동 조절되지 않습니다.

해결 — 달력을 시트 위까지 고정 영역으로 두고, 그 실제 높이를 주 수로 나눠 행 높이를 결정합니다(내용 많은 일정보기는 그 이상 + 세로 스크롤). 애플 버전과 동일 구조. 아래 4곳을 바꿉니다.

① 시트 높이 계산을 collapsedFrac 기반으로 (기존 calH·sheetInit 계산 대체)

calendar_tab.dart · LayoutBuilder 상단변경 후
        final weeks = _weeksInFocusedMonth();
        const collapsedSheetH = 84.0;              // 접힌 시트(날짜·건수 헤더) 높이
        final collapsedFrac = (bodyH > 0 ? collapsedSheetH / bodyH : 0.12)
            .clamp(0.06, 0.5).toDouble();
        final sheetInit = collapsedFrac;           // 시작은 헤더만 보이게
        // (기존 calH / sheetInit=(bodyH-calH)/bodyH 계산은 삭제)

② 달력 영역을 시트 위까지 고정 — Positioned에 bottom 추가

calendar_tab.dart · Positioned변경 후
          Positioned(
            top: 0, left: 0, right: 0,
            bottom: collapsedSheetH + 12,          // ← 추가(시트 위까지 + 여유)
            child: Card(

③ TableCalendar를 Expanded+LayoutBuilder로 감싸 행 높이 채움 (Column의 mainAxisSize: MainAxisSize.min 제거)

calendar_tab.dart · 헤더 다음 MediaQuery(TableCalendar)변경 후
                Expanded(
                  child: LayoutBuilder(builder: (ctx, cc) {
                    const dowH = 22.0;
                    final fitRow = weeks > 0
                        ? (cc.maxHeight - dowH - 2) / weeks
                        : calRowHeight;
                    // A는 표격자+텍스트 셀 → 내용 많으면(일정보기) 그 이상 + 스크롤
                    var row = calRowHeight > fitRow ? calRowHeight : fitRow;
                    if (!row.isFinite || row <= 0) row = 80.0;
                    final cal = MediaQuery(
                      data: MediaQuery.of(context)
                          .copyWith(textScaler: TextScaler.noScaling),
                      child: TableCalendar(
                        rowHeight: row,             // (기존 calRowHeight)
                        /* … 기존 파라미터 그대로 … */
                      ),
                    );
                    return row > fitRow
                        ? SingleChildScrollView(child: cal)
                        : cal;
                  }),
                ),

④ 시트가 헤더보다 안 내려가게 — minChildSize·드래그 하한을 collapsedFrac로

calendar_tab.dart · DraggableScrollableSheet / 드래그 핸들변경 후
          DraggableScrollableSheet(
            initialChildSize: sheetInit,
            minChildSize: collapsedFrac,           // (기존 0.06)
            maxChildSize: 0.9, …

          // 드래그 핸들 onVerticalDragUpdate 내부:
          final s = (_sheetCtl.size - d.delta.dy / h).clamp(collapsedFrac, 0.9);
⚠
A 전용 주의 — A는 셀이 표격자+텍스트라 row = max(calRowHeight, fitRow) + 스크롤을 유지합니다. (애플 버전은 셀이 개수 원이라 row = fitRow 순수 채움 — A엔 적용하지 말 것.)
✓

검증 (Windows)

PowerShell / cmd
$env:Path += ";C:\fluttersdk\bin"
flutter analyze        # No issues found! 확인
flutter run            # 안드로이드 기기/에뮬레이터
  • 설정 → 기록 종류 관리에서 일부 항목만 고정(체크).
  • + 신규 → 유형칩 기록 → 빠른 기록 → 고정한 항목만 나오는지 확인.
  • 고정 항목이 하나도 없으면 안내 문구가 뜨는지 확인.
  • 달력: 6주인 달(예: 2026-08)에서 마지막 주(30·31)까지 안 잘리고 폰 크기·5/6주에 맞게 높이가 조절되는지 확인.