Skip to content

데스크톱 유산소 세트 시간 입력 — 초 단일에서 [분]:[초] 분리 입력과 분|초 토글까지 (2026-08-27)

  • 기간: 2026-08-27 (1세션, 오너 지시 원문: "데스크톱에서 유산소 입력할때 지금 초단위 밖에 없는데 시간입력할때, 그거 분단위로도 입력할 수 있게 해줘. 포맷은 모바일이랑 똑같게 (코드 복사하지말고 참고만)")
  • 랜딩: PR #866(d78b6c75) — 마이그레이션 없음, Vercel 자동 배포
  • 설계서: 없음(소건) — Phase 계획서·예상 효과 표는 이슈 #864 본문
  • 정본: src/react/ui/desktop/screens/DesktopPlanEditorCardParts.tsx DkpMinSecInput([분]:[초]) · 카드 로컬 상태 durMode(분|초) · 확정 뷰 시간 표기 formatDurationSeconds(measureSemantics 공용)
  • 도구: 없음
  • 게이트: tests/react/desktopPlanEditorMinSecDuration.test.mjs(회귀 6건)
  • 버그리포트: 없음(기능 건)
  • 계약: 변경 없음 — durationSeconds(초)가 저장 정본 그대로, 마커 workout.set.duration 래퍼 유지(designContract 레지스트리 무변)

Phase 현황

Phase내용상태
Phase 1[분]:[초] 입력 + 분초 토글 + 확정 뷰 mm:ss·in (DkpExCard)
Phase 2게이트 — 신규 회귀 6건 + 기존 done 뷰 단언 갱신, CI verify✅ PR #866 동반
Phase 3머지·Vercel 배포 확인·작업 기록 등록 2곳✅ 이 문서

1. 배경

모바일은 이슈 #788(2026-08-25)로 유산소 세트 시간 입력이 [분]:[초] 콜론 고정 분리 입력·분|초 토글로 바뀌었지만, 데스크톱 계획·기록 편집기(DkpExCard)는 초 단일 필드 그대로였다 — 당시 작업 기록에 "데스크톱 계획 편집기 시간·거리 입력은 단일 필드 그대로 — 별도 트랙"으로 예고된 잔여. 오너가 2026-08-27 데스크톱에도 분 단위 입력을 지시했다(이슈 #864).

2. 문제 제기

같은 값을 두 표면이 다른 단위로 받았다

20분 러닝을 데스크톱에서 기록하려면 여전히 "1200"을 암산해야 했다. 표시(세션 상세 "400m in 1:01.24")는 이미 mm:ss·in인데 입력과 확정 뷰("1830초", "400m × 61.24초")만 초 단일이라, 입력· 확정·상세 세 표기가 서로 달랐다.

3. 해결 방안

원칙 (오너 지시, 2026-08-27)

"포맷은 모바일이랑 똑같게, 코드 복사하지 말고 참고만" — 모바일 WfMinSecInput의 UX 규칙 (콜론 고정·자동 0 없음·탭 전체 선택·blur 정규화·데이터 추론 기본값)을 그대로 가져오되, 구현은 데스크톱 문법(dkp 계열·dk-input/dk-setmode 시각 문법)으로 새로 쓴다.

접근

대안판단
데스크톱판 재구현 + 분|초 세그 + 데이터 추론 기본값채택 — 모바일 UX 규칙 동일, 레이어 경계(모바일 스크린 import 금지) 유지
모바일 WfMinSecInput 직접 import기각 — 오너 지시("복사 말고 참고")·모바일 스크린 → 데스크톱 스크린 레이어 위반
공용 컴포넌트로 승격 후 양쪽 사용기각 — 시각 문법(spv-field vs dk-input)이 달라 승격 이득이 없고 이번 지시 범위 초과

4. 적용한 내용

Phase 1 — [분]:[초] 입력 + 분|초 토글 + 확정 뷰 정합 (#866)

  • DkpMinSecInput: 고정 콜론 양쪽 분·초 분리 입력. 합성값은 기존 patchSet(durationSeconds) 경로 그대로, 초 0–59 클램프·2자리 패딩·소수점 보존, 자동 0 채움 없음(0·빈 값은 빈 칸), 탭=전체 선택, blur=저장값 기준 정규 표기, 외부 값 변경(세트 복제 등)은 마지막 발행값 불일치로 재파생 — 모바일과 같은 드래프트 보유 규칙.
  • 편집 옵션 "시간 단위" 행(분|초 세그): duration 기록 필드가 있을 때만 노출("옵션 행은 기록 필드를 따라간다", #788 Phase 3 원칙). 기본값 = 해당 종목 세트에 60초 이상 기록 보유 시 분(모바일 durOv 데이터 추론과 동일 — UI no-storage 계약에서 사실상 지속성).
  • 확정(done) 뷰: "1830초" → "30:30"(formatDurationSeconds, 60초 미만은 "N초" 유지), 거리→시간 구분자 × → in — 세트 행·세션 상세 표시 정본과 동일 표기로 정합 교정.
  • CSS .dk-minsec: dk-input 시각 문법(1px line-2·r-sm·13px/600) 재사용, 분 우측·초 좌측 정렬로 콜론에 붙는 타이머 표기, focus-within 악센트 링·err 변형.

주요 결정과 그 근거

  • 재구현이지 공용화가 아니다: 데스크톱 카드의 입력 시각 문법(dk-input 테두리 박스)과 모바일 컴포저(spv-field)가 달라, 억지로 공용화하면 양쪽에 조건 분기만 는다. UX 규칙(헬퍼 산식·클램프· 드래프트 규칙)만 동일하게 맞췄다.
  • 확정 뷰까지 같은 PR: 입력만 분:초로 바꾸면 "30:30 입력 → 확정 1830초"로 입력·확정 표기가 어긋난다 — #788이 표시행까지 in을 일반화한 것과 같은 이유로 확정 뷰를 표시 정본에 붙였다.

작업 중 드러난 것

  • inputFields는 복합 세트에서 ["load","reps"] as const 튜플이라 includes("duration")이 TS2345로 떨어진다 — 기존 관용구 (x as readonly string[]).includes(...)로 통일(dkpToggleRecordingField 전례).
  • 브라우저 팬의 file:// 정적 스냅샷은 CSP로 외부 CSS·스크린샷이 막힌다 — 시각 실측은 워크트리 vite(launch.json cmd /c cd /d <wt> 패턴) + 실 CSS·SSR 실마크업 프로브 페이지가 정본 절차.

5. 적용 결과

항목결과
20분 입력(데스크톱)"1200" 환산 암산 → 분 칸 "20"(초 칸 빈 칸 유지 가능)
기존 기록(1830초) 재편집 표기1830 단일 → [30]:[30], 탭하면 해당 칸 전체 선택
빈 값·0 표기두 칸 모두 빈 칸(자동 0 없음)
확정 뷰"5000m × 1830초" → "5000m in 30:30" (60초 미만 "45초" 유지)
60초 미만 기록만 있는 종목기본 초 모드 유지(세그로 전환 가능) — 회귀 가드
저장값·통계·마커변경 없음(durationSeconds 초 정본·workout.set.duration 래퍼 유지)
게이트신규 6건 + react 전량 1808건·tsc 0건·utf8·dead-css·test-manifest 로컬 통과, CI verify 통과
기하 실측(실 CSS+SSR, 로컬 vite)minsec 박스 31px = 기존 dk-input 31px, 가로 오버플로 0
Vercel 배포success 실측 — d78b6c75 커밋 상태 success(barbelic·barbelic-docs) + Production 청크 실측(desktopRoot-*.css.dk-minsec 규칙, DesktopSessionScreen-*.js에 시간 단위 세그·minsec 마크업)
실기기(오너) 확인오너 실화면 확인 완료(2026-08-27) — "오케이 확인했음", 세션 종결

6. 이번 개선으로 향상된 것

유산소 시간 입력 포맷이 모바일·데스크톱에서 같아졌다

입력([분]:[초])·확정(mm:ss·in)·상세(mm:ss·in) 세 표기가 한 정본으로 정렬 — 환산 암산 제거.

구조적으로 남는 것

  • DkpMinSecInput — durationSeconds를 편집하는 데스크톱 표면의 단위 입력 정본.
  • "옵션 행은 기록 필드를 따라간다" 원칙의 데스크톱 확장(시간 단위 행).
  • desktopPlanEditorMinSecDuration.test.mjs — 분/초 두 모드 + 확정 뷰 포맷의 마크업 회귀 가드.

남은 것

  • 종결 — 오너 실화면 확인(2026-08-27), 이슈 #864 닫음.
  • 데스크톱 거리 km|m 토글 — 범위 제외(이슈 #864 본문), 필요 시 별도 트랙.