From 6d951b9ab5c96ee3a45e93cb2bd08be8427f6158 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Wed, 12 Nov 2025 04:19:41 +0530 Subject: [PATCH] working mvp for tag selection. fails when not enough articles for a particular tag --- src/blog/components/MainContent.tsx | 142 +++++++++++++++++++--------- src/blog/providers/Article.tsx | 4 +- 2 files changed, 97 insertions(+), 49 deletions(-) diff --git a/src/blog/components/MainContent.tsx b/src/blog/components/MainContent.tsx index 69a01d6..360497c 100644 --- a/src/blog/components/MainContent.tsx +++ b/src/blog/components/MainContent.tsx @@ -16,6 +16,8 @@ import { styled } from '@mui/material/styles'; import SearchRoundedIcon from '@mui/icons-material/SearchRounded'; import RssFeedRoundedIcon from '@mui/icons-material/RssFeedRounded'; +import { ArticleModel } from "../types/models"; + const StyledCard = styled(Card)(({ theme }) => ({ display: 'flex', @@ -119,6 +121,33 @@ export default function MainContent({ null, ); + const [visibleArticles, setVisibleArticles] = React.useState(articles); + const [activeTag, setActiveTag] = React.useState(null); + + const filterArticlesByTag = (tag: string) => { + if (tag === 'all') { + // 🟢 Show all articles + setVisibleArticles(articles); + setActiveTag('all'); + return; + } + + if (activeTag === tag) { + // 🟡 Toggle off current tag → reset to all + setVisibleArticles(articles); + setActiveTag('all'); + return; + } + + // 🔵 Filter by selected tag + const filtered = articles.filter((article) => article.tag === tag); + console.log('👀 All Articles:', articles); + console.log(`👀 Filtered (${tag}):`, filtered); + + setVisibleArticles(filtered); + setActiveTag(tag); + }; + const handleFocus = (index: number) => { setFocusedCardIndex(index); }; @@ -127,8 +156,9 @@ export default function MainContent({ setFocusedCardIndex(null); }; - const handleClick = () => { - console.info('You clicked the filter chip.'); + const handleTagClick = (tag: string) => { + setActiveTag((prev) => (prev === tag ? 'all' : tag)); + filterArticlesByTag(tag) }; return ( @@ -171,41 +201,59 @@ export default function MainContent({ overflow: 'auto', }} > - handleTagClick('all')} size="medium" - label="Company" + label="All categories" + color={activeTag === 'all' ? 'primary' : 'default'} + variant={activeTag === 'all' ? 'filled' : 'outlined'} sx={{ - backgroundColor: 'transparent', - border: 'none', + borderRadius: '8px', + fontWeight: activeTag === 'all' ? 600 : 400, }} /> handleTagClick('infra')} size="medium" - label="Product" + label="Infra" + color={activeTag === 'infra' ? 'primary' : 'default'} + variant={activeTag === 'infra' ? 'filled' : 'outlined'} sx={{ - backgroundColor: 'transparent', - border: 'none', + borderRadius: '8px', + fontWeight: activeTag === 'infra' ? 600 : 400, }} /> handleTagClick('code')} size="medium" - label="Design" + label="Code" + color={activeTag === 'code' ? 'primary' : 'default'} + variant={activeTag === 'code' ? 'filled' : 'outlined'} sx={{ - backgroundColor: 'transparent', - border: 'none', + borderRadius: '8px', + fontWeight: activeTag === 'code' ? 600 : 400, }} /> handleTagClick('media')} size="medium" - label="Engineering" + label="Media" + color={activeTag === 'media' ? 'primary' : 'default'} + variant={activeTag === 'media' ? 'filled' : 'outlined'} sx={{ - backgroundColor: 'transparent', - border: 'none', + borderRadius: '8px', + fontWeight: activeTag === 'media' ? 600 : 400, + }} + /> + handleTagClick('monitoring')} + size="medium" + label="Monitoring" + color={activeTag === 'monitoring' ? 'primary' : 'default'} + variant={activeTag === 'monitoring' ? 'filled' : 'outlined'} + sx={{ + borderRadius: '8px', + fontWeight: activeTag === 'all' ? 600 : 400, }} /> @@ -237,7 +285,7 @@ export default function MainContent({ - {articles[0].tag} + {visibleArticles[0].tag} - {articles[0].title} + {visibleArticles[0].title} - {articles[0].description} + {visibleArticles[0].description} - + @@ -270,7 +318,7 @@ export default function MainContent({ - {articles[1].tag} + {visibleArticles[1].tag} - {articles[1].title} + {visibleArticles[1].title} - {articles[1].description} + {visibleArticles[1].description} - + @@ -304,7 +352,7 @@ export default function MainContent({ - {articles[2].tag} + {visibleArticles[2].tag} - {articles[2].title} + {visibleArticles[2].title} - {articles[2].description} + {visibleArticles[2].description} - + @@ -347,21 +395,21 @@ export default function MainContent({ >
- {articles[3].tag} + {visibleArticles[3].tag} - {articles[3].title} + {visibleArticles[3].title} - {articles[3].description} + {visibleArticles[3].description}
- +
- {articles[4].tag} + {visibleArticles[4].tag} - {articles[4].title} + {visibleArticles[4].title} - {articles[4].description} + {visibleArticles[4].description}
- +
@@ -413,7 +461,7 @@ export default function MainContent({ - {articles[5].tag} + {visibleArticles[5].tag} - {articles[5].title} + {visibleArticles[5].title} - {articles[5].description} + {visibleArticles[5].description} - + diff --git a/src/blog/providers/Article.tsx b/src/blog/providers/Article.tsx index 9809215..381f82b 100644 --- a/src/blog/providers/Article.tsx +++ b/src/blog/providers/Article.tsx @@ -10,7 +10,7 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child const [articles, setArticles] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const { token } = useAuth(); // ✅ access token if needed + const { token } = useAuth(); /** 🔹 Fetch articles (JWT automatically attached by api.ts interceptor) */ const fetchArticles = async () => { @@ -18,7 +18,7 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child setLoading(true); setError(null); - const res = await api.get('/articles', { params: { skip: 0, limit: 10 } }); + const res = await api.get('/articles', { params: { skip: 0, limit: 100 } }); const formatted = res.data.map((a) => ({ ...a, id: a._id || undefined })); setArticles(formatted); } catch (err: any) {