Files
InvestmentTrackerApp/PortfolioJournal/Views/Components/ProgressRing.swift
T
alexandrev-tibco ed737bc290 Calm 2.0 Fase 3: Home iPad columna única, Goals con anillos, Journal timeline, Sources polish (build 53)
Home iPad/Mac (feedback del usuario: 'me gusta más el iPhone'):
- Fuera el grid de 2 columnas (acoplaba alturas de fila y dejaba huecos entre
  cards de tamaños distintos) → columna única centrada a 720pt, patrón
  Things/Day One. Eliminado el drag-drop del grid, columnSpan y el overlay
  full-screen (~120 líneas); el orden/visibilidad sigue en Customize.

Goals:
- ProgressRing nuevo (anillo estilo Fitness con porcentaje centrado y color
  semántico: verde=logrado, ámbar=retrasado, acento=en camino) en GoalRowView
  y en la card de Goals del Home. GoalProgressBar queda solo en la share card.

Journal:
- Momentum & Streaks vive ahora en la cabecera del Journal (la historia del
  hábito es narrativa, no dashboard).
- Filas timeline: círculo de mood como ancla visual (tint semántico por mood),
  mes + estrellas + preview de nota.

Sources:
- Badge 'Needs update' como chip ámbar visible; valor en tipografía rounded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WoScpmHdVj1aUf4rAp6hbe
2026-07-09 11:11:04 +02:00

31 lines
1.1 KiB
Swift

import SwiftUI
/// Fitness-style progress ring: track + rounded-cap arc + centered percentage.
/// Color is semantic (pace/achievement), passed by the caller.
struct ProgressRing: View {
let progress: Double
var tint: Color = .appPrimary
var size: CGFloat = 56
var lineWidth: CGFloat = 6
private var clamped: Double { min(max(progress, 0), 1) }
var body: some View {
ZStack {
Circle()
.stroke(tint.opacity(0.15), lineWidth: lineWidth)
Circle()
.trim(from: 0, to: clamped)
.stroke(tint, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
.rotationEffect(.degrees(-90))
.animation(.easeOut(duration: 0.6), value: clamped)
Text("\(Int((clamped * 100).rounded()))%")
.font(.system(size: size * 0.26, weight: .bold, design: .rounded))
.foregroundColor(tint)
.minimumScaleFactor(0.7)
}
.frame(width: size, height: size)
.accessibilityLabel(Text("\(Int((clamped * 100).rounded()))%"))
}
}