import SwiftUI struct TaskDetails { let taskId: Int let businessId: Int let categoryId: Int let title: String let createdOn: Date let statusId: Int let categoryName: String let categoryColor: String // Order info let orderId: Int let orderRemarks: String let orderSubmittedOn: Date? // Location info let servicePointId: Int let servicePointName: String let servicePointTypeId: Int let deliveryAddress: String let deliveryLat: Double let deliveryLng: Double // Customer info let customerUserId: Int let customerFirstName: String let customerLastName: String let customerPhone: String let customerPhotoUrl: String // Beacon info let beaconUUID: String // Line items & table members let lineItems: [OrderLineItem] let tableMembers: [TableMember] /// Decode directly from a [String: Any] dictionary (matches Flutter's fromJson) init(json: [String: Any]) { taskId = WorkTask.parseInt(json["TaskID"]) ?? 0 businessId = WorkTask.parseInt(json["BusinessID"] ?? json["TaskBusinessID"]) ?? 0 categoryId = WorkTask.parseInt(json["TaskCategoryID"] ?? json["CategoryID"]) ?? 0 title = (json["Title"] as? String) ?? (json["TaskTitle"] as? String) ?? "" createdOn = WorkTask.parseDate(json["CreatedOn"] ?? json["TaskCreatedOn"]) ?? Date() statusId = WorkTask.parseInt(json["StatusID"] ?? json["TaskStatusID"]) ?? 0 categoryName = WorkTask.nonEmpty(json["CategoryName"]) ?? WorkTask.nonEmpty(json["Name"]) ?? WorkTask.nonEmpty(json["TaskCategoryName"]) ?? "General" categoryColor = WorkTask.nonEmpty(json["CategoryColor"]) ?? WorkTask.nonEmpty(json["Color"]) ?? WorkTask.nonEmpty(json["TaskCategoryColor"]) ?? "#888888" orderId = WorkTask.parseInt(json["OrderID"]) ?? 0 orderRemarks = (json["OrderRemarks"] as? String) ?? (json["Remarks"] as? String) ?? "" if let s = (json["OrderSubmittedOn"] ?? json["SubmittedOn"]) as? String, !s.isEmpty { orderSubmittedOn = APIService.parseDate(s) } else { orderSubmittedOn = nil } servicePointId = WorkTask.parseInt(json["ServicePointID"]) ?? 0 servicePointName = (json["ServicePointName"] as? String) ?? "" servicePointTypeId = WorkTask.parseInt(json["ServicePointTypeID"]) ?? 0 deliveryAddress = (json["DeliveryAddress"] as? String) ?? "" deliveryLat = Self.parseDouble(json["DeliveryLat"]) ?? 0 deliveryLng = Self.parseDouble(json["DeliveryLng"]) ?? 0 customerUserId = WorkTask.parseInt(json["CustomerUserID"] ?? json["CustomerID"]) ?? 0 customerFirstName = (json["CustomerFirstName"] as? String) ?? (json["FirstName"] as? String) ?? "" customerLastName = (json["CustomerLastName"] as? String) ?? (json["LastName"] as? String) ?? "" customerPhone = (json["CustomerPhone"] as? String) ?? (json["Phone"] as? String) ?? "" let rawPhoto = (json["CustomerPhotoUrl"] as? String) ?? (json["PhotoUrl"] as? String) ?? "" customerPhotoUrl = APIService.resolvePhotoUrl(rawPhoto) beaconUUID = (json["BeaconUUID"] as? String) ?? "" // Try multiple key variants for arrays if let arr = (json["LineItems"] ?? json["LINE_ITEMS"] ?? json["Items"]) as? [[String: Any]] { lineItems = arr.map { OrderLineItem(json: $0) } } else { lineItems = [] } if let arr = (json["TableMembers"] ?? json["TABLE_MEMBERS"] ?? json["Members"]) as? [[String: Any]] { tableMembers = arr.map { TableMember(json: $0) } } else { tableMembers = [] } } private static func parseDouble(_ value: Any?) -> Double? { guard let value = value else { return nil } if let d = value as? Double { return d } if let i = value as? Int { return Double(i) } if let s = value as? String, let d = Double(s) { return d } if let n = value as? NSNumber { return n.doubleValue } return nil } var color: Color { let hex = categoryColor.replacingOccurrences(of: "#", with: "") guard hex.count == 6, let val = UInt64(hex, radix: 16) else { return Color(red: 0.53, green: 0.53, blue: 0.53) } return Color( red: Double((val >> 16) & 0xFF) / 255, green: Double((val >> 8) & 0xFF) / 255, blue: Double(val & 0xFF) / 255 ) } var customerFullName: String { let parts = [customerFirstName, customerLastName].filter { !$0.isEmpty } return parts.isEmpty ? "Guest" : parts.joined(separator: " ") } var locationDisplay: String { if !deliveryAddress.isEmpty { return deliveryAddress } if !servicePointName.isEmpty { return servicePointName } return "No location specified" } var isDelivery: Bool { !deliveryAddress.isEmpty } var isTableService: Bool { servicePointId > 0 && !servicePointName.isEmpty } var timeAgo: String { let diff = Date().timeIntervalSince(createdOn) let minutes = Int(diff / 60) if minutes < 1 { return "just now" } if minutes < 60 { return "\(minutes)m ago" } let hours = minutes / 60 if hours < 24 { return "\(hours)h ago" } return "\(hours / 24)d ago" } var mainItems: [OrderLineItem] { lineItems.filter { !$0.isModifier && $0.parentLineItemId == 0 } } func modifiers(for parentLineItemId: Int) -> [OrderLineItem] { lineItems.filter { $0.parentLineItemId == parentLineItemId } } }