715 lines
32 KiB
PHP
715 lines
32 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Announcement;
|
|
use App\Models\Sponsor;
|
|
use Illuminate\Http\Request;
|
|
|
|
class SponsorController extends Controller
|
|
{
|
|
/**
|
|
* GET /api/sponsors/dashboard
|
|
*
|
|
* Returns the sponsor's profile summary and unread charity event count.
|
|
*/
|
|
public function getDashboard(Request $request)
|
|
{
|
|
/** @var Sponsor $sponsor */
|
|
$sponsor = $request->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' => $this->buildSponsorResponse($sponsor)
|
|
]
|
|
], 200);
|
|
}
|
|
|
|
/**
|
|
* Build the standardized sponsor response array with nested license and emirates_id objects.
|
|
*/
|
|
private function buildSponsorResponse(Sponsor $sponsor): array
|
|
{
|
|
$licenseData = [
|
|
'license_number' => $sponsor->license_data['license_no'] ?? $sponsor->license_data['license_number'] ?? null,
|
|
'organization_name' => $sponsor->organization_name,
|
|
'expiry_date' => $sponsor->license_expiry ? $sponsor->license_expiry->toDateString() : ($sponsor->license_data['expiry_date'] ?? null),
|
|
'document_type' => $sponsor->license_data['document_type'] ?? null,
|
|
'country' => $sponsor->license_data['country'] ?? null,
|
|
'authority' => $sponsor->license_data['authority'] ?? null,
|
|
'license_no' => $sponsor->license_data['license_no'] ?? null,
|
|
'company_name' => $sponsor->license_data['company_name'] ?? null,
|
|
'business_name' => $sponsor->license_data['business_name'] ?? null,
|
|
'license_category' => $sponsor->license_data['license_category'] ?? null,
|
|
'legal_type' => $sponsor->license_data['legal_type'] ?? null,
|
|
'issue_date' => $sponsor->license_data['issue_date'] ?? null,
|
|
'main_license_no' => $sponsor->license_data['main_license_no'] ?? null,
|
|
'register_no' => $sponsor->license_data['register_no'] ?? null,
|
|
'dcci_no' => $sponsor->license_data['dcci_no'] ?? null,
|
|
'members' => $sponsor->license_data['members'] ?? [],
|
|
];
|
|
|
|
$emiratesIdData = null;
|
|
if ($sponsor->emirates_id) {
|
|
$emiratesIdData = [
|
|
'emirates_id_number' => $sponsor->emirates_id,
|
|
'name' => $sponsor->emirates_id_name,
|
|
'nationality' => $sponsor->nationality,
|
|
'date_of_birth' => $sponsor->emirates_id_dob,
|
|
'expiry_date' => $sponsor->emirates_id_expiry,
|
|
'issue_date' => $sponsor->emirates_id_issue_date,
|
|
'employer' => $sponsor->emirates_id_employer,
|
|
'issue_place' => $sponsor->emirates_id_issue_place,
|
|
'occupation' => $sponsor->emirates_id_occupation,
|
|
];
|
|
}
|
|
|
|
return [
|
|
'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(),
|
|
'fcm_token' => $sponsor->fcm_token,
|
|
'license' => $licenseData,
|
|
'emirates_id' => $emiratesIdData,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Change sponsor's password.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function changePassword(Request $request)
|
|
{
|
|
/** @var Sponsor $sponsor */
|
|
$sponsor = $request->attributes->get('sponsor');
|
|
|
|
$validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
|
|
'current_password' => 'required|string',
|
|
'new_password' => 'required|string|min:8|confirmed',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Validation error.',
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
if (!\Illuminate\Support\Facades\Hash::check($request->current_password, $sponsor->password)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Validation error.',
|
|
'errors' => [
|
|
'current_password' => ['The current password is incorrect.']
|
|
]
|
|
], 422);
|
|
}
|
|
|
|
try {
|
|
$hashedPassword = \Illuminate\Support\Facades\Hash::make($request->new_password);
|
|
|
|
// Update sponsor table
|
|
$sponsor->update([
|
|
'password' => $hashedPassword
|
|
]);
|
|
|
|
// Sync with corresponding employer user record if found
|
|
$matchingEmployer = \App\Models\User::where('email', $sponsor->email)
|
|
->where('role', 'employer')
|
|
->first();
|
|
if ($matchingEmployer) {
|
|
$matchingEmployer->update([
|
|
'password' => $hashedPassword
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Password changed successfully.'
|
|
], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
logger()->error('Mobile Sponsor Change Password Failure: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'An error occurred while changing password.',
|
|
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /api/sponsors/profile/update
|
|
*
|
|
* Updates the authenticated sponsor's profile.
|
|
*/
|
|
public function updateProfile(Request $request)
|
|
{
|
|
/** @var Sponsor $sponsor */
|
|
$sponsor = $request->attributes->get('sponsor');
|
|
|
|
if (!$sponsor) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Unauthorized.'
|
|
], 401);
|
|
}
|
|
|
|
// Find matching employer user using sponsor's original email
|
|
$oldEmail = $sponsor->getOriginal('email') ?? $sponsor->email;
|
|
$matchingUser = \App\Models\User::where('email', $oldEmail)
|
|
->where('role', 'employer')
|
|
->first();
|
|
|
|
$matchingUserId = $matchingUser ? $matchingUser->id : 'NULL';
|
|
|
|
$validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
|
|
'name' => 'required_without:full_name|nullable|string|max:255',
|
|
'full_name' => 'required_without:name|nullable|string|max:255',
|
|
'email' => 'required|email|max:255|unique:sponsors,email,' . $sponsor->id . '|unique:users,email,' . $matchingUserId,
|
|
'mobile' => 'required|string|max:255|unique:sponsors,mobile,' . $sponsor->id,
|
|
'organization_name' => 'required|string|max:255',
|
|
'city' => 'required|string|max:100',
|
|
'address' => 'required|string|max:255',
|
|
'nationality' => 'required|string|max:100',
|
|
'country_code' => 'required|string|max:10',
|
|
'fcm_token' => 'nullable|string|max:255',
|
|
|
|
// Emirates ID — accepts nested object OR flat fields
|
|
'emirates_id' => 'nullable|array',
|
|
'emirates_id.emirates_id_number' => 'nullable|string|max:255',
|
|
'emirates_id.name' => 'nullable|string|max:255',
|
|
'emirates_id.nationality' => 'nullable|string|max:255',
|
|
'emirates_id.date_of_birth' => 'nullable|string|max:255',
|
|
'emirates_id.expiry_date' => 'nullable|string|max:255',
|
|
'emirates_id.issue_date' => 'nullable|string|max:255',
|
|
'emirates_id.employer' => 'nullable|string|max:255',
|
|
'emirates_id.issue_place' => 'nullable|string|max:255',
|
|
'emirates_id.occupation' => 'nullable|string|max:255',
|
|
|
|
// Flat emirates ID fields (backward compatibility)
|
|
'id_number' => 'nullable|string|max:255',
|
|
'card_number' => 'nullable|string|max:255',
|
|
'date_of_birth' => 'nullable|string|max:255',
|
|
'gender' => 'nullable|string|max:255',
|
|
'issue_date' => 'nullable|string|max:255',
|
|
'expiry_date' => 'nullable|string|max:255',
|
|
'occupation' => 'nullable|string|max:255',
|
|
'employer' => 'nullable|string|max:255',
|
|
'issuing_place' => 'nullable|string|max:255',
|
|
|
|
// License — accepts nested object OR flat fields
|
|
'license' => 'nullable|array',
|
|
'license.document_type' => 'nullable|string|max:255',
|
|
'license.country' => 'nullable|string|max:255',
|
|
'license.authority' => 'nullable|string|max:255',
|
|
'license.license_no' => 'nullable|string|max:255',
|
|
'license.company_name' => 'nullable|string|max:255',
|
|
'license.business_name' => 'nullable|string|max:255',
|
|
'license.license_category' => 'nullable|string|max:255',
|
|
'license.legal_type' => 'nullable|string|max:255',
|
|
'license.main_license_no' => 'nullable|string|max:255',
|
|
'license.register_no' => 'nullable|string|max:255',
|
|
'license.dcci_no' => 'nullable|string|max:255',
|
|
'license.members' => 'nullable|array',
|
|
|
|
// Flat license fields (backward compatibility)
|
|
'document_type' => 'nullable|string|max:255',
|
|
'country' => 'nullable|string|max:255',
|
|
'authority' => 'nullable|string|max:255',
|
|
'license_no' => 'nullable|string|max:255',
|
|
'company_name' => 'nullable|string|max:255',
|
|
'business_name' => 'nullable|string|max:255',
|
|
'license_category' => 'nullable|string|max:255',
|
|
'legal_type' => 'nullable|string|max:255',
|
|
'main_license_no' => 'nullable|string|max:255',
|
|
'register_no' => 'nullable|string|max:255',
|
|
'dcci_no' => 'nullable|string|max:255',
|
|
'members' => 'nullable|array',
|
|
]);
|
|
|
|
$validator->after(function ($validator) use ($request) {
|
|
$nameFromEid = $request->input('emirates_id.name') ?? $request->input('full_name');
|
|
if ($request->has('full_name') && !$request->filled('full_name') && !$nameFromEid) {
|
|
$validator->errors()->add('full_name', 'Failed to extract name from the Emirates ID. Please upload a clearer document.');
|
|
}
|
|
});
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Validation error.',
|
|
'errors' => $validator->errors()
|
|
], 422);
|
|
}
|
|
|
|
try {
|
|
// Resolve nested emirates_id input into flat variables
|
|
$eidInput = $request->input('emirates_id');
|
|
$eidNumber = null;
|
|
$eidName = null;
|
|
$eidDob = null;
|
|
$eidExpiry = null;
|
|
$eidIssueDate = null;
|
|
$eidEmployer = null;
|
|
$eidIssuePlace = null;
|
|
$eidOccupation = null;
|
|
$eidCardNumber = null;
|
|
$eidGender = null;
|
|
|
|
if (is_array($eidInput)) {
|
|
$eidNumber = $eidInput['emirates_id_number'] ?? $eidInput['id_number'] ?? null;
|
|
$eidName = $eidInput['name'] ?? null;
|
|
$eidDob = $eidInput['date_of_birth'] ?? $eidInput['dob'] ?? null;
|
|
$eidExpiry = $eidInput['expiry_date'] ?? null;
|
|
$eidIssueDate = $eidInput['issue_date'] ?? null;
|
|
$eidEmployer = $eidInput['employer'] ?? null;
|
|
$eidIssuePlace = $eidInput['issue_place'] ?? $eidInput['issuing_place'] ?? null;
|
|
$eidOccupation = $eidInput['occupation'] ?? null;
|
|
$eidCardNumber = $eidInput['card_number'] ?? null;
|
|
$eidGender = $eidInput['gender'] ?? null;
|
|
}
|
|
|
|
// Flat field fallbacks (backward compatibility)
|
|
$eidNumber = $eidNumber ?? $request->input('id_number');
|
|
$eidName = $eidName ?? $request->input('full_name');
|
|
$eidDob = $eidDob ?? $request->input('date_of_birth');
|
|
$eidExpiry = $eidExpiry ?? $request->input('expiry_date');
|
|
$eidIssueDate = $eidIssueDate ?? $request->input('issue_date');
|
|
$eidEmployer = $eidEmployer ?? $request->input('employer');
|
|
$eidIssuePlace = $eidIssuePlace ?? $request->input('issuing_place');
|
|
$eidOccupation = $eidOccupation ?? $request->input('occupation');
|
|
$eidCardNumber = $eidCardNumber ?? $request->input('card_number');
|
|
$eidGender = $eidGender ?? $request->input('gender');
|
|
|
|
$nameToUse = $eidName ?? $request->name ?? $request->full_name;
|
|
|
|
// Validate Emirates ID immutability — once set, it cannot be changed
|
|
if ($eidNumber) {
|
|
if ($sponsor->emirates_id && $sponsor->emirates_id !== $eidNumber) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Emirates ID mismatch. You cannot change your registered Emirates ID number.',
|
|
'errors' => [
|
|
'id_number' => ['Emirates ID mismatch.']
|
|
]
|
|
], 422);
|
|
}
|
|
}
|
|
|
|
// Sync with corresponding employer user and profile records if found
|
|
if ($matchingUser) {
|
|
$userData = [
|
|
'name' => $nameToUse,
|
|
'email' => $request->email,
|
|
];
|
|
if ($request->has('fcm_token')) {
|
|
$userData['fcm_token'] = $request->fcm_token;
|
|
}
|
|
$matchingUser->update($userData);
|
|
|
|
$profile = $matchingUser->employerProfile;
|
|
if (!$profile) {
|
|
$profile = new \App\Models\EmployerProfile(['user_id' => $matchingUser->id]);
|
|
}
|
|
$profile->address = $request->address;
|
|
$profile->phone = $request->mobile;
|
|
|
|
if ($eidNumber) { $profile->emirates_id_number = $eidNumber; }
|
|
if ($eidCardNumber) { $profile->emirates_id_card_number = $eidCardNumber; }
|
|
if ($eidName) { $profile->emirates_id_name = $eidName; }
|
|
if ($eidDob) { $profile->emirates_id_dob = $eidDob; }
|
|
if ($request->has('nationality')) { $profile->nationality = $request->nationality; }
|
|
if ($eidGender) { $profile->emirates_id_gender = $eidGender; }
|
|
if ($eidIssueDate) { $profile->emirates_id_issue_date = $eidIssueDate; }
|
|
if ($eidExpiry) { $profile->emirates_id_expiry = $eidExpiry; }
|
|
if ($eidOccupation) { $profile->emirates_id_occupation = $eidOccupation; }
|
|
if ($eidEmployer) { $profile->emirates_id_employer = $eidEmployer; }
|
|
if ($eidIssuePlace) { $profile->emirates_id_issue_place = $eidIssuePlace; }
|
|
|
|
$profile->save();
|
|
}
|
|
|
|
// Update Sponsor profile
|
|
$sponsorData = [
|
|
'full_name' => $nameToUse,
|
|
'email' => $request->email,
|
|
'mobile' => $request->mobile,
|
|
'organization_name' => $request->organization_name,
|
|
'city' => $request->city,
|
|
'address' => $request->address,
|
|
'nationality' => $request->nationality,
|
|
'country_code' => $request->country_code,
|
|
];
|
|
|
|
if ($request->has('fcm_token')) {
|
|
$sponsorData['fcm_token'] = $request->fcm_token;
|
|
}
|
|
|
|
if ($eidNumber) { $sponsorData['emirates_id'] = $eidNumber; }
|
|
if ($eidCardNumber) { $sponsorData['emirates_id_card_number'] = $eidCardNumber; }
|
|
if ($eidName) { $sponsorData['emirates_id_name'] = $eidName; }
|
|
if ($eidDob) { $sponsorData['emirates_id_dob'] = $eidDob; }
|
|
if ($eidGender) { $sponsorData['emirates_id_gender'] = $eidGender; }
|
|
if ($eidIssueDate) { $sponsorData['emirates_id_issue_date'] = $eidIssueDate; }
|
|
if ($eidExpiry) { $sponsorData['emirates_id_expiry'] = $eidExpiry; }
|
|
if ($eidOccupation) { $sponsorData['emirates_id_occupation'] = $eidOccupation; }
|
|
if ($eidEmployer) { $sponsorData['emirates_id_employer'] = $eidEmployer; }
|
|
if ($eidIssuePlace) { $sponsorData['emirates_id_issue_place'] = $eidIssuePlace; }
|
|
|
|
// Parse and merge license data — from nested license object or flat fields
|
|
$currentLicenseData = is_array($sponsor->license_data) ? $sponsor->license_data : [];
|
|
$licenseInput = $request->input('license');
|
|
$newLicenseData = [];
|
|
|
|
if (is_array($licenseInput)) {
|
|
foreach ([
|
|
'document_type', 'country', 'authority', 'license_no', 'company_name',
|
|
'business_name', 'license_category', 'legal_type', 'issue_date', 'expiry_date',
|
|
'main_license_no', 'register_no', 'dcci_no', 'members'
|
|
] as $field) {
|
|
if (isset($licenseInput[$field])) {
|
|
$newLicenseData[$field] = $licenseInput[$field];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Flat field fallbacks (backward compatibility)
|
|
foreach ([
|
|
'document_type', 'country', 'authority', 'license_no', 'company_name',
|
|
'business_name', 'license_category', 'legal_type', 'issue_date', 'expiry_date',
|
|
'main_license_no', 'register_no', 'dcci_no', 'members'
|
|
] as $field) {
|
|
if (!isset($newLicenseData[$field]) && $request->has($field)) {
|
|
$newLicenseData[$field] = $request->input($field);
|
|
}
|
|
}
|
|
|
|
if (!empty($newLicenseData)) {
|
|
$sponsorData['license_data'] = array_merge($currentLicenseData, $newLicenseData);
|
|
}
|
|
|
|
$sponsor->update($sponsorData);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Profile updated successfully.',
|
|
'data' => [
|
|
'sponsor' => $this->buildSponsorResponse($sponsor)
|
|
]
|
|
], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
logger()->error('Mobile Sponsor Update Profile Failure: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'An error occurred while updating profile.',
|
|
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
|
|
], 500);
|
|
}
|
|
}
|
|
}
|