attributes->get('sponsor'); $sponsorId = $sponsor ? $sponsor->id : null; try { // Recent charity/update announcements for the dashboard preview $recentEvents = Announcement::where(function ($q) use ($sponsorId) { $q->where('status', 'approved'); if ($sponsorId) { $q->orWhere('sponsor_id', $sponsorId); } }) ->latest() ->limit(5) ->get() ->map(function ($event) { $content = $event->body; if (strpos($event->body, '{"type":"Charity"') === 0) { $decoded = json_decode($event->body, true); if ($decoded) { $content = $decoded['content'] ?? $event->body; } } return [ 'id' => $event->id, 'title' => $event->title, 'body' => $content, 'type' => strtolower($event->type), 'status' => $event->status ?? 'pending', 'created_at' => $event->created_at->toIso8601String(), 'time_ago' => $event->created_at->diffForHumans(), ]; }); return response()->json([ 'success' => true, 'data' => [ 'sponsor' => [ 'id' => $sponsor->id, 'full_name' => $sponsor->full_name, 'organization_name' => $sponsor->organization_name, 'mobile' => $sponsor->mobile, 'email' => $sponsor->email, 'city' => $sponsor->city, 'nationality' => $sponsor->nationality, 'is_verified' => $sponsor->is_verified, 'status' => $sponsor->status, 'license_file' => $sponsor->license_file ? asset($sponsor->license_file) : null, 'emirates_id_file' => $sponsor->emirates_id_file ? asset($sponsor->emirates_id_file) : null, 'license_expiry' => $sponsor->license_expiry ? $sponsor->license_expiry->toDateString() : null, 'validity' => $sponsor->license_expiry ? ($sponsor->license_expiry->isFuture() ? 'Valid' : 'Expired') : 'Pending Review', 'joined_at' => $sponsor->created_at->toIso8601String(), ], 'recent_charity_events' => $recentEvents, 'total_events' => Announcement::where(function ($q) use ($sponsorId) { $q->where('status', 'approved'); if ($sponsorId) { $q->orWhere('sponsor_id', $sponsorId); } })->count(), 'employer_stats' => [ 'total' => \App\Models\User::where('role', 'employer')->count(), 'active' => \App\Models\User::where('role', 'employer')->where('subscription_status', 'active')->count(), ], 'worker_stats' => [ 'total' => \App\Models\Worker::count(), 'active' => \App\Models\Worker::where('status', 'active')->count(), ], ] ], 200); } catch (\Exception $e) { logger()->error('Sponsor Dashboard API Failure: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'An error occurred while loading your dashboard.', 'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error' ], 500); } } /** * GET /api/sponsors/charity-events * * Returns a paginated list of all charity/announcement events. */ public function getCharityEvents(Request $request) { try { $page = (int) $request->input('page', 1); $perPage = (int) $request->input('per_page', 15); $type = $request->input('type'); // optional filter: 'charity', 'update', etc. /** @var Sponsor $sponsor */ $sponsor = $request->attributes->get('sponsor'); $sponsorId = $sponsor ? $sponsor->id : null; $query = Announcement::with(['employer.employerProfile', 'sponsor']) ->where(function ($q) use ($sponsorId) { $q->where('status', 'approved'); if ($sponsorId) { $q->orWhere('sponsor_id', $sponsorId); } }) ->latest(); if ($type) { if (strtolower($type) === 'charity') { $query->whereIn('type', ['charity', 'Charity']); } else { $query->where('type', $type); } } $total = $query->count(); $offset = ($page - 1) * $perPage; $events = $query->skip($offset)->take($perPage)->get() ->map(function ($event) { $postedBy = 'System'; $organization = 'Migrant Support'; if ($event->sponsor_id) { $postedBy = $event->sponsor->full_name; $organization = $event->sponsor->organization_name; } elseif ($event->employer_id) { $postedBy = $event->employer->name; $organization = optional($event->employer)->employerProfile->company_name ?? 'Migrant Support'; } // Decode charity details if they exist in json $charityDetails = null; $content = $event->body; if (strpos($event->body, '{"type":"Charity"') === 0) { $decoded = json_decode($event->body, true); if ($decoded) { $charityDetails = $decoded; $content = $decoded['content'] ?? $event->body; } } return [ 'id' => $event->id, 'title' => $event->title, 'body' => $content, 'type' => strtolower($event->type), 'status' => $event->status ?? 'pending', 'remarks' => $event->remarks, 'posted_by' => $postedBy, 'organization' => $organization, 'created_at' => $event->created_at->toIso8601String(), 'time_ago' => $event->created_at->diffForHumans(), 'charity_details' => $charityDetails, ]; }); return response()->json([ 'success' => true, 'data' => [ 'events' => $events, 'pagination' => [ 'total' => $total, 'per_page' => $perPage, 'current_page' => $page, 'last_page' => max(1, (int) ceil($total / $perPage)), ], ] ], 200); } catch (\Exception $e) { logger()->error('Sponsor Charity Events API Failure: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'An error occurred while fetching charity events.', 'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error' ], 500); } } /** * POST /api/sponsors/charity-events * * Creates/Posts a new charity event for the authenticated sponsor. */ public function postCharityEvent(Request $request) { /** @var Sponsor $sponsor */ $sponsor = $request->attributes->get('sponsor'); if (!$sponsor) { return response()->json([ 'success' => false, 'message' => 'Unauthorized.' ], 401); } $validator = \Illuminate\Support\Facades\Validator::make($request->all(), [ 'title' => 'required|string|max:255', 'body' => 'required|string', 'type' => 'nullable|string|in:charity,info,warning,success', 'event_date' => 'required|string', 'start_time' => 'required|string', 'end_time' => 'required|string', 'provided_items' => 'required|string', 'location_details' => 'required|string', 'location_pin' => 'required|string|url', ]); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => $validator->errors() ], 422); } try { $eventTime = $request->start_time . ' - ' . $request->end_time; $bodyJson = json_encode([ 'type' => 'Charity', 'provided_items' => $request->provided_items, 'event_date' => $request->event_date, 'event_time' => $eventTime, 'location_details' => $request->location_details, 'location_pin' => $request->location_pin, 'content' => $request->body, ]); $event = Announcement::create([ 'title' => $request->title, 'body' => $bodyJson, 'type' => $request->type ?? 'charity', 'sponsor_id' => $sponsor->id, 'status' => 'pending', ]); // Decode charity details for the response representation $charityDetails = null; $content = $event->body; if (strpos($event->body, '{"type":"Charity"') === 0) { $decoded = json_decode($event->body, true); if ($decoded) { $charityDetails = $decoded; $content = $decoded['content'] ?? $event->body; } } return response()->json([ 'success' => true, 'message' => 'Charity event posted successfully.', 'data' => [ 'id' => $event->id, 'title' => $event->title, 'body' => $content, 'type' => strtolower($event->type), 'posted_by' => $sponsor->full_name, 'organization' => $sponsor->organization_name, 'created_at' => $event->created_at->toIso8601String(), 'charity_details' => $charityDetails, ] ], 201); } catch (\Exception $e) { logger()->error('Sponsor Post Charity Event API Failure: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'An error occurred while posting the charity event.', 'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error' ], 500); } } /** * GET /api/sponsors/profile * * Returns the authenticated sponsor's full profile. */ public function getProfile(Request $request) { /** @var Sponsor $sponsor */ $sponsor = $request->attributes->get('sponsor'); return response()->json([ 'success' => true, 'data' => [ 'sponsor' => [ 'id' => $sponsor->id, 'full_name' => $sponsor->full_name, 'organization_name' => $sponsor->organization_name, 'mobile' => $sponsor->mobile, 'email' => $sponsor->email, 'nationality' => $sponsor->nationality, 'city' => $sponsor->city, 'address' => $sponsor->address, 'country_code' => $sponsor->country_code, 'is_verified' => $sponsor->is_verified, 'status' => $sponsor->status, 'license_file' => $sponsor->license_file ? asset($sponsor->license_file) : null, 'emirates_id_file' => $sponsor->emirates_id_file ? asset($sponsor->emirates_id_file) : null, 'license_expiry' => $sponsor->license_expiry ? $sponsor->license_expiry->toDateString() : null, 'validity' => $sponsor->license_expiry ? ($sponsor->license_expiry->isFuture() ? 'Valid' : 'Expired') : 'Pending Review', 'joined_at' => $sponsor->created_at->toIso8601String(), ] ] ], 200); } }