611 lines
18 KiB
PHP
611 lines
18 KiB
PHP
@extends('layout.app')
|
|
|
|
@section('title', 'Detail Rekomendasi')
|
|
|
|
@section('content')
|
|
<div class="admin-container">
|
|
<!-- Page Header -->
|
|
<div class="page-header">
|
|
<div class="row align-items-center">
|
|
<div class="col-12">
|
|
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3">
|
|
<div class="d-flex align-items-center">
|
|
<div class="icon-title-page bg-primary text-white me-3">
|
|
<i class="fas fa-chart-bar"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="mb-1">Detail Rekomendasi Makanan</h3>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb mb-0">
|
|
<li class="breadcrumb-item"><a href="{{ route('admindash') }}">Dashboard</a></li>
|
|
<li class="breadcrumb-item"><a href="{{ route('rekomendasi.index') }}">Daftar Rekomendasi</a></li>
|
|
<li class="breadcrumb-item active" aria-current="page">Detail</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<a href="{{ route('rekomendasi.index') }}" class="admin-btn btn-secondary">
|
|
<i class="fas fa-arrow-left me-2"></i>Kembali
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@if(session('success'))
|
|
<div class="admin-alert alert-success" role="alert">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-check-circle me-2"></i>
|
|
<div>{{ session('success') }}</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
@endif
|
|
|
|
@if(session('error'))
|
|
<div class="admin-alert alert-danger" role="alert">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-exclamation-circle me-2"></i>
|
|
<div>{{ session('error') }}</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Stats Overview -->
|
|
<div class="stats-overview mb-4">
|
|
<div class="row g-3">
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="stat-card bg-gradient-primary h-100">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-clock"></i>
|
|
</div>
|
|
<div class="stat-details">
|
|
<h4 class="stat-value">{{ $waktuMakan->nama }}</h4>
|
|
<p class="stat-label">Waktu Makan</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="stat-card bg-gradient-success h-100">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-list-check"></i>
|
|
</div>
|
|
<div class="stat-details">
|
|
<h4 class="stat-value">{{ count($hasilPerKomponen) }}</h4>
|
|
<p class="stat-label">Total Komponen</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="stat-card bg-gradient-info h-100">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-clipboard-list"></i>
|
|
</div>
|
|
<div class="stat-details">
|
|
<h4 class="stat-value">{{ count($kriterias) }}</h4>
|
|
<p class="stat-label">Total Kriteria</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="stat-card bg-gradient-orange h-100">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-calculator"></i>
|
|
</div>
|
|
<div class="stat-details">
|
|
<h4 class="stat-value">
|
|
@if(isset($latestCR))
|
|
<span class="cr-value">{{ number_format($latestCR->cr, 4) }}</span>
|
|
<span class="cr-status">({{ $latestCR->is_consistent ? 'Konsisten' : 'Perlu Review' }})</span>
|
|
@else
|
|
<span class="cr-value">Belum dihitung</span>
|
|
@endif
|
|
</h4>
|
|
<p class="stat-label">Consistency Ratio (CR)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Recommendation Results -->
|
|
<div class="recommendation-results">
|
|
@foreach($hasilPerKomponen as $komponenId => $hasil)
|
|
<div class="recommendation-card mb-4">
|
|
<div class="card-header bg-gradient-primary">
|
|
<h5 class="mb-0 text-white">
|
|
<i class="fas fa-chart-bar me-2"></i>
|
|
Hasil Perhitungan - {{ $hasil['komponen']->nama }}
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<!-- Kriteria Section -->
|
|
<div class="criteria-section mb-4">
|
|
<h6 class="section-title mb-3">
|
|
<i class="fas fa-list-check me-2"></i>Kriteria yang Digunakan
|
|
</h6>
|
|
<div class="row g-3">
|
|
@foreach($kriterias as $kriteria)
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="criteria-card h-100">
|
|
<div class="d-flex align-items-center">
|
|
<div class="criteria-icon">
|
|
<i class="fas fa-check-circle"></i>
|
|
</div>
|
|
<div class="criteria-details">
|
|
<div class="criteria-name">{{ $kriteria->nama }}</div>
|
|
@if(isset($bobotKriteria[$kriteria->id]))
|
|
<div class="criteria-weight">
|
|
Bobot: {{ number_format($bobotKriteria[$kriteria->id], 4) }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Consistency Ratio Section -->
|
|
<div class="consistency-section mb-4">
|
|
<h6 class="section-title mb-3">
|
|
<i class="fas fa-calculator me-2"></i>Consistency Ratio per Kriteria
|
|
</h6>
|
|
<div class="row g-3">
|
|
@foreach($kriterias as $kriteria)
|
|
@php
|
|
$crData = \App\Models\ConsistencyRatioAlternatif::where([
|
|
'kriteria_id' => $kriteria->id,
|
|
'komponen_id' => $hasil['komponen']->id,
|
|
'waktu_makan_id' => $waktuMakan->id
|
|
])->latest()->first();
|
|
@endphp
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="consistency-card h-100 {{ $crData && $crData->is_consistent ? 'consistent' : 'inconsistent' }}">
|
|
<div class="consistency-header">
|
|
<h6 class="mb-0">{{ $kriteria->nama }}</h6>
|
|
<div class="consistency-icon">
|
|
@if($crData && $crData->is_consistent)
|
|
<i class="fas fa-check-circle"></i>
|
|
@else
|
|
<i class="fas fa-exclamation-circle"></i>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
<div class="consistency-details">
|
|
<div class="detail-item">
|
|
<span class="label">CI:</span>
|
|
<span class="value">{{ $crData ? number_format($crData->ci, 4) : 'N/A' }}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">CR:</span>
|
|
<span class="value">{{ $crData ? number_format($crData->cr, 4) : 'N/A' }}</span>
|
|
</div>
|
|
<div class="status-badge {{ $crData && $crData->is_consistent ? 'consistent' : 'inconsistent' }}">
|
|
@if($crData && $crData->is_consistent)
|
|
<i class="fas fa-check me-1"></i>Konsisten
|
|
@else
|
|
<i class="fas fa-exclamation-triangle me-1"></i>Perlu Review
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Table Section -->
|
|
<div class="table-section">
|
|
<div class="table-header bg-gradient-success">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-table me-2"></i>
|
|
Hasil Normalisasi
|
|
</h6>
|
|
</div>
|
|
<div class="table-content">
|
|
<div class="alert alert-info mb-3">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
Nilai yang ditampilkan adalah hasil normalisasi dari matriks perbandingan
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-hover mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 60px">No</th>
|
|
<th>Makanan</th>
|
|
@foreach($kriterias as $kriteria)
|
|
<th class="text-center">{{ $kriteria->nama }}</th>
|
|
@endforeach
|
|
<th class="text-center">Skor Akhir</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($hasil['rekomendasis'] as $rekomendasi)
|
|
<tr>
|
|
<td class="text-center">{{ $loop->iteration }}</td>
|
|
<td>{{ $rekomendasi->makanan->nama }}</td>
|
|
@foreach($kriterias as $kriteria)
|
|
<td class="text-center score-cell">
|
|
{{ number_format($hasil['detailSkor'][$rekomendasi->makanan_id][$kriteria->nama], 4) }}
|
|
</td>
|
|
@endforeach
|
|
<td class="text-center fw-bold score-cell">
|
|
{{ number_format($rekomendasi->nilai_akhir, 4) }}
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
@push('styles')
|
|
<style>
|
|
/* Base Container */
|
|
.admin-container {
|
|
padding: 1.5rem;
|
|
max-width: 1600px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* Page Header */
|
|
.page-header {
|
|
margin-bottom: 2rem;
|
|
background: #fff;
|
|
border-radius: 1rem;
|
|
padding: 1.5rem;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.icon-title-page {
|
|
width: 45px;
|
|
height: 45px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 10px;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
/* Stats Cards */
|
|
.stats-overview {
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.stat-card {
|
|
padding: 1.5rem;
|
|
border-radius: 1rem;
|
|
color: white;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1.5rem;
|
|
height: 100%;
|
|
transition: transform 0.3s ease;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
position: relative;
|
|
overflow: hidden;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.stat-card:hover {
|
|
transform: translateY(-5px);
|
|
}
|
|
|
|
.stat-icon {
|
|
font-size: 2rem;
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.stat-details {
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 1.5rem;
|
|
font-weight: 600;
|
|
margin-bottom: 0.25rem;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.stat-label {
|
|
margin: 0;
|
|
opacity: 0.9;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
/* Recommendation Card */
|
|
.recommendation-card {
|
|
background: #fff;
|
|
border-radius: 1rem;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
overflow: hidden;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.recommendation-card:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.card-header {
|
|
padding: 1.25rem;
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.card-body {
|
|
padding: 1.5rem;
|
|
}
|
|
|
|
/* Criteria Cards */
|
|
.criteria-card {
|
|
background: #fff;
|
|
border-radius: 0.75rem;
|
|
padding: 1.25rem;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
transition: transform 0.3s ease;
|
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
height: 100%;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.criteria-card:hover {
|
|
transform: translateY(-3px);
|
|
}
|
|
|
|
.criteria-icon {
|
|
color: #4caf50;
|
|
font-size: 1.25rem;
|
|
margin-right: 1rem;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.criteria-details {
|
|
flex-grow: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.criteria-name {
|
|
font-weight: 600;
|
|
color: #343a40;
|
|
margin-bottom: 0.25rem;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.criteria-weight {
|
|
font-size: 0.875rem;
|
|
color: #6c757d;
|
|
}
|
|
|
|
/* Table Section */
|
|
.table-section {
|
|
background: #fff;
|
|
border-radius: 1rem;
|
|
overflow: hidden;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
margin-top: 1.5rem;
|
|
}
|
|
|
|
.table-header {
|
|
padding: 1rem 1.25rem;
|
|
color: white;
|
|
}
|
|
|
|
.table-content {
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.table {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.table th {
|
|
background: #f8f9fa;
|
|
font-weight: 600;
|
|
padding: 1rem;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.table td {
|
|
padding: 1rem;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.score-cell {
|
|
font-family: 'Roboto Mono', monospace;
|
|
color: #2196f3;
|
|
}
|
|
|
|
/* Alerts */
|
|
.admin-alert {
|
|
border-radius: 0.75rem;
|
|
padding: 1rem 1.25rem;
|
|
margin-bottom: 1.5rem;
|
|
border: none;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
/* Gradients */
|
|
.bg-gradient-primary { background: linear-gradient(135deg, #2196f3, #1976d2); }
|
|
.bg-gradient-success { background: linear-gradient(135deg, #4caf50, #388e3c); }
|
|
.bg-gradient-info { background: linear-gradient(135deg, #00bcd4, #0097a7); }
|
|
.bg-gradient-orange { background: linear-gradient(135deg, #ff8a00, #ff5f00); }
|
|
|
|
/* Consistency Cards */
|
|
.consistency-section {
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.consistency-card {
|
|
background: #fff;
|
|
border-radius: 1rem;
|
|
padding: 1.25rem;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
transition: all 0.3s ease;
|
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.consistency-card.consistent {
|
|
border-left: 4px solid #4caf50;
|
|
}
|
|
|
|
.consistency-card.inconsistent {
|
|
border-left: 4px solid #ff9800;
|
|
}
|
|
|
|
.consistency-card:hover {
|
|
transform: translateY(-3px);
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.consistency-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 1rem;
|
|
padding-bottom: 0.75rem;
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.consistency-header h6 {
|
|
font-weight: 600;
|
|
color: #2c3e50;
|
|
margin: 0;
|
|
}
|
|
|
|
.consistency-icon {
|
|
font-size: 1.25rem;
|
|
}
|
|
|
|
.consistency-card.consistent .consistency-icon {
|
|
color: #4caf50;
|
|
}
|
|
|
|
.consistency-card.inconsistent .consistency-icon {
|
|
color: #ff9800;
|
|
}
|
|
|
|
.consistency-details {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.detail-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.detail-item .label {
|
|
color: #6c757d;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.detail-item .value {
|
|
font-family: 'Roboto Mono', monospace;
|
|
font-weight: 500;
|
|
color: #2196f3;
|
|
}
|
|
|
|
.status-badge {
|
|
margin-top: 0.5rem;
|
|
padding: 0.5rem;
|
|
border-radius: 0.5rem;
|
|
font-size: 0.85rem;
|
|
text-align: center;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.status-badge.consistent {
|
|
background: rgba(76, 175, 80, 0.1);
|
|
color: #2e7d32;
|
|
}
|
|
|
|
.status-badge.inconsistent {
|
|
background: rgba(255, 152, 0, 0.1);
|
|
color: #ef6c00;
|
|
}
|
|
|
|
/* Responsive Adjustments */
|
|
@media (max-width: 1200px) {
|
|
.stat-value {
|
|
font-size: 1.25rem;
|
|
}
|
|
|
|
.stat-icon {
|
|
font-size: 1.75rem;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.admin-container {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.page-header {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.stat-card {
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.card-body {
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.table-responsive {
|
|
margin: 0 -1.25rem;
|
|
}
|
|
|
|
.consistency-card {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.consistency-header {
|
|
margin-bottom: 0.75rem;
|
|
padding-bottom: 0.5rem;
|
|
}
|
|
|
|
.detail-item {
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.status-badge {
|
|
font-size: 0.8rem;
|
|
padding: 0.4rem;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 576px) {
|
|
.stat-card {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.stat-icon {
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.criteria-card {
|
|
padding: 1rem;
|
|
}
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@endsection
|
|
|