48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
import type { Novel } from '../__generated__/graphql'
|
|
import { Card, CardContent, CardHeader, CardTitle } from './ui/card'
|
|
|
|
type NovelCardProps = {
|
|
novel: Novel
|
|
}
|
|
|
|
function pickText(novelText?: Novel['name'] | Novel['description']) {
|
|
const texts = novelText?.texts ?? []
|
|
const english = texts.find((t) => t.language === 'EN')
|
|
return (english ?? texts[0])?.text ?? 'No description available.'
|
|
}
|
|
|
|
export function NovelCard({ novel }: NovelCardProps) {
|
|
const title = pickText(novel.name)
|
|
const description = pickText(novel.description)
|
|
const cover = novel.coverImage
|
|
|
|
const coverSrc = cover?.newPath ?? cover?.originalPath
|
|
|
|
return (
|
|
<Card className="overflow-hidden border shadow-sm hover:shadow-md transition-shadow">
|
|
{coverSrc ? (
|
|
<div className="aspect-[3/4] w-full overflow-hidden bg-muted/50">
|
|
<img
|
|
src={coverSrc}
|
|
alt={title}
|
|
className="h-full w-full object-cover"
|
|
loading="lazy"
|
|
/>
|
|
</div>
|
|
) : (
|
|
<div className="aspect-[3/4] w-full bg-muted/50" />
|
|
)}
|
|
<CardHeader className="space-y-2">
|
|
<CardTitle className="line-clamp-2 text-lg leading-tight">
|
|
{title}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="pt-0">
|
|
<p className="line-clamp-3 text-sm text-muted-foreground">
|
|
{description}
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|