import React from "react"; import { cn } from "~/lib/utils"; import { Eye, EyeOff, AlertCircle, CheckCircle2 } from "lucide-react"; import { Input } from "./input"; import { Label } from "./label"; interface BaseFieldProps { label?: string; error?: string; helper?: string; required?: boolean; className?: string; containerClassName?: string; } interface TextFieldProps extends BaseFieldProps { id: string; type?: "text" | "email" | "tel" | "url"; value: string; onChange: (value: string) => void; placeholder?: string; disabled?: boolean; autoComplete?: string; leftIcon?: React.ReactNode; rightIcon?: React.ReactNode; maxLength?: number; minLength?: number; } export function TextField({ id, label, type = "text", value, onChange, placeholder, error, helper, required, disabled, autoComplete, leftIcon, rightIcon, maxLength, minLength, className, containerClassName, }: TextFieldProps) { const hasError = !!error; const hasSuccess = !hasError && value.length > 0; return (
{label && ( )}
{leftIcon && (
{leftIcon}
)} onChange(e.target.value)} placeholder={placeholder} disabled={disabled} autoComplete={autoComplete} maxLength={maxLength} minLength={minLength} className={cn( "w-full h-12 px-4 font-persian text-right transition-all duration-200", leftIcon && "pr-10", (rightIcon || hasError || hasSuccess) && "pl-10", hasError && "border-destructive focus:border-destructive focus:ring-destructive/20", hasSuccess && "border-green-500 focus:border-green-500 focus:ring-green-500/20", className, )} /> {(rightIcon || hasError || hasSuccess) && (
{hasError ? ( ) : hasSuccess ? ( ) : ( rightIcon && ( {rightIcon} ) )}
)}
{error && (

{error}

)} {helper && !error && (

{helper}

)} {maxLength && (
{value.length}/{maxLength}
)}
); } interface PasswordFieldProps extends BaseFieldProps { id: string; value: string; onChange: (value: string) => void; placeholder?: string; disabled?: boolean; autoComplete?: string; showStrength?: boolean; minLength?: number; } export function PasswordField({ id, label, value, onChange, placeholder, error, helper, required, disabled, autoComplete = "current-password", showStrength = false, minLength, className, containerClassName, }: PasswordFieldProps) { const [showPassword, setShowPassword] = React.useState(false); const hasError = !!error; const getPasswordStrength = ( password: string, ): { score: number; text: string; color: string; } => { if (!password) return { score: 0, text: "", color: "" }; let score = 0; if (password.length >= 8) score++; if (/[a-z]/.test(password)) score++; if (/[A-Z]/.test(password)) score++; if (/[0-9]/.test(password)) score++; if (/[^a-zA-Z0-9]/.test(password)) score++; const strength = [ { text: "بسیار ضعیف", color: "text-red-500" }, { text: "ضعیف", color: "text-orange-500" }, { text: "متوسط", color: "text-yellow-500" }, { text: "قوی", color: "text-blue-500" }, { text: "بسیار قوی", color: "text-green-500" }, ]; return { score, text: strength[Math.min(score, 4)].text, color: strength[Math.min(score, 4)].color, }; }; const strength = showStrength ? getPasswordStrength(value) : null; return (
{label && ( )}
onChange(e.target.value)} placeholder={placeholder} disabled={disabled} autoComplete={autoComplete} minLength={minLength} className={cn( "w-full h-12 px-4 pl-10 font-persian text-right transition-all duration-200", hasError && "border-destructive focus:border-destructive focus:ring-destructive/20", className, )} />
{showStrength && value && (
قدرت رمز عبور: {strength?.text}
{[1, 2, 3, 4, 5].map((step) => (
))}
)} {error && (

{error}

)} {helper && !error && (

{helper}

)}
); } interface CheckboxFieldProps extends BaseFieldProps { id: string; checked: boolean; onChange: (checked: boolean) => void; disabled?: boolean; size?: "sm" | "md" | "lg"; } export function CheckboxField({ id, label, checked, onChange, error, helper, required, disabled, size = "md", className, containerClassName, }: CheckboxFieldProps) { const sizes = { sm: "w-3 h-3", md: "w-4 h-4", lg: "w-5 h-5", }; return (
onChange(e.target.checked)} disabled={disabled} className={cn( sizes[size], "text-[var(--color-login-primary)] bg-background border-input rounded focus:ring-[var(--color-login-primary)] focus:ring-2 accent-[var(--color-login-primary)] transition-all duration-200", disabled && "opacity-50 cursor-not-allowed", error && "border-destructive focus:ring-destructive", className, )} /> {label && ( )}
{error && (

{error}

)} {helper && !error && (

{helper}

)}
); } interface FieldGroupProps { children: React.ReactNode; className?: string; } export function FieldGroup({ children, className }: FieldGroupProps) { return
{children}
; } interface FormActionsProps { children: React.ReactNode; className?: string; } export function FormActions({ children, className }: FormActionsProps) { return (
{children}
); }