import { getJson, sendJson, sendJsonBlob } from './api.js'; export function createSlideController(deps) { var previewSlides = []; var previewIdx = 0; function openSlidesFromSlug(slug) { deps.showBusy('Loading slides...'); getJson('/api/learning/content/' + encodeURIComponent(slug) + '/slides') .then(function(data) { deps.hideBusy(); if (!data.success) { deps.showToast(data.error || 'Could not load slides', 'error'); return; } openSlideModal(data.slides, data.css); }) .catch(function(err) { deps.hideBusy(); deps.showToast(err.message, 'error'); }); } function previewCurrentSlides() { var md = deps.getMarkdown(); if (!md) { deps.showToast('No slide content yet. Use AI Generate first.', 'info'); return; } deps.showBusy('Rendering slides...'); sendJson('/api/admin/learning/preview-slides', 'POST', { markdown: md }) .then(function(data) { deps.hideBusy(); if (!data.success) { deps.showToast(data.error || 'Preview failed', 'error'); return; } openSlideModal(data.slides, data.css); }) .catch(function(err) { deps.hideBusy(); deps.showToast(err.message, 'error'); }); } function openSlideModal(slides, css) { closeSlideModal(); previewSlides = slides || []; previewIdx = 0; var modal = document.getElementById('slide-preview-modal'); var cssEl = document.getElementById('slide-preview-css'); var dotsEl = document.getElementById('slide-preview-dots'); if (!modal || !previewSlides.length) { deps.showToast('No slides to display', 'error'); return; } if (cssEl) cssEl.textContent = css || ''; if (dotsEl) dotsEl.innerHTML = renderDots(previewSlides.length); modal.classList.remove('hidden'); document.body.style.overflow = 'hidden'; renderSlide(0); wireModalInput(modal); } function renderSlide(idx) { var content = document.getElementById('slide-preview-content'); var counter = document.getElementById('slide-preview-counter'); var dots = document.querySelectorAll('.slide-dot'); var prev = document.getElementById('slide-nav-prev'); var next = document.getElementById('slide-nav-next'); if (!content || !previewSlides.length) return; previewIdx = Math.max(0, Math.min(idx, previewSlides.length - 1)); content.innerHTML = previewSlides[previewIdx]; if (counter) counter.textContent = (previewIdx + 1) + ' / ' + previewSlides.length; if (prev) prev.style.opacity = previewIdx === 0 ? '0.3' : '1'; if (next) next.style.opacity = previewIdx === previewSlides.length - 1 ? '0.3' : '1'; dots.forEach(function(d, i) { d.classList.toggle('active', i === previewIdx); }); } function slideStep(dir) { renderSlide(previewIdx + dir); } function closeSlideModal() { var modal = document.getElementById('slide-preview-modal'); if (modal) modal.classList.add('hidden'); document.body.style.overflow = ''; if (document._slideKeyHandler) { document.removeEventListener('keydown', document._slideKeyHandler); document._slideKeyHandler = null; } if (modal && modal._touchStart) { modal.removeEventListener('touchstart', modal._touchStart); modal._touchStart = null; } if (modal && modal._touchEnd) { modal.removeEventListener('touchend', modal._touchEnd); modal._touchEnd = null; } } function downloadPptx() { var md = deps.getMarkdown(); if (!md) { deps.showToast('No slide content yet', 'error'); return; } var title = deps.getTitle() || 'presentation'; var btn = document.getElementById('btn-lh-download-pptx'); if (btn) { btn.disabled = true; btn.innerHTML = ' Building...'; } sendJsonBlob('/api/admin/learning/generate-pptx', 'POST', { markdown: md, title: title }) .then(function(blob) { var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = makePptxFilename(title); a.click(); URL.revokeObjectURL(url); deps.showToast('PPTX downloaded!', 'success'); }) .catch(function(err) { deps.showToast(err.message, 'error'); }) .finally(function() { if (btn) { btn.disabled = false; btn.innerHTML = ' Download PPTX'; } }); } function wireModalInput(modal) { document._slideKeyHandler = function(e) { if (e.key === 'ArrowRight' || e.key === 'ArrowDown') slideStep(1); else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') slideStep(-1); else if (e.key === 'Escape') closeSlideModal(); }; document.addEventListener('keydown', document._slideKeyHandler); var touchStartX = 0; modal._touchStart = function(e) { touchStartX = e.touches[0].clientX; }; modal._touchEnd = function(e) { var dx = e.changedTouches[0].clientX - touchStartX; if (Math.abs(dx) > 40) slideStep(dx < 0 ? 1 : -1); }; modal.addEventListener('touchstart', modal._touchStart); modal.addEventListener('touchend', modal._touchEnd); } return { closeSlideModal: closeSlideModal, downloadPptx: downloadPptx, openSlidesFromSlug: openSlidesFromSlug, previewCurrentSlides: previewCurrentSlides, renderSlide: renderSlide, slideStep: slideStep }; } export function makePptxFilename(title) { return String(title || 'presentation').replace(/\s+/g, '-').toLowerCase() + '.pptx'; } function renderDots(count) { var html = ''; for (var i = 0; i < count; i++) { html += ''; } return html; }