Primera build enviada

This commit is contained in:
2026-01-19 14:40:43 +01:00
parent c6be398e5a
commit b03d35194f
36 changed files with 1641 additions and 561 deletions
@@ -89,6 +89,9 @@ struct DashboardView: View {
.sheet(isPresented: $showingCustomize) {
DashboardCustomizeView(configs: $sectionConfigs)
}
.sheet(isPresented: $viewModel.showingPaywall) {
PaywallView()
}
}
}
@@ -107,13 +110,13 @@ struct DashboardView: View {
Divider()
ForEach(accountStore.accounts) { account in
ForEach(availableAccounts, id: \.objectID) { account in
Button {
accountStore.selectAccount(account)
} label: {
HStack {
Text(account.name)
if accountStore.selectedAccount?.id == account.id && !accountStore.showAllAccounts {
if accountStore.selectedAccount?.safeId == account.safeId && !accountStore.showAllAccounts {
Image(systemName: "checkmark")
}
}
@@ -124,6 +127,10 @@ struct DashboardView: View {
}
}
private var availableAccounts: [Account] {
accountStore.accounts.filter { $0.safeId != nil }
}
private var visibleSections: [DashboardSectionConfig] {
sectionConfigs.filter { $0.isVisible }
}
@@ -144,7 +151,16 @@ struct DashboardView: View {
changeLabel: calmModeEnabled ? "since last update" : "today",
isPositive: calmModeEnabled
? viewModel.latestPortfolioChange.absolute >= 0
: viewModel.isDayChangePositive
: viewModel.isDayChangePositive,
forecast: viewModel.portfolioForecast,
isPremium: iapService.isPremium,
onUnlockTap: {
viewModel.showingPaywall = true
},
yearChange: viewModel.portfolioSummary.formattedYearChange,
sinceInceptionChange: viewModel.portfolioSummary.formattedAllTimeReturn,
isYearPositive: viewModel.isYearChangePositive,
isSinceInceptionPositive: viewModel.portfolioSummary.allTimeReturn >= 0
)
}
case .monthlyCheckIn:
@@ -243,6 +259,13 @@ struct TotalValueCard: View {
let changeText: String
let changeLabel: String
let isPositive: Bool
var forecast: PortfolioForecast?
var isPremium: Bool = false
var onUnlockTap: (() -> Void)?
var yearChange: String?
var sinceInceptionChange: String?
var isYearPositive: Bool = true
var isSinceInceptionPositive: Bool = true
var body: some View {
VStack(spacing: 8) {
@@ -264,6 +287,77 @@ struct TotalValueCard: View {
.foregroundColor(.white.opacity(0.8))
}
.foregroundColor(.white)
// YoY and Since Inception returns
if yearChange != nil || sinceInceptionChange != nil {
HStack(spacing: 16) {
if let yearChange = yearChange {
VStack(spacing: 2) {
Text("YoY")
.font(.caption2)
.foregroundColor(.white.opacity(0.7))
Text(yearChange)
.font(.caption.weight(.semibold))
.foregroundColor(.white)
}
}
if let sinceInceptionChange = sinceInceptionChange {
VStack(spacing: 2) {
Text("Since inception")
.font(.caption2)
.foregroundColor(.white.opacity(0.7))
Text(sinceInceptionChange)
.font(.caption.weight(.semibold))
.foregroundColor(.white)
}
}
}
.padding(.top, 4)
}
// Forecast section
if let forecast = forecast {
Divider()
.background(Color.white.opacity(0.3))
.padding(.vertical, 8)
if isPremium {
VStack(spacing: 4) {
HStack(spacing: 4) {
Image(systemName: "wand.and.stars")
.font(.caption)
Text("12-month forecast")
.font(.caption)
}
.foregroundColor(.white.opacity(0.85))
Text(forecast.formattedForecastValue)
.font(.title2.weight(.bold))
.foregroundColor(.white)
Text(forecast.formattedGrowthPercentage)
.font(.caption.weight(.semibold))
.foregroundColor(forecast.isPositiveGrowth ? .white : .white.opacity(0.8))
}
} else {
Button {
onUnlockTap?()
} label: {
HStack(spacing: 6) {
Image(systemName: "lock.fill")
.font(.caption)
Text("Unlock 12-month forecast")
.font(.caption.weight(.semibold))
}
.foregroundColor(.white)
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(Color.white.opacity(0.2))
.cornerRadius(16)
}
}
}
}
.frame(maxWidth: .infinity)
.padding(.vertical, 24)