2026-01-06 14:17:55 +01:00

124 lines
2.8 KiB
TypeScript

interface ArticleFieldProps {
id: string
label: string
value: string | number
onChange: (value: string | number) => void
required?: boolean
type?: 'text' | 'textarea' | 'number'
rows?: number
placeholder?: string
helpText?: string
min?: number
}
function NumberOrTextInput({
id,
type,
value,
placeholder,
required,
min,
onChange,
className,
}: {
id: string
type: 'text' | 'number'
value: string | number
placeholder?: string
required: boolean
min?: number
className: string
onChange: (value: string | number) => void
}): React.ReactElement {
const inputProps = {
id,
type,
value,
className,
required,
...(placeholder ? { placeholder } : {}),
...(typeof min === 'number' ? { min } : {}),
}
return (
<input
{...inputProps}
onChange={(e) => onChange(type === 'number' ? Number(e.target.value) || 0 : e.target.value)}
/>
)
}
function TextAreaInput({
id,
value,
placeholder,
required,
rows,
className,
onChange,
}: {
id: string
value: string | number
placeholder?: string
required: boolean
rows?: number
className: string
onChange: (value: string | number) => void
}): React.ReactElement {
const areaProps = {
id,
value,
className,
required,
...(placeholder ? { placeholder } : {}),
...(rows ? { rows } : {}),
}
return (
<textarea
{...areaProps}
onChange={(e) => onChange(e.target.value)}
/>
)
}
export function ArticleField(props: ArticleFieldProps): React.ReactElement {
const { id, label, value, onChange, required = false, type = 'text', rows, placeholder, helpText, min } =
props
const inputClass =
'w-full px-3 py-2 bg-cyber-darker border border-neon-cyan/20 rounded-lg text-cyber-accent placeholder-cyber-accent/50 focus:ring-2 focus:ring-neon-cyan/50 focus:border-neon-cyan/50 focus:outline-none transition-colors'
const input =
type === 'textarea' ? (
<TextAreaInput
id={id}
value={value}
required={required}
className={inputClass}
onChange={onChange}
{...(placeholder ? { placeholder } : {})}
{...(rows ? { rows } : {})}
/>
) : (
<NumberOrTextInput
id={id}
type={type}
value={value}
required={required}
className={inputClass}
onChange={onChange}
{...(placeholder ? { placeholder } : {})}
{...(typeof min === 'number' ? { min } : {})}
/>
)
return (
<div>
<label htmlFor={id} className="block text-sm font-medium text-cyber-accent mb-1">
{label} {required && <span className="text-neon-cyan">*</span>}
</label>
{input}
{helpText && <p className="text-xs text-cyber-accent/70 mt-1">{helpText}</p>}
</div>
)
}