import React from 'react';
/**
* Generic form field component that renders different input types based on props.
* It handles label, value, change handler, error display, required indicator,
* and basic styling.
*
* @param {object} props - Component props.
* @param {string} props.label - The label for the form field.
* @param {string} props.name - The name attribute for the input element.
* @param {string} [props.type='text'] - The type of input ('text', 'select', 'textarea', 'time', etc.).
* @param {string|number} props.value - The current value of the input.
* @param {function} props.onChange - The handler function for input changes.
* @param {string} [props.error] - An error message to display below the input.
* @param {boolean} [props.required=false] - Indicates if the field is required.
* @param {Array<{value: string|number, label: string}>} [props.options=[]] - Options for 'select' type inputs.
* @param {string} [props.placeholder=''] - The placeholder text for the input.
* @param {string} [props.className=''] - Additional CSS classes for the input element.
* @returns {React.Element} The rendered form field component.
*/
const FormField = ({
label,
name,
type = 'text',
value,
onChange,
error,
required = false,
options = [],
placeholder = '',
className = ''
}) => {
const baseInputClasses = `mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 ${
error ? 'border-red-500' : ''
} ${className}`;
const renderInput = () => {
switch (type) {
case 'select':
return (
<select
name={name}
value={value}
onChange={onChange}
className={baseInputClasses}
required={required}
>
<option value="">{placeholder || `Select ${label}...`}</option>
{options.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
);
case 'textarea':
return (
<textarea
name={name}
value={value}
onChange={onChange}
placeholder={placeholder}
className={baseInputClasses}
required={required}
rows={4}
/>
);
case 'time':
return (
<input
type="time"
name={name}
value={value}
onChange={onChange}
className={baseInputClasses}
required={required}
/>
);
default:
return (
<input
type={type}
name={name}
value={value}
onChange={onChange}
placeholder={placeholder}
className={baseInputClasses}
required={required}
/>
);
}
};
return (
<div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-1">
{label}
{required && <span className="text-red-500 ml-1">*</span>}
</label>
{renderInput()}
{error && (
<p className="mt-1 text-sm text-red-600">{error}</p>
)}
</div>
);
};
export default FormField;
Source