Fixes UI iPad + diagnóstico iCloud (build 57)
Feedback del usuario en iPad: - Allocation: gráfica de tarta → semicírculo estilo hemiciclo (parlamento). SemicircleAllocation con arcos dibujados a mano (SemicircleArc Shape), segmentos por cuota en 180°, total/selección en el centro, tap por segmento. - Charts de Analyze (Compare, Period vs Period, Year vs Year) ahora SÍ muestran KPIs en la cabecera de iPad como el resto: Compare (líder/rezagado por modo), Period (retorno final por periodo), YoY (retorno final por año seleccionado). - Momentum & Streaks en el sidebar del Journal (iPad, 320pt): variante compact — tiles en fila sin subtítulos que rompían a 3 líneas, sin bloque de logros. iCloud: - CKErrorPartialFailure (CKErrorDomain code 2) mostraba un mensaje opaco. CoreDataStack.hint(for:) recorre CKPartialErrorsByItemIDKey y clasifica el código dominante → hint accionable (esquema/quota/red). Settings muestra el hint legible sobre el detalle técnico. lastSyncErrorHint publicado. Strings ×7. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoScpmHdVj1aUf4rAp6hbe
This commit is contained in:
@@ -772,6 +772,9 @@ struct MonthlyCheckInCard: View {
|
||||
// MARK: - Momentum & Streaks Card
|
||||
|
||||
struct MomentumStreaksCard: View {
|
||||
/// In narrow containers (the Journal sidebar on iPad) the 3-across stat tiles
|
||||
/// and achievement detail don't fit — stack tiles in a grid and drop detail.
|
||||
var compact = false
|
||||
@State private var stats: MonthlyCheckInStats = .empty
|
||||
|
||||
var body: some View {
|
||||
@@ -791,22 +794,30 @@ struct MomentumStreaksCard: View {
|
||||
}
|
||||
}
|
||||
|
||||
HStack(spacing: 12) {
|
||||
statTile(
|
||||
title: "Streak",
|
||||
value: "\(stats.currentStreak)x",
|
||||
subtitle: "On-time in a row"
|
||||
)
|
||||
statTile(
|
||||
title: "Best",
|
||||
value: "\(stats.bestStreak)x",
|
||||
subtitle: "Personal best"
|
||||
)
|
||||
statTile(
|
||||
title: "Avg early",
|
||||
value: formattedDaysText(for: stats.averageDaysBeforeDeadline),
|
||||
subtitle: "vs deadline"
|
||||
)
|
||||
if compact {
|
||||
HStack(spacing: 8) {
|
||||
compactStatTile(title: "Streak", value: "\(stats.currentStreak)x")
|
||||
compactStatTile(title: "Best", value: "\(stats.bestStreak)x")
|
||||
compactStatTile(title: "Avg early", value: formattedDaysText(for: stats.averageDaysBeforeDeadline))
|
||||
}
|
||||
} else {
|
||||
HStack(spacing: 12) {
|
||||
statTile(
|
||||
title: "Streak",
|
||||
value: "\(stats.currentStreak)x",
|
||||
subtitle: "On-time in a row"
|
||||
)
|
||||
statTile(
|
||||
title: "Best",
|
||||
value: "\(stats.bestStreak)x",
|
||||
subtitle: "Personal best"
|
||||
)
|
||||
statTile(
|
||||
title: "Avg early",
|
||||
value: formattedDaysText(for: stats.averageDaysBeforeDeadline),
|
||||
subtitle: "vs deadline"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ProgressView(value: stats.onTimeRate, total: 1)
|
||||
@@ -839,7 +850,7 @@ struct MomentumStreaksCard: View {
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
if !stats.achievements.isEmpty {
|
||||
if !stats.achievements.isEmpty && !compact {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text(String(localized: "achievements_title"))
|
||||
.font(.subheadline.weight(.semibold))
|
||||
@@ -887,6 +898,25 @@ struct MomentumStreaksCard: View {
|
||||
stats = MonthlyCheckInStore.stats(referenceDate: Date())
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func compactStatTile(title: String, value: String) -> some View {
|
||||
VStack(spacing: 2) {
|
||||
Text(value)
|
||||
.font(.headline)
|
||||
.minimumScaleFactor(0.7)
|
||||
.lineLimit(1)
|
||||
Text(title)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.8)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 10)
|
||||
.background(Color.gray.opacity(0.08))
|
||||
.cornerRadius(AppConstants.UI.smallCornerRadius)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func statTile(title: String, value: String, subtitle: String) -> some View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
|
||||
Reference in New Issue
Block a user