| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- import SwiftUI
- struct PremiumFeaturesView: View {
- enum PlanOption: String {
- case perpetual
- case yearly
- }
- @Environment(\.dismiss) private var dismiss
- @State private var selectedPlan: PlanOption = .perpetual
- @State private var showingCheckout = false
- @State private var showingSuccessAlert = false
- private let featureRows: [(String, String)] = [
- ("Desktop Widgets", "Add frequently used apps as desktop widgets"),
- ("Custom web Apps", "Manage personalized applications"),
- ("Hotkey", "Quickly launch specific apps by setting shortcuts"),
- ("Status Bar Shortcuts", "Add app quick-access to status bar"),
- ("Desktop Shortcuts", "Create one-click app shortcuts on desktop"),
- ("Quick Search", "Search directly on Google without opening browser"),
- ("Ad Blocker", "Intelligently blocks ads and pop-ups for better browsing"),
- ("Auto Startup", "Launch automatically with system"),
- ("App Pin", "Keep app windows always on top"),
- ("Family Sharing", "One purchase for the whole family to share"),
- ]
- private let cardColors: [Color] = [
- .blue, .purple, .red, .green, .orange,
- .indigo, .pink, .cyan, .gray, .mint,
- ]
- var body: some View {
- ZStack {
- LinearGradient(
- colors: [Color.black.opacity(0.9), Color(red: 0.08, green: 0.1, blue: 0.14)],
- startPoint: .topLeading,
- endPoint: .bottomTrailing
- )
- .ignoresSafeArea()
- Rectangle()
- .fill(
- RadialGradient(
- colors: [Color.blue.opacity(0.25), .clear],
- center: .bottomTrailing,
- startRadius: 40,
- endRadius: 380
- )
- )
- .ignoresSafeArea()
- ScrollView {
- VStack(alignment: .leading, spacing: 14) {
- HStack {
- Button(action: { dismiss() }) {
- Image(systemName: "xmark")
- .font(.system(size: 13, weight: .semibold))
- .foregroundStyle(.white.opacity(0.88))
- }
- .buttonStyle(.plain)
- Spacer()
- Text("Restore")
- .font(.system(size: 11, weight: .semibold))
- .foregroundStyle(.white.opacity(0.9))
- .padding(.horizontal, 8)
- .padding(.vertical, 3)
- .background(
- RoundedRectangle(cornerRadius: 7, style: .continuous)
- .fill(Color.white.opacity(0.16))
- )
- }
- Text("Upgrade to unlock all\nPremium Features")
- .font(.system(size: 20, weight: .bold))
- .foregroundStyle(.white)
- .lineSpacing(1)
- LazyVGrid(
- columns: [GridItem(.flexible(), spacing: 10), GridItem(.flexible(), spacing: 10)],
- spacing: 10
- ) {
- ForEach(Array(featureRows.enumerated()), id: \.offset) { index, feature in
- featureCard(title: feature.0, subtitle: feature.1, color: cardColors[index % cardColors.count])
- }
- }
- priceCard(
- title: "Perpetual",
- price: "Rs 9,900.00",
- subtitle: "Own the software for lifetime",
- badgeText: "One-time payment",
- isSelected: selectedPlan == .perpetual
- )
- .onTapGesture {
- selectedPlan = .perpetual
- }
- priceCard(
- title: "Yearly",
- price: "Rs 7,900.00/year",
- subtitle: "Rs 658.33/mo",
- badgeText: nil,
- isSelected: selectedPlan == .yearly
- )
- .onTapGesture {
- selectedPlan = .yearly
- }
- Button(action: { showingCheckout = true }) {
- Text("Continue")
- .font(.system(size: 16, weight: .bold))
- .foregroundStyle(.white)
- .frame(maxWidth: .infinity)
- .padding(.vertical, 12)
- .background(
- RoundedRectangle(cornerRadius: 16, style: .continuous)
- .fill(Color.blue.opacity(0.9))
- )
- }
- .buttonStyle(.plain)
- .padding(.top, 6)
- HStack {
- Spacer()
- Text("Privacy Policy")
- .font(.system(size: 11, weight: .medium))
- .foregroundStyle(.white.opacity(0.7))
- Spacer()
- Text("Terms of Service")
- .font(.system(size: 11, weight: .medium))
- .foregroundStyle(.white.opacity(0.7))
- Spacer()
- }
- .padding(.top, 2)
- }
- .padding(16)
- }
- }
- .sheet(isPresented: $showingCheckout) {
- PaymentCheckoutView(
- selectedPlan: selectedPlan,
- onCancel: { showingCheckout = false },
- onConfirm: {
- showingCheckout = false
- showingSuccessAlert = true
- }
- )
- .frame(minWidth: 500, minHeight: 520)
- }
- .alert("Payment Successful", isPresented: $showingSuccessAlert) {
- Button("Done") { dismiss() }
- } message: {
- Text("Your \(selectedPlan == .perpetual ? "Perpetual" : "Yearly") plan has been activated.")
- }
- }
- private func featureCard(title: String, subtitle: String, color: Color) -> some View {
- HStack(alignment: .top, spacing: 10) {
- Circle()
- .fill(color.opacity(0.95))
- .frame(width: 28, height: 28)
- .overlay(
- Image(systemName: "sparkles")
- .font(.system(size: 11, weight: .semibold))
- .foregroundStyle(.white)
- )
- VStack(alignment: .leading, spacing: 3) {
- Text(title)
- .font(.system(size: 11.5, weight: .bold))
- .foregroundStyle(.white)
- .lineLimit(1)
- Text(subtitle)
- .font(.system(size: 9.5, weight: .medium))
- .foregroundStyle(.white.opacity(0.85))
- .lineLimit(2)
- }
- Spacer(minLength: 0)
- }
- .padding(10)
- .frame(maxWidth: .infinity, minHeight: 66, alignment: .leading)
- .background(
- RoundedRectangle(cornerRadius: 12, style: .continuous)
- .fill(Color.white.opacity(0.14))
- )
- }
- private func priceCard(title: String, price: String, subtitle: String, badgeText: String?, isSelected: Bool) -> some View {
- HStack(alignment: .center) {
- VStack(alignment: .leading, spacing: 5) {
- Text(title)
- .font(.system(size: 12, weight: .bold))
- .foregroundStyle(.white)
- Text(subtitle)
- .font(.system(size: 7.5, weight: .medium))
- .foregroundStyle(.white.opacity(0.72))
- }
- Spacer()
- VStack(alignment: .trailing, spacing: 7) {
- Text(price)
- .font(.system(size: 10, weight: .bold))
- .foregroundStyle(.white)
- .minimumScaleFactor(0.7)
- .lineLimit(1)
- if let badgeText {
- Text(badgeText)
- .font(.system(size: 7.5, weight: .bold))
- .foregroundStyle(.white)
- .padding(.horizontal, 8)
- .padding(.vertical, 4)
- .background(
- RoundedRectangle(cornerRadius: 7, style: .continuous)
- .fill(Color.blue.opacity(0.95))
- )
- }
- }
- }
- .padding(10)
- .background(
- RoundedRectangle(cornerRadius: 14, style: .continuous)
- .stroke(isSelected ? Color.blue.opacity(0.95) : Color.white.opacity(0.4), lineWidth: isSelected ? 2 : 1.5)
- .background(
- RoundedRectangle(cornerRadius: 14, style: .continuous)
- .fill(isSelected ? Color.blue.opacity(0.12) : Color.white.opacity(0.05))
- )
- )
- .contentShape(RoundedRectangle(cornerRadius: 14, style: .continuous))
- }
- }
- private struct PaymentCheckoutView: View {
- let selectedPlan: PremiumFeaturesView.PlanOption
- let onCancel: () -> Void
- let onConfirm: () -> Void
- @State private var cardholderName = ""
- @State private var cardNumber = ""
- @State private var expiry = ""
- @State private var cvv = ""
- @State private var saveCard = true
- private var amountText: String {
- switch selectedPlan {
- case .perpetual:
- return "Rs 9,900.00"
- case .yearly:
- return "Rs 7,900.00/year"
- }
- }
- private var canSubmit: Bool {
- !cardholderName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
- cardNumber.filter(\.isNumber).count >= 12 &&
- expiry.count >= 4 &&
- cvv.filter(\.isNumber).count >= 3
- }
- var body: some View {
- ZStack {
- LinearGradient(
- colors: [Color.black.opacity(0.95), Color(red: 0.09, green: 0.11, blue: 0.16)],
- startPoint: .topLeading,
- endPoint: .bottomTrailing
- )
- .ignoresSafeArea()
- VStack(alignment: .leading, spacing: 16) {
- HStack {
- Text("Add Credit Card")
- .font(.system(size: 22, weight: .bold))
- .foregroundStyle(.white)
- Spacer()
- Button("Cancel", action: onCancel)
- .buttonStyle(.plain)
- .foregroundStyle(.white.opacity(0.8))
- }
- Text("Selected plan: \(selectedPlan == .perpetual ? "Perpetual" : "Yearly")")
- .font(.system(size: 13, weight: .medium))
- .foregroundStyle(.white.opacity(0.8))
- VStack(spacing: 12) {
- checkoutField(title: "Cardholder Name", text: $cardholderName, placeholder: "Name on card")
- checkoutField(title: "Card Number", text: $cardNumber, placeholder: "1234 5678 9012 3456")
- HStack(spacing: 12) {
- checkoutField(title: "Expiry (MM/YY)", text: $expiry, placeholder: "08/28")
- checkoutField(title: "CVV", text: $cvv, placeholder: "123")
- }
- }
- Toggle("Save card for future purchases", isOn: $saveCard)
- .toggleStyle(.checkbox)
- .foregroundStyle(.white.opacity(0.88))
- HStack {
- Text("Total")
- .foregroundStyle(.white.opacity(0.85))
- Spacer()
- Text(amountText)
- .font(.system(size: 15, weight: .bold))
- .foregroundStyle(.white)
- }
- .padding(12)
- .background(
- RoundedRectangle(cornerRadius: 10, style: .continuous)
- .fill(Color.white.opacity(0.08))
- )
- Button(action: onConfirm) {
- Text("Pay \(amountText)")
- .font(.system(size: 15, weight: .bold))
- .foregroundStyle(.white)
- .frame(maxWidth: .infinity)
- .padding(.vertical, 12)
- .background(
- RoundedRectangle(cornerRadius: 12, style: .continuous)
- .fill(canSubmit ? Color.blue.opacity(0.95) : Color.gray.opacity(0.6))
- )
- }
- .buttonStyle(.plain)
- .disabled(!canSubmit)
- Spacer(minLength: 0)
- }
- .padding(20)
- }
- }
- private func checkoutField(title: String, text: Binding<String>, placeholder: String) -> some View {
- VStack(alignment: .leading, spacing: 6) {
- Text(title)
- .font(.system(size: 12, weight: .semibold))
- .foregroundStyle(.white.opacity(0.85))
- TextField(placeholder, text: text)
- .textFieldStyle(.plain)
- .foregroundStyle(.white)
- .padding(.horizontal, 10)
- .padding(.vertical, 9)
- .background(
- RoundedRectangle(cornerRadius: 10, style: .continuous)
- .fill(Color.white.opacity(0.1))
- )
- .overlay(
- RoundedRectangle(cornerRadius: 10, style: .continuous)
- .stroke(Color.white.opacity(0.13), lineWidth: 1)
- )
- }
- }
- }
- #Preview {
- PremiumFeaturesView()
- .frame(width: 560, height: 690)
- }
|