krz/rune

an ios client for njalla

clone: git clone https://gitbay.org/krz/rune.git

v1.0.0: Rune/Views/Domains/DomainListView.swift · raw

 1import SwiftUI
 2
 3struct DomainListView: View {
 4    @ObservedObject var viewModel: DomainViewModel
 5    let client: NjallaClient?
 6
 7    var body: some View {
 8        NavigationStack {
 9            Group {
10                if let client {
11                    content(client: client)
12                } else {
13                    ContentUnavailableView("Sign in required", systemImage: "key.fill", description: Text("Add a valid Njalla API token to load domains."))
14                }
15            }
16            .navigationTitle("Domains")
17        }
18        .alert("API Error", isPresented: errorBinding) {
19            Button("OK", role: .cancel) {}
20        } message: {
21            Text(viewModel.errorMessage ?? "")
22        }
23    }
24
25    @ViewBuilder
26    private func content(client: NjallaClient) -> some View {
27        if viewModel.isLoadingDomains && viewModel.domains.isEmpty {
28            ProgressView()
29        } else if viewModel.domains.isEmpty {
30            ContentUnavailableView("No Domains", systemImage: "globe", description: Text("No domains found on this account."))
31        } else {
32            List(viewModel.domains) { domain in
33                NavigationLink {
34                    DomainDetailView(domainName: domain.name, viewModel: viewModel, client: client)
35                } label: {
36                    DomainRow(domain: domain)
37                }
38            }
39            .listStyle(.insetGrouped)
40            .refreshable {
41                await viewModel.loadDomains(client: client)
42            }
43        }
44    }
45
46    private var errorBinding: Binding<Bool> {
47        Binding(
48            get: { viewModel.errorMessage != nil },
49            set: { newValue in
50                if !newValue {
51                    viewModel.errorMessage = nil
52                }
53            }
54        )
55    }
56}
57
58private struct DomainRow: View {
59    let domain: Domain
60
61    var body: some View {
62        VStack(alignment: .leading, spacing: 6) {
63            Text(domain.name)
64                .font(.headline)
65
66            HStack {
67                if let status = domain.status {
68                    Text(status)
69                }
70
71                if let expiry = domain.expiry {
72                    Text("Expiry: \(expiry.formattedExpiry())")
73                }
74            }
75            .font(.subheadline)
76            .foregroundStyle(.secondary)
77
78            if let autorenew = domain.autorenew {
79                Text(autorenew ? "Autorenew On" : "Autorenew Off")
80                    .font(.subheadline)
81                    .foregroundStyle(.secondary)
82            }
83        }
84        .padding(.vertical, 4)
85    }
86}