287 lines
17 KiB
PHP
287 lines
17 KiB
PHP
<x-app-layout>
|
|
|
|
<div class="w-full max-w-3xl mx-auto">
|
|
|
|
<div class="text-center mb-6 md:mb-10 px-2">
|
|
<h1 class="text-2xl sm:text-3xl md:text-4xl font-heading font-bold text-gray-900 mb-2 md:mb-4">
|
|
Cek Kesegaran Ikan Anda
|
|
</h1>
|
|
<p class="text-gray-500 text-sm md:text-lg max-w-xl mx-auto">
|
|
Unggah foto insang ikan dengan pencahayaan yang baik, dan biarkan teknologi AI kami menganalisis kualitasnya secara real-time.
|
|
</p>
|
|
</div>
|
|
|
|
{{-- PANDUAN UPLOAD --}}
|
|
<div class="mb-6 md:mb-8">
|
|
<div class="bg-gradient-to-br from-blue-50 to-cyan-50 border border-blue-100 rounded-2xl p-5 md:p-8">
|
|
<h3 class="font-heading font-bold text-gray-800 text-base md:text-lg mb-4 flex items-center">
|
|
<i class="bi bi-info-circle-fill text-primary mr-2"></i>
|
|
Panduan Pengambilan Foto
|
|
</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 items-center">
|
|
<ul class="space-y-3">
|
|
<li class="flex items-start text-sm text-gray-600">
|
|
<span class="flex-shrink-0 w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center mr-3 mt-0.5">
|
|
<i class="bi bi-check text-xs font-bold"></i>
|
|
</span>
|
|
<span><strong class="text-gray-800">Fokus ke area insang</strong> — buka tutup insang ikan dan foto langsung ke bagian merah/merah muda.</span>
|
|
</li>
|
|
<li class="flex items-start text-sm text-gray-600">
|
|
<span class="flex-shrink-0 w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center mr-3 mt-0.5">
|
|
<i class="bi bi-check text-xs font-bold"></i>
|
|
</span>
|
|
<span><strong class="text-gray-800">Pencahayaan cukup</strong> — gunakan cahaya alami atau lampu terang, hindari foto gelap atau berbayang.</span>
|
|
</li>
|
|
<li class="flex items-start text-sm text-gray-600">
|
|
<span class="flex-shrink-0 w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center mr-3 mt-0.5">
|
|
<i class="bi bi-check text-xs font-bold"></i>
|
|
</span>
|
|
<span><strong class="text-gray-800">Jarak dekat</strong> — ambil foto sedekat mungkin agar detail insang terlihat jelas.</span>
|
|
</li>
|
|
<li class="flex items-start text-sm text-gray-600">
|
|
<span class="flex-shrink-0 w-6 h-6 bg-red-100 text-red-500 rounded-full flex items-center justify-center mr-3 mt-0.5">
|
|
<i class="bi bi-x text-xs font-bold"></i>
|
|
</span>
|
|
<span><strong class="text-gray-800">Hindari foto buram</strong> atau terlalu jauh sehingga insang tidak terlihat jelas.</span>
|
|
</li>
|
|
</ul>
|
|
<div class="flex flex-row gap-3">
|
|
<div class="flex-1 rounded-xl overflow-hidden border-2 border-green-200 shadow-sm">
|
|
<div class="bg-green-500 py-1.5 text-center">
|
|
<span class="text-[10px] font-bold text-white uppercase tracking-wider">
|
|
<i class="bi bi-check-circle mr-1"></i> Contoh Benar
|
|
</span>
|
|
</div>
|
|
<img src={{ asset('images/Insang-Benar.jpeg') }} alt="Contoh foto insang yang benar" class="w-full h-32 object-cover">
|
|
<div class="bg-green-50 px-2 py-1.5 w-full">
|
|
<p class="text-[9px] text-green-700 font-medium text-center w-full">Insang jelas, pencahayaan baik</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex-1 rounded-xl overflow-hidden border-2 border-red-200 shadow-sm">
|
|
<div class="bg-red-500 py-1.5 text-center">
|
|
<span class="text-[10px] font-bold text-white uppercase tracking-wider">
|
|
<i class="bi bi-x-circle mr-1"></i> Contoh Salah
|
|
</span>
|
|
</div>
|
|
<img src={{ asset('images/Insang-Salah.jpeg') }} alt="Contoh foto insang yang salah" class="w-full h-32 object-cover">
|
|
<div class="bg-red-50 px-2 py-1.5 w-full">
|
|
<p class="text-[9px] text-red-600 font-medium text-center w-full">Gelap, buram, bukan insang</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-2xl md:rounded-3xl shadow-xl shadow-blue-900/5 p-5 sm:p-6 md:p-12 border border-gray-100">
|
|
|
|
<form action="{{ route('klasifikasi.store') }}" method="POST" enctype="multipart/form-data" class="space-y-5 md:space-y-8">
|
|
@csrf
|
|
|
|
<label class="relative flex flex-col items-center justify-center w-full min-h-[220px] md:min-h-[300px] border-2 border-dashed border-gray-300 rounded-2xl bg-gray-50/50 hover:bg-blue-50 hover:border-blue-400 transition-all cursor-pointer overflow-hidden group p-4">
|
|
<div id="upload-prompt" class="flex flex-col items-center justify-center text-center transition-all duration-300 group-hover:scale-105">
|
|
<div class="w-14 h-14 md:w-20 md:h-20 bg-white rounded-full shadow-sm flex items-center justify-center mb-4 md:mb-6 text-blue-500">
|
|
<i class="bi bi-cloud-arrow-up text-2xl md:text-4xl"></i>
|
|
</div>
|
|
<p class="mb-1 md:mb-2 text-base md:text-lg text-gray-700">
|
|
<span class="font-bold text-blue-600">Klik untuk memilih gambar</span> <span class="hidden sm:inline">atau seret ke sini</span>
|
|
</p>
|
|
<p class="text-xs md:text-sm text-gray-400 font-medium">PNG, JPG, JPEG (Maks. 2MB)</p>
|
|
</div>
|
|
<img id="image-preview" class="hidden absolute inset-0 w-full h-full object-contain p-2 md:p-4 bg-gray-50/50 backdrop-blur-sm" src="" alt="Preview Gambar">
|
|
<input type="file" name="image" accept="image/png, image/jpeg, image/jpg" class="hidden" required onchange="previewImage(this)">
|
|
</label>
|
|
|
|
@error('image')
|
|
<div class="text-red-500 text-xs md:text-sm font-medium pl-2 -mt-2 md:-mt-4">
|
|
<i class="bi bi-exclamation-circle mr-1"></i> {{ $message }}
|
|
</div>
|
|
@enderror
|
|
|
|
<button type="submit" class="w-full bg-primary hover:bg-primary-dark text-white font-bold py-3 md:py-4 rounded-xl md:rounded-2xl text-base md:text-lg transition-all shadow-md hover:shadow-lg flex items-center justify-center">
|
|
<i class="bi bi-stars mr-2"></i> Analisis Gambar
|
|
</button>
|
|
</form>
|
|
|
|
{{-- ===================== HASIL KLASIFIKASI BERHASIL ===================== --}}
|
|
@if(session('kelas'))
|
|
<div class="mt-8 md:mt-12 pt-6 md:pt-10 border-t-2 border-dashed border-gray-100 animate-fade-in-up">
|
|
<div class="flex items-center justify-center mb-6 md:mb-8">
|
|
<span class="bg-gray-100 text-gray-500 px-3 py-1 md:px-4 md:py-1.5 rounded-full text-xs md:text-sm font-bold tracking-widest uppercase">
|
|
Hasil Analisis
|
|
</span>
|
|
</div>
|
|
|
|
<div class="flex flex-col md:flex-row items-stretch gap-5 md:gap-8 bg-white md:p-2">
|
|
|
|
<div class="shrink-0 flex flex-row md:flex-col gap-3 md:gap-4">
|
|
@if(session('image_url'))
|
|
<div class="flex-1 md:flex-none rounded-xl md:rounded-2xl overflow-hidden bg-gray-100 border border-gray-200 shadow-sm">
|
|
<div class="bg-gray-200 py-1.5 text-center border-b border-gray-300">
|
|
<span class="text-[10px] md:text-xs font-bold text-gray-600 uppercase tracking-wider">Gambar Asli</span>
|
|
</div>
|
|
<img src="{{ session('image_url') }}" class="w-full md:w-48 h-36 md:h-40 object-cover">
|
|
</div>
|
|
@endif
|
|
|
|
@if(session('cropped_image'))
|
|
<div class="flex-1 md:flex-none rounded-xl md:rounded-2xl overflow-hidden bg-gray-50 border border-gray-200 shadow-sm">
|
|
<div class="bg-gray-100 py-1.5 text-center border-b border-gray-200">
|
|
<span class="text-[10px] md:text-xs font-bold text-gray-600 uppercase tracking-wider">
|
|
<i class="bi bi-crop mr-1"></i> Hasil Crop
|
|
</span>
|
|
</div>
|
|
<img src="data:image/jpeg;base64,{{ session('cropped_image') }}" class="w-full md:w-48 h-36 md:h-40 object-cover">
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="flex-1 flex flex-col justify-center w-full space-y-4 md:space-y-6">
|
|
@if(session('tingkat_kesegaran'))
|
|
<div>
|
|
<p class="text-gray-400 text-[10px] md:text-xs font-bold uppercase tracking-widest mb-2 md:mb-3">Status Kesegaran</p>
|
|
@if(strtolower(session('kelas')) == 'segar' || strtolower(session('kelas')) == 'fresh')
|
|
<div class="inline-flex items-center px-4 py-2.5 md:px-5 md:py-3 bg-green-50 text-green-700 rounded-xl font-bold text-base md:text-lg border border-green-200 shadow-sm">
|
|
<i class="bi bi-check-circle-fill text-xl md:text-2xl mr-2 md:mr-3"></i>
|
|
{{ session('tingkat_kesegaran') }}
|
|
</div>
|
|
@else
|
|
<div class="inline-flex items-center px-4 py-2.5 md:px-5 md:py-3 bg-red-50 text-red-700 rounded-xl font-bold text-base md:text-lg border border-red-200 shadow-sm">
|
|
<i class="bi bi-x-circle-fill text-xl md:text-2xl mr-2 md:mr-3"></i>
|
|
{{ session('tingkat_kesegaran') }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
<div class="w-full">
|
|
<div class="p-3 md:p-4 bg-gray-50 rounded-xl border border-gray-100 mb-4 md:mb-5">
|
|
<p class="text-[10px] md:text-xs text-gray-500 font-bold uppercase tracking-wider mb-1 md:mb-2">
|
|
<i class="bi bi-eye mr-1 text-primary"></i> Catatan Visual
|
|
</p>
|
|
@if(strtolower(session('kelas')) == 'segar' || strtolower(session('kelas')) == 'fresh')
|
|
<p class="text-xs md:text-sm text-gray-700 leading-relaxed">
|
|
Berdasarkan analisis visual, fitur pada insang ikan ini menunjukkan ciri-ciri <strong>dalam kondisi baik</strong>.
|
|
</p>
|
|
@else
|
|
<p class="text-xs md:text-sm text-gray-700 leading-relaxed">
|
|
Berdasarkan analisis visual, terdeteksi <strong>ciri-ciri penurunan kualitas</strong> pada insang ikan (seperti warna yang cenderung memucat atau menggelap).
|
|
</p>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="flex justify-between items-end mb-1.5 md:mb-2">
|
|
<p class="text-[10px] md:text-xs text-gray-500 font-semibold uppercase tracking-wide">Skor Tingkat Kesegaran</p>
|
|
<p class="text-xs md:text-sm text-primary font-bold">
|
|
{{ is_float(session('prob_fresh')) && session('prob_fresh') <= 1 ? number_format(session('prob_fresh') * 100, 1) : number_format(session('prob_fresh'), 1) }}%
|
|
</p>
|
|
</div>
|
|
<div class="w-full bg-gray-100 rounded-full h-2 md:h-2.5 overflow-hidden">
|
|
<div class="bg-primary h-2 md:h-2.5 rounded-full transition-all duration-1000 ease-out"
|
|
style="width: {{ floatval(session('prob_fresh')) > 1 ? floatval(session('prob_fresh')) : floatval(session('prob_fresh')) * 100 }}%">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- ===================== GAMBAR TERTOLAK (BUKAN INSANG) ===================== --}}
|
|
@if(session('error_insang'))
|
|
<div class="mt-8 md:mt-12 pt-6 md:pt-10 border-t-2 border-dashed border-gray-100 animate-fade-in-up">
|
|
<div class="flex items-center justify-center mb-6 md:mb-8">
|
|
<span class="bg-red-50 text-red-500 px-3 py-1 md:px-4 md:py-1.5 rounded-full text-xs md:text-sm font-bold tracking-widest uppercase border border-red-200">
|
|
<i class="bi bi-x-circle mr-1"></i> Gambar Ditolak
|
|
</span>
|
|
</div>
|
|
|
|
<div class="flex flex-col md:flex-row items-stretch gap-5 md:gap-8">
|
|
|
|
{{-- Gambar yang diupload tetap ditampilkan --}}
|
|
@if(session('image_url'))
|
|
<div class="shrink-0">
|
|
<div class="rounded-xl md:rounded-2xl overflow-hidden border-2 border-red-200 shadow-sm">
|
|
<div class="bg-red-100 py-1.5 text-center border-b border-red-200">
|
|
<span class="text-[10px] md:text-xs font-bold text-red-600 uppercase tracking-wider">
|
|
<i class="bi bi-image mr-1"></i> Gambar Diupload
|
|
</span>
|
|
</div>
|
|
<img src="{{ session('image_url') }}" class="w-full md:w-48 h-36 md:h-40 object-cover">
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Pop up pesan penolakan --}}
|
|
<div class="flex-1 flex flex-col justify-center">
|
|
<div class="bg-red-50 border border-red-200 rounded-2xl p-5 md:p-6">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-12 h-12 bg-red-100 rounded-xl flex items-center justify-center flex-shrink-0">
|
|
<i class="bi bi-shield-x text-red-500 text-2xl"></i>
|
|
</div>
|
|
<div>
|
|
<h4 class="font-heading font-bold text-red-700 text-base md:text-lg mb-2">
|
|
Objek Bukan Insang Ikan
|
|
</h4>
|
|
<p class="text-red-600 text-sm leading-relaxed mb-4">
|
|
{{ session('error_insang') }}
|
|
</p>
|
|
<div class="bg-white border border-red-100 rounded-xl p-3 md:p-4">
|
|
<p class="text-[10px] md:text-xs text-gray-500 font-bold uppercase tracking-wider mb-2">
|
|
<i class="bi bi-lightbulb text-yellow-500 mr-1"></i> Saran
|
|
</p>
|
|
<ul class="space-y-1.5 text-xs md:text-sm text-gray-600">
|
|
<li class="flex items-start gap-2">
|
|
<i class="bi bi-arrow-right text-primary mt-0.5 flex-shrink-0"></i>
|
|
Pastikan foto menampilkan area insang ikan secara jelas
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<i class="bi bi-arrow-right text-primary mt-0.5 flex-shrink-0"></i>
|
|
Buka tutup insang ikan sebelum mengambil foto
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<i class="bi bi-arrow-right text-primary mt-0.5 flex-shrink-0"></i>
|
|
Gunakan pencahayaan yang cukup agar warna insang terlihat jelas
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
@keyframes fadeInUp {
|
|
from { opacity: 0; transform: translateY(10px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.animate-fade-in-up {
|
|
animation: fadeInUp 0.5s ease-out forwards;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
function previewImage(input) {
|
|
const preview = document.getElementById('image-preview');
|
|
const prompt = document.getElementById('upload-prompt');
|
|
if (input.files && input.files[0]) {
|
|
const reader = new FileReader();
|
|
reader.onload = function(e) {
|
|
preview.src = e.target.result;
|
|
preview.classList.remove('hidden');
|
|
prompt.classList.add('opacity-0');
|
|
setTimeout(() => prompt.classList.add('hidden'), 300);
|
|
}
|
|
reader.readAsDataURL(input.files[0]);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
</x-app-layout> |