* @created 2025-08-08 * @location Made in Germany 🇩🇪 */ namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; /** * User Model * Represents application users with authentication and profile features */ class User extends Authenticatable implements MustVerifyEmail { use HasApiTokens, HasFactory, Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'first_name', 'last_name', 'email', 'password', 'phone', 'date_of_birth', 'gender', 'avatar', 'bio', 'website', 'linkedin', 'github', 'twitter', 'preferences', 'newsletter_subscribed', 'last_login_at', 'last_login_ip', 'status', 'suspended_at', 'suspension_reason', 'login_attempts', 'locked_until', 'locale', 'timezone', 'two_factor_enabled', 'two_factor_secret', 'two_factor_recovery_codes', 'profile_completed_at' ]; /** * The attributes that should be hidden for serialization. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'last_login_at' => 'datetime', 'date_of_birth' => 'date', 'suspended_at' => 'datetime', 'locked_until' => 'datetime', 'profile_completed_at' => 'datetime', 'newsletter_subscribed' => 'boolean', 'two_factor_enabled' => 'boolean', 'preferences' => 'array', 'two_factor_recovery_codes' => 'array', 'password' => 'hashed', ]; } /** * Get the user's full name. */ public function getFullNameAttribute(): string { return "{$this->first_name} {$this->last_name}"; } /** * Get the user's initials. */ public function getInitialsAttribute(): string { return strtoupper(substr($this->first_name, 0, 1) . substr($this->last_name, 0, 1)); } /** * Get the user's avatar URL. */ public function getAvatarUrlAttribute(): string { if ($this->avatar) { return asset('storage/avatars/' . $this->avatar); } return "https://ui-avatars.com/api/?name={$this->initials}&background=667eea&color=fff&size=200"; } /** * Check if user has completed their profile. */ public function hasCompletedProfile(): bool { $requiredFields = ['first_name', 'last_name', 'email', 'phone', 'city', 'country']; foreach ($requiredFields as $field) { if (empty($this->$field)) { return false; } } return true; } /** * Get the user's resumes. */ public function resumes(): HasMany { return $this->hasMany(Resume::class)->orderBy('updated_at', 'desc'); } /** * Get the user's active resumes. */ public function activeResumes(): HasMany { return $this->resumes()->where('is_active', true); } /** * Get the user's completed resumes. */ public function completedResumes(): HasMany { return $this->resumes()->where('is_completed', true); } /** * Update user's last login information. */ public function updateLastLogin(string $ipAddress): void { $this->update([ 'last_login_at' => now(), 'last_login_ip' => $ipAddress, ]); } /** * Scope a query to only include active users. */ public function scopeActive($query) { return $query->where('is_active', true); } /** * Scope a query to only include verified users. */ public function scopeVerified($query) { return $query->whereNotNull('email_verified_at'); } }