dynamic listing of top 6 or less upto 2 articles
This commit is contained in:
@@ -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}
|
</Grid>
|
||||||
onBlur={handleBlur}
|
))}
|
||||||
/>
|
</>
|
||||||
</Grid>
|
)}
|
||||||
<Grid size={{ xs: 12, md: 6 }}>
|
|
||||||
<ArticleCardSize6
|
{/* ---- 3 articles: 4 | 4 | 4 ---- */}
|
||||||
article={articles[1]}
|
{count === 3 && (
|
||||||
index={1}
|
<>
|
||||||
focusedCardIndex={focusedCardIndex}
|
{visibleArticles.map((a, i) => (
|
||||||
onSelectArticle={onSelectArticle}
|
<Grid key={i} size={{ xs, md: md4 }}>
|
||||||
onFocus={handleFocus}
|
{renderCard(a, i, '4')}
|
||||||
onBlur={handleBlur}
|
</Grid>
|
||||||
/>
|
))}
|
||||||
</Grid>
|
</>
|
||||||
<Grid size={{ xs: 12, md: 4 }}>
|
)}
|
||||||
<ArticleCardSize4
|
|
||||||
article={articles[2]}
|
{/* ---- 4 articles: (6|6) + (6|6) ---- */}
|
||||||
index={2}
|
{count === 4 && (
|
||||||
focusedCardIndex={focusedCardIndex}
|
<>
|
||||||
onSelectArticle={onSelectArticle}
|
{visibleArticles.map((a, i) => (
|
||||||
onFocus={handleFocus}
|
<Grid key={i} size={{ xs, md: md6 }}>
|
||||||
onBlur={handleBlur}
|
{renderCard(a, i, '6')}
|
||||||
/>
|
</Grid>
|
||||||
</Grid>
|
))}
|
||||||
<Grid size={{ xs: 12, md: 4 }}>
|
</>
|
||||||
<Box
|
)}
|
||||||
sx={{ display: 'flex', flexDirection: 'column', gap: 2, height: '100%' }}
|
|
||||||
>
|
{/* ---- 5 articles: (6|6) + (4|4|4) ---- */}
|
||||||
<ArticleCardSize2
|
{count === 5 && (
|
||||||
article={articles[3]}
|
<>
|
||||||
index={3}
|
{/* Row 1: 2 x size6 */}
|
||||||
focusedCardIndex={focusedCardIndex}
|
{visibleArticles.slice(0, 2).map((a, i) => (
|
||||||
onSelectArticle={onSelectArticle}
|
<Grid key={i} size={{ xs, md: md6 }}>
|
||||||
onFocus={handleFocus}
|
{renderCard(a, i, '6')}
|
||||||
onBlur={handleBlur}
|
</Grid>
|
||||||
/>
|
))}
|
||||||
<ArticleCardSize2
|
|
||||||
article={articles[4]}
|
{/* Row 2: 3 x size4 */}
|
||||||
index={4}
|
{visibleArticles.slice(2).map((a, i) => (
|
||||||
focusedCardIndex={focusedCardIndex}
|
<Grid key={i + 2} size={{ xs, md: md4 }}>
|
||||||
onSelectArticle={onSelectArticle}
|
{renderCard(a, i + 2, '4')}
|
||||||
onFocus={handleFocus}
|
</Grid>
|
||||||
onBlur={handleBlur}
|
))}
|
||||||
/>
|
</>
|
||||||
</Box>
|
)}
|
||||||
</Grid>
|
|
||||||
<Grid size={{ xs: 12, md: 4 }}>
|
{/* ---- 6 articles: (6|6) + (4|2x2|4) ---- */}
|
||||||
<ArticleCardSize4
|
{count === 6 && (
|
||||||
article={articles[5]}
|
<>
|
||||||
index={5}
|
{/* Top row: 2 x size6 */}
|
||||||
focusedCardIndex={focusedCardIndex}
|
{visibleArticles.slice(0, 2).map((a, i) => (
|
||||||
onSelectArticle={onSelectArticle}
|
<Grid key={i} size={{ xs, md: md6 }}>
|
||||||
onFocus={handleFocus}
|
{renderCard(a, i, '6')}
|
||||||
onBlur={handleBlur}
|
</Grid>
|
||||||
/>
|
))}
|
||||||
</Grid>
|
|
||||||
|
{/* Bottom row: 4 + 2x2 + 4 */}
|
||||||
|
<Grid size={{ xs, md: md4 }}>
|
||||||
|
{renderCard(visibleArticles[2], 2, '4')}
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs, md: md4 }}>
|
||||||
|
<Box
|
||||||
|
sx={{ display: 'flex', flexDirection: 'column', gap: 2, height: '100%' }}
|
||||||
|
>
|
||||||
|
{visibleArticles.slice(3, 3 + nested).map((a, i) =>
|
||||||
|
renderCard(a, i + 3, '2')
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs, md: md4 }}>
|
||||||
|
{renderCard(visibleArticles[5], 5, '4')}
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user