MIF_E31222307/resources/views/admin/alternatif/perbandingan.blade.php

481 lines
16 KiB
PHP

@extends('layout.app')
@section('title', 'Perbandingan Alternatif')
@push('styles')
<style>
.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;
}
.card:hover {
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.card-header {
background: linear-gradient(45deg, #0d6efd, #0dcaf0);
color: white;
border: none;
border-radius: 15px 15px 0 0 !important;
padding: 1.5rem;
}
.card-body {
padding: 1.5rem;
}
.table {
margin-bottom: 0;
}
.table th {
background-color: #f8f9fa;
font-weight: 600;
text-align: center;
vertical-align: middle;
padding: 1rem;
}
.table td {
text-align: center;
vertical-align: middle;
padding: 1rem;
}
.table-hover tbody tr:hover {
background-color: rgba(0,0,0,.075);
}
.score-cell {
font-weight: 500;
color: #0d6efd;
}
.highest-score {
background-color: #d1e7dd !important;
color: #0f5132;
font-weight: bold;
}
.alert-info {
background-color: #e8f4f8;
border-color: #d6e9f9;
border-radius: 10px;
}
.komponen-section {
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;
overflow: hidden;
}
.komponen-section:hover {
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.komponen-header {
background: linear-gradient(45deg, #0d6efd, #0dcaf0);
color: white;
padding: 1.5rem;
border-radius: 15px 15px 0 0;
}
.komponen-body {
background: white;
padding: 1.5rem;
border-radius: 0 0 15px 15px;
}
.rekomendasi-section {
background: #d1e7dd;
border-radius: 10px;
padding: 1.5rem;
margin-bottom: 1.5rem;
transition: all 0.3s ease;
}
.rekomendasi-section:hover {
box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.1);
}
.rekomendasi-section h6 {
color: #0f5132;
margin-bottom: 1rem;
display: flex;
align-items: center;
}
.rekomendasi-section h6 i {
margin-right: 0.75rem;
}
.rekomendasi-list {
list-style: none;
padding-left: 0;
margin-bottom: 0;
}
.rekomendasi-list li {
padding: 1rem;
background: #fff;
border-radius: 10px;
margin-bottom: 0.75rem;
transition: all 0.3s ease;
display: flex;
align-items: center;
}
.rekomendasi-list li:hover {
transform: translateY(-2px);
box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.1);
}
.rekomendasi-list li i {
margin-right: 0.75rem;
color: #0f5132;
}
.rekomendasi-list li:last-child {
margin-bottom: 0;
}
.breadcrumb {
background: transparent;
padding: 0;
}
.breadcrumb-item a {
color: #0d6efd;
text-decoration: none;
}
.breadcrumb-item.active {
color: #6c757d;
}
#loadingOverlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
backdrop-filter: blur(5px);
}
.loading-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: white;
background: rgba(13, 110, 253, 0.9);
padding: 2rem;
border-radius: 15px;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.3);
}
.loading-spinner {
width: 3rem;
height: 3rem;
margin-bottom: 1rem;
}
@media (max-width: 768px) {
.table-responsive {
border-radius: 10px;
border: 1px solid #dee2e6;
}
.card-header, .komponen-header {
padding: 1rem;
}
.card-body, .komponen-body {
padding: 1rem;
}
.table td, .table th {
padding: 0.75rem;
}
.rekomendasi-section {
padding: 1rem;
}
.rekomendasi-list li {
padding: 0.75rem;
}
}
/* Consistency Ratio Cards */
.cr-card {
padding: 1rem;
border-radius: 0.75rem;
color: white;
height: 100%;
transition: all 0.3s ease;
}
.cr-card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.cr-title {
font-weight: 600;
margin-bottom: 0.5rem;
}
.cr-value {
font-size: 1.1rem;
font-weight: 500;
margin-bottom: 0.5rem;
}
.cr-status {
font-size: 0.9rem;
opacity: 0.9;
}
.bg-success {
background: linear-gradient(135deg, #4caf50, #388e3c);
}
.bg-warning {
background: linear-gradient(135deg, #ff9800, #f57c00);
}
</style>
@endpush
@section('content')
<div class="content-wrapper">
<div class="row">
<div class="col-12">
<!-- Page Title -->
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="card-title mb-0">Hasil Normalisasi Kriteria</h4>
<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('alternatif.pilih') }}">Pilih Alternatif</a></li>
<li class="breadcrumb-item"><a href="{{ route('alternatif.view') }}">Lihat Alternatif</a></li>
<li class="breadcrumb-item active">Perbandingan</li>
</ol>
</nav>
</div>
@if(session('error'))
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle me-2"></i>
{{ session('error') }}
</div>
@endif
<div class="alert alert-info mb-4">
<h5 class="alert-heading mb-2">
<i class="fas fa-info-circle me-2"></i>
Informasi Kriteria
</h5>
<ul class="mb-0">
<li>Untuk kriteria cost (Lemak dan Natrium): Nilai yang lebih kecil lebih baik</li>
<li>Untuk kriteria benefit (Energi dan Karbohidrat): Nilai yang lebih besar lebih baik</li>
<li>Total normalisasi untuk setiap kriteria selalu berjumlah 1.0000</li>
</ul>
</div>
@php
$alternatifsByKomponen = session('alternatifs_by_komponen');
@endphp
@foreach($alternatifsByKomponen as $komponenId => $komponenData)
<div class="komponen-section mb-4">
<div class="komponen-header">
<h5 class="mb-0">
<i class="fas fa-utensils me-2"></i>
{{ $komponenData['nama_komponen'] }}
</h5>
</div>
<div class="komponen-body">
<!-- Consistency Ratio Section -->
<div class="consistency-info mb-4">
<h6 class="section-title mb-3">
<i class="fas fa-check-circle me-2"></i>
Consistency Ratio (CR) per Kriteria
</h6>
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>
Perhitungan CR sementara dinonaktifkan untuk troubleshooting.
</div>
<!-- <div class="row g-3">
@foreach($kriterias as $kriteria)
@php
$crData = \App\Models\ConsistencyRatioAlternatif::where([
'kriteria_id' => $kriteria->id,
'komponen_id' => $komponenId,
'waktu_makan_id' => session('hasil_rekomendasi.waktu_makan_id')
])->first();
@endphp
<div class="col-md-3">
<div class="cr-card {{ $crData && $crData->is_consistent ? 'bg-success' : 'bg-warning' }}">
<div class="cr-title">{{ $kriteria->nama }}</div>
<div class="cr-value">
CR: {{ $crData ? number_format($crData->cr, 4) : 'N/A' }}
</div>
<div class="cr-status">
@if($crData && $crData->is_consistent)
<i class="fas fa-check-circle me-1"></i> Konsisten
@else
<i class="fas fa-exclamation-circle me-1"></i> Perlu Review
@endif
</div>
</div>
</div>
@endforeach
</div> -->
</div>
<!-- Normalization Table -->
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th style="width: 60px">No</th>
<th>Nama Makanan</th>
<th>Lemak (Normalisasi)</th>
<th>Natrium (Normalisasi)</th>
<th>Energi (Normalisasi)</th>
<th>Karbohidrat (Normalisasi)</th>
</tr>
</thead>
<tbody>
@php
$no = 1;
// Hitung total untuk setiap kriteria
$totalLemakInvers = array_sum(array_column($komponenData['alternatifs'], 'lemak_invers'));
$totalNatriumInvers = array_sum(array_column($komponenData['alternatifs'], 'natrium_invers'));
$totalEnergi = array_sum(array_column($komponenData['alternatifs'], 'energi'));
$totalKarbohidrat = array_sum(array_column($komponenData['alternatifs'], 'karbohidrat'));
@endphp
@foreach($komponenData['alternatifs'] as $alternatif)
<tr>
<td>{{ $no++ }}</td>
<td class="text-start">{{ $alternatif['nama'] }}</td>
<td class="score-cell">{{ number_format($alternatif['lemak_invers'] / $totalLemakInvers, 4) }}</td>
<td class="score-cell">{{ number_format($alternatif['natrium_invers'] / $totalNatriumInvers, 4) }}</td>
<td class="score-cell">{{ number_format($alternatif['energi'] / $totalEnergi, 4) }}</td>
<td class="score-cell">{{ number_format($alternatif['karbohidrat'] / $totalKarbohidrat, 4) }}</td>
</tr>
@endforeach
<tr>
<td colspan="2" class="text-end fw-bold">Total</td>
<td class="fw-bold">1.0000</td>
<td class="fw-bold">1.0000</td>
<td class="fw-bold">1.0000</td>
<td class="fw-bold">1.0000</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@endforeach
<!-- Form untuk menyimpan normalisasi -->
<form action="{{ route('alternatif.simpan.normalisasi') }}" method="POST" id="formNormalisasi">
@csrf
<!-- Simpan semua data dalam satu input JSON -->
<input type="hidden" name="normalisasi_data_json" value="{{ json_encode([
'data' => collect($alternatifsByKomponen)->map(function($komponenData, $komponenId) use ($totalLemakInvers, $totalNatriumInvers, $totalEnergi, $totalKarbohidrat) {
return [
'nama_komponen' => $komponenData['nama_komponen'],
'alternatifs' => collect($komponenData['alternatifs'])->map(function($alternatif) use ($totalLemakInvers, $totalNatriumInvers, $totalEnergi, $totalKarbohidrat) {
return [
'id' => $alternatif['id'],
'nama' => $alternatif['nama'],
'lemak_normalized' => $alternatif['lemak_invers'] / $totalLemakInvers,
'natrium_normalized' => $alternatif['natrium_invers'] / $totalNatriumInvers,
'energi_normalized' => $alternatif['energi'] / $totalEnergi,
'karbohidrat_normalized' => $alternatif['karbohidrat'] / $totalKarbohidrat
];
})->values()->all()
];
})->all()
]) }}">
<div class="text-center mt-4 mb-5">
<button type="button" id="btnSimpanNormalisasi" class="btn btn-success btn-lg">
<i class="fas fa-save me-2"></i>Simpan dan Lanjutkan
</button>
</div>
</form>
<!-- Loading Overlay -->
<div id="loadingOverlay">
<div class="loading-content">
<div class="spinner-border text-light loading-spinner" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<h5 class="mb-0">Memproses Data...</h5>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
$(document).ready(function() {
// Initialize tooltips
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
});
// Animate on scroll
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: true,
mirror: false
});
// Handle form submission with confirmation
$('#btnSimpanNormalisasi').on('click', function(e) {
e.preventDefault();
// Konfirmasi sebelum submit
Swal.fire({
title: 'Konfirmasi',
text: 'Apakah Anda yakin data perbandingan ini sudah benar dan ingin disimpan untuk proses normalisasi?',
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Ya, Simpan',
cancelButtonText: 'Batal',
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
// Tampilkan loading overlay
$('#loadingOverlay').fadeIn();
// Submit form secara normal
$('#formNormalisasi').submit();
}
});
});
});
</script>
@endpush