diff --git a/api.php b/api.php index db42875..1dc9d8c 100644 --- a/api.php +++ b/api.php @@ -2006,6 +2006,68 @@ switch ($action) { echo json_encode(['success' => true]); break; + case 'guide_image_upload': + requireAuth(); + requireAdmin(); + $companyId = requireCompany(); + if ($method !== 'POST') break; + if (empty($_FILES['image'])) { + http_response_code(400); + echo json_encode(['error' => 'Kuva puuttuu']); + break; + } + $file = $_FILES['image']; + if ($file['error'] !== UPLOAD_ERR_OK) { + http_response_code(400); + echo json_encode(['error' => 'Kuvan lähetys epäonnistui']); + break; + } + if ($file['size'] > 5 * 1024 * 1024) { + http_response_code(400); + echo json_encode(['error' => 'Kuva on liian suuri (max 5 MB)']); + break; + } + $allowedExt = ['png', 'jpg', 'jpeg', 'gif', 'webp']; + $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); + if (!in_array($ext, $allowedExt)) { + http_response_code(400); + echo json_encode(['error' => 'Sallitut tiedostotyypit: PNG, JPG, GIF, WebP']); + break; + } + $imgDir = getCompanyDir($companyId) . '/guide_images'; + if (!file_exists($imgDir)) mkdir($imgDir, 0755, true); + $filename = uniqid() . '.' . ($ext === 'jpeg' ? 'jpg' : $ext); + if (move_uploaded_file($file['tmp_name'], $imgDir . '/' . $filename)) { + $url = 'api.php?action=guide_image&file=' . urlencode($filename); + echo json_encode(['success' => true, 'url' => $url, 'filename' => $filename]); + } else { + http_response_code(500); + echo json_encode(['error' => 'Tallennusvirhe']); + } + break; + + case 'guide_image': + requireAuth(); + $companyId = requireCompany(); + $filename = basename($_GET['file'] ?? ''); + if (!$filename || !preg_match('/^[a-f0-9]+\.(png|jpg|gif|webp)$/', $filename)) { + http_response_code(400); + echo 'Virheellinen tiedostonimi'; + break; + } + $path = getCompanyDir($companyId) . '/guide_images/' . $filename; + if (!file_exists($path)) { + http_response_code(404); + echo 'Kuvaa ei löydy'; + break; + } + $mimes = ['png' => 'image/png', 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'webp' => 'image/webp']; + $ext = pathinfo($filename, PATHINFO_EXTENSION); + header('Content-Type: ' . ($mimes[$ext] ?? 'application/octet-stream')); + header('Cache-Control: public, max-age=86400'); + readfile($path); + exit; + // ---------- ARCHIVE ---------- case 'archived_customers': requireAuth(); diff --git a/index.html b/index.html index 8d7a880..c6a72e8 100644 --- a/index.html +++ b/index.html @@ -407,6 +407,8 @@ + + diff --git a/script.js b/script.js index 1ab6f06..90099b8 100644 --- a/script.js +++ b/script.js @@ -3500,6 +3500,8 @@ function renderMarkdown(md) { html = html.replace(/\*\*\*(.+?)\*\*\*/g, '$1'); html = html.replace(/\*\*(.+?)\*\*/g, '$1'); html = html.replace(/\*(.+?)\*/g, '$1'); + // Kuvat (ennen linkkejä!) + html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '$1'); // Linkit html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1'); // Lainaukset @@ -3731,6 +3733,32 @@ document.getElementById('btn-guide-preview-toggle')?.addEventListener('click', ( } }); +// Kuva-upload +document.getElementById('btn-guide-image')?.addEventListener('click', () => { + document.getElementById('guide-image-input')?.click(); +}); +document.getElementById('guide-image-input')?.addEventListener('change', async (e) => { + const file = e.target.files[0]; + if (!file) return; + const formData = new FormData(); + formData.append('image', file); + try { + const res = await fetch(`${API}?action=guide_image_upload`, { + method: 'POST', credentials: 'include', body: formData + }); + const result = await res.json(); + if (!res.ok) throw new Error(result.error || 'Virhe'); + // Lisää Markdown-kuvatagi editoriin + const ta = document.getElementById('guide-form-content'); + const pos = ta.selectionStart; + const mdImg = `![${file.name}](${result.url})`; + ta.value = ta.value.substring(0, pos) + mdImg + ta.value.substring(ta.selectionEnd); + ta.focus(); + ta.selectionStart = ta.selectionEnd = pos + mdImg.length; + } catch (err) { alert(err.message); } + e.target.value = ''; // nollaa input +}); + // Kategorianhallinta document.getElementById('btn-manage-guide-cats')?.addEventListener('click', () => { renderGuideCatList();