From e21c34fdc3d0d04bc228fe5d9f9c84dc9f11fcb5 Mon Sep 17 00:00:00 2001 From: Beingpax Date: Wed, 29 Oct 2025 20:52:09 +0545 Subject: [PATCH] Added promotional cards --- .../Metrics/DashboardPromotionsSection.swift | 57 +++++++------------ VoiceInk/Views/Metrics/MetricsContent.swift | 5 +- VoiceInk/Views/MetricsView.swift | 10 +++- 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/VoiceInk/Views/Metrics/DashboardPromotionsSection.swift b/VoiceInk/Views/Metrics/DashboardPromotionsSection.swift index fa15e43..39ee886 100644 --- a/VoiceInk/Views/Metrics/DashboardPromotionsSection.swift +++ b/VoiceInk/Views/Metrics/DashboardPromotionsSection.swift @@ -5,8 +5,14 @@ struct DashboardPromotionsSection: View { let licenseState: LicenseViewModel.LicenseState private var shouldShowUpgradePromotion: Bool { - guard case .trial(let daysRemaining) = licenseState else { return false } - return daysRemaining <= 9 + switch licenseState { + case .trial(let daysRemaining): + return daysRemaining <= 2 + case .trialExpired: + return true + case .licensed: + return false + } } private var shouldShowAffiliatePromotion: Bool { @@ -26,16 +32,8 @@ struct DashboardPromotionsSection: View { if shouldShowUpgradePromotion { DashboardPromotionCard( badge: "30% OFF", - title: "Share VoiceInk, Save 30%", - message: "Tell your audience about VoiceInk on social and unlock a 30% discount on VoiceInk Pro when they upgrade.", - gradient: LinearGradient( - colors: [ - Color(red: 0.08, green: 0.48, blue: 0.85), - Color(red: 0.05, green: 0.18, blue: 0.42) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ), + title: "Unlock VoiceInk Pro For Less", + message: "Share VoiceInk on your socials, and instantly unlock a 30% discount on VoiceInk Pro.", accentSymbol: "megaphone.fill", glowColor: Color(red: 0.08, green: 0.48, blue: 0.85), actionTitle: "Share & Unlock", @@ -50,14 +48,6 @@ struct DashboardPromotionsSection: View { badge: "AFFILIATE 30%", title: "Earn With The VoiceInk Affiliate Program", message: "Share VoiceInk with friends or your audience and receive 30% on every referral that upgrades.", - gradient: LinearGradient( - colors: [ - Color(red: 0.08, green: 0.48, blue: 0.85), - Color(red: 0.05, green: 0.18, blue: 0.42) - ], - startPoint: .topLeading, - endPoint: .bottomTrailing - ), accentSymbol: "link.badge.plus", glowColor: Color(red: 0.08, green: 0.48, blue: 0.85), actionTitle: "Explore Affiliate", @@ -90,12 +80,20 @@ private struct DashboardPromotionCard: View { let badge: String let title: String let message: String - let gradient: LinearGradient let accentSymbol: String let glowColor: Color let actionTitle: String let actionIcon: String let action: () -> Void + + private static let defaultGradient: LinearGradient = LinearGradient( + colors: [ + Color(red: 0.08, green: 0.48, blue: 0.85), + Color(red: 0.05, green: 0.18, blue: 0.42) + ], + startPoint: .topLeading, + endPoint: .bottomTrailing + ) var body: some View { VStack(alignment: .leading, spacing: 18) { @@ -147,26 +145,13 @@ private struct DashboardPromotionCard: View { .frame(maxWidth: .infinity, minHeight: 200, alignment: .topLeading) .background( RoundedRectangle(cornerRadius: 28, style: .continuous) - .fill(gradient) - .overlay { - ZStack { - Circle() - .fill(.white.opacity(0.12)) - .frame(width: 140, height: 140) - .offset(x: 60, y: -60) - Circle() - .strokeBorder(.white.opacity(0.15), lineWidth: 1) - .frame(width: 170, height: 170) - .offset(x: -40, y: 70) - } - .clipped() - } + .fill(Self.defaultGradient) ) .clipShape(RoundedRectangle(cornerRadius: 28, style: .continuous)) .overlay( RoundedRectangle(cornerRadius: 28, style: .continuous) .stroke(.white.opacity(0.08), lineWidth: 1) ) - .shadow(color: glowColor.opacity(0.28), radius: 24, x: 0, y: 14) + .shadow(color: glowColor.opacity(0.15), radius: 12, x: 0, y: 8) } } diff --git a/VoiceInk/Views/Metrics/MetricsContent.swift b/VoiceInk/Views/Metrics/MetricsContent.swift index 81d776e..a01db40 100644 --- a/VoiceInk/Views/Metrics/MetricsContent.swift +++ b/VoiceInk/Views/Metrics/MetricsContent.swift @@ -2,6 +2,7 @@ import SwiftUI struct MetricsContent: View { let transcriptions: [Transcription] + let licenseState: LicenseViewModel.LicenseState var body: some View { Group { @@ -12,7 +13,7 @@ struct MetricsContent: View { VStack(spacing: 24) { heroSection metricsSection - DashboardPromotionsSection() + DashboardPromotionsSection(licenseState: licenseState) } .padding(.vertical, 28) .padding(.horizontal, 32) @@ -241,7 +242,7 @@ private enum Formatters { static func formattedDuration(_ interval: TimeInterval, style: DateComponentsFormatter.UnitsStyle, fallback: String = "–") -> String { guard interval > 0 else { return fallback } durationFormatter.unitsStyle = style - durationFormatter.allowedUnits = interval >= 3600 ? [.hour, .minute] : [.second] + durationFormatter.allowedUnits = interval >= 3600 ? [.hour, .minute] : [.minute, .second] return durationFormatter.string(from: interval) ?? fallback } } diff --git a/VoiceInk/Views/MetricsView.swift b/VoiceInk/Views/MetricsView.swift index 85a6be0..b2b92a6 100644 --- a/VoiceInk/Views/MetricsView.swift +++ b/VoiceInk/Views/MetricsView.swift @@ -51,9 +51,15 @@ struct MetricsView: View { Group { if skipSetupCheck { - MetricsContent(transcriptions: Array(transcriptions)) + MetricsContent( + transcriptions: Array(transcriptions), + licenseState: licenseViewModel.licenseState + ) } else if isSetupComplete { - MetricsContent(transcriptions: Array(transcriptions)) + MetricsContent( + transcriptions: Array(transcriptions), + licenseState: licenseViewModel.licenseState + ) } else { MetricsSetupView() }