This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

add additi9onal filters to admin panel

+108 -8
+40
src/components/Admin/AdminPanel.css
··· 641 641 border-radius: 3px; 642 642 margin-left: 5px; 643 643 } 644 + 645 + .filter-group { 646 + margin-bottom: 10px; 647 + } 648 + 649 + .search-container { 650 + position: relative; 651 + display: flex; 652 + align-items: center; 653 + } 654 + 655 + .reset-filters-button { 656 + position: absolute; 657 + right: 10px; 658 + background: none; 659 + border: none; 660 + cursor: pointer; 661 + font-size: 16px; 662 + color: #666; 663 + } 664 + 665 + .reset-filters-button:hover { 666 + color: #ff3333; 667 + } 668 + 669 + .resources-summary { 670 + margin: 5px 0; 671 + font-size: 0.9rem; 672 + color: #666; 673 + padding: 0 10px; 674 + } 675 + 676 + .category-filter, 677 + .tag-filter { 678 + width: 100%; 679 + padding: 8px; 680 + border: 1px solid #ddd; 681 + border-radius: 4px; 682 + margin-bottom: 5px; 683 + } 644 684 645 685 /* Accessibility */ 646 686 .sr-only {
+68 -8
src/components/Admin/AdminPanel.js
··· 15 15 const [statusFilter, setStatusFilter] = useState('all'); 16 16 const [searchQuery, setSearchQuery] = useState(''); 17 17 const [completenessFilter, setCompletenessFilter] = useState('all'); 18 + const [categoryFilter, setCategoryFilter] = useState('all'); 19 + const [tagFilter, setTagFilter] = useState('all'); 18 20 19 21 // Login state 20 22 const [email, setEmail] = useState(''); ··· 176 178 document.removeEventListener('keydown', handleKeyNavigation); 177 179 }; 178 180 }, [handleKeyNavigation]); 181 + 182 + // Reset filters 183 + const resetFilters = () => { 184 + setStatusFilter('all'); 185 + setCompletenessFilter('all'); 186 + setCategoryFilter('all'); 187 + setTagFilter('all'); 188 + setSearchQuery(''); 189 + }; 179 190 180 191 // Calculate resource completeness percentage 181 192 const calculateCompleteness = (resource) => { ··· 243 254 }); 244 255 }; 245 256 246 - // Filter resources based on status, search query, and completeness 257 + // Filter resources based on status, search query, completeness, category, and tag 247 258 const filteredResources = resources.filter(resource => { 248 259 // Status filter 249 260 if (statusFilter !== 'all' && resource.status !== statusFilter) return false; ··· 256 267 if (completenessFilter === 'complete' && resource.completeness < 100) return false; 257 268 if (completenessFilter.startsWith('min-') && resource.completeness < parseInt(completenessFilter.substring(4))) return false; 258 269 if (completenessFilter.startsWith('max-') && resource.completeness > parseInt(completenessFilter.substring(4))) return false; 270 + 271 + // Category filter 272 + if (categoryFilter !== 'all' && (!resource.categoryIds || !resource.categoryIds.includes(parseInt(categoryFilter)))) return false; 273 + 274 + // Tag filter 275 + if (tagFilter !== 'all' && (!resource.tagIds || !resource.tagIds.includes(parseInt(tagFilter)))) return false; 259 276 260 277 return true; 261 278 }); ··· 596 613 </div> 597 614 <div className="sidebar-filters"> 598 615 <div className="filter-group"> 599 - <input 600 - type="text" 601 - placeholder="Search resources..." 602 - value={searchQuery} 603 - onChange={(e) => setSearchQuery(e.target.value)} 604 - className="search-input" 605 - /> 616 + <div className="search-container"> 617 + <input 618 + type="text" 619 + placeholder="Search resources..." 620 + value={searchQuery} 621 + onChange={(e) => setSearchQuery(e.target.value)} 622 + className="search-input" 623 + /> 624 + {(searchQuery || statusFilter !== 'all' || completenessFilter !== 'all' || 625 + categoryFilter !== 'all' || tagFilter !== 'all') && ( 626 + <button 627 + onClick={resetFilters} 628 + className="reset-filters-button" 629 + title="Reset all filters" 630 + > 631 + 632 + </button> 633 + )} 634 + </div> 606 635 </div> 607 636 <div className="filter-group"> 608 637 <select ··· 631 660 <option value="max-75">Less than 75%</option> 632 661 </select> 633 662 </div> 663 + <div className="filter-group"> 664 + <select 665 + value={categoryFilter} 666 + onChange={(e) => setCategoryFilter(e.target.value)} 667 + className="category-filter" 668 + > 669 + <option value="all">All Categories</option> 670 + {categories.map(category => ( 671 + <option key={category.id} value={category.id}> 672 + {category.emoji} {category.name} 673 + </option> 674 + ))} 675 + </select> 676 + <select 677 + value={tagFilter} 678 + onChange={(e) => setTagFilter(e.target.value)} 679 + className="tag-filter" 680 + > 681 + <option value="all">All Tags</option> 682 + {tags.map(tag => ( 683 + <option key={tag.id} value={tag.id}> 684 + #{tag.name} 685 + </option> 686 + ))} 687 + </select> 688 + </div> 689 + </div> 690 + <div className="resources-summary"> 691 + <span className="resources-count"> 692 + Showing {filteredResources.length} of {resources.length} resources 693 + </span> 634 694 </div> 635 695 <div className="resources-list"> 636 696 {filteredResources.length > 0 ? (