mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 17:51:12 -05:00
110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
import { memo } from 'react';
|
|
import { Loader2, Clock, Database, CheckCircle2, XCircle } from 'lucide-react';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
export type TransactionStatus =
|
|
| 'idle'
|
|
| 'processing'
|
|
| 'timeout'
|
|
| 'cached'
|
|
| 'completed'
|
|
| 'failed';
|
|
|
|
interface TransactionStatusIndicatorProps {
|
|
status: TransactionStatus;
|
|
message?: string;
|
|
className?: string;
|
|
showLabel?: boolean;
|
|
}
|
|
|
|
export const TransactionStatusIndicator = memo(({
|
|
status,
|
|
message,
|
|
className,
|
|
showLabel = true,
|
|
}: TransactionStatusIndicatorProps) => {
|
|
if (status === 'idle') return null;
|
|
|
|
const getStatusConfig = () => {
|
|
switch (status) {
|
|
case 'processing':
|
|
return {
|
|
icon: Loader2,
|
|
label: 'Processing',
|
|
description: 'Transaction in progress...',
|
|
variant: 'secondary' as const,
|
|
className: 'bg-blue-100 text-blue-800 border-blue-200 dark:bg-blue-950 dark:text-blue-200 dark:border-blue-800',
|
|
iconClassName: 'animate-spin',
|
|
};
|
|
case 'timeout':
|
|
return {
|
|
icon: Clock,
|
|
label: 'Timeout',
|
|
description: message || 'Transaction timed out. Lock may have been auto-released.',
|
|
variant: 'destructive' as const,
|
|
className: 'bg-orange-100 text-orange-800 border-orange-200 dark:bg-orange-950 dark:text-orange-200 dark:border-orange-800',
|
|
iconClassName: '',
|
|
};
|
|
case 'cached':
|
|
return {
|
|
icon: Database,
|
|
label: 'Cached',
|
|
description: message || 'Using cached result from duplicate request',
|
|
variant: 'outline' as const,
|
|
className: 'bg-purple-100 text-purple-800 border-purple-200 dark:bg-purple-950 dark:text-purple-200 dark:border-purple-800',
|
|
iconClassName: '',
|
|
};
|
|
case 'completed':
|
|
return {
|
|
icon: CheckCircle2,
|
|
label: 'Completed',
|
|
description: 'Transaction completed successfully',
|
|
variant: 'default' as const,
|
|
className: 'bg-green-100 text-green-800 border-green-200 dark:bg-green-950 dark:text-green-200 dark:border-green-800',
|
|
iconClassName: '',
|
|
};
|
|
case 'failed':
|
|
return {
|
|
icon: XCircle,
|
|
label: 'Failed',
|
|
description: message || 'Transaction failed',
|
|
variant: 'destructive' as const,
|
|
className: '',
|
|
iconClassName: '',
|
|
};
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const config = getStatusConfig();
|
|
if (!config) return null;
|
|
|
|
const Icon = config.icon;
|
|
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Badge
|
|
variant={config.variant}
|
|
className={cn(
|
|
'flex items-center gap-1.5 px-2 py-1',
|
|
config.className,
|
|
className
|
|
)}
|
|
>
|
|
<Icon className={cn('h-3.5 w-3.5', config.iconClassName)} />
|
|
{showLabel && <span className="text-xs font-medium">{config.label}</span>}
|
|
</Badge>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p className="text-sm">{config.description}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
});
|
|
|
|
TransactionStatusIndicator.displayName = 'TransactionStatusIndicator';
|