diff --git a/views/css/index.css b/views/css/index.css index f2f7233..37f6ff4 100644 --- a/views/css/index.css +++ b/views/css/index.css @@ -584,3 +584,111 @@ hr{ cursor: pointer; border-radius: 99%; } + +/* ======================================== + FAQ SEARCH FEATURE STYLES + ======================================== */ + +/* Search input focus effect */ +#faq-search-input:focus { + box-shadow: 0 0 0 4px rgba(168, 85, 247, 0.1); +} + +.tw-dark #faq-search-input:focus { + box-shadow: 0 0 0 4px rgba(168, 85, 247, 0.2); +} + +/* Clear button hover effect */ +#faq-search-clear { + cursor: pointer; + transition: all 0.2s ease; +} + +#faq-search-clear:hover { + transform: scale(1.1); +} + +/* Results counter animation */ +#faq-search-results { + animation: slideDown 0.3s ease-out; +} + +@keyframes slideDown { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* FAQ highlight effect when searching */ +.faq-highlight { + position: relative; +} + +.faq-highlight::before { + content: ''; + position: absolute; + left: -8px; + top: 50%; + transform: translateY(-50%); + width: 4px; + height: 60%; + background: linear-gradient(180deg, #a855f7, #8b5cf6); + border-radius: 2px; + animation: pulseGlow 2s ease-in-out infinite; +} + +@keyframes pulseGlow { + 0%, 100% { + opacity: 0.6; + } + 50% { + opacity: 1; + box-shadow: 0 0 8px rgba(168, 85, 247, 0.5); + } +} + +/* No results message styling */ +#faq-result-count { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.5rem 1rem; + border-radius: 0.5rem; + font-weight: 500; + background-color: rgba(168, 85, 247, 0.05); +} + +.tw-dark #faq-result-count { + background-color: rgba(168, 85, 247, 0.1); +} + +/* Search input placeholder animation */ +@keyframes placeholderShift { + 0%, 100% { + opacity: 0.6; + } + 50% { + opacity: 0.8; + } +} + +#faq-search-input::placeholder { + animation: placeholderShift 3s ease-in-out infinite; +} + +/* Mobile responsiveness for search */ +@media (max-width: 768px) { + #faq-search-input { + font-size: 14px; + padding: 0.75rem 2.5rem; + } + + #faq-search-input::placeholder { + font-size: 13px; + } +} diff --git a/views/index.html b/views/index.html index 043fe0c..67d5cf9 100644 --- a/views/index.html +++ b/views/index.html @@ -1831,10 +1831,37 @@

> Regarding GSSOC FAQ BOT

+ + +
+
+
+ +
+ + +
+
+ +
+
+
-
+

@@ -1895,7 +1922,7 @@


-
+

@@ -1955,7 +1982,7 @@


-
+

@@ -2058,7 +2085,7 @@


-
+

diff --git a/views/scripts/components.js b/views/scripts/components.js index 343858f..92366b1 100644 --- a/views/scripts/components.js +++ b/views/scripts/components.js @@ -259,6 +259,155 @@ fetch('/faqs.json') }); +// ======================================== +// FAQ SEARCH & FILTER FUNCTIONALITY +// ======================================== + +document.addEventListener('DOMContentLoaded', function() { + const searchInput = document.getElementById('faq-search-input'); + const clearButton = document.getElementById('faq-search-clear'); + const resultsDiv = document.getElementById('faq-search-results'); + const resultCount = document.getElementById('faq-result-count'); + const faqContainer = document.getElementById('faq-container'); + + if (!searchInput || !faqContainer) return; + + // Get all FAQ items + const faqItems = faqContainer.querySelectorAll('[data-faq-item]'); + const totalFaqs = faqItems.length; + + /** + * Filter FAQ items based on search query + */ + function filterFAQs() { + const query = searchInput.value.toLowerCase().trim(); + + // Show/hide clear button + if (query.length > 0) { + clearButton.classList.remove('tw-hidden'); + } else { + clearButton.classList.add('tw-hidden'); + } + + // If query is empty, show all FAQs + if (query.length === 0) { + faqItems.forEach(item => { + item.style.display = ''; + item.classList.remove('faq-highlight'); + const hr = item.nextElementSibling; + if (hr && hr.tagName === 'HR') { + hr.style.display = ''; + } + }); + resultsDiv.classList.add('tw-hidden'); + return; + } + + let visibleCount = 0; + + // Filter FAQs + faqItems.forEach((item, index) => { + const question = item.getAttribute('data-faq-question') || ''; + const answer = item.getAttribute('data-faq-answer') || ''; + const searchText = (question + ' ' + answer).toLowerCase(); + + const matches = searchText.includes(query); + + if (matches) { + item.style.display = ''; + item.classList.add('faq-highlight'); + visibleCount++; + + // Show separator if not last visible item + const hr = item.nextElementSibling; + if (hr && hr.tagName === 'HR') { + hr.style.display = ''; + } + } else { + item.style.display = 'none'; + item.classList.remove('faq-highlight'); + + // Hide separator + const hr = item.nextElementSibling; + if (hr && hr.tagName === 'HR') { + hr.style.display = 'none'; + } + } + }); + + // Update results count + resultsDiv.classList.remove('tw-hidden'); + if (visibleCount === 0) { + resultCount.innerHTML = ` + + No FAQs found for "${escapeHtml(query)}". Try different keywords. + `; + resultCount.className = 'tw-text-orange-600 dark:tw-text-orange-400'; + } else if (visibleCount === totalFaqs) { + resultCount.innerHTML = ` + + Showing all ${totalFaqs} FAQs + `; + resultCount.className = 'tw-text-green-600 dark:tw-text-green-400'; + } else { + resultCount.innerHTML = ` + + Found ${visibleCount} of ${totalFaqs} FAQs matching "${escapeHtml(query)}" + `; + resultCount.className = 'tw-text-purple-600 dark:tw-text-purple-400'; + } + } + + /** + * Clear search input and reset filters + */ + function clearSearch() { + searchInput.value = ''; + searchInput.focus(); + filterFAQs(); + } + + /** + * Escape HTML to prevent XSS + */ + function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + + // Event listeners + searchInput.addEventListener('input', filterFAQs); + searchInput.addEventListener('keyup', function(e) { + if (e.key === 'Escape') { + clearSearch(); + } + }); + + clearButton.addEventListener('click', clearSearch); + + // Add subtle animation to highlighted FAQs + const style = document.createElement('style'); + style.textContent = ` + .faq-highlight { + animation: highlightFade 0.3s ease-in-out; + } + + @keyframes highlightFade { + 0% { + transform: translateX(-5px); + opacity: 0.7; + } + 100% { + transform: translateX(0); + opacity: 1; + } + } + `; + document.head.appendChild(style); +}); + + //Scroll Button Functionality // Get reference to the button const scrollBtn = document.getElementById('scrollTopBtn');