feat: history and calculate needs for user
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\NutritionPlanSource;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUlids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class NutritionPlan extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\NutritionPlanFactory> */
|
||||
use HasFactory, HasUlids;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'source',
|
||||
'formula_version',
|
||||
'calories',
|
||||
'proteins',
|
||||
'carbs',
|
||||
'fats',
|
||||
'resting_metabolism',
|
||||
'maintenance_calories',
|
||||
'calorie_adjustment_percent',
|
||||
'calculation_details',
|
||||
'is_active',
|
||||
'effective_from',
|
||||
'effective_until',
|
||||
];
|
||||
|
||||
protected $attributes = [
|
||||
'is_active' => true,
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'source' => NutritionPlanSource::class,
|
||||
'calories' => 'integer',
|
||||
'proteins' => 'float',
|
||||
'carbs' => 'float',
|
||||
'fats' => 'float',
|
||||
'resting_metabolism' => 'integer',
|
||||
'maintenance_calories' => 'integer',
|
||||
'calorie_adjustment_percent' => 'float',
|
||||
'calculation_details' => 'array',
|
||||
'is_active' => 'boolean',
|
||||
'effective_from' => 'immutable_datetime',
|
||||
'effective_until' => 'immutable_datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function weeklyReviews(): HasMany
|
||||
{
|
||||
return $this->hasMany(WeeklyReview::class);
|
||||
}
|
||||
}
|
||||
+39
-8
@@ -51,6 +51,7 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
'password',
|
||||
'avatar_url',
|
||||
'height',
|
||||
'target_weight',
|
||||
'bio',
|
||||
'account_verified_at',
|
||||
'certification_purchased_at',
|
||||
@@ -58,15 +59,13 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
'subscription_store',
|
||||
'subscription_expires_at',
|
||||
'subscription_is_trial',
|
||||
'daily_calorie_goal',
|
||||
'daily_protein_goal',
|
||||
'daily_carbs_goal',
|
||||
'daily_fats_goal',
|
||||
'physical_activity_level',
|
||||
'weight_goal',
|
||||
'pace_preference',
|
||||
'sex',
|
||||
'date_of_birth',
|
||||
'onboarding_completed_at',
|
||||
'nutrition_estimate_accepted_at',
|
||||
'terms_accepted_at',
|
||||
'social_notifications_enabled',
|
||||
'engagement_reminders_enabled',
|
||||
@@ -97,16 +96,16 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
'account_verified_at' => 'datetime',
|
||||
'certification_purchased_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'daily_calorie_goal' => 'integer',
|
||||
'daily_protein_goal' => 'float',
|
||||
'daily_carbs_goal' => 'float',
|
||||
'daily_fats_goal' => 'float',
|
||||
'height' => 'integer',
|
||||
'target_weight' => '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',
|
||||
'onboarding_completed_at' => 'datetime',
|
||||
'nutrition_estimate_accepted_at' => 'datetime',
|
||||
'terms_accepted_at' => 'datetime',
|
||||
'social_notifications_enabled' => 'boolean',
|
||||
'engagement_reminders_enabled' => 'boolean',
|
||||
@@ -146,6 +145,38 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
|
||||
return $this->hasMany(WorkoutSessions::class);
|
||||
}
|
||||
|
||||
public function nutritionPlans(): HasMany
|
||||
{
|
||||
return $this->hasMany(NutritionPlan::class);
|
||||
}
|
||||
|
||||
public function activeNutritionPlan(): HasOne
|
||||
{
|
||||
return $this->hasOne(NutritionPlan::class)
|
||||
->where('is_active', true)
|
||||
->latestOfMany('effective_from');
|
||||
}
|
||||
|
||||
public function weightEntries(): HasMany
|
||||
{
|
||||
return $this->hasMany(WeightEntry::class);
|
||||
}
|
||||
|
||||
public function latestWeightEntry(): HasOne
|
||||
{
|
||||
return $this->hasOne(WeightEntry::class)->latestOfMany('measured_at');
|
||||
}
|
||||
|
||||
public function weeklyReviews(): HasMany
|
||||
{
|
||||
return $this->hasMany(WeeklyReview::class);
|
||||
}
|
||||
|
||||
public function hasCompletedNutritionOnboarding(): bool
|
||||
{
|
||||
return $this->onboarding_completed_at !== null;
|
||||
}
|
||||
|
||||
public function stravaConnection(): HasOne
|
||||
{
|
||||
return $this->hasOne(StravaConnection::class);
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\WeeklyReviewStatus;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUlids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class WeeklyReview extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\WeeklyReviewFactory> */
|
||||
use HasFactory, HasUlids;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'nutrition_plan_id',
|
||||
'period_start',
|
||||
'period_end',
|
||||
'average_calories',
|
||||
'average_proteins',
|
||||
'average_carbs',
|
||||
'average_fats',
|
||||
'logged_days_count',
|
||||
'weight_entries_count',
|
||||
'weight_trend_kg',
|
||||
'target_weight_trend_kg',
|
||||
'status',
|
||||
'recommended_calorie_adjustment',
|
||||
'message_code',
|
||||
'metrics',
|
||||
'generated_at',
|
||||
'accepted_at',
|
||||
'accepted_nutrition_plan_id',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'period_start' => 'immutable_date',
|
||||
'period_end' => 'immutable_date',
|
||||
'average_calories' => 'float',
|
||||
'average_proteins' => 'float',
|
||||
'average_carbs' => 'float',
|
||||
'average_fats' => 'float',
|
||||
'logged_days_count' => 'integer',
|
||||
'weight_entries_count' => 'integer',
|
||||
'weight_trend_kg' => 'float',
|
||||
'target_weight_trend_kg' => 'float',
|
||||
'status' => WeeklyReviewStatus::class,
|
||||
'recommended_calorie_adjustment' => 'integer',
|
||||
'metrics' => 'array',
|
||||
'generated_at' => 'immutable_datetime',
|
||||
'accepted_at' => 'immutable_datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function nutritionPlan(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(NutritionPlan::class);
|
||||
}
|
||||
|
||||
public function acceptedNutritionPlan(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(NutritionPlan::class, 'accepted_nutrition_plan_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUlids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class WeightEntry extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\WeightEntryFactory> */
|
||||
use HasFactory, HasUlids;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'weight_kg',
|
||||
'source',
|
||||
'measured_at',
|
||||
];
|
||||
|
||||
protected $attributes = [
|
||||
'source' => 'manual',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'weight_kg' => 'float',
|
||||
'measured_at' => 'immutable_datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user