TIFNGK_E41222722/templates/upload.html

273 lines
11 KiB
HTML

{% extends "base.html" %}
{% block title %}Upload Gambar{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card shadow">
<div class="card-header bg-success text-white">
<h4 class="mb-0"><i class="fas fa-upload me-2"></i>Upload Gambar Sapi</h4>
</div>
<div class="card-body">
<div class="alert alert-info mb-4">
<i class="fas fa-info-circle me-2"></i>
<strong>Petunjuk:</strong> Upload satu atau lebih gambar sapi dengan format JPG, JPEG, PNG, atau BMP.
Jika terdeteksi sakit, anda akan diarahkan ke Sistem Pakar untuk diagnosis lebih lanjut.
</div>
{% if error %}
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle me-2"></i>
{{ error }}
</div>
{% endif %}
<form method="POST" action="{{ url_for('predict') }}" enctype="multipart/form-data" id="uploadForm">
<div class="mb-4">
<div class="upload-area border border-2 border-dashed rounded p-4 text-center"
id="uploadArea">
<i class="fas fa-cloud-upload-alt fa-4x text-success mb-3"></i>
<h5>Drag & Drop, atau Pilih dari Galeri</h5>
<p class="text-muted mb-3">Format: JPG, JPEG, PNG, BMP (Maks. 16MB per file)</p>
<input type="file" class="d-none" id="file" name="image"
accept="image/*" multiple>
<div class="d-flex flex-wrap justify-content-center gap-2">
<button type="button" class="btn btn-success" id="browseBtn">
<i class="fas fa-images me-2"></i>Pilih File
</button>
<button type="button" class="btn btn-outline-success" id="cameraBtn">
<i class="fas fa-camera me-2"></i>Kamera
</button>
</div>
</div>
<div id="fileInfo" class="mt-3 d-none"></div>
</div>
<div id="previewContainer" style="display: none;">
<h6 class="mb-3"><i class="fas fa-image me-2"></i>Preview Gambar:</h6>
<div class="row" id="previewGrid"></div>
</div>
<button type="submit" class="btn btn-success btn-lg w-100 mt-3" id="submitBtn" disabled>
<i class="fas fa-search me-2"></i>Upload & Deteksi
</button>
</form>
<div id="loading" class="text-center mt-4 d-none">
<div class="spinner-border text-success" style="width: 3rem; height: 3rem;" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="mt-3 fw-bold">Sedang menganalisis gambar...</p>
<p class="text-muted small">Proses ini membutuhkan waktu beberapa detik</p>
</div>
<div class="mt-4">
<h6 class="mb-2">Format yang Didukung:</h6>
<div class="d-flex gap-2">
<span class="badge bg-secondary">JPG</span>
<span class="badge bg-secondary">JPEG</span>
<span class="badge bg-secondary">PNG</span>
<span class="badge bg-secondary">BMP</span>
</div>
</div>
</div>
</div>
<div class="card mt-4">
<div class="card-header bg-info text-white">
<h5 class="mb-0"><i class="fas fa-lightbulb me-2"></i>Tips Pengambilan Gambar</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-check-circle text-success me-2"></i>Disarankan:</h6>
<ul class="list-unstyled">
<li><i class="fas fa-arrow-right text-success me-2"></i>Gambar dengan pencahayaan cukup</li>
<li><i class="fas fa-arrow-right text-success me-2"></i>Fokus pada bagian mulut dan kaki</li>
<li><i class="fas fa-arrow-right text-success me-2"></i>Ambil dari jarak dekat (0.5-1 meter)</li>
<li><i class="fas fa-arrow-right text-success me-2"></i>Gunakan latar belakang polos</li>
</ul>
</div>
<div class="col-md-6">
<h6><i class="fas fa-times-circle text-danger me-2"></i>Tidak Disarankan:</h6>
<ul class="list-unstyled">
<li><i class="fas fa-times text-danger me-2"></i>Gambar buram atau blur</li>
<li><i class="fas fa-times text-danger me-2"></i>Terlalu jauh dari objek</li>
<li><i class="fas fa-times text-danger me-2"></i>Pencahayaan kurang/tidak merata</li>
<li><i class="fas fa-times text-danger me-2"></i>Banyak objek dalam satu frame</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.upload-area {
border: 2px dashed #28a745 !important;
background-color: #f8f9fa;
transition: all 0.3s;
cursor: pointer;
}
.upload-area:hover {
background-color: #e9ecef;
border-color: #218838 !important;
}
.upload-area.dragover {
background-color: #d4edda;
border-color: #28a745 !important;
}
.preview-wrapper {
position: relative;
display: inline-block;
}
.preview-wrapper img {
height: 120px;
object-fit: cover;
width: 100%;
border-radius: 4px;
}
</style>
{% endblock %}
{% block scripts %}
<script>
document.addEventListener('DOMContentLoaded', function() {
var uploadArea = document.getElementById('uploadArea');
var fileInput = document.getElementById('file');
var browseBtn = document.getElementById('browseBtn');
var fileInfo = document.getElementById('fileInfo');
var previewContainer = document.getElementById('previewContainer');
var previewGrid = document.getElementById('previewGrid');
var submitBtn = document.getElementById('submitBtn');
var loading = document.getElementById('loading');
var uploadForm = document.getElementById('uploadForm');
if (!uploadArea || !fileInput || !browseBtn || !submitBtn || !uploadForm) return;
uploadArea.addEventListener('click', function() {
fileInput.click();
});
browseBtn.addEventListener('click', function(e) {
e.stopPropagation();
fileInput.click();
});
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(name) {
uploadArea.addEventListener(name, function(e) {
e.preventDefault();
e.stopPropagation();
}, false);
});
['dragenter', 'dragover'].forEach(function(name) {
uploadArea.addEventListener(name, function() {
uploadArea.classList.add('dragover');
}, false);
});
['dragleave', 'drop'].forEach(function(name) {
uploadArea.addEventListener(name, function() {
uploadArea.classList.remove('dragover');
}, false);
});
uploadArea.addEventListener('drop', function(e) {
fileInput.files = e.dataTransfer.files;
handleFiles(fileInput.files);
}, false);
fileInput.addEventListener('change', function() {
if (this.files.length > 0) {
handleFiles(this.files);
}
});
function handleFiles(files) {
var validFiles = [];
for (var i = 0; i < files.length; i++) {
var f = files[i];
if (f.size > 16 * 1024 * 1024) {
alert('File ' + f.name + ' terlalu besar (maks 16MB)');
continue;
}
var allowed = ['image/jpeg', 'image/jpg', 'image/png', 'image/bmp'];
if (allowed.indexOf(f.type) === -1) {
alert('File ' + f.name + ' tidak didukung');
continue;
}
validFiles.push(f);
}
if (validFiles.length === 0) {
fileInput.value = '';
submitBtn.disabled = true;
submitBtn.innerHTML = '<i class="fas fa-search me-2"></i>Upload & Deteksi';
if (fileInfo) fileInfo.classList.add('d-none');
if (previewContainer) previewContainer.style.display = 'none';
return;
}
if (fileInfo) {
fileInfo.classList.remove('d-none');
fileInfo.innerHTML = '<div class="alert alert-info">' + validFiles.length + ' file dipilih</div>';
}
if (previewContainer && previewGrid) {
previewContainer.style.display = 'block';
previewGrid.innerHTML = '';
for (var j = 0; j < validFiles.length; j++) {
(function(file) {
var col = document.createElement('div');
col.className = 'col-md-3 col-6 mb-3';
col.innerHTML = '<div class="card h-100"><div class="card-body p-1 text-center"><div class="preview-wrapper"><img></div><small class="text-muted mt-1 d-block">' + file.name + '</small></div></div>';
previewGrid.appendChild(col);
var reader = new FileReader();
reader.onload = function(e) {
col.querySelector('img').src = e.target.result;
};
reader.readAsDataURL(file);
})(validFiles[j]);
}
}
submitBtn.disabled = false;
submitBtn.innerHTML = '<i class="fas fa-search me-2"></i>Deteksi Semua (' + validFiles.length + ' gambar)';
}
uploadForm.addEventListener('submit', function(e) {
submitBtn.disabled = true;
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Memproses...';
if (loading) loading.classList.remove('d-none');
});
// Camera button
var cameraBtn = document.getElementById('cameraBtn');
if (cameraBtn) {
cameraBtn.addEventListener('click', function(e) {
e.stopPropagation();
var camInput = document.createElement('input');
camInput.type = 'file';
camInput.accept = 'image/*';
camInput.capture = 'environment';
camInput.multiple = true;
camInput.onchange = function() {
if (this.files.length > 0) {
fileInput.files = this.files;
handleFiles(this.files);
}
};
camInput.click();
});
}
});
</script>
{% endblock %}