This repository has no description
0

Configure Feed

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

add tags support and remove quality rating

+15 -72
+15 -72
src/components/Resources/Resources.js
··· 9 9 const [resources, setResources] = useState([]); 10 10 const [activeCategory, setActiveCategory] = useState('All'); 11 11 const [searchQuery, setSearchQuery] = useState(''); 12 - const [qualityFilter, setQualityFilter] = useState(0); // Changed to numeric value (0 = All) 13 12 const [showNewOnly, setShowNewOnly] = useState(false); 14 13 const [isLoading, setIsLoading] = useState(true); 15 14 ··· 36 35 try { 37 36 const preferences = JSON.parse(savedPreferences); 38 37 setActiveCategory(preferences.activeCategory || 'All'); 39 - setQualityFilter(preferences.qualityFilter || 0); 40 38 setShowNewOnly(preferences.showNewOnly || false); 41 39 } catch (error) { 42 40 console.error('Error loading preferences:', error); ··· 48 46 useEffect(() => { 49 47 const preferences = { 50 48 activeCategory, 51 - qualityFilter, 52 49 showNewOnly 53 50 }; 54 51 localStorage.setItem('resourcesPreferences', JSON.stringify(preferences)); 55 - }, [activeCategory, qualityFilter, showNewOnly]); 52 + }, [activeCategory, showNewOnly]); 56 53 57 54 // Fetch resources from Supabase 58 55 useEffect(() => { ··· 183 180 return resource.categories && resource.categories.some(cat => cat.name === categoryName); 184 181 }; 185 182 186 - // Filter resources based on active category, search query, quality filter, and new filter 183 + // Filter resources based on active category, search query, and new filter 187 184 const filteredResources = useMemo(() => { 188 185 return resources.filter(resource => { 189 186 // Filter by category ··· 195 192 resource.description.toLowerCase().includes(searchQuery.toLowerCase()) || 196 193 (resource.domain && resource.domain.toLowerCase().includes(searchQuery.toLowerCase())); 197 194 198 - // Filter by quality (changed to numeric) 199 - const qualityMatch = 200 - qualityFilter === 0 || 201 - resource.quality >= qualityFilter; 202 - 203 195 // Filter by "new" status if the toggle is active 204 196 const newMatch = !showNewOnly || isNewResource(resource.created_at); 205 197 206 - return categoryMatch && searchMatch && qualityMatch && newMatch; 198 + return categoryMatch && searchMatch && newMatch; 207 199 }); 208 - }, [resources, activeCategory, searchQuery, qualityFilter, showNewOnly]); 200 + }, [resources, activeCategory, searchQuery, showNewOnly]); 209 201 210 202 // Get featured resources 211 203 const featuredResources = useMemo(() => { ··· 257 249 return grouped; 258 250 }, [filteredResources, activeCategory, categories]); 259 251 260 - // Should show featured section only when All category is selected, no quality filter is active, and search query is empty 261 - const shouldShowFeatured = activeCategory === 'All' && qualityFilter === 0 && searchQuery.trim() === ''; 262 - 263 - // Handle star rating click for quality filter 264 - const handleStarClick = (rating) => { 265 - setQualityFilter(rating === qualityFilter ? 0 : rating); 266 - }; 252 + // Should show featured section only when All category is selected and search query is empty 253 + const shouldShowFeatured = activeCategory === 'All' && searchQuery.trim() === ''; 267 254 268 255 // Handle search input change 269 256 const handleSearchChange = (e) => { ··· 332 319 </select> 333 320 </div> 334 321 335 - {/* Quality Filter using Stars */} 336 - <div className="quality-filter"> 337 - <span className="filter-label">Quality:</span> 338 - <div className="star-filter-container"> 339 - {[1, 2, 3, 4, 5].map((rating) => ( 340 - <span 341 - key={rating} 342 - onClick={() => handleStarClick(rating)} 343 - className={`quality-star ${rating <= qualityFilter ? 'filled' : 'empty'}`} 344 - title={`${rating} stars or higher`} 345 - role="button" 346 - tabIndex="0" 347 - aria-label={`Filter by ${rating} stars or higher`} 348 - onKeyPress={(e) => e.key === 'Enter' && handleStarClick(rating)} 349 - > 350 - 351 - </span> 352 - ))} 353 - {qualityFilter > 0 && ( 354 - <span 355 - className="quality-filter-clear" 356 - onClick={() => setQualityFilter(0)} 357 - title="Clear filter" 358 - role="button" 359 - tabIndex="0" 360 - aria-label="Clear quality filter" 361 - onKeyPress={(e) => e.key === 'Enter' && setQualityFilter(0)} 362 - > 363 - 364 - </span> 365 - )} 366 - </div> 367 - </div> 368 - 369 322 {/* New resources toggle */} 370 323 <div className="new-filter"> 371 324 <label className="toggle-label" htmlFor="new-toggle"> ··· 464 417 465 418 // ResourceCard component for displaying individual resources 466 419 const ResourceCard = ({ resource, isNew }) => { 467 - // Function to render stars based on quality rating 468 - const renderQualityStars = (quality) => { 469 - const stars = []; 470 - for (let i = 1; i <= 5; i++) { 471 - stars.push( 472 - <span 473 - key={i} 474 - className={`quality-star ${i <= quality ? 'filled' : 'empty'}`} 475 - > 476 - 477 - </span> 478 - ); 479 - } 480 - return stars; 481 - }; 482 - 483 420 return ( 484 421 <a 485 422 href={resource.url} ··· 508 445 <span className="resource-category">Misc</span> 509 446 )} 510 447 </div> 511 - <div className="resource-quality"> 512 - {renderQualityStars(resource.quality)} 513 - </div> 514 448 </div> 449 + {resource.tags && resource.tags.length > 0 && ( 450 + <div className="resource-tags"> 451 + {resource.tags.map((tag, idx) => ( 452 + <span key={idx} className="resource-tag"> 453 + {tag.name} 454 + </span> 455 + ))} 456 + </div> 457 + )} 515 458 </div> 516 459 </a> 517 460 );