Compare commits
3 commits
main
...
schwifty/p
| Author | SHA1 | Date | |
|---|---|---|---|
| d5d1c35b55 | |||
| 54923ba341 | |||
| db7fe31b8a |
7 changed files with 32 additions and 23 deletions
|
|
@ -691,14 +691,14 @@ actor APIService {
|
|||
|
||||
func getAvatarUrl() async throws -> String? {
|
||||
let json = try await getJSON("/auth/avatar.php")
|
||||
print("[Avatar] Response: \(json)")
|
||||
if IS_DEV { print("[Avatar] Response: \(json)") }
|
||||
guard ok(json) else {
|
||||
print("[Avatar] Response not OK")
|
||||
if IS_DEV { print("[Avatar] Response not OK") }
|
||||
return nil
|
||||
}
|
||||
|
||||
let data = json["DATA"] as? [String: Any] ?? json
|
||||
print("[Avatar] Data: \(data)")
|
||||
if IS_DEV { print("[Avatar] Data: \(data)") }
|
||||
|
||||
// Try all possible key variations for avatar URL
|
||||
let keys = ["AVATAR_URL", "AVATARURL", "AvatarUrl", "avatarUrl", "avatar_url",
|
||||
|
|
@ -707,16 +707,16 @@ actor APIService {
|
|||
for key in keys {
|
||||
if let url = data[key] as? String, !url.isEmpty {
|
||||
let resolved = Self.resolvePhotoUrl(url)
|
||||
print("[Avatar] Found key '\(key)' with value: \(url) -> \(resolved)")
|
||||
if IS_DEV { print("[Avatar] Found key '\(key)' with value: \(url) -> \(resolved)") }
|
||||
return resolved
|
||||
}
|
||||
if let url = json[key] as? String, !url.isEmpty {
|
||||
let resolved = Self.resolvePhotoUrl(url)
|
||||
print("[Avatar] Found key '\(key)' in json with value: \(url) -> \(resolved)")
|
||||
if IS_DEV { print("[Avatar] Found key '\(key)' in json with value: \(url) -> \(resolved)") }
|
||||
return resolved
|
||||
}
|
||||
}
|
||||
print("[Avatar] No avatar URL found in response")
|
||||
if IS_DEV { print("[Avatar] No avatar URL found in response") }
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -724,7 +724,7 @@ actor APIService {
|
|||
func getUserAvatarUrl(userId: Int) async throws -> String? {
|
||||
// Try the avatar endpoint with UserID
|
||||
let json = try await postJSON("/auth/avatar.php", payload: ["UserID": userId])
|
||||
print("[Avatar] getUserAvatarUrl(\(userId)) Response: \(json)")
|
||||
if IS_DEV { print("[Avatar] getUserAvatarUrl(\(userId)) Response: \(json)") }
|
||||
|
||||
let data = json["DATA"] as? [String: Any] ?? json
|
||||
|
||||
|
|
@ -733,15 +733,15 @@ actor APIService {
|
|||
"UserPhotoUrl", "USERPHOTOURL", "userPhotoUrl"]
|
||||
for key in keys {
|
||||
if let url = data[key] as? String, !url.isEmpty {
|
||||
print("[Avatar] Found avatar for userId \(userId): \(url)")
|
||||
if IS_DEV { print("[Avatar] Found avatar for userId \(userId): \(url)") }
|
||||
return Self.resolvePhotoUrl(url)
|
||||
}
|
||||
if let url = json[key] as? String, !url.isEmpty {
|
||||
print("[Avatar] Found avatar for userId \(userId): \(url)")
|
||||
if IS_DEV { print("[Avatar] Found avatar for userId \(userId): \(url)") }
|
||||
return Self.resolvePhotoUrl(url)
|
||||
}
|
||||
}
|
||||
print("[Avatar] No avatar found for userId \(userId), all keys: \(json.keys.sorted())")
|
||||
if IS_DEV { print("[Avatar] No avatar found for userId \(userId), all keys: \(json.keys.sorted())") }
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ final class BeaconScanner: NSObject, ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
print("[BeaconScanner] Started scanning for \(BeaconShardPool.uuids.count) shard UUIDs, target ServicePointId: \(targetServicePointId)")
|
||||
if IS_DEV { print("[BeaconScanner] Started scanning for \(BeaconShardPool.uuids.count) shard UUIDs, target ServicePointId: \(targetServicePointId)") }
|
||||
}
|
||||
|
||||
func stopScanning() {
|
||||
|
|
@ -137,12 +137,12 @@ final class BeaconScanner: NSObject, ObservableObject {
|
|||
await MainActor.run {
|
||||
self.resolvedBeacons[key] = servicePointId
|
||||
self.pendingResolutions.remove(key)
|
||||
print("[BeaconScanner] Resolved \(key) -> ServicePointId \(servicePointId)")
|
||||
if IS_DEV { print("[BeaconScanner] Resolved \(key) -> ServicePointId \(servicePointId)") }
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.pendingResolutions.remove(key)
|
||||
print("[BeaconScanner] Failed to resolve \(key): \(error)")
|
||||
if IS_DEV { print("[BeaconScanner] Failed to resolve \(key): \(error)") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ extension BeaconScanner: CLLocationManagerDelegate {
|
|||
|
||||
if rssiSamples.count >= minSamplesToConfirm {
|
||||
let avg = Double(rssiSamples.reduce(0, +)) / Double(rssiSamples.count)
|
||||
print("[BeaconScanner] Target beacon confirmed! Avg RSSI: \(avg)")
|
||||
if IS_DEV { print("[BeaconScanner] Target beacon confirmed! Avg RSSI: \(avg)") }
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.onBeaconDetected(avg)
|
||||
}
|
||||
|
|
@ -210,6 +210,6 @@ extension BeaconScanner: CLLocationManagerDelegate {
|
|||
}
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didFailRangingFor constraint: CLBeaconIdentityConstraint, error: Error) {
|
||||
print("[BeaconScanner] Ranging failed: \(error)")
|
||||
if IS_DEV { print("[BeaconScanner] Ranging failed: \(error)") }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ struct AboutScreen: View {
|
|||
aboutInfo = try await APIService.shared.getAboutInfo()
|
||||
} catch {
|
||||
// Use fallback on error
|
||||
print("Failed to load about info: \(error)")
|
||||
if IS_DEV { print("Failed to load about info: \(error)") }
|
||||
}
|
||||
isLoading = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ struct BusinessSelectionScreen: View {
|
|||
@State private var selectedBusiness: Employment?
|
||||
@State private var debugText = ""
|
||||
|
||||
private let refreshTimer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()
|
||||
private let refreshTimer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ struct MyTasksScreen: View {
|
|||
FilterTab(value: "completed", label: "Done", icon: "checkmark.circle.fill"),
|
||||
]
|
||||
|
||||
private let refreshTimer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()
|
||||
private let refreshTimer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ struct TaskDetailScreen: View {
|
|||
@State private var showCancelOrderAlert = false
|
||||
@State private var isCancelingOrder = false
|
||||
@State private var taskAccepted = false // Track if task was just accepted
|
||||
@State private var hasCompleted = false // Guard against double-completion
|
||||
@State private var customerAvatarUrl: String? // Fetched separately if not in task details
|
||||
|
||||
// Rating dialog
|
||||
|
|
@ -100,6 +101,7 @@ struct TaskDetailScreen: View {
|
|||
} else if result == "cancelled" || result == "error" {
|
||||
autoCompleting = false
|
||||
beaconDetected = false
|
||||
hasCompleted = false
|
||||
beaconScanner?.resetSamples()
|
||||
beaconScanner?.startScanning()
|
||||
}
|
||||
|
|
@ -629,6 +631,7 @@ struct TaskDetailScreen: View {
|
|||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.tint(Color(red: 0.13, green: 0.55, blue: 0.13))
|
||||
.disabled(hasCompleted)
|
||||
} else {
|
||||
Button { showCompleteAlert = true } label: {
|
||||
Label("Complete Task", systemImage: "checkmark.circle.fill")
|
||||
|
|
@ -637,6 +640,7 @@ struct TaskDetailScreen: View {
|
|||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.tint(.green)
|
||||
.disabled(hasCompleted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -706,12 +710,12 @@ struct TaskDetailScreen: View {
|
|||
}
|
||||
}
|
||||
|
||||
print("[Beacon] showCompleteButton=\(showCompleteButton), servicePointId=\(d.servicePointId)")
|
||||
if IS_DEV { print("[Beacon] showCompleteButton=\(showCompleteButton), servicePointId=\(d.servicePointId)") }
|
||||
if showCompleteButton && d.servicePointId > 0 {
|
||||
print("[Beacon] Starting beacon scanning for ServicePointId: \(d.servicePointId)")
|
||||
if IS_DEV { print("[Beacon] Starting beacon scanning for ServicePointId: \(d.servicePointId)") }
|
||||
startBeaconScanning(d.servicePointId)
|
||||
} else {
|
||||
print("[Beacon] NOT starting scan - showCompleteButton=\(showCompleteButton), servicePointId=\(d.servicePointId)")
|
||||
if IS_DEV { print("[Beacon] NOT starting scan - showCompleteButton=\(showCompleteButton), servicePointId=\(d.servicePointId)") }
|
||||
}
|
||||
} catch {
|
||||
self.error = error.localizedDescription
|
||||
|
|
@ -723,9 +727,10 @@ struct TaskDetailScreen: View {
|
|||
let scanner = BeaconScanner(
|
||||
targetServicePointId: servicePointId,
|
||||
onBeaconDetected: { [self] _ in
|
||||
if !beaconDetected && !autoCompleting {
|
||||
if !beaconDetected && !autoCompleting && !hasCompleted {
|
||||
beaconDetected = true
|
||||
autoCompleting = true
|
||||
hasCompleted = true
|
||||
beaconScanner?.stopScanning()
|
||||
showAutoCompleteDialog = true
|
||||
}
|
||||
|
|
@ -760,6 +765,8 @@ struct TaskDetailScreen: View {
|
|||
}
|
||||
|
||||
private func completeTask() {
|
||||
guard !hasCompleted else { return }
|
||||
hasCompleted = true
|
||||
Task {
|
||||
do {
|
||||
try await APIService.shared.completeTask(taskId: task.taskId)
|
||||
|
|
@ -768,9 +775,11 @@ struct TaskDetailScreen: View {
|
|||
if case .ratingRequired = apiError {
|
||||
showRatingDialog = true
|
||||
} else {
|
||||
hasCompleted = false
|
||||
self.error = apiError.localizedDescription
|
||||
}
|
||||
} catch {
|
||||
hasCompleted = false
|
||||
self.error = error.localizedDescription
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct TaskListScreen: View {
|
|||
@State private var selectedTask: WorkTask?
|
||||
@State private var showingMyTasks = false
|
||||
|
||||
private let refreshTimer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()
|
||||
private let refreshTimer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue