mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import React from 'react';
|
|
import { clsx } from 'clsx';
|
|
import { Download, RefreshCw } from 'lucide-react';
|
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/Card';
|
|
import { Button } from '@/components/ui';
|
|
|
|
export interface ChartCardProps {
|
|
title: string;
|
|
description?: string;
|
|
children: React.ReactNode;
|
|
onExport?: () => void;
|
|
onRefresh?: () => void;
|
|
isLoading?: boolean;
|
|
className?: string;
|
|
actions?: React.ReactNode;
|
|
}
|
|
|
|
/**
|
|
* Chart card wrapper component
|
|
*/
|
|
export const ChartCard = ({
|
|
title,
|
|
description,
|
|
children,
|
|
onExport,
|
|
onRefresh,
|
|
isLoading = false,
|
|
className,
|
|
actions,
|
|
}: ChartCardProps) => {
|
|
return (
|
|
<Card className={clsx('h-full', className)}>
|
|
<CardHeader>
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex-1">
|
|
<CardTitle>{title}</CardTitle>
|
|
{description && <CardDescription className="mt-1">{description}</CardDescription>}
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
{onRefresh && (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={onRefresh}
|
|
disabled={isLoading}
|
|
aria-label="Refresh chart"
|
|
>
|
|
<RefreshCw className={clsx('h-4 w-4', { 'animate-spin': isLoading })} />
|
|
</Button>
|
|
)}
|
|
{onExport && (
|
|
<Button variant="ghost" size="sm" onClick={onExport} aria-label="Export chart">
|
|
<Download className="h-4 w-4" />
|
|
</Button>
|
|
)}
|
|
{actions}
|
|
</div>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{isLoading ? (
|
|
<div className="flex items-center justify-center h-64">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
|
|
</div>
|
|
) : (
|
|
children
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
};
|
|
|