krz/rune

an ios client for njalla

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

main: 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    }
19
20    @ViewBuilder
21    private func content(client: NjallaClient) -> some View {
22        List {
23            if let errorMessage = viewModel.domainsErrorMessage {
24                Section {
25                    InlineErrorView(message: errorMessage, retryTitle: "Retry Domains") {
26                        Task {
27                            await viewModel.loadDomains(client: client)
28                        }
29                    }
30                    .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
31                }
32            }
33
34            if (!viewModel.hasLoadedDomains || viewModel.isLoadingDomains) && viewModel.domains.isEmpty {
35                Section {
36                    HStack {
37                        Spacer()
38                        ProgressView("Loading Domains")
39                        Spacer()
40                    }
41                }
42            } else if viewModel.domains.isEmpty {
43                Section {
44                    ContentUnavailableView(
45                        "No Domains",
46                        systemImage: "globe",
47                        description: Text("No domains found. Pull to refresh after domains are added to this account.")
48                    )
49                }
50            } else {
51                ForEach(viewModel.domains) { domain in
52                    NavigationLink {
53                        DomainDetailView(domainName: domain.name, viewModel: viewModel, client: client)
54                    } label: {
55                        DomainRow(domain: domain)
56                    }
57                }
58            }
59        }
60        .listStyle(.insetGrouped)
61        .refreshable {
62            await viewModel.loadDomains(client: client)
63        }
64    }
65}
66
67private struct DomainRow: View {
68    let domain: Domain
69
70    var body: some View {
71        VStack(alignment: .leading, spacing: 6) {
72            Text(domain.name)
73                .font(.headline)
74
75            HStack {
76                if let status = domain.status {
77                    Text(status)
78                }
79
80                if let expiry = domain.expiry {
81                    Text("Expiry: \(expiry.formattedExpiry())")
82                }
83            }
84            .font(.subheadline)
85            .foregroundStyle(.secondary)
86
87            if let autorenew = domain.autorenew {
88                Text(autorenew ? "Autorenew On" : "Autorenew Off")
89                    .font(.subheadline)
90                    .foregroundStyle(.secondary)
91            }
92        }
93        .padding(.vertical, 4)
94    }
95}