*/ use HasApiTokens, HasFactory, HasUlids, Notifiable, SoftDeletes; /** * The attributes that are mass assignable. * * @var list */ protected $fillable = [ 'name', 'email', 'locale', 'role', 'email_verified_at', 'password', 'avatar_url', 'height', 'bio', 'account_verified_at', 'daily_calorie_goal', 'daily_protein_goal', 'daily_carbs_goal', 'daily_fats_goal', 'physical_activity_level', 'weight_goal', 'pace_preference', 'sex', 'date_of_birth', 'suspended_at', 'suspended_by', 'suspended_reason', ]; /** * The attributes that should be hidden for serialization. * * @var list */ protected $hidden = [ 'password', 'remember_token', ]; /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'account_verified_at' => 'datetime', 'password' => 'hashed', 'daily_calorie_goal' => 'integer', 'daily_protein_goal' => 'float', 'daily_carbs_goal' => 'float', 'daily_fats_goal' => 'float', 'physical_activity_level' => PhysicalActivityLevel::class, 'weight_goal' => WeightGoal::class, 'pace_preference' => PacePreference::class, 'sex' => UserSex::class, 'role' => UserRole::class, 'date_of_birth' => 'immutable_date', 'suspended_at' => 'datetime', ]; } public function getFilamentAvatarUrl(): ?string { return Storage::url($this->avatar_url); } public function deviceTokens(): HasMany { return $this->hasMany(DeviceToken::class); } public function mealPosts(): HasMany { return $this->hasMany(MealPosts::class); } public function workouts(): HasMany { return $this->hasMany(WorkoutSessions::class); } public function stravaConnection(): HasOne { return $this->hasOne(StravaConnection::class); } public function reportsMade(): HasMany { return $this->hasMany(Report::class, 'reporter_id'); } public function receivedReports(): MorphMany { return $this->morphMany(Report::class, 'reportable'); } public function moderationCase(): MorphOne { return $this->morphOne(ModerationCase::class, 'caseable'); } public function assignedModerationCases(): HasMany { return $this->hasMany(ModerationCase::class, 'assigned_to'); } public function resolvedModerationCases(): HasMany { return $this->hasMany(ModerationCase::class, 'resolved_by'); } public function suspendedBy(): BelongsTo { return $this->belongsTo(self::class, 'suspended_by'); } public function isSuspended(): bool { return $this->suspended_at !== null; } public function routeNotificationForExpoPush(): array { return $this->deviceTokens() ->orderBy('id') ->pluck('expo_push_token') ->all(); } public function preferredLocale(): ?string { return $this->locale ?: 'en'; } public function isAdmin(): bool { return $this->role === UserRole::ADMIN; } public function canAccessPanel(Panel $panel): bool { return $this->role === UserRole::ADMIN || $this->role === UserRole::MODERATOR; } }