'REP-101', 'reporter' => 'Marina Cleaners (Employer)', 'reported_user' => 'Grace Omondi (Worker)', 'reason' => 'Profile details mismatch / False advertising', 'description' => 'The worker claims to have 4 years experience in childcare, but when interviewed, they stated they only did housekeeping.', 'status' => 'Pending Review', 'severity' => 'Medium', 'created_at' => '2026-05-22 14:30', ], [ 'id' => 'REP-102', 'reporter' => 'Siti Aminah (Worker)', 'reported_user' => 'Golden Hospitality (Employer)', 'reason' => 'Abusive message exchange', 'description' => 'Employer used inappropriate language during direct chat after worker declined an weekend offer.', 'status' => 'Escalated', 'severity' => 'High', 'created_at' => '2026-05-21 09:15', ], [ 'id' => 'REP-103', 'reporter' => 'System (Auto-Flag)', 'reported_user' => 'Amina Diop (Worker)', 'reason' => 'Suspicious document signature mismatch', 'description' => 'OCR matching detected that the signature and name on the Passport does not match the registration name.', 'status' => 'Under Investigation', 'severity' => 'High', 'created_at' => '2026-05-20 18:45', ], [ 'id' => 'REP-104', 'reporter' => 'Hassan Al Hosani (Employer)', 'reported_user' => 'Maria Santos (Worker)', 'reason' => 'No-show for interview', 'description' => 'Worker confirmed three consecutive video interviews but failed to join without notice.', 'status' => 'Resolved', 'severity' => 'Low', 'created_at' => '2026-05-18 11:00', ] ]; $rules = [ ['id' => 1, 'name' => 'IP-Range Duplication Alert', 'trigger' => 'More than 3 worker accounts from the same IP', 'status' => 'Active'], ['id' => 2, 'name' => 'OCR Match Confidence Threshold', 'trigger' => 'Passport verification confidence below 75%', 'status' => 'Active'], ['id' => 3, 'name' => 'Keyword Abuse Filter', 'trigger' => 'Vulgar/abusive words in employer messages', 'status' => 'Active'], ['id' => 4, 'name' => 'Availability Change Spammer', 'trigger' => 'Toggling availability status > 10 times in 24 hrs', 'status' => 'Inactive'], ]; $moderationQueue = [ [ 'id' => 'MOD-01', 'user' => 'Leila Bekri', 'type' => 'Worker Bio Update', 'content' => 'I am a highly skilled executive housekeeper and private chef with 8 years of luxury hospitality experience in Dubai. Contact me at +971-55-901-2384 for immediate placement.', 'flag' => 'Contains contact details (Phone number violation)', 'status' => 'Pending Approval' ], [ 'id' => 'MOD-02', 'user' => 'Fatima Zahra', 'type' => 'Worker Profile Photo', 'content' => 'https://images.unsplash.com/photo-1544717305-2782549b5136?q=80&w=600', 'flag' => 'Professional headshot check', 'status' => 'Approved' ] ]; return Inertia::render('Admin/Safety/Index', [ 'reports' => $reports, 'rules' => $rules, 'moderation_queue' => $moderationQueue ]); } /** * Resolve a safety report */ public function resolveSafetyReport(Request $request, $id) { $request->validate([ 'action' => 'required|string', 'admin_notes' => 'nullable|string' ]); return back()->with('success', "Safety Report {$id} has been resolved successfully with action: " . strtoupper($request->action)); } /** * Disputes Management Module */ public function disputes() { $tickets = [ [ 'id' => 'DISP-701', 'employer' => 'Marina Cleaners', 'worker' => 'Grace Omondi', 'subject' => 'Advance Payment Refund Dispute', 'amount_aed' => 499, 'status' => 'Open', 'created_at' => '2026-05-20', 'chat_logs' => [ ['sender' => 'Employer', 'time' => '10:05 AM', 'message' => 'I paid you the advance of 499 AED for direct transport, but you did not report to work.'], ['sender' => 'Worker', 'time' => '10:12 AM', 'message' => 'The agency driver was delayed and did not bring the entry permit paper, so I could not travel.'], ['sender' => 'Employer', 'time' => '10:14 AM', 'message' => 'That is your responsibility, I need the refund or immediate attendance.'], ['sender' => 'Worker', 'time' => '10:20 AM', 'message' => 'I do not have the money anymore, the transport ticket was already bought and non-refundable.'], ], 'evidence' => [ ['type' => 'Receipt', 'name' => 'payment_slip.pdf', 'url' => '#'], ['type' => 'Agreement', 'name' => 'hiring_agreement_signed.pdf', 'url' => '#'], ], 'admin_notes' => 'Awaiting confirmation of driver delay from the visa coordinator.' ], [ 'id' => 'DISP-702', 'employer' => 'Al Barari Real Estate', 'worker' => 'Maria Santos', 'subject' => 'Sudden Contract Termination', 'amount_aed' => 1299, 'status' => 'Under Investigation', 'created_at' => '2026-05-18', 'chat_logs' => [ ['sender' => 'Employer', 'time' => '11:00 AM', 'message' => 'We must terminate the child care contract as we are relocating to the UK next month.'], ['sender' => 'Worker', 'time' => '11:05 AM', 'message' => 'But my contract states a 30-day notice period or 1 month salary in lieu of notice.'], ['sender' => 'Employer', 'time' => '11:08 AM', 'message' => ' Relocation is a force majeure event, we can only pay for days worked.'], ], 'evidence' => [ ['type' => 'Contract', 'name' => 'relocation_uk_notice.pdf', 'url' => '#'], ], 'admin_notes' => 'Relocation relocates jurisdiction, review local UAE standard domestic contract clause 9.' ], [ 'id' => 'DISP-703', 'employer' => 'Golden Hospitality', 'worker' => 'Siti Aminah', 'subject' => 'Withheld Passport Allegation', 'amount_aed' => 0, 'status' => 'Resolved', 'created_at' => '2026-05-15', 'chat_logs' => [ ['sender' => 'Worker', 'time' => '02:00 PM', 'message' => 'Please return my passport, I need to renew my visa this week.'], ['sender' => 'Employer', 'time' => '02:10 PM', 'message' => 'We kept it for safekeeping in the company safe, you can request it whenever you want.'], ], 'evidence' => [], 'admin_notes' => 'Contacted HR manager directly. Passport was handed back to the worker on May 17th. Verified and closed.' ] ]; return Inertia::render('Admin/Disputes/Index', [ 'tickets' => $tickets ]); } /** * Resolve a Dispute Ticket */ public function resolveDispute(Request $request, $id) { $request->validate([ 'resolution' => 'required|string', 'action_taken' => 'required|string', ]); return back()->with('success', "Dispute ticket {$id} has been resolved successfully. Resolution: " . strtoupper($request->action_taken)); } /** * Add admin notes to a dispute */ public function addDisputeNote(Request $request, $id) { $request->validate([ 'note' => 'required|string' ]); return back()->with('success', "Internal admin note added to Dispute ticket {$id}."); } /** * Notifications & Campaign Management */ public function notifications() { $campaigns = [ [ 'id' => 1, 'channel' => 'Push Notification', 'recipient_type' => 'All Active Workers', 'title' => 'Availability Update Reminder', 'message' => 'Hi, please update your availability status in the app to remain visible to hiring employers this week!', 'sent_at' => '2026-05-22 10:00 AM', 'delivery_rate' => '94.2%', 'clicks' => '1,120 clicks' ], [ 'id' => 2, 'channel' => 'WhatsApp Notification', 'recipient_type' => 'Unverified Workers (Morocco & Philippines)', 'title' => 'Emirates ID Upload Alert', 'message' => 'Hello! Upload your Emirates ID to unlock direct hiring and premium salaries on the UAE Domestic Worker Marketplace. Click here: [Link]', 'sent_at' => '2026-05-20 02:30 PM', 'delivery_rate' => '98.5%', 'clicks' => '654 clicks' ], [ 'id' => 3, 'channel' => 'Push Notification', 'recipient_type' => 'Premium Employers', 'title' => 'Weekend Candidates Alert', 'message' => '12 new highly-rated verified housekeeping candidates joined today. Browse and schedule interviews now!', 'sent_at' => '2026-05-19 08:00 AM', 'delivery_rate' => '91.8%', 'clicks' => '420 clicks' ] ]; $whatsappTemplates = [ [ 'name' => 'availability_checkin_trigger', 'category' => 'Utility', 'language' => 'English & Arabic', 'text' => 'Hi {{1}}, we noticed you haven\'t updated your job availability since last week. Are you still seeking work? Reply 1 for Yes, 2 for No.', 'status' => 'Approved' ], [ 'name' => 'employer_verification_passed', 'category' => 'Account Status', 'language' => 'English', 'text' => 'Dear {{1}}, congratulations! Your employer profile for {{2}} has been verified. You can now access full candidate dossiers. Browse workers here: {{3}}', 'status' => 'Approved' ], [ 'name' => 'dispute_escalation_alert', 'category' => 'Security', 'language' => 'English', 'text' => 'Important: A dispute ticket ({{1}}) has been initiated regarding contract {{2}}. An admin mediator will reach out shortly.', 'status' => 'Pending Approval' ] ]; return Inertia::render('Admin/Notifications/Index', [ 'campaigns' => $campaigns, 'whatsapp_templates' => $whatsappTemplates ]); } /** * Broadcast notification campaign */ public function broadcastNotification(Request $request) { $request->validate([ 'channel' => 'required|in:push,whatsapp,both', 'recipients' => 'required|string', 'title' => 'required|string|max:100', 'message' => 'required|string' ]); return back()->with('success', "Notification campaign broadcasted successfully to all {$request->recipients} users!"); } /** * Payments, Revenue Reports & Refund Control */ public function refundPayment(Request $request, $id) { $request->validate([ 'refund_reason' => 'required|string', 'amount' => 'required|numeric|min:1' ]); return back()->with('success', "Refund of AED {$request->amount} initiated successfully for transaction {$id}. Refund reason: {$request->refund_reason}"); } /** * Interactive Reports & Analytics Hub */ public function analytics() { // Supply rich visual charts metadata $userGrowth = [ ['month' => 'Dec 25', 'workers' => 850, 'employers' => 210], ['month' => 'Jan 26', 'workers' => 990, 'employers' => 240], ['month' => 'Feb 26', 'workers' => 1100, 'employers' => 280], ['month' => 'Mar 26', 'workers' => 1250, 'employers' => 310], ['month' => 'Apr 26', 'workers' => 1350, 'employers' => 345], ['month' => 'May 26', 'workers' => 1420, 'employers' => 380] ]; $revenueBreakdown = [ ['month' => 'Dec 25', 'basic' => 15000, 'premium' => 18000, 'vip' => 12000], ['month' => 'Jan 26', 'basic' => 16500, 'premium' => 19500, 'vip' => 13500], ['month' => 'Feb 26', 'basic' => 18000, 'premium' => 22000, 'vip' => 15000], ['month' => 'Mar 26', 'basic' => 19200, 'premium' => 25000, 'vip' => 18500], ['month' => 'Apr 26', 'basic' => 21000, 'premium' => 29000, 'vip' => 22000], ['month' => 'May 26', 'basic' => 22500, 'premium' => 32000, 'vip' => 24000] ]; $retentionRates = [ ['cohort' => 'Month 1', 'rate' => 92], ['cohort' => 'Month 2', 'rate' => 84], ['cohort' => 'Month 3', 'rate' => 79], ['cohort' => 'Month 4', 'rate' => 74], ['cohort' => 'Month 5', 'rate' => 71], ['cohort' => 'Month 6', 'rate' => 68], ]; $hiringFunnel = [ ['stage' => 'Profiles Browsed', 'count' => 12500], ['stage' => 'Chats Initiated', 'count' => 4820], ['stage' => 'Interviews Held', 'count' => 1860], ['stage' => 'Offers Extended', 'count' => 920], ['stage' => 'Workers Hired', 'count' => 610], ]; return Inertia::render('Admin/Analytics/Index', [ 'user_growth' => $userGrowth, 'revenue_breakdown' => $revenueBreakdown, 'retention_rates' => $retentionRates, 'hiring_funnel' => $hiringFunnel ]); } /** * Global Database Searchable Audit Logs */ public function auditLogs(Request $request) { $searchTerm = $request->input('search', ''); $category = $request->input('category', 'all'); $allLogs = [ // Admin Action Logs [ 'id' => 'LOG-991', 'category' => 'admin_action', 'user' => 'SuperAdmin (support@marketplace.com)', 'action' => 'Suspended Employer account Golden Hospitality due to dispute findings', 'ip_address' => '192.168.1.1', 'timestamp' => '2026-05-23 16:45', ], [ 'id' => 'LOG-992', 'category' => 'admin_action', 'user' => 'Admin Vetting Officer', 'action' => 'Manually approved Worker Leila Bekri passport verification overriding OCR confidence', 'ip_address' => '192.168.1.5', 'timestamp' => '2026-05-23 15:20', ], // Verification Logs [ 'id' => 'LOG-993', 'category' => 'verification', 'user' => 'System OCR engine', 'action' => 'Auto-OCR Passport verification SUCCESS for worker Fatima Zahra (Morocco) • Confidence 98%', 'ip_address' => 'Auto-Trigger', 'timestamp' => '2026-05-23 14:15', ], [ 'id' => 'LOG-994', 'category' => 'verification', 'user' => 'System OCR engine', 'action' => 'Auto-OCR Passport FLAG suspicious document detected for worker Grace Omondi', 'ip_address' => 'Auto-Trigger', 'timestamp' => '2026-05-23 13:42', ], // Payment Logs [ 'id' => 'LOG-995', 'category' => 'payment', 'user' => 'Stripe Webhook', 'action' => 'Subscription PAYMENT charge of AED 499 COMPLETED. Employer: Al Barari Real Estate', 'ip_address' => 'Stripe Gateway', 'timestamp' => '2026-05-23 10:30', ], [ 'id' => 'LOG-996', 'category' => 'payment', 'user' => 'Stripe Webhook', 'action' => 'Subscription PAYMENT charge of AED 199 FAILED (Insufficient funds). Employer: Dubai Mall Services', 'ip_address' => 'Stripe Gateway', 'timestamp' => '2026-05-22 17:10', ], // Dispute Logs [ 'id' => 'LOG-997', 'category' => 'dispute', 'user' => 'SuperAdmin (support@marketplace.com)', 'action' => 'Opened Dispute Ticket DISP-701 regarding Advance Refund between Marina Cleaners & Grace Omondi', 'ip_address' => '192.168.1.1', 'timestamp' => '2026-05-22 14:45', ], // User Activity Logs [ 'id' => 'LOG-998', 'category' => 'user_activity', 'user' => 'Maria Santos (Worker)', 'action' => 'Logged in successfully via iOS Mobile App', 'ip_address' => '94.200.12.83 (Dubai)', 'timestamp' => '2026-05-23 17:02', ], [ 'id' => 'LOG-999', 'category' => 'user_activity', 'user' => 'Marina Cleaners (Employer)', 'action' => 'Browsed 14 worker candidate profiles & saved 3 shortlists', 'ip_address' => '91.74.203.11 (Abu Dhabi)', 'timestamp' => '2026-05-23 16:58', ] ]; // Filter search & category $filtered = array_filter($allLogs, function ($log) use ($searchTerm, $category) { $catMatches = $category === 'all' || $log['category'] === $category; $searchMatches = empty($searchTerm) || stripos($log['user'], $searchTerm) !== false || stripos($log['action'], $searchTerm) !== false || stripos($log['id'], $searchTerm) !== false; return $catMatches && $searchMatches; }); return Inertia::render('Admin/AuditLogs/Index', [ 'logs' => array_values($filtered), 'search' => $searchTerm, 'category' => $category, ]); } }