45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
import type { ReactNode } from "react";
|
||
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||
import { cn } from "@/lib/utils";
|
||
|
||
type AdminPageCardProps = {
|
||
title: string;
|
||
description?: string;
|
||
actions?: ReactNode;
|
||
children: ReactNode;
|
||
className?: string;
|
||
contentClassName?: string;
|
||
/** 页内锚点(如 #records) */
|
||
id?: string;
|
||
};
|
||
|
||
/** 与列表/运营台一致的 admin-list-card 外层,用于设置、奖池等多区块页。 */
|
||
export function AdminPageCard({
|
||
title,
|
||
description,
|
||
actions,
|
||
children,
|
||
className,
|
||
contentClassName,
|
||
id,
|
||
}: AdminPageCardProps) {
|
||
return (
|
||
<Card id={id} className={cn("admin-list-card scroll-mt-24", className)}>
|
||
<CardHeader
|
||
className={cn(
|
||
"admin-list-header",
|
||
actions != null && "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",
|
||
)}
|
||
>
|
||
<div className="min-w-0 space-y-1">
|
||
<CardTitle className="admin-list-title">{title}</CardTitle>
|
||
{description ? <CardDescription className="text-sm">{description}</CardDescription> : null}
|
||
</div>
|
||
{actions ? <div className="flex shrink-0 flex-wrap items-center gap-2">{actions}</div> : null}
|
||
</CardHeader>
|
||
<CardContent className={cn("admin-list-content", contentClassName)}>{children}</CardContent>
|
||
</Card>
|
||
);
|
||
}
|