devscard/src/sections/favorites/favorites-section.astro
2023-01-16 21:46:10 +01:00

87 lines
2.4 KiB
Text

---
import type { ComponentInstance } from 'astro';
import SectionCard from '@/components/section-card.astro';
import Typography from '@/components/typography.astro';
import type { SectionKey } from '@/types/data';
import type { Book, FavoritesSection, Media, Person, Video } from '@/types/favorites-section';
import BookTile from './book-tile.astro';
import MediaTile from './media-tile.astro';
import PersonTile from './person-tile.astro';
import VideoTile from './video-tile.astro';
export interface Props extends FavoritesSection {}
const {
config: { title },
books,
medias,
people,
videos,
} = Astro.props;
type Subsection = 'books' | 'medias' | 'people' | 'videos';
type SubsectionData = Book | Media | Person | Video;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- required to avoid type casting
type SubsectionComponent = (_props: { value: any }) => ComponentInstance;
interface FavoritesSubsection<T extends SubsectionData> {
name: Subsection;
data: T[];
title: string;
columnsLayout: string;
Component: SubsectionComponent;
}
const booksSubsection: FavoritesSubsection<Book> = {
name: 'books',
columnsLayout: 'grid-cols-fluid200',
Component: BookTile,
...books,
};
const mediasSubsection: FavoritesSubsection<Media> = {
name: 'medias',
columnsLayout: 'grid-cols-fluid120',
Component: MediaTile,
...medias,
};
const peopleSubsection: FavoritesSubsection<Person> = {
name: 'people',
columnsLayout: 'grid-cols-fluid120',
Component: PersonTile,
...people,
};
const videosSubsection: FavoritesSubsection<Video> = {
name: 'videos',
columnsLayout: 'grid-cols-fluid240',
Component: VideoTile,
...videos,
};
const subsections = [booksSubsection, peopleSubsection, videosSubsection, mediasSubsection];
const section: SectionKey = 'favorites';
---
<SectionCard section={section} title={title}>
<div class="flex flex-col gap-16">
{
subsections.map(({ Component, data, name, columnsLayout, title: subsectionTitle }) => (
<div class="flex flex-col gap-6">
<Typography variant="section-subtitle" id={`${section}-${name}-heading`}>
{subsectionTitle}
</Typography>
<div class:list={['grid gap-8', columnsLayout]}>
{data.map((value) => (
<Component value={value} />
))}
</div>
</div>
))
}
</div>
</SectionCard>