diff --git a/admin.html b/admin.html
index b5c0d2f..d1f59f6 100644
--- a/admin.html
+++ b/admin.html
@@ -455,11 +455,45 @@
// ===========================
// IMAGE UPLOAD
// ===========================
+ async function resizeImage(file, maxPx = 1920, quality = 0.85) {
+ if (file.type === 'image/gif') return file;
+ return new Promise(resolve => {
+ const img = new Image();
+ const url = URL.createObjectURL(file);
+ img.onload = () => {
+ URL.revokeObjectURL(url);
+ const ratio = Math.min(maxPx / img.naturalWidth, maxPx / img.naturalHeight, 1);
+ if (ratio === 1 && file.size < 1.5 * 1024 * 1024) { resolve(file); return; }
+ const canvas = document.createElement('canvas');
+ canvas.width = Math.round(img.naturalWidth * ratio);
+ canvas.height = Math.round(img.naturalHeight * ratio);
+ canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
+ canvas.toBlob(
+ blob => resolve(new File([blob], 'image.jpg', { type: 'image/jpeg' })),
+ 'image/jpeg', quality
+ );
+ };
+ img.src = url;
+ });
+ }
+
async function uploadImgAdmin(input, hiddenId, previewId, labelId) {
const file = input.files[0];
if (!file) return;
+
+ const allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
+ if (!allowed.includes(file.type)) {
+ showToast('⚠️ Tuetut muodot: JPG, PNG, GIF, WebP');
+ input.value = '';
+ return;
+ }
+
+ const lbl = document.getElementById(labelId);
+ lbl.style.opacity = '0.5';
+
+ const resized = await resizeImage(file);
const formData = new FormData();
- formData.append('file', file);
+ formData.append('file', resized, resized.name || 'image.jpg');
try {
const res = await fetch('upload.php', { method: 'POST', body: formData });
if (!res.ok) throw new Error(await res.text());
@@ -468,9 +502,11 @@
const prev = document.getElementById(previewId);
prev.src = data.url;
prev.style.display = 'block';
- document.getElementById(labelId).classList.add('has-image');
+ lbl.classList.add('has-image');
} catch (e) {
- showToast('⚠️ Kuvan lataus epäonnistui.');
+ showToast('⚠️ Kuvan lataus epäonnistui. Tuetut muodot: JPG, PNG, GIF, WebP.');
+ } finally {
+ lbl.style.opacity = '';
}
}
diff --git a/script.js b/script.js
index e090bc3..0699293 100644
--- a/script.js
+++ b/script.js
@@ -389,11 +389,47 @@ function closeSubmitModal() {
document.body.style.overflow = '';
}
+async function resizeImage(file, maxPx = 1920, quality = 0.85) {
+ // Älä muuta GIF:ejä (animaatio menisi rikki)
+ if (file.type === 'image/gif') return file;
+ return new Promise(resolve => {
+ const img = new Image();
+ const url = URL.createObjectURL(file);
+ img.onload = () => {
+ URL.revokeObjectURL(url);
+ const ratio = Math.min(maxPx / img.naturalWidth, maxPx / img.naturalHeight, 1);
+ // Jos kuva on jo tarpeeksi pieni, palauta sellaisenaan
+ if (ratio === 1 && file.size < 1.5 * 1024 * 1024) { resolve(file); return; }
+ const canvas = document.createElement('canvas');
+ canvas.width = Math.round(img.naturalWidth * ratio);
+ canvas.height = Math.round(img.naturalHeight * ratio);
+ canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
+ canvas.toBlob(
+ blob => resolve(new File([blob], 'image.jpg', { type: 'image/jpeg' })),
+ 'image/jpeg', quality
+ );
+ };
+ img.src = url;
+ });
+}
+
async function uploadImg(input, hiddenId, previewId, labelId) {
const file = input.files[0];
if (!file) return;
+
+ const allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
+ if (!allowed.includes(file.type)) {
+ alert('Tuetut kuvamuodot: JPG, PNG, GIF, WebP');
+ input.value = '';
+ return;
+ }
+
+ const lbl = document.getElementById(labelId);
+ lbl.style.opacity = '0.5';
+
+ const resized = await resizeImage(file);
const formData = new FormData();
- formData.append('file', file);
+ formData.append('file', resized, resized.name || 'image.jpg');
try {
const res = await fetch('upload.php', { method: 'POST', body: formData });
if (!res.ok) throw new Error(await res.text());
@@ -402,9 +438,11 @@ async function uploadImg(input, hiddenId, previewId, labelId) {
const prev = document.getElementById(previewId);
prev.src = data.url;
prev.style.display = 'block';
- document.getElementById(labelId).classList.add('has-image');
+ lbl.classList.add('has-image');
} catch (e) {
- alert('Kuvan lataus epäonnistui: ' + e.message);
+ alert('Kuvan lataus epäonnistui. Tuetut muodot: JPG, PNG, GIF, WebP (max 8 MB).');
+ } finally {
+ lbl.style.opacity = '';
}
}