UiDaySummary Props Contract — 하루 운동 종합 조회
화면 픽스처(앱 저장소):
src/react/ui/mobile/fixtures/DaySummaryScreen.fixture.ts
Updated: 2026-06-12 · 2026-07-21 개편(하루 상세 — 종목별 메인세트 요약 + 계획/기록 추가 진입점 이관)
모바일 src/react/ui/mobile/screens/DaySummaryScreen.jsx (window.UiDaySummary). 하루(날짜 1일)의 운동 종합: 합계(종목/세트/볼륨) + 그날 세션 카드 목록(종목·세트 나열) → 세션 상세로 이동. 순수 프레젠테이션 — Supabase/서비스/스토리지 import 금지, 상태는 props만.
ts
type DaySummaryProps = {
date: string; // ISO "2026-06-04"
// (condition prop은 기능 폐기로 제거 — 2026-08-24, 컴포넌트도 수용하지 않음)
// 하이드레이션된 세션 배열 — 완료 세션은 실제 기록(exercises.sets[].done), 계획 세션은 draft 세트
sessions: Array<{
id: string;
status: "completed" | "planned" | "missed";
title: string;
summary?: string;
startTime?: string; endTime?: string; durationMin?: number; // 있으면 카드 헤드에 시간 표기 (2026-07-21)
note?: string; // 완료 세션 리뷰 말풍선
exercises: Array<{ id?: string; name: string; kind?: "note"; note?: string; sets: Array<{ reps: number; load: number; done?: boolean; type?: string }> }>;
// (세션 상세로 그대로 전달 가능한 full 형태 권장 — onOpenSession(s)이 받음)
}>;
setPurposeZones: [number, number, number]; // view mapper가 계산한 [근지구력, 근비대, 스트렝스] 세트 수
today?: string; // ISO — date >= today면 "운동 계획 추가", 과거면 "지난 운동 기록 추가" (2026-07-21)
isWorkoutActive?: boolean; // 진행 중 운동 — 보기모드엔 추가 버튼 미노출
onOpenSession: (s) => void; // 세션 카드 탭 → 세션 상세(UiSessionDetail) 라우팅은 컨테이너 책임
onCreatePlan?: (date) => void; // 계획 추가 (hook addPlanButton · action calendar.plan.add — 일지 화면에서 이관, 2026-07-21)
onAddPastRecord?: (date) => void; // 지난 기록 추가 (hook addPastRecordButton — backfill)
onBack: () => void; // 하단 풀블리드 뒤로가기 바
};동작:
- 합계는 완료(completed) 세션의 done 세트 기준 (종목 수 = done 세트가 있는 종목 수, 볼륨 = Σ load×reps,
kind:"note"자유 기록은 미기여). - 종목 행 = 데스크톱 journalDayMains 문법의 모바일 독립 이식(2026-07-21): "A. 종목명 n세트" + 메인세트 토큰 시퀀스(
80kg×5, 82.5kg×3— done·main 세트, 최고 중량 토큰 볼드, 무중량은n회). 세트가 하나라도 있는 종목은 메인 세트가 0개여도 행을 유지한다(0세트, 토큰 없음 — 웜업만 있는 러닝 등; 데스크톱 journalDayMains도 동일, 2026-08-22). 자유 기록은 제목 + 메모 앞 2줄 미리보기. - 계획/놓침 세션은 카드로만 표시(칩 예정/놓침), 합계 미포함. 카드 헤드에 시간(startTime~endTime) 표기.
- 원 그래프(세트 강도·목적·RPE 도넛)·탑세트 = 주/월 범위 드로어 전용 (2026-08-27, 오너 지시): 모바일 하루 상세는 3항 요약 + 세션 카드만 그린다(
(wk || mo)게이트). 하루 단위 서버 탑세트(체중 태그·유효 무게) 표기는 데스크톱 일지 패널(DkJDayPanel)이 계속 소유한다. - 탑세트 TOP 3 (2026-08-23, 오너 D1 — 표시 표면은 위 2026-08-27 지시로 축소): 서버
summary.topSets(유효 무게 = max(0, 든 무게 × 무게 배수 + 체중 × 체중계수 − 보조 무게) 순위 — 이슈 #1200, 유효 무게 0 제외)를 그대로 표시 — 행 = 유효 kg × 회, 맨몸 세트(bwFactor > 0)는.ld .bw태그 "체중"/"체중+Nkg"(보조 세트는 "체중−Nkg", 서버 행assist_kg→assistKg, 이슈 #1202 Phase 5), 캡션 "유효 무게 기준", KPI "최고 중량 세트" = 1위 유효 kg(topSetKg/topSetBwTag,ui/shared/bodyweightSemantics.ts). 서버 행이 없는 주/월 뷰는 기존 e1RM/1RM 클라 폴백. - 세션 0개 → "이날의 운동 기록이 없어요" 빈 카드.
- 하단: date >= today → "운동 계획 추가", 과거 → "지난 운동 기록 추가" (isWorkoutActive면 둘 다 미노출).
- view 마커
dashboard.day.summary→ 탭바 숨김(다른 상세 화면과 동일), 하단은 뒤로가기 바.
진입 경로 (컨테이너 라우팅)
- 운동 일지(풀스크린 달력): 날짜 셀 탭 →
UiSessionScreen이onSelectDate(iso)+onOpenDaySummary(iso)호출 (2026-07-21 — 세션 유무 무관, 빈 날도 진입). - 홈 주간 출석: 요일 타일 탭(hook
homeAttendanceDay) →UiHomeScreenonOpenDay(dateISO). - 종합에서 세션 카드 탭 → 세션 상세. 상세 뒤로 → 종합으로 복귀(출발지 추적은 컨테이너 책임 — 셸은 origin 저장 패턴 사용).
마커
- 세션 카드: 기존 등록명
session.open재사용. 계획 추가 = 기존addPlanButton/calendar.plan.add, 기록 추가 =addPastRecordButton(일지 화면에서 이관). - 신규 action 마커 0건. 식별용 hook:
daySummaryView/daySummaryBack/homeAttendanceDay.
홈 출석 칸 → 하루 드로어 (2026-07-30)
- HomeScreen 신규 props(선택):
today·selectedDay(iso|null) ·selectedDaySessions·onCloseDay()·isWorkoutActive·onEditPlan/onUpdateSession/onDeleteSession/onDownloadImage(세션 상세 스와프용). - 홈 "이번 주 운동 요약" 요일 칸 탭 =
onOpenDay(date)→ 컨테이너가selectedDay/selectedDaySessions공급 → 홈 위에 일지와 동일한 하루 드로어(hookhomeDaySheet, 신규 — Codex 등록 필요)가 열림. 탭 이동 없음. 드로어 안 세션 탭 = 같은 시트 내용 스와프(UiSessionSheetBody, sessionDetailSheet hook 재사용). - DaySummary 풀스크린 화면은 계약 유지(다른 진입점용).
UiDayDetailBody — 하루/주/월 공용 본문 (2026-08-27 개편)
공용 본문 컴포넌트(ui/mobile/lib/DayDetailBody.tsx)는 일지 하루 오버레이·홈/리포트/피드 하루 드로어·주간/월간 요약이 함께 쓴다. 이번 개편으로 바뀐 계약:
| prop | 타입 | 의미 |
|---|---|---|
dateTitle? | ReactNode | 요약 블록 위에 얹는 날짜 헤더 노드(호출 화면이 그린다 — 일지 오버레이는 YYYY.MM.DD 요일 + 전날/다음날 스텝퍼 한 행). 미공급 = 헤더 없음(드로어). |
stepPrev? / stepNext? | ReactNode | 요약 블록 좌·우에 세로 가운데로 붙는 스텝퍼 노드(선택). 일지 오버레이는 dateTitle 안에 스텝퍼를 두므로 미사용. |
표시 규칙:
- 운동 요약 = 3항 고정: 총 무게 / 운동 시간 / 세트 수(괄호로 총 반복수) — 균등 3열·가운데 정렬. 기록이 없는 날도
0kg / 0분 / 0세트 (0랩)으로 렌더(구 hasDone 게이트 폐기). 구 8항(완료 세션·운동 종목·최고 강도 등)은 삭제. - ⚠ hook
daySummaryExercises소멸 — "운동 종목" 수치가 없어졌다. 계측이 이 훅을 읽으면 Codex 측 정리 필요.daySummaryVolume·daySummarySets는 유지. - 세션 목록 = 세션 단위 카드(
.dsv-scards > .scard): 카드 전체가 세션 상세 진입(role=button·Enter/Space, 마커session.open은 카드 루트) + 헤더 우측 "자세히 ›". 헤더 = 상태 칩 → 세션명 → 시각. 구 타임 레일(.dsv-rail·노드·연결선)은 삭제. - 세트 표기 =
ui/shared/measureSemantics.ts의formatSetRuns축약(100kg 5x3, 묶음 구분 = 쉼표) — 피드·화이트보드와 같은 포매터. 완료·예정·미완·동기화 대기 전 상태가 세트 내용을 노출하며, 완료가 아닌 상태는 페이드(0.62)+그레이 레터로 구분. - 섹션 소제목(번호 배지 + 제목)은 전 섹션에서 삭제.
- 상세 대기 스켈레톤 (2026-08-29, 이슈 #905): 세션 행이
_calendarDetailPending: true(달력 읽기 모델이 하루 모델 도착 전 완료 세션 full에 싣는 플래그 —calendarReadModelMapper.fullForCalendarEntry)를 실으면 카드는 세트 축약(DsvExSum) 대신.dsv-exskel스켈레톤을 그린다: 실제 종목명 행(월 행exercise_ids기반 플레이스홀더, 세트 0개) + 세트열 자리 셔머(.skeleton.sk-seq,.pend-reveal즉시 표시 — 2026-09-10 #1554에서 재방문 시 투명화·지연 제거). 종목을 모르면 이름 자리선(.sk-nm) 1행. 목적 = 하루 상세 첫 진입 시 카드가 최종 높이 근사치로 떠서 내용 도착 시 성장하지 않게. 플래그가 없거나 false면 종전 렌더 그대로.