438 lines
13 KiB
TypeScript
438 lines
13 KiB
TypeScript
import type { Staff, User, Event } from "../features/workforce/type";
|
|
|
|
/**
|
|
* Mock Workforce Service
|
|
* Provides placeholder data for UI development
|
|
* Replace with actual API calls when backend is ready
|
|
*/
|
|
|
|
const mockUsers: Record<string, User> = {
|
|
admin: {
|
|
id: "admin-001",
|
|
email: "admin@krow.com",
|
|
role: "admin",
|
|
user_role: "admin",
|
|
name: "Admin User",
|
|
company_name: "Krow Workforce",
|
|
},
|
|
vendor: {
|
|
id: "vendor-001",
|
|
email: "vendor@staffagency.com",
|
|
role: "vendor",
|
|
user_role: "vendor",
|
|
name: "Vendor User",
|
|
company_name: "Staff Agency Pro",
|
|
},
|
|
client: {
|
|
id: "client-001",
|
|
email: "client@eventco.com",
|
|
role: "client",
|
|
user_role: "client",
|
|
name: "Client User",
|
|
company_name: "Event Co.",
|
|
},
|
|
operator: {
|
|
id: "operator-001",
|
|
email: "operator@krow.com",
|
|
role: "operator",
|
|
user_role: "operator",
|
|
name: "Operator User",
|
|
company_name: "Krow Workforce",
|
|
},
|
|
};
|
|
|
|
const mockStaff = [
|
|
{
|
|
id: "staff-001",
|
|
employee_name: "Sarah Johnson",
|
|
position: "Event Coordinator",
|
|
photo: "https://i.pravatar.cc/150?u=staff-001",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-001",
|
|
profile_type: "Senior",
|
|
email: "sarah.johnson@example.com",
|
|
contact_number: "+1 (555) 123-4567",
|
|
status: "Active",
|
|
skills: ["Event Management", "Customer Service", "Coordination"],
|
|
department: "Events",
|
|
hub_location: "New York",
|
|
averageRating: 4.8,
|
|
reliability_score: 95,
|
|
shift_coverage_percentage: 98,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 1).toISOString(),
|
|
employment_type: "Contract",
|
|
manager: "John Smith",
|
|
cancellation_count: 0,
|
|
no_show_count: 0,
|
|
total_shifts: 145,
|
|
},
|
|
{
|
|
id: "staff-002",
|
|
employee_name: "Michael Chen",
|
|
position: "Logistics Manager",
|
|
photo: "https://i.pravatar.cc/150?u=staff-002",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-002",
|
|
profile_type: "Intermediate",
|
|
email: "michael.chen@example.com",
|
|
contact_number: "+1 (555) 234-5678",
|
|
status: "Active",
|
|
skills: ["Logistics", "Operations", "Planning"],
|
|
department: "Operations",
|
|
hub_location: "Los Angeles",
|
|
averageRating: 4.6,
|
|
reliability_score: 88,
|
|
shift_coverage_percentage: 85,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 24 * 3).toISOString(),
|
|
employment_type: "Full-time",
|
|
manager: "Jane Williams",
|
|
cancellation_count: 2,
|
|
no_show_count: 1,
|
|
total_shifts: 156,
|
|
},
|
|
{
|
|
id: "staff-003",
|
|
employee_name: "Emma Rodriguez",
|
|
position: "Customer Service Rep",
|
|
photo: "https://i.pravatar.cc/150?u=staff-003",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-003",
|
|
profile_type: "Junior",
|
|
email: "emma.rodriguez@example.com",
|
|
contact_number: "+1 (555) 345-6789",
|
|
status: "Pending",
|
|
skills: ["Customer Service", "Communication"],
|
|
department: "Support",
|
|
hub_location: "Chicago",
|
|
averageRating: 4.3,
|
|
reliability_score: 72,
|
|
shift_coverage_percentage: 65,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 24 * 10).toISOString(),
|
|
employment_type: "Part-time",
|
|
manager: "Robert Brown",
|
|
cancellation_count: 5,
|
|
no_show_count: 3,
|
|
total_shifts: 89,
|
|
},
|
|
{
|
|
id: "staff-004",
|
|
employee_name: "James Wilson",
|
|
position: "Security Officer",
|
|
photo: "https://i.pravatar.cc/150?u=staff-004",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-004",
|
|
profile_type: "Senior",
|
|
email: "james.wilson@example.com",
|
|
contact_number: "+1 (555) 456-7890",
|
|
status: "Active",
|
|
skills: ["Security", "Safety"],
|
|
department: "Security",
|
|
hub_location: "Miami",
|
|
averageRating: 4.9,
|
|
reliability_score: 99,
|
|
shift_coverage_percentage: 100,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 2).toISOString(),
|
|
employment_type: "Full-time",
|
|
manager: "Patricia Davis",
|
|
cancellation_count: 0,
|
|
no_show_count: 0,
|
|
total_shifts: 198,
|
|
},
|
|
{
|
|
id: "staff-005",
|
|
employee_name: "Lisa Anderson",
|
|
position: "HR Specialist",
|
|
photo: "https://i.pravatar.cc/150?u=staff-005",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-005",
|
|
profile_type: "Intermediate",
|
|
email: "lisa.anderson@example.com",
|
|
contact_number: "+1 (555) 567-8901",
|
|
status: "Suspended",
|
|
skills: ["HR", "Recruitment"],
|
|
department: "Human Resources",
|
|
hub_location: "New York",
|
|
averageRating: 4.5,
|
|
reliability_score: 91,
|
|
shift_coverage_percentage: 92,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30).toISOString(),
|
|
employment_type: "Full-time",
|
|
manager: "John Smith",
|
|
cancellation_count: 1,
|
|
no_show_count: 0,
|
|
total_shifts: 167,
|
|
},
|
|
{
|
|
id: "staff-006",
|
|
employee_name: "David Martinez",
|
|
position: "Data Analyst",
|
|
photo: "https://i.pravatar.cc/150?u=staff-006",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-006",
|
|
profile_type: "Senior",
|
|
email: "david.martinez@example.com",
|
|
contact_number: "+1 (555) 678-9012",
|
|
status: "Active",
|
|
skills: ["Data Analysis", "Reporting", "SQL"],
|
|
department: "Analytics",
|
|
hub_location: "San Francisco",
|
|
averageRating: 4.7,
|
|
reliability_score: 93,
|
|
shift_coverage_percentage: 87,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5).toISOString(),
|
|
employment_type: "Contract",
|
|
manager: "Michael Thompson",
|
|
cancellation_count: 1,
|
|
no_show_count: 1,
|
|
total_shifts: 134,
|
|
},
|
|
{
|
|
id: "staff-007",
|
|
employee_name: "Jessica Lee",
|
|
position: "Project Manager",
|
|
photo: "https://i.pravatar.cc/150?u=staff-007",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-007",
|
|
profile_type: "Senior",
|
|
email: "jessica.lee@example.com",
|
|
contact_number: "+1 (555) 789-0123",
|
|
status: "Active",
|
|
skills: ["Project Management", "Agile"],
|
|
department: "Projects",
|
|
hub_location: "Boston",
|
|
averageRating: 4.4,
|
|
reliability_score: 85,
|
|
shift_coverage_percentage: 79,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7).toISOString(),
|
|
employment_type: "Full-time",
|
|
manager: "Sarah Johnson",
|
|
cancellation_count: 3,
|
|
no_show_count: 1,
|
|
total_shifts: 142,
|
|
},
|
|
{
|
|
id: "staff-008",
|
|
employee_name: "Kevin Thompson",
|
|
position: "Business Analyst",
|
|
photo: "https://i.pravatar.cc/150?u=staff-008",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-008",
|
|
profile_type: "Intermediate",
|
|
email: "kevin.thompson@example.com",
|
|
contact_number: "+1 (555) 890-1234",
|
|
status: "Pending",
|
|
skills: ["Business Analysis", "Strategy"],
|
|
department: "Strategy",
|
|
hub_location: "Austin",
|
|
averageRating: 4.2,
|
|
reliability_score: 68,
|
|
shift_coverage_percentage: 72,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 24 * 14).toISOString(),
|
|
employment_type: "Part-time",
|
|
manager: "Robert Brown",
|
|
cancellation_count: 6,
|
|
no_show_count: 2,
|
|
total_shifts: 95,
|
|
},
|
|
{
|
|
id: "staff-009",
|
|
employee_name: "Nicole White",
|
|
position: "Marketing Manager",
|
|
photo: "https://i.pravatar.cc/150?u=staff-009",
|
|
photo_url: "https://i.pravatar.cc/150?u=staff-009",
|
|
profile_type: "Senior",
|
|
email: "nicole.white@example.com",
|
|
contact_number: "+1 (555) 901-2345",
|
|
status: "Active",
|
|
skills: ["Marketing", "Branding"],
|
|
department: "Marketing",
|
|
hub_location: "Seattle",
|
|
averageRating: 4.6,
|
|
reliability_score: 89,
|
|
shift_coverage_percentage: 86,
|
|
vendor_id: "vendor-001",
|
|
vendor_name: "Staff Agency Pro",
|
|
created_by: "vendor@staffagency.com",
|
|
created_date: new Date().toISOString(),
|
|
last_active: new Date(Date.now() - 1000 * 60 * 60 * 24 * 4).toISOString(),
|
|
employment_type: "Full-time",
|
|
manager: "Patricia Davis",
|
|
cancellation_count: 2,
|
|
no_show_count: 0,
|
|
total_shifts: 178,
|
|
},
|
|
] as unknown as Staff[];
|
|
|
|
const mockEvents: Event[] = [
|
|
{
|
|
id: "event-001",
|
|
business_name: "Event Co.",
|
|
client_email: "client@eventco.com",
|
|
created_by: "client@eventco.com",
|
|
assigned_staff: [
|
|
{ staff_id: "staff-001" },
|
|
{ staff_id: "staff-004" },
|
|
],
|
|
},
|
|
{
|
|
id: "event-002",
|
|
business_name: "Event Co.",
|
|
client_email: "client@eventco.com",
|
|
created_by: "client@eventco.com",
|
|
assigned_staff: [
|
|
{ staff_id: "staff-002" },
|
|
{ staff_id: "staff-009" },
|
|
],
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Simulates API delay for realistic behavior
|
|
*/
|
|
const delay = (ms: number = 500) =>
|
|
new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
/**
|
|
* Workforce Service - Mock implementation
|
|
*/
|
|
export const workforceService = {
|
|
auth: {
|
|
/**
|
|
* Get current user (mocked)
|
|
* In production, this would verify Firebase auth session
|
|
*/
|
|
me: async (): Promise<User> => {
|
|
await delay(800);
|
|
// Return a random user for demonstration
|
|
const users = Object.values(mockUsers);
|
|
return users[Math.floor(Math.random() * users.length)];
|
|
},
|
|
|
|
/**
|
|
* Sign out user (mocked)
|
|
*/
|
|
logout: async (): Promise<void> => {
|
|
await delay(300);
|
|
console.log("User logged out (mock)");
|
|
},
|
|
},
|
|
|
|
entities: {
|
|
Staff: {
|
|
/**
|
|
* List all staff members
|
|
* @param sortBy - Sort field (e.g., '-created_date' for descending)
|
|
*/
|
|
list: async (sortBy?: string): Promise<Staff[]> => {
|
|
await delay(1200);
|
|
|
|
const staffList = [...mockStaff];
|
|
|
|
// Simple sorting logic
|
|
if (sortBy === "-created_date") {
|
|
staffList.sort(
|
|
(a, b) =>
|
|
new Date(b.created_date || 0).getTime() -
|
|
new Date(a.created_date || 0).getTime()
|
|
);
|
|
} else if (sortBy === "created_date") {
|
|
staffList.sort(
|
|
(a, b) =>
|
|
new Date(a.created_date || 0).getTime() -
|
|
new Date(b.created_date || 0).getTime()
|
|
);
|
|
}
|
|
|
|
return staffList;
|
|
},
|
|
|
|
/**
|
|
* Get single staff member by ID
|
|
*/
|
|
get: async (id: string): Promise<Staff | null> => {
|
|
await delay(600);
|
|
return mockStaff.find((s) => s.id === id) || null;
|
|
},
|
|
|
|
/**
|
|
* Create new staff member
|
|
*/
|
|
create: async (staff: Partial<Staff>): Promise<Staff> => {
|
|
await delay(1000);
|
|
const newStaff: Staff = {
|
|
...staff,
|
|
id: `staff-${Date.now()}`,
|
|
created_date: new Date().toISOString(),
|
|
} as Staff;
|
|
mockStaff.push(newStaff);
|
|
return newStaff;
|
|
},
|
|
|
|
/**
|
|
* Update staff member
|
|
*/
|
|
update: async (id: string, updates: Partial<Staff>): Promise<Staff> => {
|
|
await delay(800);
|
|
const index = mockStaff.findIndex((s) => s.id === id);
|
|
if (index === -1) throw new Error("Staff not found");
|
|
mockStaff[index] = { ...mockStaff[index], ...updates };
|
|
return mockStaff[index];
|
|
},
|
|
|
|
/**
|
|
* Delete staff member
|
|
*/
|
|
delete: async (id: string): Promise<void> => {
|
|
await delay(600);
|
|
const index = mockStaff.findIndex((s) => s.id === id);
|
|
if (index === -1) throw new Error("Staff not found");
|
|
mockStaff.splice(index, 1);
|
|
},
|
|
},
|
|
|
|
Event: {
|
|
/**
|
|
* List all events
|
|
*/
|
|
list: async (): Promise<Event[]> => {
|
|
await delay(1000);
|
|
return [...mockEvents];
|
|
},
|
|
|
|
/**
|
|
* Get single event by ID
|
|
*/
|
|
get: async (id: string): Promise<Event | null> => {
|
|
await delay(600);
|
|
return mockEvents.find((e) => e.id === id) || null;
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export default workforceService;
|