wasChanged('status')) { $oldStatus = $worker->getOriginal('status'); $newStatus = $worker->status; $worker->notify(new \App\Notifications\GenericNotification( "Profile Status Update", "Your profile status has changed from '" . ucfirst($oldStatus) . "' to '" . ucfirst($newStatus) . "'.", [ 'type' => 'worker_status_change', 'worker_id' => $worker->id, 'old_status' => $oldStatus, 'new_status' => $newStatus, ] )); } }); } protected $fillable = [ 'name', 'email', 'phone', 'language', 'password', 'nationality', 'country', 'city', 'area', 'preferred_location', 'live_in_out', 'age', 'gender', 'salary', 'availability', 'experience', 'religion', 'bio', 'verified', 'status', 'api_token', 'in_country', 'visa_status', 'preferred_job_type', 'main_profession', 'fcm_token', ]; protected $hidden = [ 'password', 'api_token', // Hide from public serialization, returned only during auth endpoints specifically ]; protected $casts = [ 'verified' => 'boolean', 'in_country' => 'boolean', 'salary' => 'decimal:2', 'password' => 'hashed', ]; protected $appends = [ 'passport_status', 'visa_status', 'emirates_id_status', 'document_expiry_days', 'document_expiry_status', 'visa_expiry_date', 'rating', 'reviews_count', ]; public function getPassportStatusAttribute() { $passport = $this->documents->where('type', 'passport')->first(); if (!$passport) { return 'Passport Pending'; } return $this->verified ? 'Passport Verified' : 'Passport Pending'; } public function getVisaStatusAttribute() { if ($this->attributes['visa_status'] ?? null) { $val = $this->attributes['visa_status']; $normalized = strtolower(trim($val)); if (str_contains($normalized, 'residence')) { return 'Residence Visa'; } elseif (str_contains($normalized, 'employment')) { return 'Employment Visa'; } else { return 'Tourist Visa'; } } $visa = $this->documents->where('type', 'visa')->first(); if (!$visa) { return 'Residence Visa'; } $ocrData = $visa->ocr_data; $vType = $ocrData['visa_type'] ?? null; if ($vType) { $normalized = strtolower(trim($vType)); if (str_contains($normalized, 'residence')) { return 'Residence Visa'; } elseif (str_contains($normalized, 'employment')) { return 'Employment Visa'; } } return 'Tourist Visa'; } public function setVisaStatusAttribute($value) { if (empty($value)) { $this->attributes['visa_status'] = null; return; } $normalized = strtolower(trim($value)); if (str_contains($normalized, 'residence')) { $this->attributes['visa_status'] = 'Residence Visa'; } elseif (str_contains($normalized, 'employment')) { $this->attributes['visa_status'] = 'Employment Visa'; } else { $this->attributes['visa_status'] = 'Tourist Visa'; } } public function getEmiratesIdStatusAttribute() { return $this->passport_status; } public function getVisaExpiryDateAttribute() { $visa = $this->documents->where('type', 'visa')->first(); return $visa ? $visa->expiry_date : null; } public function getDocumentExpiryDaysAttribute() { $visa = $this->documents->where('type', 'visa')->first(); $doc = $visa; if (!$doc || !$doc->expiry_date) { $passport = $this->documents->where('type', 'passport')->first(); $doc = $passport; } if ($doc && $doc->expiry_date) { $expiry = \Carbon\Carbon::parse($doc->expiry_date); return (int)now()->startOfDay()->diffInDays(\Carbon\Carbon::parse($expiry)->startOfDay(), false); } return null; } public function getDocumentExpiryStatusAttribute() { $visa = $this->documents->where('type', 'visa')->first(); $doc = $visa; $typeLabel = 'Visa'; if (!$doc || !$doc->expiry_date) { $passport = $this->documents->where('type', 'passport')->first(); $doc = $passport; $typeLabel = 'Passport'; } if ($doc && $doc->expiry_date) { $expiry = \Carbon\Carbon::parse($doc->expiry_date); $days = (int)now()->startOfDay()->diffInDays(\Carbon\Carbon::parse($expiry)->startOfDay(), false); if ($days < 0) { return "$typeLabel Expired"; } return "$typeLabel expires in $days days"; } return 'No Documents'; } public function skills() { return $this->belongsToMany(Skill::class, 'worker_skills'); } public function documents() { return $this->hasMany(WorkerDocument::class); } // Relationship for job offers received public function offers() { return $this->hasMany(JobOffer::class, 'worker_id'); } public function reviews() { return $this->hasMany(Review::class); } public function employerReviews() { return $this->hasMany(EmployerReview::class, 'worker_id'); } public function getRatingAttribute() { // Prevent infinite recursion by not using relationships if we want to avoid eager load loops, // but typically $this->reviews is safe as long as we don't eager load recursively. $dbReviews = $this->reviews; $count = $dbReviews->count(); return $count > 0 ? round($dbReviews->avg('rating'), 1) : 0.0; } public function getReviewsCountAttribute() { return $this->reviews()->count(); } public function profileViews() { return $this->hasMany(ProfileView::class); } }