Enhance FormFieldWrapper Validation

Add real-time validation feedback to FormFieldWrapper:
- Manage validation state (idle/valid/invalid)
- Show green check icon when valid
- Show inline error icon when invalid
- Integrate with existing Input/Textarea components without altering core behavior
This commit is contained in:
gpt-engineer-app[bot]
2025-11-11 23:38:07 +00:00
parent 6fef107728
commit 7d085a0702

View File

@@ -5,6 +5,7 @@ import { Label } from "@/components/ui/label";
import { TermTooltip } from "@/components/ui/term-tooltip"; import { TermTooltip } from "@/components/ui/term-tooltip";
import { fieldHints } from "@/lib/enhancedValidation"; import { fieldHints } from "@/lib/enhancedValidation";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { CheckCircle2, AlertCircle } from "lucide-react";
/** /**
* Field types that automatically get hints and terminology support * Field types that automatically get hints and terminology support
@@ -201,6 +202,11 @@ export function FormFieldWrapper({
const showCharCount = isTextarea && maxLength && typeof value === 'string'; const showCharCount = isTextarea && maxLength && typeof value === 'string';
const charCount = typeof value === 'string' ? value.length : 0; const charCount = typeof value === 'string' ? value.length : 0;
// Determine validation state
const hasValue = value !== undefined && value !== null && value !== '';
const isValid = !error && hasValue;
const hasError = !!error;
return ( return (
<div className={cn("space-y-2", className)}> <div className={cn("space-y-2", className)}>
{/* Label with optional terminology tooltip */} {/* Label with optional terminology tooltip */}
@@ -220,11 +226,16 @@ export function FormFieldWrapper({
)} )}
</Label> </Label>
{/* Input or Textarea */} {/* Input or Textarea with validation icons */}
<div className="relative">
{isTextarea ? ( {isTextarea ? (
<Textarea <Textarea
id={id} id={id}
className={cn(error && "border-destructive")} className={cn(
"pr-10",
error && "border-destructive",
isValid && "border-green-500/50"
)}
maxLength={maxLength} maxLength={maxLength}
{...textareaProps} {...textareaProps}
/> />
@@ -232,12 +243,29 @@ export function FormFieldWrapper({
<Input <Input
id={id} id={id}
type={inputType} type={inputType}
className={cn(error && "border-destructive")} className={cn(
"pr-10",
error && "border-destructive",
isValid && "border-green-500/50"
)}
maxLength={maxLength} maxLength={maxLength}
{...inputProps} {...inputProps}
/> />
)} )}
{/* Validation icon */}
{(isValid || hasError) && (
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
{isValid && (
<CheckCircle2 className="h-4 w-4 text-green-500" />
)}
{hasError && (
<AlertCircle className="h-4 w-4 text-destructive" />
)}
</div>
)}
</div>
{/* Hint text (if not hidden and exists) */} {/* Hint text (if not hidden and exists) */}
{!hideHint && displayHint && !error && ( {!hideHint && displayHint && !error && (
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">