dynamic listing of top 6 or less upto 2 articles

This commit is contained in:
2025-11-12 05:06:29 +05:30
parent fc39d832c1
commit b09900f8ec
2 changed files with 125 additions and 74 deletions

View File

@@ -1,20 +1,23 @@
import * as React from 'react'; import React from 'react';
import Box from '@mui/material/Box'; import { Grid, Box } from '@mui/material';
import Grid from '@mui/material/Grid'; import ArticleCardSize6 from './ArticleCardSize6';
import ArticleCardSize4 from './ArticleCardSize4';
import ArticleCardSize2 from './ArticleCardSize2';
import { ArticleModel } from "../../types/models"; import { ArticleModel } from "../../types/models";
import ArticleCardSize6 from "../ArticleCards/ArticleCardSize6"; import { ArticleGridProps } from "../../types/props";
import ArticleCardSize4 from "../ArticleCards/ArticleCardSize4";
import ArticleCardSize2 from "../ArticleCards/ArticleCardSize2";
export default function ArticleCardsGrid({ export default function ArticleCardsGrid({
articles, articles,
onSelectArticle, onSelectArticle,
}: { xs = 12,
articles: any[]; md6 = 6,
onSelectArticle: (index: number) => void; md4 = 4,
}) { nested = 2,
}: ArticleGridProps ) {
const visibleArticles = articles.slice(0, 6)
const count = visibleArticles.length;
const [focusedCardIndex, setFocusedCardIndex] = React.useState<number | null>( const [focusedCardIndex, setFocusedCardIndex] = React.useState<number | null>(
null, null,
); );
@@ -27,70 +30,109 @@ export default function ArticleCardsGrid({
setFocusedCardIndex(null); setFocusedCardIndex(null);
}; };
const renderCard = (article: ArticleModel, index: number, type: '6' | '4' | '2' = '6') => {
const CardComponent =
type === '6' ? ArticleCardSize6 :
type === '4' ? ArticleCardSize4 :
ArticleCardSize2;
return (
<CardComponent
key={index}
article={article}
index={index}
focusedCardIndex={focusedCardIndex}
onSelectArticle={onSelectArticle}
onFocus={handleFocus}
onBlur={handleBlur}
/>
);
};
return ( return (
<Grid container spacing={2} columns={12}> <Grid container spacing={2} columns={12}>
<Grid size={{ xs: 12, md: 6 }}> {/* ---- 2 articles: 6 | 6 ---- */}
<ArticleCardSize6 {count === 2 && (
article={articles[0]} <>
index={0} {visibleArticles.map((a, i) => (
focusedCardIndex={focusedCardIndex} <Grid key={i} size={{ xs, md: md6 }}>
onSelectArticle={onSelectArticle} {renderCard(a, i, '6')}
onFocus={handleFocus}
onBlur={handleBlur}
/>
</Grid> </Grid>
<Grid size={{ xs: 12, md: 6 }}> ))}
<ArticleCardSize6 </>
article={articles[1]} )}
index={1}
focusedCardIndex={focusedCardIndex} {/* ---- 3 articles: 4 | 4 | 4 ---- */}
onSelectArticle={onSelectArticle} {count === 3 && (
onFocus={handleFocus} <>
onBlur={handleBlur} {visibleArticles.map((a, i) => (
/> <Grid key={i} size={{ xs, md: md4 }}>
{renderCard(a, i, '4')}
</Grid> </Grid>
<Grid size={{ xs: 12, md: 4 }}> ))}
<ArticleCardSize4 </>
article={articles[2]} )}
index={2}
focusedCardIndex={focusedCardIndex} {/* ---- 4 articles: (6|6) + (6|6) ---- */}
onSelectArticle={onSelectArticle} {count === 4 && (
onFocus={handleFocus} <>
onBlur={handleBlur} {visibleArticles.map((a, i) => (
/> <Grid key={i} size={{ xs, md: md6 }}>
{renderCard(a, i, '6')}
</Grid> </Grid>
<Grid size={{ xs: 12, md: 4 }}> ))}
</>
)}
{/* ---- 5 articles: (6|6) + (4|4|4) ---- */}
{count === 5 && (
<>
{/* Row 1: 2 x size6 */}
{visibleArticles.slice(0, 2).map((a, i) => (
<Grid key={i} size={{ xs, md: md6 }}>
{renderCard(a, i, '6')}
</Grid>
))}
{/* Row 2: 3 x size4 */}
{visibleArticles.slice(2).map((a, i) => (
<Grid key={i + 2} size={{ xs, md: md4 }}>
{renderCard(a, i + 2, '4')}
</Grid>
))}
</>
)}
{/* ---- 6 articles: (6|6) + (4|2x2|4) ---- */}
{count === 6 && (
<>
{/* Top row: 2 x size6 */}
{visibleArticles.slice(0, 2).map((a, i) => (
<Grid key={i} size={{ xs, md: md6 }}>
{renderCard(a, i, '6')}
</Grid>
))}
{/* Bottom row: 4 + 2x2 + 4 */}
<Grid size={{ xs, md: md4 }}>
{renderCard(visibleArticles[2], 2, '4')}
</Grid>
<Grid size={{ xs, md: md4 }}>
<Box <Box
sx={{ display: 'flex', flexDirection: 'column', gap: 2, height: '100%' }} sx={{ display: 'flex', flexDirection: 'column', gap: 2, height: '100%' }}
> >
<ArticleCardSize2 {visibleArticles.slice(3, 3 + nested).map((a, i) =>
article={articles[3]} renderCard(a, i + 3, '2')
index={3} )}
focusedCardIndex={focusedCardIndex}
onSelectArticle={onSelectArticle}
onFocus={handleFocus}
onBlur={handleBlur}
/>
<ArticleCardSize2
article={articles[4]}
index={4}
focusedCardIndex={focusedCardIndex}
onSelectArticle={onSelectArticle}
onFocus={handleFocus}
onBlur={handleBlur}
/>
</Box> </Box>
</Grid> </Grid>
<Grid size={{ xs: 12, md: 4 }}>
<ArticleCardSize4 <Grid size={{ xs, md: md4 }}>
article={articles[5]} {renderCard(visibleArticles[5], 5, '4')}
index={5}
focusedCardIndex={focusedCardIndex}
onSelectArticle={onSelectArticle}
onFocus={handleFocus}
onBlur={handleBlur}
/>
</Grid> </Grid>
</>
)}
</Grid> </Grid>
); );
} }

View File

@@ -21,3 +21,12 @@ export interface ArticleCardProps {
onFocus: (index: number) => void; onFocus: (index: number) => void;
onBlur: () => void; onBlur: () => void;
} }
export interface ArticleGridProps {
articles: ArticleModel[];
onSelectArticle: (index: number) => void;
xs?: number; // default 12 for mobile full-width
md6?: number; // default 6 (half-width)
md4?: number; // default 4 (third-width)
nested?: 1 | 2; // number of stacked cards in a nested column
}