diff --git a/Gymly/Settings/FloatingClouds.swift b/Gymly/Settings/FloatingClouds.swift index c925de4..ed117b9 100644 --- a/Gymly/Settings/FloatingClouds.swift +++ b/Gymly/Settings/FloatingClouds.swift @@ -141,6 +141,35 @@ struct CloudsTheme { bottomTrailing: Color(red: 0.3, green: 0.7, blue: 1.0, opacity: 0.75) ) } + + static func premium(_ scheme: ColorScheme) -> CloudsTheme { + CloudsTheme( + // Deep indigo/purple-black background for sophisticated luxury + background: scheme == .dark + ? Color(red: 0.05, green: 0.03, blue: 0.10) // Deep indigo black + : Color(red: 0.08, green: 0.06, blue: 0.12), // Dark purple charcoal + + // Royal purple shimmer - top left + topLeading: scheme == .dark + ? Color(red: 0.45, green: 0.20, blue: 0.75, opacity: 0.80) // Royal purple + : Color(red: 0.50, green: 0.25, blue: 0.70, opacity: 0.70), + + // Deep violet glow - top right + topTrailing: scheme == .dark + ? Color(red: 0.60, green: 0.30, blue: 0.85, opacity: 0.70) // Deep violet + : Color(red: 0.55, green: 0.30, blue: 0.75, opacity: 0.60), + + // Rich plum warmth - bottom left + bottomLeading: scheme == .dark + ? Color(red: 0.35, green: 0.15, blue: 0.55, opacity: 0.65) // Rich plum + : Color(red: 0.40, green: 0.20, blue: 0.55, opacity: 0.55), + + // Lavender/light purple - bottom right + bottomTrailing: scheme == .dark + ? Color(red: 0.65, green: 0.45, blue: 0.90, opacity: 0.75) // Lavender purple + : Color(red: 0.60, green: 0.40, blue: 0.80, opacity: 0.65) + ) + } } class CloudProvider: ObservableObject { diff --git a/Gymly/Settings/NewSettingsView.swift b/Gymly/Settings/NewSettingsView.swift index a8dc52b..c06603f 100644 --- a/Gymly/Settings/NewSettingsView.swift +++ b/Gymly/Settings/NewSettingsView.swift @@ -78,9 +78,7 @@ struct NewSettingsView: View { // Premium Section Section("Premium") { - Button(action: { - // TODO: Show premium upgrade flow - }) { + NavigationLink(destination: PremiumSubscriptionView()) { HStack { Image(systemName: "star.fill") .foregroundColor(.yellow) @@ -93,9 +91,6 @@ struct NewSettingsView: View { .font(.caption) } Spacer() - Image(systemName: "chevron.right") - .foregroundColor(.secondary) - .font(.caption) } } .frame(width: 300) diff --git a/Gymly/Settings/PremiumSubscriptionView.swift b/Gymly/Settings/PremiumSubscriptionView.swift new file mode 100644 index 0000000..bcb8759 --- /dev/null +++ b/Gymly/Settings/PremiumSubscriptionView.swift @@ -0,0 +1,297 @@ +// +// PremiumSubscriptionView.swift +// Gymly +// +// Created by Sebastián Kučera on 20.10.2025. +// + +import SwiftUI + +struct PremiumSubscriptionView: View { + @Environment(\.dismiss) var dismiss + @Environment(\.colorScheme) private var scheme + @State private var selectedPlan: SubscriptionPlan = .monthly + + enum SubscriptionPlan { + case monthly + case yearly + + var price: String { + switch self { + case .monthly: return "2.99€" + case .yearly: return "29.99€" + } + } + + var period: String { + switch self { + case .monthly: return "month" + case .yearly: return "year" + } + } + + var savings: String? { + switch self { + case .monthly: return nil + case .yearly: return "Save 17%" + } + } + } + + var body: some View { + NavigationView { + ZStack { + FloatingClouds(theme: CloudsTheme.premium(scheme)) + .ignoresSafeArea() + + ScrollView { + VStack(spacing: 24) { + // Header + VStack(spacing: 12) { + Image(systemName: "star.fill") + .font(.system(size: 60)) + .foregroundColor(.yellow) + + Text("Gymly Pro") + .font(.largeTitle) + .fontWeight(.bold) + + Text("Unlock your full potential") + .font(.subheadline) + .foregroundStyle(.secondary) + } + .padding(.top, 40) + .padding(.bottom, 20) + + // Features List + VStack(spacing: 16) { + FeatureRow( + icon: "brain.head.profile", + title: "Smart Progression Coach", + description: "AI suggests optimal weight increases" + ) + + FeatureRow( + icon: "trophy.fill", + title: "Automatic PR Tracking", + description: "Never miss a personal record" + ) + + FeatureRow( + icon: "camera.fill", + title: "Progress Photo Timeline", + description: "Track your visual transformation" + ) + + FeatureRow( + icon: "chart.line.uptrend.xyaxis", + title: "Extended Analytics", + description: "Week, month, and all-time graphs" + ) + + FeatureRow( + icon: "apple.intelligence", + title: "AI Workout Summary", + description: "Weekly insights & recommendations" + ) + + FeatureRow( + icon: "book.fill", + title: "Workout Templates", + description: "Pre-built programs for your goals" + ) + + FeatureRow( + icon: "flame.fill", + title: "Advanced Streak Analytics", + description: "Motivation & predictions" + ) + + FeatureRow( + icon: "square.and.arrow.up", + title: "Export Your Data", + description: "CSV/PDF reports anytime" + ) + + FeatureRow( + icon: "calendar", + title: "Unlimited History", + description: "Lifetime workout access" + ) + + FeatureRow( + icon: "paintbrush.fill", + title: "Custom App Appearance", + description: "Choose your theme & colors" + ) + } + .padding(.horizontal, 24) + + // Pricing Plans + VStack(spacing: 12) { + Text("Choose Your Plan") + .font(.headline) + .padding(.top, 20) + + // Monthly Plan + PlanCard( + plan: .monthly, + isSelected: selectedPlan == .monthly + ) { + selectedPlan = .monthly + } + + // Yearly Plan + PlanCard( + plan: .yearly, + isSelected: selectedPlan == .yearly + ) { + selectedPlan = .yearly + } + } + .padding(.horizontal, 24) + + // CTA Button + Button(action: { + // TODO: Implement subscription purchase + print("Starting subscription: \(selectedPlan)") + }) { + VStack(spacing: 8) { + Text("Start 7-Day Free Trial") + .font(.headline) + .foregroundColor(.white) + + Text("Then \(selectedPlan.price)/\(selectedPlan.period)") + .font(.caption) + .foregroundColor(.white.opacity(0.8)) + } + .frame(maxWidth: .infinity) + .padding() + .background(Color.red) + .cornerRadius(12) + } + .padding(.horizontal, 24) + .padding(.top, 8) + + // Fine Print + VStack(spacing: 8) { + Text("Cancel anytime. No commitment.") + .font(.caption) + .foregroundStyle(.secondary) + + HStack(spacing: 16) { + Button("Terms of Service") { + // TODO: Open terms + } + .font(.caption2) + .foregroundStyle(.secondary) + + Button("Privacy Policy") { + // TODO: Open privacy + } + .font(.caption2) + .foregroundStyle(.secondary) + + Button("Restore Purchase") { + // TODO: Restore purchase + } + .font(.caption2) + .foregroundStyle(.secondary) + } + } + .padding(.bottom, 40) + } + } + } + .navigationBarTitleDisplayMode(.inline) + } + } +} + +// MARK: - Feature Row Component +struct FeatureRow: View { + let icon: String + let title: String + let description: String + + var body: some View { + HStack(spacing: 16) { + Image(systemName: icon) + .font(.system(size: 28)) + .foregroundColor(.red) + .frame(width: 40) + + VStack(alignment: .leading, spacing: 4) { + Text(title) + .font(.headline) + .foregroundColor(.primary) + + Text(description) + .font(.caption) + .foregroundStyle(.secondary) + } + + Spacer() + } + .padding(.vertical, 8) + } +} + +// MARK: - Plan Card Component +struct PlanCard: View { + let plan: PremiumSubscriptionView.SubscriptionPlan + let isSelected: Bool + let action: () -> Void + + var body: some View { + Button(action: action) { + HStack { + VStack(alignment: .leading, spacing: 4) { + HStack { + Text(plan.period.capitalized) + .font(.headline) + .foregroundColor(.primary) + + if let savings = plan.savings { + Text(savings) + .font(.caption) + .fontWeight(.semibold) + .foregroundColor(.green) + .padding(.horizontal, 8) + .padding(.vertical, 4) + .background(Color.green.opacity(0.2)) + .cornerRadius(6) + } + } + + Text("\(plan.price)/\(plan.period)") + .font(.title2) + .fontWeight(.bold) + .foregroundColor(.primary) + } + + Spacer() + + if isSelected { + Image(systemName: "checkmark.circle.fill") + .font(.system(size: 24)) + .foregroundColor(.red) + } + } + .padding() + .background( + RoundedRectangle(cornerRadius: 12) + .fill(Color.black.opacity(0.3)) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(isSelected ? Color.red : Color.clear, lineWidth: 2) + ) + ) + } + .buttonStyle(.plain) + } +} + +#Preview { + PremiumSubscriptionView() +}