Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Resources Library - CommunityConnect Hub</title> | |
| <link rel="icon" type="image/x-icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>๐</text></svg>"> | |
| <link rel="stylesheet" href="style.css"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: { | |
| 50: '#eff6ff', | |
| 100: '#dbeafe', | |
| 200: '#bfdbfe', | |
| 300: '#93c5fd', | |
| 400: '#60a5fa', | |
| 500: '#3b82f6', | |
| 600: '#2563eb', | |
| 700: '#1d4ed8', | |
| 800: '#1e40af', | |
| 900: '#1e3a8a', | |
| }, | |
| secondary: { | |
| 50: '#f0fdfa', | |
| 100: '#ccfbf1', | |
| 200: '#99f6e4', | |
| 300: '#5eead4', | |
| 400: '#2dd4bf', | |
| 500: '#14b8a6', | |
| 600: '#0d9488', | |
| 700: '#0f766e', | |
| 800: '#115e59', | |
| 900: '#134e4a', | |
| } | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| </head> | |
| <body class="bg-gray-50"> | |
| <!-- Navigation Component --> | |
| <custom-navbar></custom-navbar> | |
| <!-- Hero Section --> | |
| <section class="bg-gradient-to-r from-primary-600 to-secondary-600 text-white py-20"> | |
| <div class="container mx-auto px-6"> | |
| <h1 class="text-4xl lg:text-5xl font-bold mb-4">Resources Library</h1> | |
| <p class="text-xl text-primary-100">Access valuable resources, guides, and tools to support your journey.</p> | |
| </div> | |
| </section> | |
| <!-- Search Bar --> | |
| <section class="py-8 bg-white border-b"> | |
| <div class="container mx-auto px-6"> | |
| <div class="max-w-2xl mx-auto"> | |
| <div class="relative"> | |
| <input | |
| type="text" | |
| id="search-input" | |
| placeholder="Search resources..." | |
| class="w-full px-6 py-4 pr-12 border rounded-full focus:outline-none focus:ring-2 focus:ring-primary-500 text-lg" | |
| > | |
| <button class="absolute right-2 top-1/2 transform -translate-y-1/2 bg-primary-600 text-white p-3 rounded-full hover:bg-primary-700 transition-colors"> | |
| <i data-feather="search" class="w-5 h-5"></i> | |
| </button> | |
| </div> | |
| <div class="flex flex-wrap gap-2 mt-4 justify-center"> | |
| <span class="text-sm text-gray-600">Popular searches:</span> | |
| <button class="search-tag text-sm bg-gray-100 px-3 py-1 rounded-full hover:bg-gray-200 transition-colors">Job Training</button> | |
| <button class="search-tag text-sm bg-gray-100 px-3 py-1 rounded-full hover:bg-gray-200 transition-colors">Health Guide</button> | |
| <button class="search-tag text-sm bg-gray-100 px-3 py-1 rounded-full hover:bg-gray-200 transition-colors">Education</button> | |
| <button class="search-tag text-sm bg-gray-100 px-3 py-1 rounded-full hover:bg-gray-200 transition-colors">Legal Help</button> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Categories --> | |
| <section class="py-8"> | |
| <div class="container mx-auto px-6"> | |
| <div class="flex flex-wrap justify-center gap-4"> | |
| <button class="category-btn px-6 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors" data-category="all"> | |
| All Resources | |
| </button> | |
| <button class="category-btn px-6 py-2 bg-white border rounded-lg hover:bg-gray-50 transition-colors" data-category="guides"> | |
| Guides | |
| </button> | |
| <button class="category-btn px-6 py-2 bg-white border rounded-lg hover:bg-gray-50 transition-colors" data-category="templates"> | |
| Templates | |
| </button> | |
| <button class="category-btn px-6 py-2 bg-white border rounded-lg hover:bg-gray-50 transition-colors" data-category="videos"> | |
| Videos | |
| </button> | |
| <button class="category-btn px-6 py-2 bg-white border rounded-lg hover:bg-gray-50 transition-colors" data-category="documents"> | |
| Documents | |
| </button> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Featured Resources --> | |
| <section class="py-12 bg-white"> | |
| <div class="container mx-auto px-6"> | |
| <div class="text-center mb-8"> | |
| <h2 class="text-3xl font-bold text-gray-800 mb-4">Featured Resources</h2> | |
| <div class="w-24 h-1 bg-secondary-500 mx-auto"></div> | |
| </div> | |
| <div id="featured-container" class="grid md:grid-cols-2 lg:grid-cols-3 gap-6"> | |
| <!-- Featured resources will be loaded here --> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- All Resources --> | |
| <section class="py-12"> | |
| <div class="container mx-auto px-6"> | |
| <div class="flex justify-between items-center mb-8"> | |
| <h2 class="text-2xl font-bold text-gray-800">All Resources</h2> | |
| <select id="sort-select" class="px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"> | |
| <option value="recent">Most Recent</option> | |
| <option value="popular">Most Popular</option> | |
| <option value="name">Name (A-Z)</option> | |
| </select> | |
| </div> | |
| <div id="resources-container" class="grid md:grid-cols-2 lg:grid-cols-4 gap-6"> | |
| <!-- Resources will be loaded here --> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Newsletter Signup --> | |
| <section class="py-20 bg-primary-600 text-white"> | |
| <div class="container mx-auto px-6"> | |
| <div class="max-w-2xl mx-auto text-center"> | |
| <h2 class="text-3xl font-bold mb-4">Stay Updated</h2> | |
| <p class="text-xl mb-8 text-primary-100">Get the latest resources and community updates delivered to your inbox.</p> | |
| <form class="flex flex-col sm:flex-row gap-4 max-w-md mx-auto"> | |
| <input type="email" placeholder="Enter your email" class="flex-1 px-4 py-3 rounded-lg text-gray-800 focus:outline-none focus:ring-2 focus:ring-white"> | |
| <button type="submit" class="bg-white text-primary-600 px-6 py-3 rounded-lg font-semibold hover:bg-gray-100 transition-colors"> | |
| Subscribe | |
| </button> | |
| </form> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Footer Component --> | |
| <custom-footer></custom-footer> | |
| <!-- Scripts --> | |
| <script src="components/navbar.js"></script> | |
| <script src="components/footer.js"></script> | |
| <script src="script.js"></script> | |
| <script src="api.js"></script> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', async () => { | |
| feather.replace(); | |
| let allResources = []; | |
| let filteredResources = []; | |
| let currentCategory = 'all'; | |
| try { | |
| allResources = await api.getResources(); | |
| filteredResources = allResources; | |
| renderFeaturedResources(allResources.filter(r => r.featured)); | |
| renderResources(filteredResources); | |
| } catch (error) { | |
| document.getElementById('resources-container').innerHTML = '<div class="col-span-full text-center text-gray-500">Unable to load resources at this time.</div>'; | |
| } | |
| // Search functionality | |
| document.getElementById('search-input').addEventListener('input', (e) => { | |
| const searchTerm = e.target.value.toLowerCase(); | |
| filteredResources = allResources.filter(resource => { | |
| const matchesSearch = resource.title.toLowerCase().includes(searchTerm) || | |
| resource.description.toLowerCase().includes(searchTerm) || | |
| resource.tags.some(tag => tag.toLowerCase().includes(searchTerm)); | |
| const matchesCategory = currentCategory === 'all' || resource.type === currentCategory; | |
| return matchesSearch && matchesCategory; | |
| }); | |
| renderResources(filteredResources); | |
| }); | |
| // Category filter | |
| document.querySelectorAll('.category-btn').forEach(btn => { | |
| btn.addEventListener('click', (e) => { | |
| // Update button styles | |
| document.querySelectorAll('.category-btn').forEach(b => { | |
| b.className = 'category-btn px-6 py-2 bg-white border rounded-lg hover:bg-gray-50 transition-colors'; | |
| }); | |
| e.target.className = 'category-btn px-6 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors'; | |
| currentCategory = e.target.dataset.category; | |
| filterResources(); | |
| }); | |
| }); | |
| // Sort functionality | |
| document.getElementById('sort-select').addEventListener('change', (e) => { | |
| const sortBy = e.target.value; | |
| let sorted = [...filteredResources]; | |
| switch(sortBy) { | |
| case 'recent': | |
| sorted.sort((a, b) => new Date(b.date) - new Date(a.date)); | |
| break; | |
| case 'popular': | |
| sorted.sort((a, b) => b.downloads - a.downloads); | |
| break; | |
| case 'name': | |
| sorted.sort((a, b) => a.title.localeCompare(b.title)); | |
| break; | |
| } | |
| renderResources(sorted); | |
| }); | |
| // Search tags | |
| document.querySelectorAll('.search-tag').forEach(tag => { | |
| tag.addEventListener('click', () => { | |
| document.getElementById('search-input').value = tag.textContent; | |
| document.getElementById('search-input').dispatchEvent(new Event('input')); | |
| }); | |
| }); | |
| function filterResources() { | |
| filteredResources = currentCategory === 'all' | |
| ? allResources | |
| : allResources.filter(r => r.type === currentCategory); | |
| renderResources(filteredResources); | |
| } | |
| function renderFeaturedResources(resources) { | |
| const container = document.getElementById('featured-container'); | |
| container.innerHTML = resources.map(resource => ` | |
| <div class="bg-gradient-to-br from-primary-50 to-secondary-50 rounded-xl p-6 hover:shadow-lg transition-shadow"> | |
| <div class="bg-white w-12 h-12 rounded-lg flex items-center justify-center mb-4"> | |
| <i data-feather="${getResourceIcon(resource.type)}" class="w-6 h-6 text-primary-600"></i> | |
| </div> | |
| <h3 class="text-lg font-semibold mb-2">${resource.title}</h3> | |
| <p class="text-gray-600 mb-4">${resource.description}</p> | |
| <button class="bg-primary-600 text-white px-4 py-2 rounded-lg hover:bg-primary-700 transition-colors"> | |
| Download | |
| </button> | |
| </div> | |
| `).join(''); | |
| feather.replace(); | |
| } | |
| function renderResources(resources) { | |
| const container = document.getElementById('resources-container'); | |
| if (resources.length === 0) { | |
| container.innerHTML = '<div class="col-span-full text-center text-gray-500">No resources found.</div>'; | |
| return; | |
| } | |
| container.innerHTML = resources.map(resource => ` | |
| <div class="bg-white rounded-xl p-6 shadow hover:shadow-lg transition-shadow"> | |
| <div class="flex items-start justify-between mb-4"> | |
| <div class="bg-${getTypeColor(resource.type)}-100 p-2 rounded-lg"> | |
| <i data-feather="${getResourceIcon(resource.type)}" class="w-6 h-6 text-${getTypeColor(resource.type)}-600"></i> | |
| </div> | |
| <span class="text-xs text-gray-500">${resource.downloads || 0} downloads</span> | |
| </div> | |
| <h3 class="font-semibold mb-2 line-clamp-2">${resource.title}</h3> | |
| <p class="text-sm text-gray-600 mb-4 line-clamp-3">${resource.description}</p> | |
| <div class="flex flex-wrap gap-1 mb-4"> | |
| ${resource.tags.slice(0, 3).map(tag => ` | |
| <span class="text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded">${tag}</span> | |
| `).join('')} | |
| </div> | |
| <button onclick="downloadResource('${resource.id}')" class="w-full bg-${getTypeColor(resource.type)}-600 text-white py-2 rounded-lg hover:bg-${getTypeColor(resource.type)}-700 transition-colors text-sm"> | |
| Download | |
| </button> | |
| </div> | |
| `).join(''); | |
| feather.replace(); | |
| } | |
| function getResourceIcon(type) { | |
| const icons = { | |
| guides: 'book-open', | |
| templates: 'file-text', | |
| videos: 'play-circle', | |
| documents: 'folder' | |
| }; | |
| return icons[type] || 'file'; | |
| } | |
| function getTypeColor(type) { | |
| const colors = { | |
| guides: 'primary', | |
| templates: 'secondary', | |
| videos: 'purple', | |
| documents: 'green' | |
| }; | |
| return colors[type] || 'gray'; | |
| } | |
| window.downloadResource = async (resourceId) => { | |
| try { | |
| // Simulate download | |
| const resource = allResources.find(r => r.id === resourceId); | |
| if (resource) { | |
| // Increment download count | |
| resource.downloads = (resource.downloads || 0) + 1; | |
| renderResources(filteredResources); | |
| // In a real app, this would trigger a file download | |
| alert(`Downloading: ${resource.title}`); | |
| } | |
| } catch (error) { | |
| alert('Error downloading resource'); | |
| } | |
| }; | |
| }); | |
| </script> | |
| </body> | |
| </html> |