Add debug logging for orderTotal

This commit is contained in:
John Pinkyfloyd 2026-02-17 09:35:19 -08:00
parent 4a2f984c94
commit 40b1ee5d60
3 changed files with 160 additions and 85 deletions

View file

@ -441,7 +441,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3; CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = U83YL8VRF3; DEVELOPMENT_TEAM = U83YL8VRF3;
GENERATE_INFOPLIST_FILE = NO; GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = PayfritWorks/Info.plist; INFOPLIST_FILE = PayfritWorks/Info.plist;
@ -456,8 +456,8 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.payfrit.works; PRODUCT_BUNDLE_IDENTIFIER = com.mizerek.payfritworks;
PRODUCT_NAME = "Payfrit Works"; PRODUCT_NAME = "Payfrit Works";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = NO;
@ -473,7 +473,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3; CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = U83YL8VRF3; DEVELOPMENT_TEAM = U83YL8VRF3;
GENERATE_INFOPLIST_FILE = NO; GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = PayfritWorks/Info.plist; INFOPLIST_FILE = PayfritWorks/Info.plist;
@ -488,8 +488,8 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.payfrit.works; PRODUCT_BUNDLE_IDENTIFIER = com.mizerek.payfritworks;
PRODUCT_NAME = "Payfrit Works"; PRODUCT_NAME = "Payfrit Works";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = NO;

View file

@ -3,6 +3,28 @@ import SwiftUI
struct AboutScreen: View { struct AboutScreen: View {
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
@State private var appearAnimation = false @State private var appearAnimation = false
@State private var aboutInfo: AboutInfo?
@State private var isLoading = true
@State private var error: String?
// Fallback content if API fails
private let fallbackInfo = AboutInfo(
description: "Payfrit Works helps you manage tasks, accept cash payments, and earn money. Get notified of new tasks, complete them efficiently, and track your earnings.",
features: [
AboutFeature(icon: "checkmark.circle", title: "Claim Tasks", description: "View available tasks from businesses you work for and claim them with one tap."),
AboutFeature(icon: "dollarsign.circle", title: "Accept Cash", description: "Collect cash payments from customers with automatic change calculation."),
AboutFeature(icon: "antenna.radiowaves.left.and.right", title: "Beacon Auto-Complete", description: "Tasks complete automatically when you're near the customer's table beacon."),
AboutFeature(icon: "creditcard", title: "Earn & Get Paid", description: "Track your earnings in real-time and receive payouts to your bank account.")
],
contacts: [
AboutContact(icon: "globe", label: "Website", url: "https://www.payfrit.com")
],
copyright: "© 2026 Payfrit. All rights reserved."
)
private var displayInfo: AboutInfo {
aboutInfo ?? fallbackInfo
}
var body: some View { var body: some View {
ScrollView { ScrollView {
@ -19,7 +41,7 @@ struct AboutScreen: View {
.fontWeight(.bold) .fontWeight(.bold)
.foregroundColor(.primary) .foregroundColor(.primary)
Text("Version 1.0.0") Text("Version \(appVersion)")
.font(.caption) .font(.caption)
.foregroundColor(.secondary) .foregroundColor(.secondary)
} }
@ -28,88 +50,57 @@ struct AboutScreen: View {
.scaleEffect(appearAnimation ? 1 : 0.9) .scaleEffect(appearAnimation ? 1 : 0.9)
.opacity(appearAnimation ? 1 : 0) .opacity(appearAnimation ? 1 : 0)
// Intro if isLoading {
Text("Payfrit Works helps you manage tasks, accept cash payments, and earn money. Get notified of new tasks, complete them efficiently, and track your earnings.") ProgressView()
.padding(.vertical, 20)
} else {
// Description
if !displayInfo.description.isEmpty {
Text(displayInfo.description)
.font(.caption) .font(.caption)
.foregroundColor(.secondary) .foregroundColor(.secondary)
.multilineTextAlignment(.leading) .multilineTextAlignment(.leading)
.padding(.horizontal, 16) .padding(.horizontal, 16)
.opacity(appearAnimation ? 1 : 0) .opacity(appearAnimation ? 1 : 0)
.offset(y: appearAnimation ? 0 : 15) .offset(y: appearAnimation ? 0 : 15)
}
// Feature cards // Feature cards
VStack(spacing: 12) { VStack(spacing: 12) {
ForEach(Array(displayInfo.features.enumerated()), id: \.offset) { index, feature in
featureCard( featureCard(
icon: "checkmark.circle", icon: mapIconName(feature.icon),
title: "Claim Tasks", title: feature.title,
description: "View available tasks from businesses you work for and claim them with one tap." description: feature.description
) )
.staggeredAppear(index: 0, appeared: appearAnimation) .staggeredAppear(index: index, appeared: appearAnimation)
}
featureCard(
icon: "dollarsign.circle",
title: "Accept Cash",
description: "Collect cash payments from customers with automatic change calculation."
)
.staggeredAppear(index: 1, appeared: appearAnimation)
featureCard(
icon: "antenna.radiowaves.left.and.right",
title: "Beacon Auto-Complete",
description: "Tasks complete automatically when you're near the customer's table beacon."
)
.staggeredAppear(index: 2, appeared: appearAnimation)
featureCard(
icon: "creditcard",
title: "Earn & Get Paid",
description: "Track your earnings in real-time and receive payouts to your bank account."
)
.staggeredAppear(index: 3, appeared: appearAnimation)
} }
.padding(.horizontal, 16) .padding(.horizontal, 16)
// Links // Contact links
if !displayInfo.contacts.isEmpty {
VStack(spacing: 8) { VStack(spacing: 8) {
Link(destination: URL(string: "https://www.payfrit.com")!) { ForEach(Array(displayInfo.contacts.enumerated()), id: \.offset) { index, contact in
HStack(spacing: 10) { if let url = URL(string: contact.url) {
Image(systemName: "globe") Link(destination: url) {
.font(.subheadline) contactRow(contact: contact)
.foregroundColor(.payfritGreen)
.frame(width: 28, height: 28)
.background(Color.payfritGreen.opacity(0.1))
.clipShape(RoundedRectangle(cornerRadius: 6, style: .continuous))
VStack(alignment: .leading, spacing: 2) {
Text("Website")
.font(.caption)
.fontWeight(.medium)
.foregroundColor(.primary)
Text("www.payfrit.com")
.font(.caption2)
.foregroundColor(.secondary)
} }
Spacer()
Image(systemName: "arrow.up.right")
.font(.caption2)
.foregroundColor(.secondary)
} }
.padding(12)
.background(Color(.secondarySystemGroupedBackground))
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.contentShape(Rectangle())
} }
} }
.padding(.horizontal, 16) .padding(.horizontal, 16)
.staggeredAppear(index: 4, appeared: appearAnimation) .staggeredAppear(index: displayInfo.features.count, appeared: appearAnimation)
}
// Copyright // Copyright
Text("\u{00A9} 2026 Payfrit. All rights reserved.") if !displayInfo.copyright.isEmpty {
Text(displayInfo.copyright)
.font(.caption2) .font(.caption2)
.foregroundColor(.secondary) .foregroundColor(.secondary)
.padding(.top, 4) .padding(.top, 4)
}
}
Spacer() Spacer()
.frame(height: 20) .frame(height: 20)
@ -118,6 +109,9 @@ struct AboutScreen: View {
.background(Color(.systemGroupedBackground).ignoresSafeArea()) .background(Color(.systemGroupedBackground).ignoresSafeArea())
.navigationTitle("About Payfrit") .navigationTitle("About Payfrit")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.task {
await loadAboutInfo()
}
.onAppear { .onAppear {
withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) {
appearAnimation = true appearAnimation = true
@ -125,6 +119,55 @@ struct AboutScreen: View {
} }
} }
private var appVersion: String {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0"
}
private func loadAboutInfo() async {
do {
aboutInfo = try await APIService.shared.getAboutInfo()
} catch {
// Use fallback on error
print("Failed to load about info: \(error)")
}
isLoading = false
}
/// Map icon names from API to SF Symbols
private func mapIconName(_ apiIcon: String) -> String {
// If it's already an SF Symbol name, use it
if UIImage(systemName: apiIcon) != nil {
return apiIcon
}
// Map common icon names
switch apiIcon.lowercased() {
case "beacon", "radar", "walkup":
return "wave.3.right"
case "group", "friends", "people":
return "person.3"
case "delivery", "bag", "takeaway":
return "bag"
case "payment", "card", "credit":
return "creditcard"
case "globe", "web", "website":
return "globe"
case "email", "mail":
return "envelope"
case "phone", "call":
return "phone"
case "chat", "message":
return "message"
case "task", "tasks", "check":
return "checkmark.circle"
case "cash", "money", "dollar":
return "dollarsign.circle"
case "earn", "payout":
return "creditcard"
default:
return "star"
}
}
private func featureCard(icon: String, title: String, description: String) -> some View { private func featureCard(icon: String, title: String, description: String) -> some View {
HStack(spacing: 10) { HStack(spacing: 10) {
Image(systemName: icon) Image(systemName: icon)
@ -151,6 +194,37 @@ struct AboutScreen: View {
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous)) .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.contentShape(Rectangle()) .contentShape(Rectangle())
} }
private func contactRow(contact: AboutContact) -> some View {
HStack(spacing: 10) {
Image(systemName: mapIconName(contact.icon))
.font(.subheadline)
.foregroundColor(.payfritGreen)
.frame(width: 28, height: 28)
.background(Color.payfritGreen.opacity(0.1))
.clipShape(RoundedRectangle(cornerRadius: 6, style: .continuous))
VStack(alignment: .leading, spacing: 2) {
Text(contact.label)
.font(.caption)
.fontWeight(.medium)
.foregroundColor(.primary)
Text(contact.url.replacingOccurrences(of: "https://", with: "").replacingOccurrences(of: "http://", with: ""))
.font(.caption2)
.foregroundColor(.secondary)
}
Spacer()
Image(systemName: "arrow.up.right")
.font(.caption2)
.foregroundColor(.secondary)
}
.padding(12)
.background(Color(.secondarySystemGroupedBackground))
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.contentShape(Rectangle())
}
} }
// MARK: - Staggered Appear Modifier // MARK: - Staggered Appear Modifier

View file

@ -183,6 +183,7 @@ struct TaskDetailScreen: View {
let fromDetails = details?.orderTotal ?? 0 let fromDetails = details?.orderTotal ?? 0
let fromTask = task.orderTotal let fromTask = task.orderTotal
let cents = fromDetails > 0 ? fromDetails : fromTask let cents = fromDetails > 0 ? fromDetails : fromTask
NSLog("[Cash] orderTotal fromDetails=%.2f, fromTask=%.2f, using=%.2f, asInt=%d", fromDetails, fromTask, cents, Int(cents))
return Int(cents) return Int(cents)
} }