summaryrefslogtreecommitdiff
path: root/DomainDig/PaywallView.swift
blob: a21448f13024718e707e7fe5fce19d0fda554663 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import StoreKit
import SwiftUI

struct PaywallView: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.appDensity) private var appDensity
    @State private var purchaseService = PurchaseService.shared

    var body: some View {
        NavigationStack {
            List {
                Section {
                    Text("Pro unlocks automation, larger runs, and export convenience while keeping the core lookup experience free.")
                        .font(appDensity.font(.body, design: .default))
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }

                Section("What Pro Unlocks") {
                    featureRow("Unlimited tracked domains")
                    featureRow("Workflows")
                    featureRow("Larger batch sizes")
                    featureRow("Advanced exports")
                }

                Section("Subscription") {
                    if purchaseService.isLoadingProducts {
                        ProgressView("Loading pricing…")
                    } else if purchaseService.products.isEmpty {
                        Text("Pricing is unavailable right now.")
                            .font(appDensity.font(.caption, design: .default))
                            .foregroundStyle(.secondary)

                        Button("Retry") {
                            Task {
                                await purchaseService.refreshProducts()
                            }
                        }
                    } else {
                        ForEach(purchaseService.products, id: \.id) { product in
                            Button {
                                Task {
                                    await purchaseService.purchase(product)
                                }
                            } label: {
                                VStack(alignment: .leading, spacing: 6) {
                                    Text(subscriptionTitle(for: product))
                                        .font(appDensity.font(.headline, design: .default, weight: .semibold))
                                        .foregroundStyle(.primary)
                                    Text(product.displayPrice)
                                        .font(appDensity.font(.callout, design: .default))
                                        .foregroundStyle(.secondary)
                                }
                                .frame(maxWidth: .infinity, alignment: .leading)
                            }
                            .disabled(purchaseService.isPurchasing || purchaseService.isRestoring)
                        }
                    }

                    if let statusMessage = purchaseService.statusMessage {
                        Text(statusMessage)
                            .font(appDensity.font(.caption, design: .default))
                            .foregroundStyle(.secondary)
                    }

                    if let errorMessage = purchaseService.errorMessage {
                        Text(errorMessage)
                            .font(appDensity.font(.caption, design: .default))
                            .foregroundStyle(.red)
                    }
                }

                Section("Account") {
                    Button(purchaseService.isRestoring ? "Restoring…" : "Restore Purchases") {
                        Task {
                            await purchaseService.restorePurchases()
                        }
                    }
                    .disabled(purchaseService.isPurchasing || purchaseService.isRestoring)

                    if purchaseService.hasProAccess {
                        Button("Manage Subscription") {
                            Task {
                                await purchaseService.manageSubscription()
                            }
                        }
                    }
                }
            }
            .navigationTitle("DomainDig Pro")
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Done") {
                        dismiss()
                    }
                }
            }
        }
        .task {
            await purchaseService.refreshProducts()
            await purchaseService.refreshEntitlements()
        }
        .onDisappear {
            purchaseService.clearMessages()
        }
    }

    private func featureRow(_ title: String) -> some View {
        Text(title)
            .font(appDensity.font(.body, design: .default))
    }

    private func subscriptionTitle(for product: Product) -> String {
        switch product.id {
        case PurchaseService.monthlyProductID:
            return "Pro Monthly"
        case PurchaseService.yearlyProductID:
            return "Pro Yearly"
        default:
            return product.displayName
        }
    }
}