summaryrefslogtreecommitdiff
path: root/DomainDig/BatchResultsView.swift
blob: e74183041afcf8f1ea44466a277d6bc280e22e65 (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
import SwiftUI

struct BatchResultsView: View {
    @Bindable var viewModel: DomainViewModel
    let title: String

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack(alignment: .top) {
                SectionTitleView(title: title)
                Spacer()
                if viewModel.batchLookupRunning {
                    VStack(alignment: .trailing, spacing: 4) {
                        ProgressView(value: Double(viewModel.batchCompletedCount), total: Double(max(viewModel.batchTotalCount, 1)))
                            .tint(.cyan)
                            .frame(width: 120)
                        Text(viewModel.batchProgressLabel)
                            .font(.system(.caption2, design: .monospaced))
                            .foregroundStyle(.secondary)
                    }
                } else if !viewModel.batchResults.isEmpty {
                    Text("\(viewModel.batchResults.count) domains")
                        .font(.system(.caption2, design: .monospaced))
                        .foregroundStyle(.secondary)
                }
            }

            if viewModel.batchResults.isEmpty {
                MessageCardView(text: "No batch results yet", isError: false)
            } else {
                CardView(allowsHorizontalScroll: false) {
                    ForEach(viewModel.batchResults) { result in
                        if let entry = viewModel.historyEntry(for: result) {
                            NavigationLink {
                                HistoryDetailView(viewModel: viewModel, entry: entry)
                            } label: {
                                BatchResultRowView(result: result)
                            }
                            .buttonStyle(.plain)
                        } else {
                            BatchResultRowView(result: result)
                        }
                    }
                }
            }
        }
    }
}

struct BatchResultRowView: View {
    let result: BatchLookupResult

    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            HStack(alignment: .firstTextBaseline, spacing: 8) {
                Text(result.domain)
                    .font(.system(.callout, design: .monospaced))
                    .foregroundStyle(.primary)
                    .lineLimit(1)
                Spacer(minLength: 8)
                Text(result.quickStatus)
                    .font(.system(.caption2, design: .monospaced))
                    .foregroundStyle(quickStatusColor)
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .background(quickStatusColor.opacity(0.16))
                    .clipShape(Capsule())
            }

            HStack(spacing: 10) {
                Text(availabilityText)
                Text(result.primaryIP ?? "No IP")
                Text(result.timestamp.formatted(date: .abbreviated, time: .shortened))
            }
            .font(.system(.caption2, design: .monospaced))
            .foregroundStyle(.secondary)

            if let errorMessage = result.errorMessage {
                Text(errorMessage)
                    .font(.system(.caption2, design: .monospaced))
                    .foregroundStyle(.red)
            }
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(.vertical, 4)
    }

    private var availabilityText: String {
        switch result.availability {
        case .available:
            return "Available"
        case .registered:
            return "Registered"
        case .unknown, .none:
            return "Unknown"
        }
    }

    private var quickStatusColor: Color {
        switch result.status {
        case .pending:
            return .secondary
        case .running:
            return .cyan
        case .completed:
            if result.quickStatus == "Changed" {
                return .yellow
            }
            return .green
        case .failed:
            return .red
        }
    }
}