dress/resources/js/components/input-error.tsx

65 lines
2.1 KiB
TypeScript

import type { HTMLAttributes } from 'react';
import { cn } from '@/lib/utils';
import { useMemo } from 'react';
interface InputErrorProps extends HTMLAttributes<HTMLParagraphElement> {
message?: string;
label?: string;
}
export default function InputError({
message,
label,
className = '',
...props
}: InputErrorProps) {
const formattedError = useMemo(() => {
if (!message) return null;
if (!label) return message;
// Preserve all-caps labels (like NIK), otherwise capitalize first letter and lowercase the rest
const isAllOptionsCaps = label === label.toUpperCase() && label.length > 1;
const formattedLabel = isAllOptionsCaps
? label
: label.charAt(0).toUpperCase() + label.slice(1).toLowerCase();
const words = message.split(' ');
// List of common Indonesian and English validation verbs/connectors that follow the attribute
const verbs = [
'wajib', 'harus', 'berupa', 'adalah', 'minimal', 'maksimal', 'tidak', 'kurang', 'lebih', 'antara', 'sudah',
'is', 'must', 'field', 'has', 'was', 'should', 'cannot', 'required', 'invalid'
];
// Find the first occurrence of a verb
let verbIndex = -1;
for (let i = 0; i < words.length; i++) {
if (verbs.includes(words[i].toLowerCase())) {
verbIndex = i;
break;
}
}
if (verbIndex !== -1) {
// Replace everything before the verb with the label
return `${formattedLabel} ${words.slice(verbIndex).join(' ')}`;
}
// Fallback to replacing only the first word if no verb found
if (words.length > 0) {
return `${formattedLabel} ${words.slice(1).join(' ')}`;
}
return message;
}, [message, label]);
return formattedError ? (
<p
{...props}
className={cn('text-sm text-red-600 dark:text-red-400', className)}
>
{formattedError}
</p>
) : null;
}