// Hamed Site - Baby & Toddler Photo Album App let currentTab = 'gallery'; let activeAlbumId = null; let currentSearch = ''; let currentFavoriteOnly = false; let allPhotos = []; let activeLightboxIndex = 0; let isAudioPlaying = false; let audioCtx = null; let musicInterval = null; // Initialize on DOM load document.addEventListener('DOMContentLoaded', () => { loadPhotos(); loadStats(); setupEventListeners(); }); function setupEventListeners() { // Search input const searchInput = document.getElementById('searchInput'); if (searchInput) { let debounceTimeout; searchInput.addEventListener('input', (e) => { clearTimeout(debounceTimeout); debounceTimeout = setTimeout(() => { currentSearch = e.target.value.trim(); loadPhotos(); }, 300); }); } // Keyboard navigation for lightbox document.addEventListener('keydown', (e) => { const lightbox = document.getElementById('lightboxModal'); if (lightbox && lightbox.classList.contains('open')) { if (e.key === 'ArrowRight' || e.key === 'ArrowUp') { prevLightbox(); } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') { nextLightbox(); } else if (e.key === 'Escape') { closeModal('lightboxModal'); } } }); // File input drag & drop const dropArea = document.getElementById('fileDropArea'); const fileInput = document.getElementById('photoFileInput'); if (dropArea && fileInput) { dropArea.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', () => handleFileSelect(fileInput.files[0])); ['dragenter', 'dragover'].forEach(name => { dropArea.addEventListener(name, (e) => { e.preventDefault(); dropArea.style.borderColor = '#2563eb'; dropArea.style.background = '#dbeafe'; }); }); ['dragleave', 'drop'].forEach(name => { dropArea.addEventListener(name, (e) => { e.preventDefault(); dropArea.style.borderColor = '#93c5fd'; dropArea.style.background = '#eff6ff'; }); }); dropArea.addEventListener('drop', (e) => { if (e.dataTransfer.files && e.dataTransfer.files[0]) { fileInput.files = e.dataTransfer.files; handleFileSelect(e.dataTransfer.files[0]); } }); } } function handleFileSelect(file) { if (!file) return; const previewContainer = document.getElementById('photoPreviewContainer'); const previewImg = document.getElementById('photoPreviewImg'); const dropText = document.getElementById('dropText'); if (file.type.startsWith('image/')) { const reader = new FileReader(); reader.onload = (e) => { previewImg.src = e.target.result; previewContainer.style.display = 'block'; dropText.style.display = 'none'; }; reader.readAsDataURL(file); } } // Switch Tab function switchTab(tabName) { currentTab = tabName; document.querySelectorAll('.tab-btn').forEach(btn => { btn.classList.toggle('active', btn.dataset.tab === tabName); }); document.querySelectorAll('.tab-pane').forEach(pane => { pane.style.display = pane.id === `tab-${tabName}` ? 'block' : 'none'; }); if (tabName === 'gallery') { loadPhotos(); } else if (tabName === 'albums') { loadAlbums(); } else if (tabName === 'quotes') { loadQuotes(); } else if (tabName === 'milestones') { loadMilestones(); } else if (tabName === 'slideshow') { startSlideshow(); } } // API Helper async function api(action, data = null, isFormData = false) { try { let options = { method: data ? 'POST' : 'GET' }; if (data) { if (isFormData) { options.body = data; } else { options.headers = { 'Content-Type': 'application/json' }; options.body = JSON.stringify(data); } } const res = await fetch(`index.php?api=${action}`, options); return await res.json(); } catch (err) { console.error('API Error:', err); showToast('خطا در برقراری ارتباط با سرور', 'error'); return { success: false, error: err.message }; } } // Load Photos async function loadPhotos() { const grid = document.getElementById('photosGrid'); if (!grid) return; grid.innerHTML = '

در حال بارگذاری عکس‌های قشنگ... 👶🎈

'; let url = `photos&search=${encodeURIComponent(currentSearch)}`; if (activeAlbumId) url += `&album_id=${activeAlbumId}`; if (currentFavoriteOnly) url += `&favorite_only=1`; const res = await api(url); if (res.success) { allPhotos = res.data; renderPhotos(res.data); } } function renderPhotos(photos) { const grid = document.getElementById('photosGrid'); if (!photos || photos.length === 0) { grid.innerHTML = `
📸

هنوز عکسی در این بخش ثبت نشده!

با زدن دکمه «+ افزودن عکس جدید» اولین خاطره شیرین را اضافه کنید.

`; return; } grid.innerHTML = photos.map((p, index) => `
${p.title} ${p.age_tag || '۳ سالگی'}
${p.album_icon || '🎈'} ${p.album_title || 'آلبوم عمومی'}

${escapeHtml(p.title)}

${escapeHtml(p.caption || '')}

`).join(''); } // Filter Album function filterByAlbum(albumId, btnElement) { activeAlbumId = albumId; document.querySelectorAll('.filter-chip').forEach(c => c.classList.remove('active')); if (btnElement) btnElement.classList.add('active'); loadPhotos(); } function toggleFavoriteFilter() { currentFavoriteOnly = !currentFavoriteOnly; const btn = document.getElementById('favFilterBtn'); if (btn) { btn.classList.toggle('active', currentFavoriteOnly); btn.innerText = currentFavoriteOnly ? '⭐ فقط برگزیده‌ها' : '⭐ نمایش همه'; } loadPhotos(); } // Like Photo async function likePhoto(id) { const res = await api(`like_photo&id=${id}`, {}); if (res.success) { const countSpan = document.getElementById(`likes-count-${id}`); if (countSpan) countSpan.innerText = res.likes; showConfetti(); } } // Toggle Favorite async function toggleFavorite(id) { const res = await api(`toggle_fav&id=${id}`, {}); if (res.success) { loadPhotos(); loadStats(); } } // Delete Photo async function deletePhoto(id) { if (!confirm('آیا از حذف این عکس خاطره‌انگیز مطمئن هستید؟')) return; const res = await api(`delete_photo&id=${id}`, {}); if (res.success) { showToast('عکس با موفقیت حذف شد', 'success'); loadPhotos(); loadStats(); } } // Lightbox function openLightbox(index) { if (!allPhotos || allPhotos.length === 0) return; activeLightboxIndex = index; updateLightboxContent(); openModal('lightboxModal'); } function updateLightboxContent() { const photo = allPhotos[activeLightboxIndex]; if (!photo) return; document.getElementById('lightboxImg').src = photo.file_path; document.getElementById('lightboxTitle').innerText = photo.title; document.getElementById('lightboxCaption').innerText = photo.caption || 'بدون توضیح'; document.getElementById('lightboxAlbum').innerText = `${photo.album_icon || '🎈'} ${photo.album_title || 'عمومی'}`; document.getElementById('lightboxAge').innerText = photo.age_tag || '۳ سالگی'; document.getElementById('lightboxDate').innerText = photo.photo_date || ''; document.getElementById('lightboxLikes').innerText = photo.likes_count || 0; document.getElementById('lightboxDownloadBtn').href = photo.file_path; } function nextLightbox() { if (activeLightboxIndex < allPhotos.length - 1) { activeLightboxIndex++; } else { activeLightboxIndex = 0; } updateLightboxContent(); } function prevLightbox() { if (activeLightboxIndex > 0) { activeLightboxIndex--; } else { activeLightboxIndex = allPhotos.length - 1; } updateLightboxContent(); } // Albums Tab async function loadAlbums() { const grid = document.getElementById('albumsGrid'); if (!grid) return; grid.innerHTML = '

در حال بارگذاری آلبوم‌ها... 📂

'; const res = await api('albums'); if (res.success) { if (!res.data || res.data.length === 0) { grid.innerHTML = '

هنوز آلبومی ساخته نشده است.

'; return; } grid.innerHTML = res.data.map(a => `
${a.icon || '🎈'}

${escapeHtml(a.title)}

${escapeHtml(a.description || '')}

📸 ${a.photos_count || 0} عکس
`).join(''); } } // Quotes Tab async function loadQuotes() { const grid = document.getElementById('quotesGrid'); if (!grid) return; grid.innerHTML = '

در حال بارگذاری حرف‌های بامزه... 👶

'; const res = await api('quotes'); if (res.success) { if (!res.data || res.data.length === 0) { grid.innerHTML = '

هنوز جمله‌ای ثبت نشده است.

'; return; } grid.innerHTML = res.data.map(q => `
${escapeHtml(q.quote)}
📍 ${escapeHtml(q.context || 'بدون توضیح')}
🏷️ ${q.age_tag || '۳ سالگی'} 📅 ${q.said_date || ''}
`).join(''); } } async function deleteQuote(id) { if (!confirm('حذف این جمله بامزه؟')) return; const res = await api(`delete_quote&id=${id}`, {}); if (res.success) { loadQuotes(); loadStats(); } } // Milestones Tab async function loadMilestones() { const container = document.getElementById('milestonesList'); if (!container) return; container.innerHTML = '

در حال بارگذاری مراحل رشد... 🌟

'; const res = await api('milestones'); if (res.success) { if (!res.data || res.data.length === 0) { container.innerHTML = '

هنوز مرحله رشدی ثبت نشده است.

'; return; } container.innerHTML = res.data.map(m => `
${m.icon || '🌟'}

${escapeHtml(m.title)}

${m.age_tag || '۳ سالگی'}

${escapeHtml(m.description || '')}

📅 تاریخ: ${m.milestone_date || ''}
`).join(''); } } async function deleteMilestone(id) { if (!confirm('حذف این دستاورد؟')) return; const res = await api(`delete_milestone&id=${id}`, {}); if (res.success) { loadMilestones(); loadStats(); } } // Stats async function loadStats() { const res = await api('stats'); if (res.success) { document.getElementById('statPhotosCount').innerText = res.data.photos; document.getElementById('statAlbumsCount').innerText = res.data.albums; document.getElementById('statQuotesCount').innerText = res.data.quotes; document.getElementById('statMilestonesCount').innerText = res.data.milestones; } } // Forms Submission async function submitPhotoUpload(e) { e.preventDefault(); const form = document.getElementById('uploadPhotoForm'); const formData = new FormData(form); const submitBtn = form.querySelector('button[type="submit"]'); submitBtn.disabled = true; submitBtn.innerText = 'در حال ذخیره‌سازی... ⏳'; const res = await api('upload_photo', formData, true); submitBtn.disabled = false; submitBtn.innerText = 'ذخیره در آلبوم 🎈'; if (res.success) { showToast('عکس با موفقیت به آلبوم اضافه شد!', 'success'); closeModal('uploadPhotoModal'); form.reset(); document.getElementById('photoPreviewContainer').style.display = 'none'; document.getElementById('dropText').style.display = 'block'; loadPhotos(); loadStats(); showConfetti(); } else { showToast(res.error || 'خطا در آپلود عکس', 'error'); } } async function submitNewAlbum(e) { e.preventDefault(); const form = document.getElementById('newAlbumForm'); const formData = new FormData(form); const res = await api('create_album', formData, true); if (res.success) { showToast('آلبوم جدید با موفقیت ساخته شد!', 'success'); closeModal('newAlbumModal'); form.reset(); loadAlbums(); loadStats(); // Update album dropdown in upload modal updateAlbumSelectOptions(); } else { showToast(res.error || 'خطا در ایجاد آلبوم', 'error'); } } async function submitNewQuote(e) { e.preventDefault(); const form = document.getElementById('newQuoteForm'); const formData = new FormData(form); const res = await api('create_quote', formData, true); if (res.success) { showToast('جمله بامزه ذخیره شد!', 'success'); closeModal('newQuoteModal'); form.reset(); loadQuotes(); loadStats(); } } async function submitNewMilestone(e) { e.preventDefault(); const form = document.getElementById('newMilestoneForm'); const formData = new FormData(form); const res = await api('create_milestone', formData, true); if (res.success) { showToast('دستاورد رشد ثبت شد!', 'success'); closeModal('newMilestoneModal'); form.reset(); loadMilestones(); loadStats(); } } // Modal Helpers function openModal(id) { const modal = document.getElementById(id); if (modal) modal.classList.add('open'); } function closeModal(id) { const modal = document.getElementById(id); if (modal) modal.classList.remove('open'); } // Soothing Nursery Synthesizer for Slideshow function toggleLullaby() { if (isAudioPlaying) { stopLullaby(); } else { playLullaby(); } } function playLullaby() { try { if (!audioCtx) { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } isAudioPlaying = true; document.getElementById('musicToggleBtn').innerHTML = '🔊 توقف موزیک لایت'; const notes = [261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 523.25]; // C, D, E, F, G, A, C5 let noteIdx = 0; musicInterval = setInterval(() => { if (!isAudioPlaying) return; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); const freq = notes[Math.floor(Math.random() * notes.length)]; osc.type = 'sine'; osc.frequency.setValueAtTime(freq, audioCtx.currentTime); gain.gain.setValueAtTime(0.08, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 1.2); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(); osc.stop(audioCtx.currentTime + 1.2); }, 1200); } catch (e) { console.error('Audio init error', e); } } function stopLullaby() { isAudioPlaying = false; if (musicInterval) clearInterval(musicInterval); const btn = document.getElementById('musicToggleBtn'); if (btn) btn.innerHTML = '🎵 پخش موزیک آرامش‌بخش'; } let slideshowTimer = null; let currentSlideshowIndex = 0; function startSlideshow() { if (!allPhotos || allPhotos.length === 0) return; currentSlideshowIndex = 0; renderSlideshowSlide(); if (slideshowTimer) clearInterval(slideshowTimer); slideshowTimer = setInterval(() => { currentSlideshowIndex = (currentSlideshowIndex + 1) % allPhotos.length; renderSlideshowSlide(); }, 4500); } function renderSlideshowSlide() { const photo = allPhotos[currentSlideshowIndex]; if (!photo) return; const slideImg = document.getElementById('slideshowCurrentImg'); const slideTitle = document.getElementById('slideshowCurrentTitle'); const slideDesc = document.getElementById('slideshowCurrentDesc'); if (slideImg) slideImg.src = photo.file_path; if (slideTitle) slideTitle.innerText = photo.title; if (slideDesc) slideDesc.innerText = photo.caption || `${photo.album_title || ''} • ${photo.age_tag || '۳ سالگی'}`; } // Confetti Animation function showConfetti() { for (let i = 0; i < 20; i++) { const conf = document.createElement('div'); conf.innerText = ['🎈', '⭐', '🎉', '💖', '👶', '✨'][Math.floor(Math.random() * 6)]; conf.style.position = 'fixed'; conf.style.left = Math.random() * 90 + 5 + 'vw'; conf.style.top = '100vh'; conf.style.fontSize = Math.random() * 20 + 20 + 'px'; conf.style.zIndex = 9999; conf.style.pointerEvents = 'none'; conf.style.transition = 'all 2.5s ease-out'; document.body.appendChild(conf); setTimeout(() => { conf.style.top = Math.random() * 20 + 'vh'; conf.style.opacity = '0'; conf.style.transform = `scale(${Math.random() + 0.5}) rotate(${Math.random() * 360}deg)`; }, 50); setTimeout(() => conf.remove(), 2600); } } // Toast function showToast(msg, type = 'info') { const toast = document.createElement('div'); toast.style.position = 'fixed'; toast.style.bottom = '24px'; toast.style.right = '24px'; toast.style.background = type === 'error' ? '#ef4444' : '#10b981'; toast.style.color = '#ffffff'; toast.style.padding = '12px 22px'; toast.style.borderRadius = '12px'; toast.style.fontWeight = '700'; toast.style.fontSize = '0.92rem'; toast.style.boxShadow = '0 10px 25px rgba(0,0,0,0.2)'; toast.style.zIndex = 10000; toast.style.direction = 'rtl'; toast.innerText = msg; document.body.appendChild(toast); setTimeout(() => { toast.style.transition = 'opacity 0.5s'; toast.style.opacity = '0'; setTimeout(() => toast.remove(), 500); }, 3000); } function escapeHtml(text) { if (!text) return ''; return text.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); }