Synced files: - Quote wizard frontend (all components, hooks, types, config) - API updates (config, models, routers, schemas, services) - Client work (bg-builders, gurushow) - Scripts (BGB Lesley termination, CIPP, Datto, migration) - Temp files (Bardach contacts, VWP investigation, misc) - Credentials and session logs - Email service, PHP API, session logs Machine: ACG-M-L5090 Timestamp: 2026-03-10 19:11:00 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
57 lines
1.4 KiB
TypeScript
57 lines
1.4 KiB
TypeScript
import { motion } from 'framer-motion';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
export interface ProgressBarProps {
|
|
progress: number;
|
|
showLabel?: boolean;
|
|
size?: 'sm' | 'md' | 'lg';
|
|
variant?: 'default' | 'accent';
|
|
className?: string;
|
|
}
|
|
|
|
export function ProgressBar({
|
|
progress,
|
|
showLabel = false,
|
|
size = 'md',
|
|
variant = 'accent',
|
|
className,
|
|
}: ProgressBarProps) {
|
|
const clampedProgress = Math.min(100, Math.max(0, progress));
|
|
|
|
const sizes = {
|
|
sm: 'h-1',
|
|
md: 'h-1.5',
|
|
lg: 'h-2.5',
|
|
};
|
|
|
|
const variants = {
|
|
default: 'bg-[#333d49]',
|
|
accent: 'bg-gradient-accent',
|
|
};
|
|
|
|
return (
|
|
<div className={cn('w-full', className)}>
|
|
{showLabel && (
|
|
<div className="flex justify-between items-center mb-2">
|
|
<span className="text-sm font-medium text-[#333d49]">Progress</span>
|
|
<span className="text-sm font-semibold text-[#fe7400]">{clampedProgress}%</span>
|
|
</div>
|
|
)}
|
|
<div
|
|
className={cn('w-full bg-gray-100 rounded-full overflow-hidden', sizes[size])}
|
|
role="progressbar"
|
|
aria-valuenow={clampedProgress}
|
|
aria-valuemin={0}
|
|
aria-valuemax={100}
|
|
>
|
|
<motion.div
|
|
className={cn('h-full rounded-full', variants[variant])}
|
|
initial={{ width: 0 }}
|
|
animate={{ width: `${clampedProgress}%` }}
|
|
transition={{ duration: 0.6, ease: [0.25, 0.46, 0.45, 0.94] }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|