73 lines
2.6 KiB
Swift
73 lines
2.6 KiB
Swift
import SwiftUI
|
|
|
|
/// One row in `ReceiptsListView`: merchant, formatted business date and
|
|
/// amount, category, and the shared `ZenithStatusBadge` (matching the web
|
|
/// dashboard's `StatusBadge.tsx`).
|
|
struct ReceiptRow: View {
|
|
let receipt: Receipt
|
|
|
|
var body: some View {
|
|
HStack(alignment: .top, spacing: ZenithSpacing.sm) {
|
|
VStack(alignment: .leading, spacing: ZenithSpacing.unit) {
|
|
Text(receipt.merchant.name.isEmpty ? "Unbekannter Händler" : receipt.merchant.name)
|
|
.zenithBodyStyle()
|
|
.fontWeight(.medium)
|
|
.lineLimit(1)
|
|
|
|
HStack(spacing: 6) {
|
|
Text(formattedDate)
|
|
Text("·")
|
|
Text(receipt.suggestedCategory.rawValue)
|
|
}
|
|
.zenithBodySmStyle()
|
|
.lineLimit(1)
|
|
}
|
|
|
|
Spacer(minLength: ZenithSpacing.xs)
|
|
|
|
VStack(alignment: .trailing, spacing: 6) {
|
|
Text(formattedAmount)
|
|
.zenithLabelMdStyle()
|
|
.fontWeight(.medium)
|
|
.multilineTextAlignment(.trailing)
|
|
|
|
ZenithStatusBadge(receipt)
|
|
.accessibilityElement(children: .combine)
|
|
}
|
|
}
|
|
.padding(.vertical, ZenithSpacing.xs)
|
|
}
|
|
|
|
// `receipt.date.isoDate` is a plain "YYYY-MM-DD" string (no time/zone
|
|
// component), so it deliberately does NOT go through ISO8601.parse
|
|
// (which expects a full timestamp and would just return nil here).
|
|
private var formattedDate: String {
|
|
guard let date = Self.isoDateOnlyFormatter.date(from: receipt.date.isoDate) else {
|
|
return receipt.date.isoDate
|
|
}
|
|
return Self.displayDateFormatter.string(from: date)
|
|
}
|
|
|
|
private var formattedAmount: String {
|
|
let code = receipt.currency.isEmpty ? "EUR" : receipt.currency
|
|
return receipt.totalAmount.value.formatted(.currency(code: code))
|
|
}
|
|
|
|
private static let isoDateOnlyFormatter: DateFormatter = {
|
|
let formatter = DateFormatter()
|
|
formatter.dateFormat = "yyyy-MM-dd"
|
|
formatter.locale = Locale(identifier: "en_US_POSIX")
|
|
formatter.timeZone = TimeZone(identifier: "UTC")
|
|
return formatter
|
|
}()
|
|
|
|
private static let displayDateFormatter: DateFormatter = {
|
|
let formatter = DateFormatter()
|
|
formatter.dateStyle = .medium
|
|
formatter.timeStyle = .none
|
|
formatter.locale = Locale(identifier: "de_DE")
|
|
formatter.timeZone = TimeZone(identifier: "UTC")
|
|
return formatter
|
|
}()
|
|
}
|