krz/hutch

an ios client for sourcehut

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

v3.9.0: Hutch/Models/TicketBulkAction.swift · raw

 1import Foundation
 2
 3enum TicketBulkActionKind: String, Sendable {
 4    case close
 5    case assign
 6
 7    var displayName: String {
 8        switch self {
 9        case .close:
10            "Close"
11        case .assign:
12            "Assign"
13        }
14    }
15
16    var pastTenseDisplayName: String {
17        switch self {
18        case .close:
19            "Closed"
20        case .assign:
21            "Assigned"
22        }
23    }
24}
25
26struct TicketBulkActionResult: Identifiable, Sendable {
27    let id = UUID()
28    let action: TicketBulkActionKind
29    let totalCount: Int
30    let updatedCount: Int
31    let unchangedCount: Int
32    let failures: [TicketBulkActionFailure]
33
34    var failedCount: Int {
35        failures.count
36    }
37
38    var title: String {
39        if updatedCount == 0, failedCount > 0 {
40            return "\(action.displayName) Failed"
41        }
42        if failedCount > 0 {
43            return "\(action.displayName) Partially Applied"
44        }
45        return "\(action.displayName) Complete"
46    }
47
48    var message: String {
49        var components: [String] = []
50
51        if updatedCount > 0 {
52            components.append("\(action.pastTenseDisplayName) \(updatedCount) \(ticketWord(for: updatedCount)).")
53        }
54
55        if unchangedCount > 0 {
56            let unchangedDescription: String
57            switch action {
58            case .close:
59                unchangedDescription = "\(unchangedCount) already closed."
60            case .assign:
61                unchangedDescription = "\(unchangedCount) already assigned."
62            }
63            components.append(unchangedDescription)
64        }
65
66        if failedCount > 0 {
67            let ids = failures
68                .map { "#\($0.ticketID)" }
69                .joined(separator: ", ")
70            components.append("Failed: \(ids).")
71        }
72
73        if components.isEmpty {
74            components.append("No tickets were selected.")
75        }
76
77        return components.joined(separator: " ")
78    }
79
80    private func ticketWord(for count: Int) -> String {
81        count == 1 ? "ticket" : "tickets"
82    }
83}
84
85struct TicketBulkActionFailure: Sendable {
86    let ticketID: Int
87    let message: String
88}