initial commit
This commit is contained in:
@@ -3,86 +3,453 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\{Cat, Medicine, Food, Supply, Matting, Treatment};
|
||||
use App\Models\{Cat, Medicine, Food, Supply, Matting, Treatment, Kitten};
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function index()
|
||||
public function index(Request $request)
|
||||
{
|
||||
// 1. Statistik Utama
|
||||
$now = Carbon::now();
|
||||
$selectedMonth = $request->get('month', $now->format('m'));
|
||||
$selectedYear = $request->get('year', $now->format('Y'));
|
||||
$selectedGender = $request->get('gender');
|
||||
$selectedStatus = $request->get('status');
|
||||
|
||||
$stats = [
|
||||
'total_cats' => Cat::count(),
|
||||
'total_staff' => \App\Models\User::count(),
|
||||
'sick_cats' => Cat::whereNotNull('riwayat_sakit_terakhir')->count(),
|
||||
'total_kittens' => Kitten::count(),
|
||||
'sick_cats' => Cat::where('treatment_status', 1)->count(),
|
||||
'total_mating' => Matting::where('status', 'proses')->count(),
|
||||
];
|
||||
|
||||
// 2. Birth Watch: Persalinan 7 Hari ke Depan (Rumus: H+63)
|
||||
$upcomingBirths = Matting::with(['dam', 'sire', 'pic'])
|
||||
$upcomingBirths = Matting::with(['dam', 'sire'])
|
||||
->where('status', 'proses')
|
||||
->whereNotNull('tanggal_kawin')
|
||||
->whereBetween('tanggal_kawin', [
|
||||
now()->subDays(70)->toDateString(),
|
||||
now()->subDays(56)->toDateString()
|
||||
])
|
||||
->whereNotNull('tgl_kawin_awal')
|
||||
->get()
|
||||
->map(function ($mating) {
|
||||
$mating->edd = Carbon::parse($mating->tanggal_kawin)->addDays(63);
|
||||
$mating->days_to_go = (int) now()->diffInDays($mating->edd, false);
|
||||
->map(function ($mating) use ($now) {
|
||||
$mating->edd = Carbon::parse($mating->tgl_kawin_awal)->addDays(63);
|
||||
$mating->days_to_go = (int) $now->copy()->startOfDay()->diffInDays($mating->edd->copy()->startOfDay(), false);
|
||||
return $mating;
|
||||
})
|
||||
->filter(fn($m) => $m->days_to_go >= -2 && $m->days_to_go <= 7)
|
||||
->filter(fn ($mating) => $mating->days_to_go >= -2 && $mating->days_to_go <= 7)
|
||||
->sortBy('days_to_go');
|
||||
|
||||
// 3. Medical Alerts
|
||||
$medicalAlerts = [
|
||||
'vaccine' => Cat::whereNotNull('jadwal_vaksin')->where('jadwal_vaksin', '<=', now()->addDays(3))->count(),
|
||||
'flea' => Cat::whereNotNull('jadwal_obat_kutu')->where('jadwal_obat_kutu', '<=', now()->addDays(3))->count(),
|
||||
'deworming' => Cat::whereNotNull('jadwal_obat_cacing')->where('jadwal_obat_cacing', '<=', now()->addDays(3))->count(),
|
||||
'grooming' => Cat::whereNotNull('jadwal_grooming')->where('jadwal_grooming', '<=', now()->addDays(3))->count(),
|
||||
$overdueAlerts = [
|
||||
'vaccine' => [
|
||||
'count' => Cat::whereNotNull('jadwal_vaksin')->where('jadwal_vaksin', '<', $now)->count(),
|
||||
'url' => route('cats.index', ['filter_overdue' => 'vaccine']),
|
||||
],
|
||||
'flea' => [
|
||||
'count' => Cat::whereNotNull('jadwal_obat_kutu')->where('jadwal_obat_kutu', '<', $now)->count(),
|
||||
'url' => route('cats.index', ['filter_overdue' => 'flea']),
|
||||
],
|
||||
'deworming' => [
|
||||
'count' => Cat::whereNotNull('jadwal_obat_cacing')->where('jadwal_obat_cacing', '<', $now)->count(),
|
||||
'url' => route('cats.index', ['filter_overdue' => 'deworming']),
|
||||
],
|
||||
'grooming' => [
|
||||
'count' => Cat::whereNotNull('jadwal_grooming')->where('jadwal_grooming', '<', $now)->count(),
|
||||
'url' => route('cats.index', ['filter_overdue' => 'grooming']),
|
||||
],
|
||||
];
|
||||
|
||||
// 4. Inventory Critical (Stok < 5)
|
||||
$lowStock = [
|
||||
'medicines' => Medicine::where('qty', '<', 5)->get(['nama_obat as name', 'qty', 'unit']),
|
||||
'foods' => Food::where('qty', '<', 5)->get(['nama_makanan as name', 'qty', 'unit']),
|
||||
'supplies' => Supply::where('qty', '<', 5)->get(['nama_perlengkapan as name', 'qty', 'unit']),
|
||||
];
|
||||
$totalLowStock = collect($lowStock)->flatten(1)->count();
|
||||
|
||||
// 5. Chart Data: Sebaran Ras (Persian, British Shorthair, dll)
|
||||
$chartData = Cat::select('ras', DB::raw('count(*) as total'))->groupBy('ras')->get();
|
||||
|
||||
// 6. Weight Trends: Rata-rata Berat (6 Bulan Terakhir)
|
||||
$weightTrends = DB::table('weight_histories')
|
||||
/*
|
||||
* Berat terakhir untuk daftar/ranking pada bulan yang dipilih.
|
||||
* Kode ini dipertahankan agar fungsi dashboard lama tetap tersedia.
|
||||
*/
|
||||
$weightQuery = DB::table('weight_histories')
|
||||
->join('cats', 'weight_histories.cat_id', '=', 'cats.id')
|
||||
->select(
|
||||
DB::raw('AVG(berat) as avg_weight'),
|
||||
DB::raw("DATE_FORMAT(tanggal_timbang, '%M') as month"),
|
||||
DB::raw('MONTH(tanggal_timbang) as month_num')
|
||||
'cats.id as cat_id',
|
||||
'cats.nama_kucing',
|
||||
'cats.jenis_kelamin',
|
||||
'cats.status',
|
||||
'cats.tanggal_lahir',
|
||||
'weight_histories.berat',
|
||||
'weight_histories.tanggal_timbang'
|
||||
)
|
||||
->where('tanggal_timbang', '>=', now()->subMonths(6))
|
||||
->groupBy('month', 'month_num')
|
||||
->orderBy('month_num')
|
||||
->get();
|
||||
->whereIn('weight_histories.id', function ($query) use ($selectedMonth, $selectedYear) {
|
||||
$query->select(DB::raw('MAX(id)'))
|
||||
->from('weight_histories')
|
||||
->whereMonth('tanggal_timbang', $selectedMonth)
|
||||
->whereYear('tanggal_timbang', $selectedYear)
|
||||
->groupBy('cat_id');
|
||||
});
|
||||
|
||||
if ($weightTrends->isEmpty()) {
|
||||
$weightTrends = collect([(object)['month' => now()->format('F'), 'avg_weight' => 0]]);
|
||||
if ($selectedGender) {
|
||||
$weightQuery->where('cats.jenis_kelamin', $selectedGender);
|
||||
}
|
||||
|
||||
// 7. Recent Activity
|
||||
$recentTreatments = Treatment::with(['cat', 'pic'])->latest()->take(5)->get();
|
||||
if ($selectedStatus) {
|
||||
if (in_array(strtolower($selectedStatus), ['adult', 'dewasa'])) {
|
||||
$weightQuery->whereIn('cats.status', ['Adult', 'Dewasa']);
|
||||
} else {
|
||||
$weightQuery->where('cats.status', $selectedStatus);
|
||||
}
|
||||
}
|
||||
|
||||
$individualWeightData = $weightQuery
|
||||
->orderBy('weight_histories.berat', 'desc')
|
||||
->get()
|
||||
->map(function ($cat) use ($now) {
|
||||
$cat->usia = $this->formatAge($cat->tanggal_lahir, $now);
|
||||
$cat->kategori_usia = $this->ageCategory($cat->tanggal_lahir, $cat->status, $now);
|
||||
return $cat;
|
||||
});
|
||||
|
||||
$weightSummary = [
|
||||
'overall' => $individualWeightData->avg('berat') ?? 0,
|
||||
'male' => $individualWeightData->where('jenis_kelamin', 'Jantan')->avg('berat') ?? 0,
|
||||
'female' => $individualWeightData->where('jenis_kelamin', 'Betina')->avg('berat') ?? 0,
|
||||
];
|
||||
|
||||
/*
|
||||
* Pemantauan berat badan.
|
||||
* Kategori umur dihitung dari tanggal lahir agar konsisten:
|
||||
* Kitten < 7 bulan, Junior 7-11 bulan, Dewasa >= 12 bulan.
|
||||
*/
|
||||
$allowedTrendMonths = [3, 6, 12, 24];
|
||||
$weightTrendMonths = (int) $request->get('weight_months', 6);
|
||||
if (!in_array($weightTrendMonths, $allowedTrendMonths, true)) {
|
||||
$weightTrendMonths = 6;
|
||||
}
|
||||
|
||||
// Filter tabel dapat menampilkan semua kategori, sedangkan grafik individual
|
||||
// selalu dibatasi pada satu kategori agar mudah dibaca.
|
||||
$allowedTableCategories = ['Semua', 'Kitten', 'Junior', 'Dewasa'];
|
||||
$weightTableCategory = $request->get('weight_category', 'Semua');
|
||||
if (!in_array($weightTableCategory, $allowedTableCategories, true)) {
|
||||
$weightTableCategory = 'Semua';
|
||||
}
|
||||
|
||||
$allowedTrendCategories = ['Kitten', 'Junior', 'Dewasa'];
|
||||
$defaultTrendCategory = $weightTableCategory !== 'Semua' ? $weightTableCategory : 'Kitten';
|
||||
$weightTrendCategory = $request->get('trend_category', $defaultTrendCategory);
|
||||
if (!in_array($weightTrendCategory, $allowedTrendCategories, true)) {
|
||||
$weightTrendCategory = 'Kitten';
|
||||
}
|
||||
|
||||
$trendStart = $now->copy()->subMonths($weightTrendMonths - 1)->startOfMonth();
|
||||
|
||||
$weightTrendRows = DB::table('weight_histories')
|
||||
->join('cats', 'weight_histories.cat_id', '=', 'cats.id')
|
||||
->select(
|
||||
'cats.id as cat_id',
|
||||
'cats.nama_kucing',
|
||||
'cats.jenis_kelamin',
|
||||
'cats.status',
|
||||
'cats.tanggal_lahir',
|
||||
'cats.foto',
|
||||
'weight_histories.berat',
|
||||
'weight_histories.tanggal_timbang'
|
||||
)
|
||||
->whereNull('cats.deleted_at')
|
||||
->whereDate('weight_histories.tanggal_timbang', '>=', $trendStart->toDateString())
|
||||
->orderBy('weight_histories.tanggal_timbang')
|
||||
->orderBy('cats.nama_kucing')
|
||||
->get()
|
||||
->map(function ($row) use ($now) {
|
||||
$row->kategori_usia = $this->ageCategory($row->tanggal_lahir, $row->status, $now);
|
||||
$date = Carbon::parse($row->tanggal_timbang);
|
||||
$row->tanggal_iso = $date->format('Y-m-d');
|
||||
$row->bulan_iso = $date->format('Y-m');
|
||||
return $row;
|
||||
});
|
||||
|
||||
// Sumbu grafik dibuat per bulan, bukan per tanggal timbang, supaya garis tidak terlalu padat.
|
||||
$categoryMonthKeys = collect();
|
||||
for ($cursor = $trendStart->copy(); $cursor->lte($now); $cursor->addMonth()) {
|
||||
$categoryMonthKeys->push($cursor->format('Y-m'));
|
||||
}
|
||||
|
||||
$categoryAverageTrend = [
|
||||
'labels' => $categoryMonthKeys,
|
||||
'series' => collect(['Kitten', 'Junior', 'Dewasa'])->map(function ($category) use ($categoryMonthKeys, $weightTrendRows) {
|
||||
$rows = $weightTrendRows->where('kategori_usia', $category);
|
||||
|
||||
return [
|
||||
'name' => $category,
|
||||
'data' => $categoryMonthKeys->map(function ($month) use ($rows) {
|
||||
// Ambil berat terakhir setiap kucing pada bulan tersebut, lalu hitung rata-ratanya.
|
||||
$latestPerCat = $rows
|
||||
->where('bulan_iso', $month)
|
||||
->groupBy('cat_id')
|
||||
->map(fn ($catRows) => $catRows->last());
|
||||
|
||||
$value = $latestPerCat->avg('berat');
|
||||
return $value === null ? null : round((float) $value, 2);
|
||||
})->values(),
|
||||
];
|
||||
})->values(),
|
||||
];
|
||||
|
||||
// Ringkasan berdasarkan berat terakhir setiap kucing pada rentang periode.
|
||||
$latestPerCatInTrend = $weightTrendRows
|
||||
->groupBy('cat_id')
|
||||
->map(fn ($rows) => $rows->last());
|
||||
|
||||
$weightCategorySummary = collect(['Kitten', 'Junior', 'Dewasa'])->mapWithKeys(function ($category) use ($latestPerCatInTrend) {
|
||||
$rows = $latestPerCatInTrend->where('kategori_usia', $category);
|
||||
return [$category => [
|
||||
'cats' => $rows->count(),
|
||||
'average' => round((float) ($rows->avg('berat') ?? 0), 2),
|
||||
'min' => $rows->isEmpty() ? 0 : round((float) $rows->min('berat'), 2),
|
||||
'max' => $rows->isEmpty() ? 0 : round((float) $rows->max('berat'), 2),
|
||||
]];
|
||||
});
|
||||
|
||||
// KPI bulan berjalan dibanding bulan sebelumnya.
|
||||
$currentMonthKey = $now->format('Y-m');
|
||||
$previousMonthKey = $now->copy()->subMonth()->format('Y-m');
|
||||
|
||||
$latestByCatMonth = $weightTrendRows
|
||||
->groupBy(fn ($row) => $row->cat_id . '|' . $row->bulan_iso)
|
||||
->map(fn ($rows) => $rows->last());
|
||||
|
||||
$currentMonthRows = $latestByCatMonth->where('bulan_iso', $currentMonthKey)->values();
|
||||
$previousMonthRows = $latestByCatMonth->where('bulan_iso', $previousMonthKey)->values();
|
||||
|
||||
$percentChange = static function (float $current, float $previous): float {
|
||||
if ($previous <= 0) {
|
||||
return $current > 0 ? 100.0 : 0.0;
|
||||
}
|
||||
return round((($current - $previous) / $previous) * 100, 1);
|
||||
};
|
||||
|
||||
$weightKpis = [
|
||||
'weighed' => [
|
||||
'value' => $currentMonthRows->pluck('cat_id')->unique()->count(),
|
||||
'change' => $percentChange(
|
||||
(float) $currentMonthRows->pluck('cat_id')->unique()->count(),
|
||||
(float) $previousMonthRows->pluck('cat_id')->unique()->count()
|
||||
),
|
||||
],
|
||||
'categories' => collect(['Kitten', 'Junior', 'Dewasa'])->mapWithKeys(function ($category) use ($currentMonthRows, $previousMonthRows, $latestPerCatInTrend, $percentChange) {
|
||||
$currentRows = $currentMonthRows->where('kategori_usia', $category);
|
||||
$previousRows = $previousMonthRows->where('kategori_usia', $category);
|
||||
|
||||
// Jika bulan berjalan belum memiliki data, tetap tampilkan posisi berat terakhir
|
||||
// tanpa mengarang persentase perubahan.
|
||||
$currentAverage = $currentRows->isNotEmpty()
|
||||
? (float) $currentRows->avg('berat')
|
||||
: (float) ($latestPerCatInTrend->where('kategori_usia', $category)->avg('berat') ?? 0);
|
||||
$previousAverage = (float) ($previousRows->avg('berat') ?? 0);
|
||||
|
||||
return [$category => [
|
||||
'average' => round($currentAverage, 2),
|
||||
'change' => $currentRows->isNotEmpty() && $previousRows->isNotEmpty()
|
||||
? $percentChange($currentAverage, $previousAverage)
|
||||
: 0.0,
|
||||
'has_comparison' => $currentRows->isNotEmpty() && $previousRows->isNotEmpty(),
|
||||
]];
|
||||
}),
|
||||
];
|
||||
|
||||
// Grafik tren kategori terpilih: maksimal 6 kucing dengan data terlengkap.
|
||||
$selectedCategoryGroups = $weightTrendRows
|
||||
->where('kategori_usia', $weightTrendCategory)
|
||||
->groupBy('cat_id')
|
||||
->sort(function ($a, $b) {
|
||||
$countComparison = $b->count() <=> $a->count();
|
||||
if ($countComparison !== 0) {
|
||||
return $countComparison;
|
||||
}
|
||||
|
||||
return strcmp((string) $b->last()->tanggal_iso, (string) $a->last()->tanggal_iso);
|
||||
})
|
||||
->take(6);
|
||||
|
||||
$weightTrendLabels = $categoryMonthKeys->values();
|
||||
$weightTrendSeries = $selectedCategoryGroups
|
||||
->map(function ($rows) use ($categoryMonthKeys) {
|
||||
$first = $rows->first();
|
||||
$monthlyValues = $rows->groupBy('bulan_iso')->map(fn ($monthRows) => round((float) $monthRows->last()->berat, 2));
|
||||
|
||||
return [
|
||||
'cat_id' => (int) $first->cat_id,
|
||||
'name' => $first->nama_kucing,
|
||||
'category' => $first->kategori_usia,
|
||||
'data' => $categoryMonthKeys->map(fn ($month) => $monthlyValues->get($month))->values(),
|
||||
'latest' => round((float) $rows->last()->berat, 2),
|
||||
];
|
||||
})
|
||||
->values();
|
||||
|
||||
// Tabel berat terbaru. Perubahan membandingkan dua catatan terakhir pada periode terpilih.
|
||||
$weightLatestTable = $weightTrendRows
|
||||
->groupBy('cat_id')
|
||||
->map(function ($rows) {
|
||||
$rows = $rows->sortBy('tanggal_timbang')->values();
|
||||
$latest = $rows->last();
|
||||
$previous = $rows->count() > 1 ? $rows->get($rows->count() - 2) : null;
|
||||
|
||||
return [
|
||||
'cat_id' => (int) $latest->cat_id,
|
||||
'name' => $latest->nama_kucing,
|
||||
'gender' => $latest->jenis_kelamin,
|
||||
'category' => $latest->kategori_usia,
|
||||
'photo' => $latest->foto,
|
||||
'latest' => round((float) $latest->berat, 2),
|
||||
'previous' => $previous ? round((float) $previous->berat, 2) : null,
|
||||
'change' => $previous ? round((float) $latest->berat - (float) $previous->berat, 2) : null,
|
||||
'date' => $latest->tanggal_iso,
|
||||
];
|
||||
})
|
||||
->when($weightTableCategory !== 'Semua', fn ($rows) => $rows->where('category', $weightTableCategory))
|
||||
->sortByDesc('date')
|
||||
->values();
|
||||
|
||||
// Inventory
|
||||
$allExpiringItems = collect();
|
||||
$lowStock = collect();
|
||||
|
||||
$inventoryTypes = [
|
||||
'medicines' => ['model' => Medicine::class, 'name' => 'nama_obat'],
|
||||
'foods' => ['model' => Food::class, 'name' => 'nama_makanan'],
|
||||
'supplies' => ['model' => Supply::class, 'name' => 'nama_perlengkapan'],
|
||||
];
|
||||
|
||||
foreach ($inventoryTypes as $type => $config) {
|
||||
$modelClass = $config['model'];
|
||||
$nameColumn = $config['name'];
|
||||
|
||||
$modelClass::where('qty', '<', 5)
|
||||
->select("$nameColumn as name", 'qty', 'unit')
|
||||
->get()
|
||||
->each(function ($item) use ($lowStock, $type) {
|
||||
$item->url = route("inventory.$type.index", ['search' => $item->name]);
|
||||
$lowStock->push($item);
|
||||
});
|
||||
|
||||
if (Schema::hasColumn((new $modelClass)->getTable(), 'expired_at')) {
|
||||
$modelClass::whereNotNull('expired_at')
|
||||
->where('expired_at', '<=', $now->copy()->addDays(30))
|
||||
->get()
|
||||
->each(function ($item) use ($allExpiringItems, $now, $type, $nameColumn) {
|
||||
$expiredDate = Carbon::parse($item->expired_at);
|
||||
$allExpiringItems->push((object) [
|
||||
'name' => $item->$nameColumn,
|
||||
'qty' => $item->qty,
|
||||
'unit' => $item->unit,
|
||||
'expired_at' => $item->expired_at,
|
||||
'url' => route("inventory.$type.index", ['search' => $item->$nameColumn]),
|
||||
'formatted_date' => $expiredDate->format('d M Y'),
|
||||
'days_left' => (int) $now->copy()->startOfDay()->diffInDays($expiredDate->copy()->startOfDay(), false),
|
||||
'is_expired' => $expiredDate->isPast(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$totalLowStock = $lowStock->count();
|
||||
$sortedItems = $allExpiringItems->sortBy('days_left');
|
||||
$perPage = 5;
|
||||
$currentPage = $request->input('expiry_page', 1);
|
||||
$offset = ($currentPage * $perPage) - $perPage;
|
||||
|
||||
$expiringItems = new LengthAwarePaginator(
|
||||
$sortedItems->slice($offset, $perPage)->values(),
|
||||
$sortedItems->count(),
|
||||
$perPage,
|
||||
$currentPage,
|
||||
[
|
||||
'path' => $request->url(),
|
||||
'query' => $request->query(),
|
||||
'pageName' => 'expiry_page',
|
||||
]
|
||||
);
|
||||
|
||||
$topDiseasesWeek = Treatment::select('diagnosa', DB::raw('count(*) as total'))
|
||||
->where('tanggal', '>=', $now->copy()->subWeek())
|
||||
->groupBy('diagnosa')
|
||||
->orderBy('total', 'desc')
|
||||
->get();
|
||||
|
||||
$topDiseasesMonth = Treatment::select('diagnosa', DB::raw('count(*) as total'))
|
||||
->where('tanggal', '>=', $now->copy()->subMonth())
|
||||
->groupBy('diagnosa')
|
||||
->orderBy('total', 'desc')
|
||||
->get();
|
||||
|
||||
$recentTreatments = Treatment::with(['cat'])->latest()->take(5)->get();
|
||||
|
||||
return view('pages.dashboard.index', compact(
|
||||
'stats',
|
||||
'upcomingBirths',
|
||||
'medicalAlerts',
|
||||
'lowStock',
|
||||
'totalLowStock',
|
||||
'chartData',
|
||||
'weightTrends',
|
||||
'recentTreatments'
|
||||
));
|
||||
'stats',
|
||||
'upcomingBirths',
|
||||
'overdueAlerts',
|
||||
'individualWeightData',
|
||||
'weightSummary',
|
||||
'weightTrendLabels',
|
||||
'weightTrendSeries',
|
||||
'categoryAverageTrend',
|
||||
'weightCategorySummary',
|
||||
'weightKpis',
|
||||
'weightLatestTable',
|
||||
'weightTableCategory',
|
||||
'weightTrendCategory',
|
||||
'weightTrendMonths',
|
||||
'lowStock',
|
||||
'totalLowStock',
|
||||
'expiringItems',
|
||||
'selectedMonth',
|
||||
'selectedYear',
|
||||
'selectedGender',
|
||||
'selectedStatus',
|
||||
'topDiseasesWeek',
|
||||
'topDiseasesMonth',
|
||||
'recentTreatments'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function ageCategory($birthDate, ?string $storedStatus, Carbon $referenceDate): string
|
||||
{
|
||||
if ($birthDate) {
|
||||
$birth = Carbon::parse($birthDate);
|
||||
$months = $birth->diffInMonths($referenceDate);
|
||||
|
||||
if ($months < 7) {
|
||||
return 'Kitten';
|
||||
}
|
||||
|
||||
if ($months < 12) {
|
||||
return 'Junior';
|
||||
}
|
||||
|
||||
return 'Dewasa';
|
||||
}
|
||||
|
||||
$status = strtolower(trim((string) $storedStatus));
|
||||
return match ($status) {
|
||||
'kitten' => 'Kitten',
|
||||
'junior' => 'Junior',
|
||||
'adult', 'dewasa' => 'Dewasa',
|
||||
default => 'Dewasa',
|
||||
};
|
||||
}
|
||||
|
||||
private function formatAge($birthDate, Carbon $referenceDate): string
|
||||
{
|
||||
if (!$birthDate) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$diff = Carbon::parse($birthDate)->diff($referenceDate);
|
||||
$parts = [];
|
||||
|
||||
if ($diff->y > 0) {
|
||||
$parts[] = $diff->y . ' th';
|
||||
}
|
||||
if ($diff->m > 0) {
|
||||
$parts[] = $diff->m . ' bln';
|
||||
}
|
||||
if ($diff->y === 0 && $diff->d > 0) {
|
||||
$parts[] = $diff->d . ' hr';
|
||||
}
|
||||
|
||||
return $parts ? implode(' ', $parts) : '0 hr';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user