Files
edr-platform/apps/edr-passenger-web/backoffice/src/components/ui/ActionButton.tsx
2026-05-31 13:15:44 +03:00

85 lines
2.2 KiB
TypeScript

'use client';
import { ReactNode, useState } from 'react';
import { LucideIcon, Loader2 } from 'lucide-react';
import { cn } from '@/lib/utils';
interface ActionButtonProps {
children: ReactNode;
onClick?: () => void | Promise<void>;
variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'export';
size?: 'sm' | 'md' | 'lg';
icon?: LucideIcon;
disabled?: boolean;
loading?: boolean;
className?: string;
type?: 'button' | 'submit' | 'reset';
}
const variants = {
primary: 'bg-[rgb(20,113,76)] text-white hover:bg-[rgb(16,90,61)] shadow-sm',
secondary: 'bg-gray-200 text-gray-700 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600',
danger: 'bg-[rgb(20,113,76)] text-white hover:bg-[rgb(16,90,61)] shadow-sm',
success: 'bg-green-600 text-white hover:bg-green-700 shadow-sm',
export: 'bg-[rgb(20,113,76)] text-white hover:bg-[rgb(16,90,61)] shadow-sm',
};
const sizes = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-sm',
lg: 'px-6 py-3 text-base',
};
export default function ActionButton({
children,
onClick,
variant = 'primary',
size = 'md',
icon: Icon,
disabled = false,
loading = false,
className,
type = 'button',
}: ActionButtonProps) {
const [isLoading, setIsLoading] = useState(false);
const handleClick = async () => {
if (!onClick || disabled || loading || isLoading) return;
try {
setIsLoading(true);
await onClick();
} catch (error) {
console.error('Action failed:', error);
} finally {
setIsLoading(false);
}
};
const isDisabled = disabled || loading || isLoading;
const showLoading = loading || isLoading;
return (
<button
type={type}
onClick={handleClick}
disabled={isDisabled}
className={cn(
'inline-flex items-center justify-center gap-2 rounded-lg font-medium transition-all duration-200',
'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[rgb(20,113,76)]',
'disabled:opacity-50 disabled:cursor-not-allowed',
variants[variant],
sizes[size],
className
)}
>
{showLoading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
Icon && <Icon className="h-4 w-4" />
)}
{children}
</button>
);
}