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:
parent
8d604649a2
commit
bbdc5a91c2
6 changed files with 47 additions and 6 deletions
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue