feat: enhance model attributes with formatted accessors for improved date representation across various models

This commit is contained in:
Yoga Pangestu 2026-04-02 11:55:29 +07:00
parent bccc36ca81
commit aa3bb2ec76
15 changed files with 374 additions and 26 deletions

View File

@ -3,6 +3,7 @@
namespace App\Models;
use App\Enums\AssignmentType;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -14,10 +15,16 @@
class Assignment extends Model implements HasMedia
{
// --- Traits ---
use HasFactory, InteractsWithMedia, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
// --- Casts ---
protected function casts(): array
{
return [
@ -26,6 +33,25 @@ protected function casts(): array
];
}
// --- Accessors & Mutators ---
protected function formattedDueDate(): Attribute
{
return Attribute::get(fn () => $this->due_date?->translatedFormat('l, d M Y H:i'));
}
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignmentPins(): HasMany
{
return $this->hasMany(AssignmentPin::class);

View File

@ -2,13 +2,30 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AssignmentPin extends Model
{
// --- Properties ---
protected $guarded = ['id'];
// --- Accessors & Mutators ---
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignment(): BelongsTo
{
return $this->belongsTo(Assignment::class);

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -10,10 +11,16 @@
class AssignmentSubmission extends Model implements HasMedia
{
// --- Traits ---
use HasFactory, InteractsWithMedia;
// --- Properties ---
protected $guarded = ['id'];
// --- Casts ---
protected function casts(): array
{
return [
@ -21,6 +28,25 @@ protected function casts(): array
];
}
// --- Accessors & Mutators ---
protected function formattedSubmittedAt(): Attribute
{
return Attribute::get(fn () => $this->submitted_at?->translatedFormat('l, d M Y H:i'));
}
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignment(): BelongsTo
{
return $this->belongsTo(Assignment::class);

View File

@ -2,16 +2,35 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AssignmentTarget extends Model
{
// --- Traits ---
use HasFactory;
// --- Properties ---
protected $guarded = ['id'];
// --- Accessors & Mutators ---
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignment(): BelongsTo
{
return $this->belongsTo(Assignment::class);

View File

@ -2,16 +2,23 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Attendance extends Model
{
// --- Traits ---
use HasFactory;
// --- Properties ---
protected $guarded = ['id'];
// --- Casts ---
protected function casts(): array
{
return [
@ -20,6 +27,30 @@ protected function casts(): array
];
}
// --- Accessors & Mutators ---
protected function formattedDate(): Attribute
{
return Attribute::get(fn () => $this->date?->translatedFormat('l, d M Y'));
}
protected function formattedAttendedAt(): Attribute
{
return Attribute::get(fn () => $this->attended_at?->translatedFormat('l, d M Y H:i'));
}
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function classSession(): BelongsTo
{
return $this->belongsTo(ClassSession::class);

View File

@ -10,8 +10,12 @@
class Changelog extends Model
{
// --- Traits ---
use HasFactory, SoftDeletes;
// --- Properties ---
protected $fillable = [
'version',
'release_date',
@ -21,24 +25,33 @@ class Changelog extends Model
'description',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
// --- Casts ---
protected $casts = [
'release_date' => 'date',
'changes' => 'array',
'release_date' => 'date',
'type' => ChangelogType::class,
];
public function formattedVersion(): Attribute
// --- Accessors & Mutators ---
protected function formattedVersion(): Attribute
{
return Attribute::get(fn () => strtoupper($this->version));
}
public function formattedReleaseDate(): Attribute
protected function formattedReleaseDate(): Attribute
{
return Attribute::get(fn () => $this->release_date->translatedFormat('l, d M Y'));
}
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
}

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -10,20 +11,55 @@
class ClassSession extends Model
{
// --- Traits ---
use HasFactory, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
// --- Casts ---
protected function casts(): array
{
return [
'date' => 'date',
'end_time' => 'datetime',
'session_number' => 'integer',
'start_time' => 'datetime',
'end_time' => 'datetime',
];
}
// --- Accessors & Mutators ---
protected function formattedDate(): Attribute
{
return Attribute::get(fn () => $this->date?->translatedFormat('l, d M Y'));
}
protected function formattedStartTime(): Attribute
{
return Attribute::get(fn () => $this->start_time?->translatedFormat('H:i'));
}
protected function formattedEndTime(): Attribute
{
return Attribute::get(fn () => $this->end_time?->translatedFormat('H:i'));
}
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignments(): HasMany
{
return $this->hasMany(Assignment::class);

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@ -10,10 +11,28 @@
class Course extends Model
{
// --- Traits ---
use HasFactory, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
// --- Accessors & Mutators ---
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignments(): HasMany
{
return $this->hasMany(Assignment::class);

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -10,10 +11,16 @@
class CourseSchedule extends Model
{
// --- Traits ---
use HasFactory, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
// --- Casts ---
protected function casts(): array
{
return [
@ -22,13 +29,37 @@ protected function casts(): array
];
}
public function course(): BelongsTo
// --- Accessors & Mutators ---
protected function formattedStartTime(): Attribute
{
return $this->belongsTo(Course::class);
return Attribute::get(fn () => $this->start_time?->translatedFormat('H:i'));
}
protected function formattedEndTime(): Attribute
{
return Attribute::get(fn () => $this->end_time?->translatedFormat('H:i'));
}
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function attendances(): HasMany
{
return $this->hasMany(Attendance::class);
}
public function course(): BelongsTo
{
return $this->belongsTo(Course::class);
}
}

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -11,17 +12,35 @@
class Material extends Model implements HasMedia
{
// --- Traits ---
use HasFactory, InteractsWithMedia, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
public function course(): BelongsTo
// --- Accessors & Mutators ---
protected function formattedCreatedAt(): Attribute
{
return $this->belongsTo(Course::class);
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function classSession(): BelongsTo
{
return $this->belongsTo(ClassSession::class);
}
public function course(): BelongsTo
{
return $this->belongsTo(Course::class);
}
}

View File

@ -5,6 +5,7 @@
use App\Enums\Sex;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -14,10 +15,16 @@
class Student extends Model
{
// --- Traits ---
use HasFactory, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
// --- Casts ---
protected function casts(): array
{
return [
@ -26,6 +33,8 @@ protected function casts(): array
];
}
// --- Scopes ---
#[Scope]
protected function male(Builder $query): void
{
@ -38,6 +47,25 @@ protected function female(Builder $query): void
$query->where('sex', Sex::Female);
}
// --- Accessors & Mutators ---
protected function formattedDateOfBirth(): Attribute
{
return Attribute::get(fn () => $this->date_of_birth?->translatedFormat('l, d M Y'));
}
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignmentPins(): HasMany
{
return $this->hasMany(AssignmentPin::class);

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -11,15 +12,28 @@
class StudyGroup extends Model
{
// --- Traits ---
use HasFactory, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
public function isLeader(Student $student): bool
// --- Accessors & Mutators ---
protected function formattedCreatedAt(): Attribute
{
return $this->leader_id === $student->id;
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function assignmentSubmissions(): HasMany
{
return $this->hasMany(AssignmentSubmission::class);
@ -60,6 +74,13 @@ public function students(): BelongsToMany
return $this->belongsToMany(Student::class, 'study_group_members');
}
// --- Methods ---
public function isLeader(Student $student): bool
{
return $this->leader_id === $student->id;
}
public static function getBusyStudentIdsForCourses(array $courseIds, ?int $excludeGroupId = null): array
{
$busyMemberIds = StudyGroupMember::whereHas(

View File

@ -2,16 +2,35 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class StudyGroupMember extends Model
{
// --- Traits ---
use HasFactory;
// --- Properties ---
protected $guarded = ['id'];
// --- Accessors & Mutators ---
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function student(): BelongsTo
{
return $this->belongsTo(Student::class);

View File

@ -20,15 +20,21 @@
class User extends Authenticatable implements FilamentUser
{
// --- Traits ---
/** @use HasFactory<UserFactory> */
use HasFacehashAvatar, HasFactory, HasRoles, Notifiable, SoftDeletes;
// --- Properties ---
protected $guarded = ['id'];
protected $hidden = [
'password',
];
// --- Casts ---
protected function casts(): array
{
return [
@ -37,6 +43,8 @@ protected function casts(): array
];
}
// --- Scopes ---
#[Scope]
protected function active(Builder $query): void
{
@ -49,10 +57,7 @@ protected function inactive(Builder $query): void
$query->where('is_active', IsActive::Inactive);
}
public function canAccessPanel(Panel $panel): bool
{
return $this->is_active === IsActive::Active;
}
// --- Accessors & Mutators ---
protected function name(): Attribute
{
@ -61,20 +66,39 @@ protected function name(): Attribute
);
}
public function student(): HasOne
protected function formattedCreatedAt(): Attribute
{
return $this->hasOne(Student::class);
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function settings(): HasOne
{
return $this->hasOne(UserSetting::class)->withDefault([
'notif_style' => NotifStyle::Cheerful,
'primary_color' => 'amber', // Cheerful yellow
'primary_color' => 'amber',
'font' => 'Inter',
'content_width' => 'full',
'border_radius' => 'lg',
'top_navigation' => false,
]);
}
public function student(): HasOne
{
return $this->hasOne(Student::class);
}
// --- Methods ---
public function canAccessPanel(Panel $panel): bool
{
return $this->is_active === IsActive::Active;
}
}

View File

@ -3,17 +3,17 @@
namespace App\Models;
use App\Enums\NotifStyle;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class UserSetting extends Model
{
// --- Properties ---
protected $guarded = ['id'];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
// --- Casts ---
protected function casts(): array
{
@ -22,4 +22,23 @@ protected function casts(): array
'top_navigation' => 'boolean',
];
}
// --- Accessors & Mutators ---
protected function formattedCreatedAt(): Attribute
{
return Attribute::get(fn () => $this->created_at->translatedFormat('l, d M Y H:i'));
}
protected function formattedUpdatedAt(): Attribute
{
return Attribute::get(fn () => $this->updated_at?->translatedFormat('l, d M Y H:i'));
}
// --- Relations ---
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}