'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' ? '' : '' ); } 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 'NON-PED'; } // 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 = '