182 lines
6.0 KiB
PHP
182 lines
6.0 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Models;
|
||
|
|
|
||
|
|
use Illuminate\Database\Eloquent\Model;
|
||
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||
|
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||
|
|
use Illuminate\Support\Facades\Storage;
|
||
|
|
use Carbon\Carbon;
|
||
|
|
|
||
|
|
class Cat extends Model
|
||
|
|
{
|
||
|
|
use SoftDeletes;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* SINKRONISASI TOTAL: 22 Kolom Database
|
||
|
|
* Memasukkan berat_terakhir, lokasi, dan kolom identitas lainnya.
|
||
|
|
*/
|
||
|
|
protected $fillable = [
|
||
|
|
'nama_kucing', 'ras', 'registry', 'jenis_kelamin', 'tanggal_lahir',
|
||
|
|
'foto', 'berat_terakhir', 'lokasi', 'riwayat_sakit_terakhir',
|
||
|
|
'jadwal_vaksin', 'jadwal_obat_cacing', 'jadwal_obat_kutu',
|
||
|
|
'jadwal_grooming', 'induk_jantan_id', 'induk_betina_id',
|
||
|
|
'lokasi_kandang', 'pic_id', 'berat_badan',
|
||
|
|
'pedigree', 'microchip', 'status', 'kode_ems' // Kolom tambahan dari UI Anda
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Casting Laravel 11/12 Style
|
||
|
|
*/
|
||
|
|
protected function casts(): array
|
||
|
|
{
|
||
|
|
return [
|
||
|
|
'tanggal_lahir' => 'date',
|
||
|
|
'jadwal_vaksin' => 'date',
|
||
|
|
'jadwal_obat_cacing' => 'date',
|
||
|
|
'jadwal_obat_kutu' => 'date',
|
||
|
|
'jadwal_grooming' => 'date',
|
||
|
|
'registry' => 'array',
|
||
|
|
'berat_badan' => 'decimal:2',
|
||
|
|
'berat_terakhir' => 'decimal:2',
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
/* -------------------------------------------------------------------------- */
|
||
|
|
/* RELATIONS */
|
||
|
|
/* -------------------------------------------------------------------------- */
|
||
|
|
|
||
|
|
public function treatments(): HasMany
|
||
|
|
{
|
||
|
|
return $this->hasMany(Treatment::class);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function weightHistories(): HasMany
|
||
|
|
{
|
||
|
|
return $this->hasMany(WeightHistory::class)->latest();
|
||
|
|
}
|
||
|
|
|
||
|
|
public function sire(): BelongsTo
|
||
|
|
{
|
||
|
|
return $this->belongsTo(Cat::class, 'induk_jantan_id')->withDefault([
|
||
|
|
'nama_kucing' => 'Unknown Sire'
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function dam(): BelongsTo
|
||
|
|
{
|
||
|
|
return $this->belongsTo(Cat::class, 'induk_betina_id')->withDefault([
|
||
|
|
'nama_kucing' => 'Unknown Dam'
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function mattingsAsSire(): HasMany
|
||
|
|
{
|
||
|
|
return $this->hasMany(Matting::class, 'sire_id');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function mattingsAsDam(): HasMany
|
||
|
|
{
|
||
|
|
return $this->hasMany(Matting::class, 'dam_id');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function pic(): BelongsTo
|
||
|
|
{
|
||
|
|
return $this->belongsTo(User::class, 'pic_id')->withDefault([
|
||
|
|
'name' => 'System'
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* -------------------------------------------------------------------------- */
|
||
|
|
/* ACCESSORS */
|
||
|
|
/* -------------------------------------------------------------------------- */
|
||
|
|
|
||
|
|
protected function genderIcon(): Attribute
|
||
|
|
{
|
||
|
|
return Attribute::make(
|
||
|
|
// Database menggunakan enum 'Jantan'/'Betina' (Case Sensitive)
|
||
|
|
get: fn () => strtolower($this->jenis_kelamin) === 'jantan'
|
||
|
|
? '<i class="fas fa-mars text-indigo-500"></i>'
|
||
|
|
: '<i class="fas fa-venus text-rose-500"></i>'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function fotoUrl(): Attribute
|
||
|
|
{
|
||
|
|
return Attribute::make(
|
||
|
|
get: fn () => $this->foto
|
||
|
|
? Storage::url($this->foto)
|
||
|
|
: asset('images/default-cat.png')
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function age(): Attribute
|
||
|
|
{
|
||
|
|
return Attribute::make(
|
||
|
|
get: function () {
|
||
|
|
if (!$this->tanggal_lahir) return 'N/A';
|
||
|
|
$diff = $this->tanggal_lahir->diff(now());
|
||
|
|
|
||
|
|
if ($diff->y > 0) return "{$diff->y} Thn, {$diff->m} Bln";
|
||
|
|
if ($diff->m > 0) return "{$diff->m} Bln, {$diff->d} Hari";
|
||
|
|
return "{$diff->d} Hari";
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Usia presisi untuk laporan medis (Tahun, Bulan, Hari)
|
||
|
|
protected function usiaDetail(): Attribute
|
||
|
|
{
|
||
|
|
return Attribute::make(
|
||
|
|
get: function () {
|
||
|
|
if (!$this->tanggal_lahir) return 'Data N/A';
|
||
|
|
$diff = $this->tanggal_lahir->diff(now());
|
||
|
|
return "{$diff->y} Thn, {$diff->m} Bln, {$diff->d} Hari";
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function registryLabel(): Attribute
|
||
|
|
{
|
||
|
|
return Attribute::make(
|
||
|
|
get: fn () => $this->registry ?? 'NON-PED'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Badges untuk registry
|
||
|
|
protected function registryBadges(): Attribute
|
||
|
|
{
|
||
|
|
return Attribute::make(
|
||
|
|
get: function () {
|
||
|
|
// Jika tidak ada registry
|
||
|
|
if (empty($this->registry)) {
|
||
|
|
return '<span class="text-[9px] text-slate-400 font-bold italic tracking-widest">NON-PED</span>';
|
||
|
|
}
|
||
|
|
|
||
|
|
// Mapping warna untuk setiap federasi
|
||
|
|
$config = [
|
||
|
|
'ICA' => ['bg' => 'bg-blue-50', 'text' => 'text-blue-700', 'border' => 'border-blue-100'],
|
||
|
|
'CFA' => ['bg' => 'bg-rose-50', 'text' => 'text-rose-700', 'border' => 'border-rose-100'],
|
||
|
|
'WCF' => ['bg' => 'bg-emerald-50', 'text' => 'text-emerald-700', 'border' => 'border-emerald-100'],
|
||
|
|
'FFF' => ['bg' => 'bg-amber-50', 'text' => 'text-amber-700', 'border' => 'border-amber-100'],
|
||
|
|
];
|
||
|
|
|
||
|
|
$html = '<div class="flex flex-wrap gap-1">';
|
||
|
|
$registries = is_array($this->registry) ? $this->registry : [$this->registry];
|
||
|
|
|
||
|
|
foreach ($registries as $reg) {
|
||
|
|
$style = $config[$reg] ?? ['bg' => 'bg-slate-50', 'text' => 'text-slate-600', 'border' => 'border-slate-200'];
|
||
|
|
|
||
|
|
$html .= "<span class='px-2 py-0.5 {$style['bg']} {$style['text']} {$style['border']} border rounded-lg text-[8px] font-black uppercase tracking-tighter shadow-sm'>";
|
||
|
|
$html .= $reg;
|
||
|
|
$html .= "</span>";
|
||
|
|
}
|
||
|
|
$html .= '</div>';
|
||
|
|
|
||
|
|
return $html;
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|