231 lines
9.1 KiB
PHP
231 lines
9.1 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Employer;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
use App\Models\User;
|
|
use App\Models\Shortlist;
|
|
use App\Models\Conversation;
|
|
use App\Models\Message;
|
|
use App\Models\Announcement;
|
|
use Carbon\Carbon;
|
|
|
|
class DashboardController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
// Resolve current employer user
|
|
$sess = session('user');
|
|
$sessId = is_array($sess) ? ($sess['id'] ?? null) : ($sess->id ?? null);
|
|
|
|
if (!$sessId) {
|
|
$user = User::where('role', 'employer')->first();
|
|
if ($user) {
|
|
session(['user' => (object)[
|
|
'id' => $user->id,
|
|
'name' => $user->name,
|
|
'email' => $user->email,
|
|
'role' => 'employer',
|
|
'subscription_status' => $user->subscription_status ?? 'active',
|
|
]]);
|
|
}
|
|
} else {
|
|
$user = User::find($sessId);
|
|
}
|
|
|
|
// Fallback user if DB has no users (precaution)
|
|
if (!$user) {
|
|
$user = new User([
|
|
'id' => 2,
|
|
'name' => 'John Doe',
|
|
'subscription_status' => 'active',
|
|
'subscription_expires_at' => now()->addDays(24),
|
|
]);
|
|
}
|
|
|
|
// Get subscription expires at date
|
|
$sub = \Illuminate\Support\Facades\DB::table('subscriptions')->where('user_id', $user->id)->where('status', 'active')->latest('id')->first();
|
|
$expiresAt = $sub ? Carbon::parse($sub->expires_at) : now()->addDays(24);
|
|
$daysRemaining = $expiresAt ? max(0, now()->diffInDays($expiresAt, false)) : 30;
|
|
|
|
// 1. Stats
|
|
$shortlistedCount = Shortlist::where('employer_id', $user->id)->count();
|
|
$messagesSent = Message::where('sender_id', $user->id)->where('sender_type', 'employer')->count();
|
|
$contactedWorkersCount = Conversation::where('employer_id', $user->id)->count();
|
|
$hiredCount = \App\Models\JobOffer::where('employer_id', $user->id)->where('status', 'accepted')->count() +
|
|
\App\Models\JobApplication::whereHas('jobPost', function($q) use ($user) {
|
|
$q->where('employer_id', $user->id);
|
|
})->where('status', 'hired')->count();
|
|
|
|
$stats = [
|
|
'shortlisted_count' => $shortlistedCount,
|
|
'messages_sent' => $messagesSent,
|
|
'days_remaining' => (int)$daysRemaining,
|
|
'contacted_workers_count' => $contactedWorkersCount,
|
|
'hired_count' => $hiredCount,
|
|
'analytics' => [
|
|
'profile_views' => 48,
|
|
'response_rate' => '94%',
|
|
'average_match_score' => '98%',
|
|
'weekly_activity' => [
|
|
['day' => 'Mon', 'views' => 5],
|
|
['day' => 'Tue', 'views' => 12],
|
|
['day' => 'Wed', 'views' => 8],
|
|
['day' => 'Thu', 'views' => 15],
|
|
['day' => 'Fri', 'views' => 4],
|
|
['day' => 'Sat', 'views' => 2],
|
|
['day' => 'Sun', 'views' => 2],
|
|
]
|
|
],
|
|
'recent_failed_payment' => false
|
|
];
|
|
|
|
// 2. Shortlisted workers
|
|
$shortlists = Shortlist::where('employer_id', $user->id)
|
|
->with(['worker.category', 'worker.skills'])
|
|
->get();
|
|
|
|
$shortlistedWorkers = $shortlists->map(function ($s) {
|
|
$w = $s->worker;
|
|
if (!$w) return null;
|
|
|
|
$isPending = str_contains(strtolower($w->passport_status), 'pending');
|
|
if ($w->status === 'hidden' || $isPending || $w->status === 'Hired') {
|
|
return null;
|
|
}
|
|
|
|
return [
|
|
'id' => $w->id,
|
|
'name' => $w->name,
|
|
'nationality' => $w->nationality,
|
|
'category' => $w->category ? $w->category->name : 'General Helper',
|
|
'skills' => $w->skills->pluck('name')->toArray(),
|
|
'photo_url' => null,
|
|
'verified' => (bool)$w->verified,
|
|
];
|
|
})->filter()->values()->toArray();
|
|
|
|
// 3. Recent messages
|
|
$dbConversations = Conversation::where('employer_id', $user->id)
|
|
->with(['worker', 'messages' => function ($q) {
|
|
$q->latest();
|
|
}])
|
|
->get();
|
|
|
|
$recentMessages = $dbConversations->map(function ($conv) {
|
|
$lastMsg = $conv->messages->first();
|
|
$worker = $conv->worker;
|
|
if (!$worker || !$lastMsg) return null;
|
|
|
|
return [
|
|
'id' => $conv->id,
|
|
'worker_name' => $worker->name,
|
|
'last_message' => $lastMsg->text,
|
|
'unread' => $lastMsg->sender_type === 'worker' && is_null($lastMsg->read_at),
|
|
'sent_at' => $lastMsg->created_at->diffForHumans(),
|
|
'timestamp' => $lastMsg->created_at,
|
|
];
|
|
})->filter()->sortByDesc('timestamp')->values()->toArray();
|
|
|
|
// 4. Charity Events
|
|
$dbAnnouncements = Announcement::latest()->limit(5)->get();
|
|
$announcements = $dbAnnouncements->map(function ($ann) {
|
|
$body = $ann->body;
|
|
$eventDate = null;
|
|
$eventTime = null;
|
|
$locationDetails = null;
|
|
$locationPin = null;
|
|
$providedItems = null;
|
|
|
|
if (strpos($ann->body, '{"type":"Charity"') === 0) {
|
|
$decoded = json_decode($ann->body, true);
|
|
if ($decoded) {
|
|
$body = $decoded['content'] ?? $ann->body;
|
|
$eventDate = $decoded['event_date'] ?? null;
|
|
$eventTime = $decoded['event_time'] ?? null;
|
|
$locationDetails = $decoded['location_details'] ?? null;
|
|
$locationPin = $decoded['location_pin'] ?? null;
|
|
$providedItems = $decoded['provided_items'] ?? null;
|
|
}
|
|
} else {
|
|
// Fallback structured details if plain text existed previously
|
|
$body = $ann->body;
|
|
$eventDate = $ann->created_at->addDays(2)->format('Y-m-d');
|
|
$eventTime = '9:00 AM - 3:00 PM';
|
|
$locationDetails = 'Al Quoz Community Center, Dubai';
|
|
$locationPin = 'https://maps.google.com';
|
|
$providedItems = 'Free Medical Checks & Food Supplies';
|
|
}
|
|
|
|
return [
|
|
'id' => $ann->id,
|
|
'title' => $ann->title,
|
|
'body' => $body,
|
|
'isCharity' => true,
|
|
'event_date' => $eventDate,
|
|
'event_time' => $eventTime,
|
|
'location_details' => $locationDetails,
|
|
'location_pin' => $locationPin,
|
|
'provided_items' => $providedItems,
|
|
'created_at' => $ann->created_at->format('M d, Y'),
|
|
];
|
|
})->toArray();
|
|
|
|
// 5. Recommended Workers
|
|
$recWorkers = \App\Models\Worker::with(['category', 'skills'])
|
|
->where('status', 'active')
|
|
->orderBy('verified', 'desc')
|
|
->limit(3)
|
|
->get();
|
|
|
|
$recommendedWorkers = $recWorkers->map(function ($w) {
|
|
$isPending = str_contains(strtolower($w->passport_status), 'pending');
|
|
if ($isPending || $w->status === 'hidden' || $w->status === 'Hired') {
|
|
return null;
|
|
}
|
|
|
|
return [
|
|
'id' => $w->id,
|
|
'name' => $w->name,
|
|
'nationality' => $w->nationality,
|
|
'category' => $w->category ? $w->category->name : 'General Helper',
|
|
'skills' => $w->skills->pluck('name')->toArray(),
|
|
'salary' => (int)$w->salary,
|
|
'rating' => 4.8,
|
|
'verified' => (bool)$w->verified,
|
|
];
|
|
})->filter()->values()->toArray();
|
|
|
|
// 6. Saved searches
|
|
$savedSearches = [
|
|
[
|
|
'id' => 1,
|
|
'name' => 'Nanny (Filipino, Live-in)',
|
|
'query' => 'category=Childcare&nationality=Philippines&availability=Immediate'
|
|
],
|
|
[
|
|
'id' => 2,
|
|
'name' => 'Housekeeper (Indian, 1500-2000 AED)',
|
|
'query' => 'category=Housekeeping&nationality=India&max_salary=2000'
|
|
]
|
|
];
|
|
|
|
return Inertia::render('Employer/Dashboard', [
|
|
'employer' => [
|
|
'name' => $user->name,
|
|
'subscription_status' => $sub ? $sub->status : 'active',
|
|
'subscription_expires_at' => $expiresAt ? $expiresAt->format('Y-m-d') : '2026-12-31',
|
|
'plan_name' => $sub ? (ucfirst($sub->plan_id) . ' Pass') : 'Premium Employer Pass',
|
|
],
|
|
'stats' => $stats,
|
|
'shortlisted_workers' => $shortlistedWorkers,
|
|
'recent_messages' => array_slice($recentMessages, 0, 5),
|
|
'announcements' => $announcements,
|
|
'recommended_workers' => $recommendedWorkers,
|
|
'saved_searches' => $savedSearches,
|
|
]);
|
|
}
|
|
}
|