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 }() }