File size: 2,893 Bytes
5da4770 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
import React, { useState, useEffect } from 'react';
import { Loader2, LucideIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Progress } from '@/components/ui/progress';
interface LoadingStateProps {
icon?: LucideIcon;
iconColor?: string;
bgColor?: string;
title: string;
subtitle?: string;
filePath?: string | null;
showProgress?: boolean;
progressText?: string;
autoProgress?: boolean;
initialProgress?: number;
}
export function LoadingState({
icon: Icon = Loader2,
iconColor = 'text-purple-500 dark:text-purple-400',
bgColor = 'bg-gradient-to-b from-purple-100 to-purple-50 shadow-inner dark:from-purple-800/40 dark:to-purple-900/60 dark:shadow-purple-950/20',
title,
subtitle,
filePath,
showProgress = true,
progressText,
autoProgress = true,
initialProgress = 0,
}: LoadingStateProps): JSX.Element {
const [progress, setProgress] = useState(initialProgress);
useEffect(() => {
if (showProgress && autoProgress) {
setProgress(0);
const timer = setInterval(() => {
setProgress((prevProgress) => {
if (prevProgress >= 95) {
clearInterval(timer);
return prevProgress;
}
return prevProgress + Math.random() * 10 + 5;
});
}, 500);
return () => clearInterval(timer);
}
}, [showProgress, autoProgress]);
return (
<div className="flex flex-col items-center justify-center h-[calc(100vh-15rem)] overflow-hidden scrollbar-hide py-12 px-6">
<div className="text-center w-full max-w-sm">
<div className={cn("w-16 h-16 rounded-full mx-auto mb-6 flex items-center justify-center", bgColor)}>
<Icon className={cn("h-8 w-8", iconColor, Icon === Loader2 && "animate-spin")} />
</div>
<h3 className="text-xl font-semibold mb-4 text-zinc-900 dark:text-zinc-100">
{title}
</h3>
{filePath && (
<div className="bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-lg p-4 w-full text-center mb-6 shadow-sm">
<code className="text-sm font-mono text-zinc-700 dark:text-zinc-300 break-all">
{filePath}
</code>
</div>
)}
{showProgress && (
<div className="space-y-3">
<Progress value={Math.min(progress, 100)} className="w-full h-1" />
<div className="flex justify-between items-center text-xs text-zinc-500 dark:text-zinc-400">
<span>{progressText || 'Processing...'}</span>
<span className="font-mono">{Math.round(Math.min(progress, 100))}%</span>
</div>
</div>
)}
{subtitle && (
<p className="text-sm text-zinc-500 dark:text-zinc-400 mt-4">
{subtitle}
</p>
)}
</div>
</div>
);
} |