Files
stash/stash-web/src/components/content/DetailView.tsx
T

89 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { categoryCount, type Category } from '../../data/types'
import { ArrowLeftIcon } from '../common/Icon'
import { AppGrid } from './AppGrid'
import { CesCardGrid } from './CesCardGrid'
import { GroupBlock } from './GroupBlock'
import { PosterGrid } from './PosterGrid'
/**
* 分类明细视图:返回条 + 面包屑 + hero(图标 / 标题 / 数量)+ 内容区。
*
* 内容区按分类类型切换:
* - apps:指定分组时只渲染该组,否则单组扁平渲染、多组带小标题分组渲染;
* - posters:6 列海报;
* - articles:上图下文白卡网格。
*/
type DetailViewProps = {
category: Category
/** 从侧栏子菜单进入时指定的分组 */
groupId?: string
onBack: () => void
/** 点击卡片 / 海报进入条目详情 */
onOpenItem: (itemId: string) => void
}
export function DetailView({ category, groupId, onBack, onOpenItem }: DetailViewProps) {
const groups = category.kind === 'apps' ? category.groups : []
const activeGroup =
groupId !== undefined ? groups.find((group) => group.id === groupId) : undefined
const title = activeGroup?.name ?? category.title
const count = activeGroup !== undefined ? activeGroup.items.length : categoryCount(category)
const breadcrumb =
activeGroup !== undefined
? `首页 / ${category.title} / ${activeGroup.name}`
: `首页 / ${category.title}`
function renderBody() {
if (category.kind === 'posters') {
return <PosterGrid items={category.items} variant="detail" onOpen={onOpenItem} />
}
if (category.kind === 'articles') {
return <CesCardGrid items={category.items} onOpen={onOpenItem} />
}
if (activeGroup !== undefined) {
return <AppGrid items={activeGroup.items} variant="detail" onOpen={onOpenItem} />
}
if (category.groups.length === 1) {
return <AppGrid items={category.groups[0].items} variant="detail" onOpen={onOpenItem} />
}
if (category.groups.length === 0) {
return <p className="section-empty">{category.emptyText ?? '暂无内容'}</p>
}
return (
<>
{category.groups.map((group) => (
<GroupBlock key={group.id} group={group} onOpen={onOpenItem} />
))}
</>
)
}
return (
<div className="detail-view">
<div className="detail-nav card-box">
<button type="button" className="detail-back" onClick={onBack}>
<ArrowLeftIcon />
返回首页
</button>
<span className="detail-breadcrumb">{breadcrumb}</span>
</div>
<div className="detail-hero">
<span className="detail-hero-icon" aria-hidden="true">
{category.icon}
</span>
<h2 className="detail-hero-title">{title}</h2>
<span className="detail-hero-count">[{count}]</span>
</div>
{renderBody()}
</div>
)
}