From 52bd58ac874e64b6a4e35dd2998ac4e8168fe802 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Tue, 26 May 2026 16:04:03 +0900 Subject: [PATCH] =?UTF-8?q?UX=20Phase=202:=20Important=20=E2=80=94=20?= =?UTF-8?q?=EC=9C=84=EA=B3=84/=EC=9D=BC=EA=B4=80=EC=84=B1=20=ED=9A=8C?= =?UTF-8?q?=EB=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 스크린샷에서 발견된 시각 위계/정보 비대칭 4건 fix. 5. Voiding 버튼 fill 격상 (가장 자주 누르는 액션을 primary로) - containerColor: MlPrimary.copy(alpha=0.1f) → MlPrimary 솔리드 - text color: MlPrimary → White - Auto Scan(주황) / Single Scan(청록)과 동급 강도로 일관성 회복 - 환자가 가장 자주 누르는 액션이 옅게 디자인되어 있던 문제 해결 6. InfoCard 우측 라벨 명시 ("Session Max") - 이전: title="X mL / Y mL" + value="65%" (라벨 없음, 의미 모호) - 새로: title="Session Max", value="X" + unit="mL" - 좌측 "Current"와 같은 톤. fill % 정보는 도넛이 이미 시각화 중이라 카드는 raw 숫자만 - 좌측 title도 "Current Measurement" → "Current"로 단순화 7. Alignment Hint 박스 톤다운 (3중 강조 해소) - fontSize 28sp → 20sp - padding horizontal 20→16dp, vertical 18→12dp - 배경 alpha 1.0 → 0.7 - corner 16→14dp - "pubic bone" 빨강 강조는 유지 (의도된 1점 강조) 8. Step 1/3 도트 indicator 추가 (텍스트 한 줄 → 시각 progress) - 이전: 13sp 회색 텍스트 한 줄 (정보 위계 너무 약함) - 새로: 14sp Bold MlPrimary + 3-dot indicator ○ 완료된 step: MlPrimary 0.6 alpha, 8dp ● 현재 step: MlPrimary 솔리드, 12dp (강조) ○ 미완료 step: 회색 0.3 alpha, 8dp Co-Authored-By: Claude Opus 4.7 (1M context) --- .../views/monitoring/PiezoMonitoringView.kt | 19 ++++---- .../ui/views/monitoring/PlacementGuideView.kt | 47 ++++++++++++++----- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt index d24ffd9..7af9bfe 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt @@ -1095,11 +1095,12 @@ fun PiezoMonitoringView(appState: AppState) { // Auto 윈도우 < 5일 때는 표시 안 함 val showMeasurement = if (isAutoMeasuring) autoVolumeWindow.size >= 5 && lastVolumeMl > 0 else lastVolumeMl > 0 val currentMeasurement = if (showMeasurement) "%.0f".format(lastVolumeMl) else "—" - InfoCard("Current Measurement", currentMeasurement, "mL", urgency.accentColor, Modifier.weight(1f)) + InfoCard("Current", currentMeasurement, "mL", urgency.accentColor, Modifier.weight(1f)) + // 우측 카드: title 명시 "Session Max", 값은 maxMeasured (단위 mL). + // 이전엔 title이 "X mL / Y mL"로 들어가고 값에 % 표기되어 의미 모호했음. + // % 정보는 도넛 차트가 이미 시각화 중 → 카드는 raw 숫자만. val maxMeasured = if (displayMaxVolumeMl > 0) "%.0f".format(displayMaxVolumeMl) else "—" - val bladderMax = "${appState.piezoSettings.maxVolume}" - val fillMain = if (fillPct > 0) "${"%.0f".format(fillPct)}%" else "—" - InfoCard("$maxMeasured mL / $bladderMax mL", fillMain, "", urgency.accentColor, Modifier.weight(1f)) + InfoCard("Session Max", maxMeasured, "mL", urgency.accentColor, Modifier.weight(1f)) } // Control buttons: Void/Catheterize / Auto / Spot @@ -1129,12 +1130,14 @@ fun PiezoMonitoringView(appState: AppState) { modifier = Modifier.weight(1f).height(btnHeight), shape = RoundedCornerShape(14.dp), colors = ButtonDefaults.buttonColors( - containerColor = MlPrimary.copy(alpha = 0.1f), - disabledContainerColor = Color.Gray.copy(alpha = 0.1f) + // 환자가 가장 자주 누르는 액션 — Auto/Single과 동일한 fill 강도로 격상. + // MlPrimary 솔리드 (이전: alpha 0.1로 묻혀있던 옅은 파랑) + containerColor = MlPrimary, + disabledContainerColor = Color.Gray.copy(alpha = 0.3f) ) ) { - // 단일 라벨로 단순화 — 이전 2줄(Voiding/Catheterization)이 좁은 폭에서 3줄로 깨짐 - Text("Voiding", fontSize = (14 * fontScale).sp, fontWeight = FontWeight.SemiBold, color = MlPrimary) + Text("Voiding", fontSize = (14 * fontScale).sp, + fontWeight = FontWeight.SemiBold, color = Color.White) } // Auto (Spot 진행 중 봉인) diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt index 7417754..6ae0211 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt @@ -198,19 +198,41 @@ fun PlacementGuideView(appState: AppState) { horizontalAlignment = Alignment.CenterHorizontally ) { // Step indicator + mode badge (이미지 위에 배치) + // Step progress — 텍스트 + 3-dot indicator (현재 단계 강조) Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.padding(vertical = 4.dp) + horizontalArrangement = Arrangement.spacedBy(10.dp), + modifier = Modifier.padding(vertical = 6.dp) ) { + val currentStepIdx = when (placementPhase) { + PlacementPhase.VERTICAL -> 0 + PlacementPhase.LATERAL -> 1 + PlacementPhase.GREEN -> 2 + } Text( - text = when (placementPhase) { - PlacementPhase.VERTICAL -> "Step 1/3" - PlacementPhase.LATERAL -> "Step 2/3" - PlacementPhase.GREEN -> "Step 3/3" - }, - fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlSecondaryText + text = "Step ${currentStepIdx + 1}/3", + fontSize = 14.sp, fontWeight = FontWeight.Bold, color = MlPrimary ) + // 3-dot indicator: 완료(○ → ●), 현재(큰 ●), 미완료(○) + Row(horizontalArrangement = Arrangement.spacedBy(6.dp), + verticalAlignment = Alignment.CenterVertically) { + repeat(3) { i -> + val isDone = i < currentStepIdx + val isCurrent = i == currentStepIdx + val dotSize = if (isCurrent) 12.dp else 8.dp + val dotColor = when { + isCurrent -> MlPrimary + isDone -> MlPrimary.copy(alpha = 0.6f) + else -> Color.Gray.copy(alpha = 0.3f) + } + Box( + modifier = Modifier + .size(dotSize) + .clip(CircleShape) + .background(dotColor) + ) + } + } if (isSweepMode) { Text( "SWEEP", @@ -263,16 +285,19 @@ fun PlacementGuideView(appState: AppState) { append(rawHint) } } + // Hint 톤다운 — 28sp+큰 박스+빨강 강조 3중 중첩이었음. + // 폰트 28→20sp, padding 18→12dp, 박스 alpha 살짝 ↓. + // "pubic bone" 빨강 강조는 유지 (의도된 1점 강조). Text( text = displayHint, - fontSize = 28.sp, + fontSize = 20.sp, fontWeight = FontWeight.SemiBold, color = hintFg, textAlign = TextAlign.Center, modifier = Modifier .fillMaxWidth() - .background(hintBg, RoundedCornerShape(16.dp)) - .padding(horizontal = 20.dp, vertical = 18.dp) + .background(hintBg.copy(alpha = 0.7f), RoundedCornerShape(14.dp)) + .padding(horizontal = 16.dp, vertical = 12.dp) ) // 큰 타이틀과 몸 사이 간격 (Body 상단 Spacer 32→8dp)