Alert

info
md
top-right
  {alertConfig.showAlert && ( 
      <Alert 
          variant={alertConfig.variant} 
          size={alertConfig.size} 
          position={alertConfig.position} 
          duration={alertConfig.duration} 
          onClose={() => setAlertConfig({ ...alertConfig, showAlert: false })}
      >
          {alertConfig.text} 
      </Alert>
  )}

  <Button onClick={() => setAlertConfig({ ...alertConfig, showAlert: true })}
      variant='outline'
  >
      Show Alert
  </Button>  

"use client";
import { useState, useEffect, useRef } from 'react';
import Button from './Button';

/**
 * @typedef {Object} AlertProps
 * @property {React.ReactNode} children - The content of the alert message.
 * @property {'success' | 'warning' | 'error' | 'info'} [variant='info'] - The variant of the alert, which determines its color.
 * @property {'xs' | 'sm' | 'md' | 'lg' | 'xl'} [size='md'] - The size of the alert, which determines its font size and padding.
 * @property {number} [duration=10000] - The duration in milliseconds to display the alert. Set to 0 to disable auto-close.
 * @property {() => void} [onClose] - Callback function triggered when the alert is closed.
 * @property {() => void} [onConfirm] - Callback function triggered when the confirm button is clicked.
 * @property {boolean} [showCloseButton=true] - Whether to show the close button.
 * @property {string} [confirmButtonLabel='Confirm'] - The label for the confirm button.
 * @property {string} [cancelButtonLabel='Cancel'] - The label for the cancel button.
 * @property {'top' | 'top-left' | 'top-right' | 'top-center' | 'bottom' | 'bottom-left' | 'bottom-right' | 'bottom-center' | 'center'} [position='top'] - The position of the alert on the screen.
 */

/**
 * A flexible and customizable alert component for displaying important messages to the user.
 *
 * @param {AlertProps} props - The props for the Alert component.
 * @returns {JSX.Element | null} The rendered Alert component or null if not open.
 */
const Alert = ({
	children,
	variant = 'info',
	size = 'md',
	duration = 10000,
	onClose,
	onConfirm,
	showCloseButton = true,
	confirmButtonLabel = 'Confirm',
	cancelButtonLabel = 'Cancel',
	position = 'top' // Default position
}) => {
	const [isOpen, setIsOpen] = useState(true);
	const timerRef = useRef(null);

	const variantClasses = {
		success: 'bg-green-100 text-green-800 text-black',
		warning: 'bg-yellow-100 text-yellow-800',
		error: 'bg-red-100 text-red-800',
		info: 'bg-blue-100 text-blue-800 ',
	};
	const ButtonVarients = {
		info: 'bg-gray-800 hover:bg-gray-700 text-gray-100 border border-gray-700 hover:border-transparent',
		error: 'bg-red-500 hover:bg-red-800 text-white',
		success: 'bg-green-500 hover:bg-green-700 text-black  ',
		warning: 'bg-yellow-400 hover:bg-yellow-500 text-white ',
	}

	const sizeClasses = {
		xs: 'text-xs px-2 py-1',
		sm: 'text-sm px-3 py-2',
		md: 'text-base px-4 py-3',
		lg: 'text-lg px-5 py-4',
		xl: 'text-xl px-6 py-5',
	};

	const Buttonsizes = {
		xs: "px-1 py-1 text-xs font-thin",
		sm: " px-2 py-1 text-sm font-light",
		md: " px-3 py-1.5 text-base font-medium",
		lg: " px-5 py-2 text-lg font-semibold",
		xl: " px-6  py-2.5 text-xl font-extrabold",
		icon: " py-2 px-2 text-base ",
	};

	const positionClasses = {
		top: 'top-4 left-1/2 transform -translate-x-1/2',
		'top-left': 'top-4 left-4',
		'top-right': 'top-4 right-4',
		'top-center': 'top-4 left-1/2 transform -translate-x-1/2',
		bottom: 'bottom-4 left-1/2 transform -translate-x-1/2',
		'bottom-left': 'bottom-4 left-4',
		'bottom-right': 'bottom-4 right-4',
		'bottom-center': 'bottom-4 left-1/2 transform -translate-x-1/2',
		center: 'top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2',

	};

	const svgfillcolor = {
		info: ' fill-gray-300',
		error: ' fill-black',
		success: ' fill-gray-900  ',
		warning: '  fill-black ',
	}



	useEffect(() => {
		if (duration > 0 && !onConfirm) {
			timerRef.current = setTimeout(() => {
				setIsOpen(false);
				onClose && onClose();
			}, duration);
		}

		return () => clearTimeout(timerRef.current);
	}, [duration, onClose, onConfirm]);

	if (!isOpen) return null;

	return (
		<div className={`fixed z-50 rounded-md shadow-lg ${variantClasses[variant]} ${sizeClasses[size]} flex flex-col  justify-between w-full max-w-sm transition-opacity duration-300 bg-gray-900 ${isOpen ? 'opacity-100' : 'opacity-0'} ${positionClasses[position]}`}>
			<div className={`p-4 text-left ${variantClasses[variant]}`}>{children}</div>
			<hr className='border-t border-gray-500 my-2 ' />

			<div className="items-center justify-end w-full space-x-2 grid grid-cols-2">
				{onConfirm && (
					<>
						<Button
							size={size}
							variant="secondary"
							onClick={() => {
								setIsOpen(false);
								onClose && onClose();
							}}
						>
							{cancelButtonLabel}
						</Button>
						<Button
							size={size}
							variant="primary"
							onClick={() => {
								setIsOpen(false);
								onConfirm();
							}}
						>
							{confirmButtonLabel}
						</Button>
					</>
				)}
				{showCloseButton && !onConfirm &&
					(
						<>
							<div>
							</div>
							<button className={`duration-100 flex items-center justify-center rounded-md disabled:opacity-50 disabled:cursor-not-allowed ${ButtonVarients[variant]} ${Buttonsizes[size] ? Buttonsizes[size] : " px-4 py-2 text-base "}  `}
								onClick={() => { setIsOpen(false); onClose && onClose(); }}>
								<svg className={`h-5 w-5  fill-gray-400 ${svgfillcolor[variant]}`} viewBox="0 0 20 20">
									<path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" />
								</svg>
							</button>
						</>
					)}
			</div>
		</div >
	)
}

export default Alert;