// Global variables let selectedService = null; let ratings = { community: 0, customer: 0, value: 0, quality: 0, recommendation: 0 }; let reviews = JSON.parse(localStorage.getItem('nomarddeskReviews')) || []; // Initialize the app document.addEventListener('DOMContentLoaded', function() { initializeParticles(); loadReviews(); feather.replace(); }); // Create animated particles function initializeParticles() { const bg = document.querySelector('.animated-bg'); if (!bg) return; for (let i = 0; i < 3; i++) { const particle = document.createElement('div'); particle.className = 'particle'; bg.appendChild(particle); } } // Scroll to review section function scrollToReview() { document.getElementById('review-section').scrollIntoView({ behavior: 'smooth' }); } // Select service function selectService(service) { selectedService = service; // Update UI document.querySelectorAll('.service-card').forEach(card => { card.classList.remove('selected'); if (card.textContent.includes(service)) { card.classList.add('selected'); } }); // Show rating section with animation const ratingSection = document.getElementById('rating-section'); ratingSection.classList.remove('hidden'); ratingSection.style.animation = 'slideUp 0.5s ease-out'; // Reset ratings Object.keys(ratings).forEach(key => { ratings[key] = 0; updateStarDisplay(key); }); } // Set rating for category function setRating(category, rating) { ratings[category] = rating; updateStarDisplay(category); // Add animation effect const stars = document.querySelectorAll(`[data-category="${category}"] .star`); stars.forEach((star, index) => { setTimeout(() => { star.style.transform = 'scale(1.2)'; setTimeout(() => { star.style.transform = 'scale(1)'; }, 100); }, index * 50); }); } // Update star display function updateStarDisplay(category) { const stars = document.querySelectorAll(`[data-category="${category}"] .star`); stars.forEach((star, index) => { if (index < ratings[category]) { star.classList.add('filled'); star.classList.remove('text-gray-600'); } else { star.classList.remove('filled'); star.classList.add('text-gray-600'); } }); } // Submit review function submitReview() { // Validate if (!selectedService) { showNotification('Please select a service', 'error'); return; } const hasRatings = Object.values(ratings).some(r => r > 0); if (!hasRatings) { showNotification('Please provide at least one rating', 'error'); return; } // Create review object const review = { id: Date.now(), service: selectedService, ratings: { ...ratings }, feedback: document.getElementById('feedback').value, date: new Date().toISOString(), averageRating: Object.values(ratings).reduce((a, b) => a + b, 0) / Object.values(ratings).filter(r => r > 0).length }; // Save review reviews.unshift(review); localStorage.setItem('nomarddeskReviews', JSON.stringify(reviews)); // Show success modal showSuccessModal(); // Reset form resetForm(); // Update display loadReviews(); } // Reset form function resetForm() { selectedService = null; Object.keys(ratings).forEach(key => { ratings[key] = 0; }); document.getElementById('feedback').value = ''; document.querySelectorAll('.service-card').forEach(card => { card.classList.remove('selected'); }); document.getElementById('rating-section').classList.add('hidden'); } // Show success modal function showSuccessModal() { const modal = document.getElementById('success-modal'); modal.style.display = 'flex'; modal.classList.add('animate-fadeIn'); } // Close modal function closeModal() { const modal = document.getElementById('success-modal'); modal.style.display = 'none'; } // Load reviews function loadReviews() { const container = document.getElementById('reviews-container'); container.innerHTML = ''; // Sample reviews if no reviews exist if (reviews.length === 0) { const sampleReviews = [ { id: 1, service: 'Telegram Promotion', ratings: { community: 5, customer: 5, value: 4, quality: 5, recommendation: 5 }, feedback: 'Excellent service! Our Telegram community grew by 10k members in just 2 weeks.', date: new Date(Date.now() - 86400000).toISOString(), averageRating: 4.8 }, { id: 2, service: 'Vibe Coding / App Development', ratings: { community: 5, customer: 5, value: 5, quality: 5, recommendation: 5 }, feedback: 'The app they built for us exceeded all expectations. Professional team and great communication!', date: new Date(Date.now() - 172800000).toISOString(), averageRating: 5 }, { id: 3, service: 'Music Marketing', ratings: { community: 4, customer: 4, value: 4, quality: 4, recommendation: 4 }, feedback: 'Helped promote my latest track effectively. Got great results within budget.', date: new Date(Date.now() - 259200000).toISOString(), averageRating: 4 } ]; reviews = sampleReviews; } // Display reviews reviews.slice(0, 6).forEach(review => { const card = createReviewCard(review); container.appendChild(card); }); } // Create review card function createReviewCard(review) { const card = document.createElement('div'); card.className = 'review-card'; const starsHtml = '★'.repeat(Math.round(review.averageRating)) + '☆'.repeat(5 - Math.round(review.averageRating)); card.innerHTML = `
${starsHtml} ${formatDate(review.date)}
${review.service} ${review.feedback ? `

${review.feedback}

` : ''}
Comm
${review.ratings.community || '-'}
Service
${review.ratings.customer || '-'}
Value
${review.ratings.value || '-'}
Quality
${review.ratings.quality || '-'}
Rec
${review.ratings.recommendation || '-'}
`; return card; } // Format date function formatDate(dateString) { const date = new Date(dateString); const now = new Date(); const diffTime = Math.abs(now - date); const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); if (diffDays === 0) return 'Today'; if (diffDays === 1) return 'Yesterday'; if (diffDays < 7) return `${diffDays} days ago`; if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`; if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`; return `${Math.floor(diffDays / 365)} years ago`; } // Filter reviews function filterReviews(filter) { const buttons = document.querySelectorAll('.filter-btn'); buttons.forEach(btn => btn.classList.remove('active')); event.target.classList.add('active'); let filteredReviews = [...reviews]; switch(filter) { case 'highest': filteredReviews.sort((a, b) => b.averageRating - a.averageRating); break; case 'recent': filteredReviews.sort((a, b) => new Date(b.date) - new Date(a.date)); break; } const container = document.getElementById('reviews-container'); container.innerHTML = ''; filteredReviews.slice(0, 6).forEach(review => { const card = createReviewCard(review); container.appendChild(card); }); } // Show notification function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `fixed top-20 right-4 px-6 py-3 rounded-lg z-50 animate-slideUp ${ type === 'error' ? 'bg-red-500' : 'bg-green-500' }`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 3000); } // Add keyboard navigation document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { closeModal(); } }); // Add smooth scroll behavior document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth' }); } }); }); // Add parallax effect to hero section window.addEventListener('scroll', function() { const scrolled = window.pageYOffset; const parallax = document.querySelector('.animated-bg'); if (parallax) { parallax.style.transform = `translateY(${scrolled * 0.5}px)`; } }); // Add intersection observer for animations const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.animation = 'slideUp 0.5s ease-out forwards'; } }); }, observerOptions); // Observe all review cards document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.review-card').forEach(card => { observer.observe(card); }); });