./knowledge-base/frontend/src/components/SearchCards.tsx
import {
Box,
Card,
CardMedia,
CardContent,
CardActionArea,
Typography,
Chip,
} from "@mui/material";
import { MenuBook as MenuBookIcon } from "@mui/icons-material";
import type { SearchResultItem } from "../types";
export interface BookGroup {
document_id: string;
title: string;
thumbnailItem: SearchResultItem;
pages: SearchResultItem[];
}
export function SearchResultCard({
result,
onClick,
}: {
result: SearchResultItem;
onClick: () => void;
}) {
return (
<Card sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
<CardActionArea
onClick={onClick}
sx={{
flexGrow: 1,
display: "flex",
flexDirection: "column",
alignItems: "stretch",
}}
>
<CardMedia
component="img"
height="200"
image={result.thumbnail_url || result.image_url}
alt={result.title}
sx={{ objectFit: "cover" }}
/>
<CardContent sx={{ flexGrow: 1 }}>
<Typography variant="h6" gutterBottom noWrap>
{result.title}
</Typography>
<Typography variant="body2" color="text.secondary" gutterBottom>
{result.era}
</Typography>
<Box sx={{ mt: 0.5, mb: 1 }}>
{result.document_genre && (
<Chip
label={`資料: ${result.document_genre}`}
size="small"
color="secondary"
sx={{ mr: 0.5, mb: 0.5 }}
/>
)}
{result.summary_policy && (
<Chip
label={`方針: ${result.summary_policy}`}
size="small"
variant="outlined"
sx={{ mr: 0.5, mb: 0.5 }}
/>
)}
</Box>
{result.ocr_supplemental_info &&
result.ocr_supplemental_info.length > 0 && (
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
{result.ocr_supplemental_info[0].substring(0, 100)}...
</Typography>
)}
</CardContent>
</CardActionArea>
</Card>
);
}
export function BookGroupCard({
group,
onClick,
}: {
group: BookGroup;
onClick: () => void;
}) {
const { title, thumbnailItem, pages } = group;
return (
<Card sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
<CardActionArea
onClick={onClick}
sx={{
flexGrow: 1,
display: "flex",
flexDirection: "column",
alignItems: "stretch",
}}
>
{thumbnailItem.thumbnail_url || thumbnailItem.image_url ? (
<CardMedia
component="img"
height="200"
image={thumbnailItem.thumbnail_url || thumbnailItem.image_url}
alt={title}
sx={{ objectFit: "cover" }}
/>
) : (
<Box
sx={{
height: 200,
display: "flex",
alignItems: "center",
justifyContent: "center",
bgcolor: "grey.100",
}}
>
<MenuBookIcon sx={{ fontSize: 64, color: "grey.400" }} />
</Box>
)}
<CardContent sx={{ flexGrow: 1 }}>
<Box
sx={{ display: "flex", alignItems: "center", gap: 0.5, mb: 0.5 }}
>
<MenuBookIcon fontSize="small" color="primary" />
<Typography variant="h6" noWrap sx={{ flexGrow: 1 }}>
{title}
</Typography>
</Box>
<Typography variant="body2" color="text.secondary" gutterBottom>
{thumbnailItem.era}
</Typography>
<Chip
label={
thumbnailItem.pdf_total_pages
? `全${thumbnailItem.pdf_total_pages}ページ`
: `${pages.length}ページ該当`
}
size="small"
color="primary"
variant="outlined"
sx={{ mt: 0.5 }}
/>
</CardContent>
</CardActionArea>
</Card>
);
}