Add role-aware cash collection for staff vs admin

Parse RoleID from myBusinesses API. CashCollectionSheet now shows
role-appropriate messaging: staff keeps cash, admin deposits to business.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
John Pinkyfloyd 2026-03-04 20:01:24 -08:00
parent 8d604649a2
commit bbdc5a91c2
6 changed files with 47 additions and 6 deletions

View file

@ -456,7 +456,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.2;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.mizerek.payfritworks;
PRODUCT_NAME = "Payfrit Works";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@ -488,7 +488,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.2;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.mizerek.payfritworks;
PRODUCT_NAME = "Payfrit Works";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

View file

@ -9,6 +9,7 @@ struct Employment: Identifiable {
let employeeStatusId: Int
let pendingTaskCount: Int
let activeTaskCount: Int
let roleId: Int // 1=Staff, 2=Manager, 3=Admin
var id: Int { employeeId }
@ -24,6 +25,7 @@ struct Employment: Identifiable {
employeeStatusId = WorkTask.parseInt(json["EmployeeStatusID"] ?? json["StatusID"]) ?? 0
pendingTaskCount = WorkTask.parseInt(json["PendingTaskCount"]) ?? 0
activeTaskCount = WorkTask.parseInt(json["ActiveTaskCount"]) ?? 0
roleId = WorkTask.parseInt(json["RoleID"] ?? json["ROLEID"] ?? json["roleId"] ?? json["role_id"]) ?? 1
}
var statusName: String {
@ -34,4 +36,14 @@ struct Employment: Identifiable {
default: return "Unknown"
}
}
/// Human-readable role name derived from roleId
var roleName: String {
switch roleId {
case 1: return "Staff"
case 2: return "Manager"
case 3: return "Admin"
default: return "Staff"
}
}
}

View file

@ -7,6 +7,7 @@ final class AppState: ObservableObject {
@Published var userPhotoUrl: String?
@Published var userToken: String?
@Published var businessId: Int = 0
@Published var roleId: Int = 1 // 1=Staff, 2=Manager, 3=Admin
@Published var isAuthenticated = false
@Published var shouldPopToRoot = false
@Published var shouldPopToTaskList = false
@ -34,8 +35,19 @@ final class AppState: ObservableObject {
self.isAuthenticated = true
}
func setBusinessId(_ id: Int) {
func setBusinessId(_ id: Int, roleId: Int = 1) {
self.businessId = id
self.roleId = roleId
}
/// Human-readable role name
var roleName: String {
switch roleId {
case 1: return "Staff"
case 2: return "Manager"
case 3: return "Admin"
default: return "Staff"
}
}
func clearAuth() {

View file

@ -72,7 +72,7 @@ struct BusinessSelectionScreen: View {
TaskListScreen(businessName: biz.businessName)
.onAppear {
Task { await APIService.shared.setBusinessId(biz.businessId) }
appState.setBusinessId(biz.businessId)
appState.setBusinessId(biz.businessId, roleId: biz.roleId)
}
}
}

View file

@ -48,7 +48,7 @@ struct ProfileScreen: View {
.fontWeight(.bold)
.foregroundColor(.primary)
Text("Worker")
Text(appState.roleName)
.font(.caption)
.foregroundColor(.secondary)
}
@ -68,7 +68,7 @@ struct ProfileScreen: View {
VStack(spacing: 0) {
infoRow(icon: "person.fill", label: "Name", value: displayName)
Divider().padding(.leading, 54)
infoRow(icon: "briefcase.fill", label: "Role", value: "Worker")
infoRow(icon: "briefcase.fill", label: "Role", value: appState.roleName)
}
.background(Color(.secondarySystemGroupedBackground))
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))

View file

@ -111,6 +111,7 @@ struct TaskDetailScreen: View {
CashCollectionSheet(
orderTotalCents: orderTotalCents,
taskId: task.taskId,
roleId: appState.roleId,
onComplete: { appState.popToRoot() }
)
}
@ -762,6 +763,7 @@ struct TaskDetailScreen: View {
struct CashCollectionSheet: View {
let orderTotalCents: Int
let taskId: Int
let roleId: Int // 1=Staff, 2=Manager, 3=Admin
let onComplete: () -> Void
@Environment(\.dismiss) var dismiss
@ -769,6 +771,8 @@ struct CashCollectionSheet: View {
@State private var isProcessing = false
@State private var errorMessage: String?
private var isAdmin: Bool { roleId >= 2 }
private var orderTotalDollars: Double { Double(orderTotalCents) / 100 }
private var cashReceivedCents: Int? {
@ -848,6 +852,19 @@ struct CashCollectionSheet: View {
.cornerRadius(12)
}
// Role-based cash routing info
HStack(spacing: 8) {
Image(systemName: isAdmin ? "building.2.fill" : "person.fill")
.foregroundColor(.secondary)
Text(isAdmin ? "Cash will be deposited to the business register" : "Cash will be applied to your balance")
.font(.callout)
.foregroundColor(.secondary)
}
.padding(12)
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(.systemGray6))
.cornerRadius(10)
if let err = errorMessage {
Text(err)
.font(.callout)