MIF_E31222307/resources/views/admin/rekomendasi.blade.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