1.5.0: aviso de huecos + resumen mensual compartible + import con vista previa
Feature 1 — Aviso de huecos: SnapshotGapDetector detecta huecos internos por source (meses sin datos entre dos snapshots). Banner desechable en Dashboard + DataGapsSheet para rellenar (abre AddSnapshotView con el mes que falta). Complementa la interpolación de gráficas: la línea se ve suave pero el usuario sabe que faltan datos reales. Feature 2 — Resumen mensual compartible: MonthlySummaryShareView (tarjeta con marca: valor, variación desde el check-in, racha, mood/rating) renderizada con ImageRenderer y compartida vía ShareService. Botón en la fila "check-in done" del Dashboard. Feature 3 — Import con vista previa: ImportPreview + previewImportAsync (dry-run READ-ONLY, no muta nada) cuenta qué se creará/actualizará usando los mismos checks de existencia que applyImport. ImportDataView muestra la confirmación antes de importar. El path real de import (applyImport/importDataAsync) NO se toca. Localización en los 7 idiomas. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L2p3gUZRNWW388rWFRjiU7
This commit is contained in:
@@ -62,6 +62,56 @@ class ShareService {
|
||||
}
|
||||
}
|
||||
|
||||
struct MonthlySummaryShareData {
|
||||
let monthLabel: String
|
||||
let totalValue: String
|
||||
let changeAmount: String
|
||||
let changePercentage: String
|
||||
let isPositive: Bool
|
||||
let streak: Int
|
||||
let mood: MonthlyCheckInMood?
|
||||
let rating: Int?
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func shareMonthlySummary(_ data: MonthlySummaryShareData) {
|
||||
FirebaseService.shared.logShare(type: "monthly_summary")
|
||||
let appName = Self.appDisplayName
|
||||
|
||||
var lines = [
|
||||
"\(data.monthLabel) — Monthly Summary",
|
||||
"Portfolio Value: \(data.totalValue)",
|
||||
"\(data.changeAmount) (\(data.changePercentage)) since last check-in"
|
||||
]
|
||||
if data.streak >= 2 {
|
||||
lines.append("Streak: \(data.streak) months")
|
||||
}
|
||||
if let mood = data.mood {
|
||||
lines.append("Mood: \(mood.title)")
|
||||
}
|
||||
lines.append("")
|
||||
lines.append("Tracked with \(appName)")
|
||||
let fallbackText = lines.joined(separator: "\n")
|
||||
|
||||
shareCard(
|
||||
cardTitle: "\(data.monthLabel) — Monthly Summary",
|
||||
fallbackText: fallbackText
|
||||
) {
|
||||
MonthlySummaryShareView(
|
||||
monthLabel: data.monthLabel,
|
||||
totalValue: data.totalValue,
|
||||
changeAmount: data.changeAmount,
|
||||
changePercentage: data.changePercentage,
|
||||
isPositive: data.isPositive,
|
||||
streak: data.streak,
|
||||
mood: data.mood,
|
||||
rating: data.rating,
|
||||
appName: appName,
|
||||
qrCodeImage: GoalShareService.generateQRCode(for: GoalShareService.appStoreURL, size: 200)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func sharePortfolioValue(
|
||||
totalValue: String,
|
||||
|
||||
Reference in New Issue
Block a user