307 lines
13 KiB
PHP
307 lines
13 KiB
PHP
@extends('layout.app')
|
|
|
|
@section('title', 'Hasil Rekomendasi')
|
|
|
|
@push('styles')
|
|
<style>
|
|
.recommendation-card {
|
|
border: none;
|
|
border-radius: 15px;
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
margin-bottom: 2rem;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.recommendation-card:hover {
|
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
.recommendation-header {
|
|
background: linear-gradient(45deg, #0d6efd, #0dcaf0);
|
|
color: white;
|
|
padding: 1.5rem;
|
|
border-radius: 15px 15px 0 0;
|
|
}
|
|
|
|
.recommendation-body {
|
|
padding: 1.5rem;
|
|
}
|
|
|
|
.component-section {
|
|
margin-bottom: 2rem;
|
|
border-radius: 15px;
|
|
overflow: hidden;
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
}
|
|
|
|
.component-header {
|
|
background: linear-gradient(45deg, #0d6efd, #0dcaf0);
|
|
color: white;
|
|
padding: 1rem 1.5rem;
|
|
border-radius: 15px 15px 0 0;
|
|
}
|
|
|
|
.component-body {
|
|
background: white;
|
|
padding: 1.5rem;
|
|
border-radius: 0 0 15px 15px;
|
|
}
|
|
|
|
.nutrition-badge {
|
|
display: inline-block;
|
|
padding: 0.35rem 0.65rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
line-height: 1;
|
|
color: #fff;
|
|
text-align: center;
|
|
white-space: nowrap;
|
|
vertical-align: baseline;
|
|
border-radius: 0.25rem;
|
|
background: linear-gradient(45deg, #0d6efd, #0dcaf0);
|
|
margin: 0.25rem;
|
|
}
|
|
|
|
.score-cell {
|
|
font-weight: 500;
|
|
color: #0d6efd;
|
|
}
|
|
|
|
.highest-score {
|
|
background-color: #d1e7dd !important;
|
|
color: #0f5132;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.criteria-weight {
|
|
font-size: 0.875rem;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.consistency-info {
|
|
background: #e9ecef;
|
|
padding: 1rem;
|
|
border-radius: 10px;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.consistency-info p {
|
|
margin-bottom: 0.5rem;
|
|
color: #495057;
|
|
}
|
|
|
|
.consistency-info i {
|
|
margin-right: 0.5rem;
|
|
color: #0d6efd;
|
|
}
|
|
|
|
.ahp-steps {
|
|
counter-reset: step;
|
|
padding-left: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.ahp-steps li {
|
|
position: relative;
|
|
padding: 1rem 1rem 1rem 3rem;
|
|
background: #f8f9fa;
|
|
border-radius: 10px;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.ahp-steps li::before {
|
|
counter-increment: step;
|
|
content: counter(step);
|
|
position: absolute;
|
|
left: 1rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 1.5rem;
|
|
height: 1.5rem;
|
|
background: #0d6efd;
|
|
color: white;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.875rem;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<!-- Page Title -->
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h3 class="mb-0">Hasil Rekomendasi Makanan</h3>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{{ route('admindash') }}">Dashboard</a></li>
|
|
<li class="breadcrumb-item"><a href="{{ route('alternatif.pilih') }}">Pilih Alternatif</a></li>
|
|
<li class="breadcrumb-item"><a href="{{ route('alternatif.perbandingan') }}">Perbandingan</a></li>
|
|
<li class="breadcrumb-item active">Hasil Rekomendasi</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
@if(session('error'))
|
|
<div class="alert alert-danger">
|
|
{{ session('error') }}
|
|
</div>
|
|
@endif
|
|
|
|
@if($makanans->isEmpty())
|
|
<div class="alert alert-warning">
|
|
<h5><i class="icon fas fa-exclamation-triangle"></i> Tidak ada data!</h5>
|
|
<p>Tidak ada makanan yang dipilih atau data tidak lengkap. Silakan kembali ke halaman pemilihan makanan.</p>
|
|
<a href="{{ route('alternatif.pilih') }}" class="btn btn-warning mt-3">
|
|
<i class="fas fa-arrow-left mr-2"></i> Kembali ke Pemilihan Makanan
|
|
</a>
|
|
</div>
|
|
@else
|
|
<!-- AHP Process Steps -->
|
|
<div class="recommendation-card mb-4">
|
|
<div class="recommendation-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-list-ol me-2"></i>Proses Perhitungan AHP
|
|
@if($waktuMakan)
|
|
- {{ $waktuMakan->nama }}
|
|
@endif
|
|
</h5>
|
|
</div>
|
|
<div class="recommendation-body">
|
|
<ol class="ahp-steps">
|
|
<li>Perhitungan bobot kriteria berdasarkan perbandingan berpasangan</li>
|
|
<li>Normalisasi matriks perbandingan kriteria</li>
|
|
<li>Perhitungan nilai alternatif untuk setiap kriteria</li>
|
|
<li>Normalisasi nilai alternatif</li>
|
|
<li>Perhitungan skor akhir dengan mengalikan bobot kriteria</li>
|
|
<li>Perangkingan alternatif berdasarkan skor akhir</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Consistency Information -->
|
|
<div class="consistency-info">
|
|
<h5 class="mb-3"><i class="fas fa-check-circle"></i>Informasi Konsistensi</h5>
|
|
<p><i class="fas fa-calculator"></i>Consistency Ratio (CR): {{ number_format($consistencyRatio, 3) }}</p>
|
|
<p><i class="fas fa-info-circle"></i>Status:
|
|
@if($consistencyRatio < 0.1)
|
|
<span class="text-success">Konsisten (CR < 0.1)</span>
|
|
@else
|
|
<span class="text-danger">Tidak Konsisten (CR > 0.1)</span>
|
|
@endif
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Results by Component -->
|
|
@foreach($komponens as $komponen)
|
|
@php
|
|
$komponenMakanans = $makanans->where('komponen_id', $komponen->id);
|
|
@endphp
|
|
|
|
@if($komponenMakanans->isNotEmpty())
|
|
<div class="component-section" data-aos="fade-up">
|
|
<div class="component-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-utensils me-2"></i>{{ $komponen->nama }}
|
|
</h5>
|
|
</div>
|
|
<div class="component-body">
|
|
<!-- Criteria Weights -->
|
|
<div class="mb-4">
|
|
<h6 class="mb-3">Bobot Kriteria:</h6>
|
|
<div class="row">
|
|
@foreach($kriterias as $kriteria)
|
|
<div class="col-md-3 mb-3">
|
|
<div class="p-3 bg-light rounded">
|
|
<strong>{{ $kriteria->nama }}</strong>
|
|
<div class="criteria-weight">
|
|
Bobot: {{ number_format($bobotKriteria[$kriteria->id] * 100, 1) }}%
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Alternative Rankings -->
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Ranking</th>
|
|
<th>Alternatif Makanan</th>
|
|
@foreach($kriterias as $kriteria)
|
|
<th>{{ $kriteria->nama }}</th>
|
|
@endforeach
|
|
<th>Total Skor</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@php
|
|
$sortedMakanans = $komponenMakanans->sortByDesc(function($makanan) use ($totalSkorMakanan) {
|
|
return $totalSkorMakanan[$makanan->id] ?? 0;
|
|
});
|
|
@endphp
|
|
|
|
@foreach($sortedMakanans as $index => $makanan)
|
|
<tr>
|
|
<td>{{ $index + 1 }}</td>
|
|
<td>
|
|
<strong>{{ $makanan->nama }}</strong>
|
|
<div class="mt-2">
|
|
<span class="nutrition-badge">
|
|
<i class="fas fa-fire me-1"></i>{{ $makanan->energi }} kal
|
|
</span>
|
|
<span class="nutrition-badge">
|
|
<i class="fas fa-hamburger me-1"></i>{{ $makanan->lemak }}g
|
|
</span>
|
|
<span class="nutrition-badge">
|
|
<i class="fas fa-bread-slice me-1"></i>{{ $makanan->karbohidrat }}g
|
|
</span>
|
|
<span class="nutrition-badge">
|
|
<i class="fas fa-salt-shaker me-1"></i>{{ $makanan->natrium }}mg
|
|
</span>
|
|
</div>
|
|
</td>
|
|
@foreach($kriterias as $kriteria)
|
|
<td class="score-cell">
|
|
{{ number_format($bobotMakanan[$makanan->id][$kriteria->id], 3) }}
|
|
</td>
|
|
@endforeach
|
|
<td class="score-cell {{ $index === 0 ? 'highest-score' : '' }}">
|
|
{{ number_format($totalSkorMakanan[$makanan->id], 3) }}
|
|
@if($index === 0)
|
|
<span class="badge bg-success ms-1">Terbaik</span>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
@endforeach
|
|
|
|
<!-- Next Step Button -->
|
|
<div class="d-flex justify-content-between mt-4 mb-5">
|
|
<a href="{{ route('alternatif.perbandingan') }}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left me-2"></i>Kembali ke Perbandingan
|
|
</a>
|
|
<a href="{{ route('admindash') }}" class="btn btn-primary">
|
|
<i class="fas fa-home me-2"></i>Kembali ke Dashboard
|
|
</a>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|