Files
diploma_todoapp/frontend/js/support.js
Tim Basten 63070fd90c feat: Enhance dashboard with stats cards and task filtering
- Added stats cards to display active, completed, overdue, and due-today tasks on the dashboard.
- Implemented search functionality to filter tasks in real-time based on user input.
- Introduced quick-pick date buttons for easier task date selection.
- Updated task rendering logic to handle empty states for task lists.
- Improved overall user interface with new CSS styles for stat cards and buttons.

chore: Update environment variables and backend error handling

- Fixed formatting in the .env file for consistency.
- Enhanced error handling in the backend API for better debugging.

feat: Revamp frontend pages with new features and pricing sections

- Redesigned the index.html page to include a hero section and feature highlights.
- Created a new features page with dynamic loading of features from JSON.
- Implemented a pricing page that loads plans from JSON and highlights the featured plan.
- Added support and FAQ sections with dynamic content loading and contact form functionality.
- Introduced JSON files for FAQs, features, and pricing to allow easy updates without code changes.
2026-04-23 16:29:52 +08:00

79 lines
2.4 KiB
JavaScript

/**
* support.js
*
* Powers the Support page.
*
* Features:
* 1. FAQ accordion
* - Loads Q&A pairs from `./data/faq.json`.
* - Renders each as a Bootstrap accordion item so only one
* answer is open at a time.
*
* 2. Contact form
* - Validates that all fields have been filled in.
* - Displays an inline success or error alert above the form.
* - Does not currently persist messages; the form is purely a
* frontend demonstration (see README / features notes).
*/
const faqContainer = document.getElementById('faqContainer');
const contactForm = document.getElementById('contactForm');
const contactStatus = document.getElementById('contactStatus');
async function loadFaqs() {
try {
const response = await fetch('./data/faq.json');
if (!response.ok) {
throw new Error(`Failed to load FAQs: ${response.status}`);
}
const data = await response.json();
renderFaqs(data.faqs);
} catch (error) {
console.error('Error:', error);
faqContainer.innerHTML = `<p class="text-white text-center">Unable to load FAQs.</p>`;
}
}
function renderFaqs(faqs) {
faqContainer.innerHTML = '';
faqs.forEach((faq, i) => {
const item = document.createElement('div');
item.className = 'accordion-item';
item.innerHTML = `
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
data-bs-target="#faq-${i}" aria-expanded="false" aria-controls="faq-${i}">
${faq.question}
</button>
</h2>
<div id="faq-${i}" class="accordion-collapse collapse" data-bs-parent="#faqContainer">
<div class="accordion-body">${faq.answer}</div>
</div>
`;
faqContainer.appendChild(item);
});
}
contactForm.addEventListener('submit', (event) => {
event.preventDefault();
const name = contactForm.name.value.trim();
const email = contactForm.email.value.trim();
const message = contactForm.message.value.trim();
if (!name || !email || !message) {
showStatus('Please fill out all fields.', 'danger');
return;
}
showStatus('Thanks, your message has been received. We will get back to you shortly.', 'success');
contactForm.reset();
});
function showStatus(message, type) {
contactStatus.className = `alert alert-${type}`;
contactStatus.textContent = message;
contactStatus.classList.remove('d-none');
}
window.addEventListener('DOMContentLoaded', loadFaqs);