frontend/src/components/atoms/Input.jsx

/**
 * @file Componente de input reutilizable.
 * @description Un componente de input versátil con etiqueta, icono, manejo de errores y visibilidad de contraseña.
 * @requires react
 * @requires prop-types
 * @requires ../../styles/atoms/Input.css
 */
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import '../../styles/atoms/Input.css';

/**
 * @function Input
 * @description Renderiza un campo de entrada con varias funcionalidades.
 * @param {object} props - Las propiedades del componente.
 * @param {string} [props.type='text'] - El tipo de input (e.g., 'text', 'password', 'email').
 * @param {string} props.value - El valor del input.
 * @param {function} props.onChange - Función que se ejecuta cuando cambia el valor del input.
 * @param {function} [props.onBlur] - Función que se ejecuta cuando el input pierde el foco.
 * @param {string} [props.placeholder] - El texto de marcador de posición del input.
 * @param {string} [props.name] - El nombre del input.
 * @param {boolean} [props.disabled=false] - Si es `true`, el input está deshabilitado.
 * @param {string} [props.className=''] - Clases CSS adicionales para el contenedor del input.
 * @param {string} [props.error] - Un mensaje de error para mostrar debajo del input.
 * @param {string} [props.label] - La etiqueta para mostrar encima del input.
 * @param {React.ReactNode} [props.icon] - Un icono para mostrar dentro del input.
 * @returns {JSX.Element} El componente de input.
 */
const Input = ({
    type = 'text',
    value,
    onChange,
    onBlur,
    placeholder,
    name,
    disabled = false,
    className = '',
    error,
    label,
    icon
}) => {
    const [showPassword, setShowPassword] = useState(false);
    const inputType = type === 'password' && showPassword ? 'text' : type;

    return (
        <div className={`input-wrapper ${className}`}>
            {label && (
                <label htmlFor={name} className="input__label">
                    {label}
                </label>
            )}
            <div className="input-container">
                {icon && <span className="input__icon">{icon}</span>}
                <input
                    id={name}
                    name={name}
                    type={inputType}
                    value={value}
                    onChange={onChange}
                    onBlur={onBlur}
                    placeholder={placeholder}
                    disabled={disabled}
                    className={`input ${error ? 'input--error' : ''} ${disabled ? 'input--disabled' : ''} ${icon ? 'input--with-icon' : ''}`}
                />
                {type === 'password' && (
                    <button
                        type="button"
                        className="input__toggle-password"
                        onClick={() => setShowPassword(!showPassword)}
                        tabIndex={-1}
                    >
                        {showPassword ? '👁️' : '👁️‍🗨️'}
                    </button>
                )}
            </div>
            {error && <span className="input__error">{error}</span>}
        </div>
    );
};

Input.propTypes = {
    /** El tipo de input. */
    type: PropTypes.string,
    /** El valor del input. */
    value: PropTypes.string,
    /** Función que se ejecuta cuando cambia el valor del input. */
    onChange: PropTypes.func.isRequired,
    /** Función que se ejecuta cuando el input pierde el foco. */
    onBlur: PropTypes.func,
    /** El texto de marcador de posición del input. */
    placeholder: PropTypes.string,
    /** El nombre del input. */
    name: PropTypes.string,
    /** Si es `true`, el input está deshabilitado. */
    disabled: PropTypes.bool,
    /** Clases CSS adicionales para el contenedor del input. */
    className: PropTypes.string,
    /** Un mensaje de error para mostrar debajo del input. */
    error: PropTypes.string,
    /** La etiqueta para mostrar encima del input. */
    label: PropTypes.string,
    /** Un icono para mostrar dentro del input. */
    icon: PropTypes.node
};

export default Input;