working mvp for tag selection. fails when not enough articles for a particular tag

This commit is contained in:
2025-11-12 04:19:41 +05:30
parent 6abdd443e0
commit 6d951b9ab5
2 changed files with 97 additions and 49 deletions

View File

@@ -16,6 +16,8 @@ import { styled } from '@mui/material/styles';
import SearchRoundedIcon from '@mui/icons-material/SearchRounded'; import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
import RssFeedRoundedIcon from '@mui/icons-material/RssFeedRounded'; import RssFeedRoundedIcon from '@mui/icons-material/RssFeedRounded';
import { ArticleModel } from "../types/models";
const StyledCard = styled(Card)(({ theme }) => ({ const StyledCard = styled(Card)(({ theme }) => ({
display: 'flex', display: 'flex',
@@ -119,6 +121,33 @@ export default function MainContent({
null, null,
); );
const [visibleArticles, setVisibleArticles] = React.useState<ArticleModel[]>(articles);
const [activeTag, setActiveTag] = React.useState<string | null>(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) => { const handleFocus = (index: number) => {
setFocusedCardIndex(index); setFocusedCardIndex(index);
}; };
@@ -127,8 +156,9 @@ export default function MainContent({
setFocusedCardIndex(null); setFocusedCardIndex(null);
}; };
const handleClick = () => { const handleTagClick = (tag: string) => {
console.info('You clicked the filter chip.'); setActiveTag((prev) => (prev === tag ? 'all' : tag));
filterArticlesByTag(tag)
}; };
return ( return (
@@ -171,41 +201,59 @@ export default function MainContent({
overflow: 'auto', overflow: 'auto',
}} }}
> >
<Chip onClick={handleClick} size="medium" label="All categories" />
<Chip <Chip
onClick={handleClick} onClick={() => handleTagClick('all')}
size="medium" size="medium"
label="Company" label="All categories"
color={activeTag === 'all' ? 'primary' : 'default'}
variant={activeTag === 'all' ? 'filled' : 'outlined'}
sx={{ sx={{
backgroundColor: 'transparent', borderRadius: '8px',
border: 'none', fontWeight: activeTag === 'all' ? 600 : 400,
}} }}
/> />
<Chip <Chip
onClick={handleClick} onClick={() => handleTagClick('infra')}
size="medium" size="medium"
label="Product" label="Infra"
color={activeTag === 'infra' ? 'primary' : 'default'}
variant={activeTag === 'infra' ? 'filled' : 'outlined'}
sx={{ sx={{
backgroundColor: 'transparent', borderRadius: '8px',
border: 'none', fontWeight: activeTag === 'infra' ? 600 : 400,
}} }}
/> />
<Chip <Chip
onClick={handleClick} onClick={() => handleTagClick('code')}
size="medium" size="medium"
label="Design" label="Code"
color={activeTag === 'code' ? 'primary' : 'default'}
variant={activeTag === 'code' ? 'filled' : 'outlined'}
sx={{ sx={{
backgroundColor: 'transparent', borderRadius: '8px',
border: 'none', fontWeight: activeTag === 'code' ? 600 : 400,
}} }}
/> />
<Chip <Chip
onClick={handleClick} onClick={() => handleTagClick('media')}
size="medium" size="medium"
label="Engineering" label="Media"
color={activeTag === 'media' ? 'primary' : 'default'}
variant={activeTag === 'media' ? 'filled' : 'outlined'}
sx={{ sx={{
backgroundColor: 'transparent', borderRadius: '8px',
border: 'none', fontWeight: activeTag === 'media' ? 600 : 400,
}}
/>
<Chip
onClick={() => handleTagClick('monitoring')}
size="medium"
label="Monitoring"
color={activeTag === 'monitoring' ? 'primary' : 'default'}
variant={activeTag === 'monitoring' ? 'filled' : 'outlined'}
sx={{
borderRadius: '8px',
fontWeight: activeTag === 'all' ? 600 : 400,
}} }}
/> />
</Box> </Box>
@@ -237,7 +285,7 @@ export default function MainContent({
<CardMedia <CardMedia
component="img" component="img"
alt="green iguana" alt="green iguana"
image={articles[0].img} image={visibleArticles[0].img}
sx={{ sx={{
aspectRatio: '16 / 9', aspectRatio: '16 / 9',
borderBottom: '1px solid', borderBottom: '1px solid',
@@ -246,16 +294,16 @@ export default function MainContent({
/> />
<StyledCardContent> <StyledCardContent>
<Typography gutterBottom variant="caption" component="div"> <Typography gutterBottom variant="caption" component="div">
{articles[0].tag} {visibleArticles[0].tag}
</Typography> </Typography>
<Typography gutterBottom variant="h6" component="div"> <Typography gutterBottom variant="h6" component="div">
{articles[0].title} {visibleArticles[0].title}
</Typography> </Typography>
<StyledTypography variant="body2" color="text.secondary" gutterBottom> <StyledTypography variant="body2" color="text.secondary" gutterBottom>
{articles[0].description} {visibleArticles[0].description}
</StyledTypography> </StyledTypography>
</StyledCardContent> </StyledCardContent>
<Author authors={articles[0].authors} /> <Author authors={visibleArticles[0].authors} />
</StyledCard> </StyledCard>
</Grid> </Grid>
<Grid size={{ xs: 12, md: 6 }}> <Grid size={{ xs: 12, md: 6 }}>
@@ -270,7 +318,7 @@ export default function MainContent({
<CardMedia <CardMedia
component="img" component="img"
alt="green iguana" alt="green iguana"
image={articles[1].img} image={visibleArticles[1].img}
aspect-ratio="16 / 9" aspect-ratio="16 / 9"
sx={{ sx={{
borderBottom: '1px solid', borderBottom: '1px solid',
@@ -279,16 +327,16 @@ export default function MainContent({
/> />
<StyledCardContent> <StyledCardContent>
<Typography gutterBottom variant="caption" component="div"> <Typography gutterBottom variant="caption" component="div">
{articles[1].tag} {visibleArticles[1].tag}
</Typography> </Typography>
<Typography gutterBottom variant="h6" component="div"> <Typography gutterBottom variant="h6" component="div">
{articles[1].title} {visibleArticles[1].title}
</Typography> </Typography>
<StyledTypography variant="body2" color="text.secondary" gutterBottom> <StyledTypography variant="body2" color="text.secondary" gutterBottom>
{articles[1].description} {visibleArticles[1].description}
</StyledTypography> </StyledTypography>
</StyledCardContent> </StyledCardContent>
<Author authors={articles[1].authors} /> <Author authors={visibleArticles[1].authors} />
</StyledCard> </StyledCard>
</Grid> </Grid>
<Grid size={{ xs: 12, md: 4 }}> <Grid size={{ xs: 12, md: 4 }}>
@@ -304,7 +352,7 @@ export default function MainContent({
<CardMedia <CardMedia
component="img" component="img"
alt="green iguana" alt="green iguana"
image={articles[2].img} image={visibleArticles[2].img}
sx={{ sx={{
height: { sm: 'auto', md: '50%' }, height: { sm: 'auto', md: '50%' },
aspectRatio: { sm: '16 / 9', md: '' }, aspectRatio: { sm: '16 / 9', md: '' },
@@ -312,16 +360,16 @@ export default function MainContent({
/> />
<StyledCardContent> <StyledCardContent>
<Typography gutterBottom variant="caption" component="div"> <Typography gutterBottom variant="caption" component="div">
{articles[2].tag} {visibleArticles[2].tag}
</Typography> </Typography>
<Typography gutterBottom variant="h6" component="div"> <Typography gutterBottom variant="h6" component="div">
{articles[2].title} {visibleArticles[2].title}
</Typography> </Typography>
<StyledTypography variant="body2" color="text.secondary" gutterBottom> <StyledTypography variant="body2" color="text.secondary" gutterBottom>
{articles[2].description} {visibleArticles[2].description}
</StyledTypography> </StyledTypography>
</StyledCardContent> </StyledCardContent>
<Author authors={articles[2].authors} /> <Author authors={visibleArticles[2].authors} />
</StyledCard> </StyledCard>
</Grid> </Grid>
<Grid size={{ xs: 12, md: 4 }}> <Grid size={{ xs: 12, md: 4 }}>
@@ -347,21 +395,21 @@ export default function MainContent({
> >
<div> <div>
<Typography gutterBottom variant="caption" component="div"> <Typography gutterBottom variant="caption" component="div">
{articles[3].tag} {visibleArticles[3].tag}
</Typography> </Typography>
<Typography gutterBottom variant="h6" component="div"> <Typography gutterBottom variant="h6" component="div">
{articles[3].title} {visibleArticles[3].title}
</Typography> </Typography>
<StyledTypography <StyledTypography
variant="body2" variant="body2"
color="text.secondary" color="text.secondary"
gutterBottom gutterBottom
> >
{articles[3].description} {visibleArticles[3].description}
</StyledTypography> </StyledTypography>
</div> </div>
</StyledCardContent> </StyledCardContent>
<Author authors={articles[3].authors} /> <Author authors={visibleArticles[3].authors} />
</StyledCard> </StyledCard>
<StyledCard <StyledCard
variant="outlined" variant="outlined"
@@ -382,21 +430,21 @@ export default function MainContent({
> >
<div> <div>
<Typography gutterBottom variant="caption" component="div"> <Typography gutterBottom variant="caption" component="div">
{articles[4].tag} {visibleArticles[4].tag}
</Typography> </Typography>
<Typography gutterBottom variant="h6" component="div"> <Typography gutterBottom variant="h6" component="div">
{articles[4].title} {visibleArticles[4].title}
</Typography> </Typography>
<StyledTypography <StyledTypography
variant="body2" variant="body2"
color="text.secondary" color="text.secondary"
gutterBottom gutterBottom
> >
{articles[4].description} {visibleArticles[4].description}
</StyledTypography> </StyledTypography>
</div> </div>
</StyledCardContent> </StyledCardContent>
<Author authors={articles[4].authors} /> <Author authors={visibleArticles[4].authors} />
</StyledCard> </StyledCard>
</Box> </Box>
</Grid> </Grid>
@@ -413,7 +461,7 @@ export default function MainContent({
<CardMedia <CardMedia
component="img" component="img"
alt="green iguana" alt="green iguana"
image={articles[5].img} image={visibleArticles[5].img}
sx={{ sx={{
height: { sm: 'auto', md: '50%' }, height: { sm: 'auto', md: '50%' },
aspectRatio: { sm: '16 / 9', md: '' }, aspectRatio: { sm: '16 / 9', md: '' },
@@ -421,16 +469,16 @@ export default function MainContent({
/> />
<StyledCardContent> <StyledCardContent>
<Typography gutterBottom variant="caption" component="div"> <Typography gutterBottom variant="caption" component="div">
{articles[5].tag} {visibleArticles[5].tag}
</Typography> </Typography>
<Typography gutterBottom variant="h6" component="div"> <Typography gutterBottom variant="h6" component="div">
{articles[5].title} {visibleArticles[5].title}
</Typography> </Typography>
<StyledTypography variant="body2" color="text.secondary" gutterBottom> <StyledTypography variant="body2" color="text.secondary" gutterBottom>
{articles[5].description} {visibleArticles[5].description}
</StyledTypography> </StyledTypography>
</StyledCardContent> </StyledCardContent>
<Author authors={articles[5].authors} /> <Author authors={visibleArticles[5].authors} />
</StyledCard> </StyledCard>
</Grid> </Grid>
</Grid> </Grid>

View File

@@ -10,7 +10,7 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child
const [articles, setArticles] = useState<ArticleModel[]>([]); const [articles, setArticles] = useState<ArticleModel[]>([]);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const { token } = useAuth(); // ✅ access token if needed const { token } = useAuth();
/** 🔹 Fetch articles (JWT automatically attached by api.ts interceptor) */ /** 🔹 Fetch articles (JWT automatically attached by api.ts interceptor) */
const fetchArticles = async () => { const fetchArticles = async () => {
@@ -18,7 +18,7 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child
setLoading(true); setLoading(true);
setError(null); setError(null);
const res = await api.get<ArticleModel[]>('/articles', { params: { skip: 0, limit: 10 } }); const res = await api.get<ArticleModel[]>('/articles', { params: { skip: 0, limit: 100 } });
const formatted = res.data.map((a) => ({ ...a, id: a._id || undefined })); const formatted = res.data.map((a) => ({ ...a, id: a._id || undefined }));
setArticles(formatted); setArticles(formatted);
} catch (err: any) { } catch (err: any) {