ERP-node/frontend/components/auth/SignupForm.tsx

264 lines
9.0 KiB
TypeScript
Raw Normal View History

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Eye, EyeOff, Loader2, ArrowLeft } from "lucide-react";
import { SignupFormData } from "@/types/auth";
import { ErrorMessage } from "./ErrorMessage";
import { useRouter } from "next/navigation";
interface SignupFormProps {
formData: SignupFormData;
isLoading: boolean;
error: string;
showPassword: boolean;
validationErrors: Record<string, string>;
touchedFields: Record<string, boolean>;
isFormValid: boolean;
onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
onBlur: (e: React.FocusEvent<HTMLInputElement>) => void;
onSubmit: (e: React.FormEvent) => void;
onTogglePassword: () => void;
}
/**
*
*/
export function SignupForm({
formData,
isLoading,
error,
showPassword,
validationErrors,
touchedFields,
isFormValid,
onInputChange,
onBlur,
onSubmit,
onTogglePassword,
}: SignupFormProps) {
const router = useRouter();
return (
<Card className="border-0 shadow-xl">
<CardHeader className="space-y-1">
<CardTitle className="text-center text-2xl"></CardTitle>
<CardDescription className="text-center"> </CardDescription>
</CardHeader>
<CardContent>
<ErrorMessage message={error} />
<form onSubmit={onSubmit} className="space-y-4">
{/* 아이디 */}
<div className="space-y-2">
<Label htmlFor="userId"> *</Label>
<Input
id="userId"
name="userId"
type="text"
placeholder="아이디를 입력하세요"
value={formData.userId}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11"
required
/>
{touchedFields?.userId && validationErrors.userId && (
2025-11-13 18:25:50 +09:00
<p className="text-destructive text-xs">{validationErrors.userId}</p>
)}
</div>
{/* 비밀번호 */}
<div className="space-y-2">
<Label htmlFor="password"> *</Label>
<div className="relative">
<Input
id="password"
name="password"
type={showPassword ? "text" : "password"}
placeholder="비밀번호를 입력하세요"
value={formData.password}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11 pr-10"
required
/>
<button
type="button"
onClick={onTogglePassword}
className="absolute top-1/2 right-3 -translate-y-1/2 transform cursor-pointer text-slate-400 transition-colors hover:text-slate-600"
disabled={isLoading}
>
{showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
</button>
</div>
{touchedFields?.password && validationErrors.password && (
2025-11-13 18:25:50 +09:00
<p className="text-destructive text-xs">{validationErrors.password}</p>
)}
</div>
{/* 비밀번호 확인 */}
<div className="space-y-2">
<Label htmlFor="passwordConfirm"> *</Label>
<div className="relative">
<Input
id="passwordConfirm"
name="passwordConfirm"
type={showPassword ? "text" : "password"}
placeholder="비밀번호를 다시 입력하세요"
value={formData.passwordConfirm}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11 pr-10"
required
/>
<button
type="button"
onClick={onTogglePassword}
className="absolute top-1/2 right-3 -translate-y-1/2 transform cursor-pointer text-slate-400 transition-colors hover:text-slate-600"
disabled={isLoading}
>
{showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
</button>
</div>
{touchedFields?.passwordConfirm && validationErrors.passwordConfirm && (
2025-11-13 18:25:50 +09:00
<p className="text-destructive text-xs">{validationErrors.passwordConfirm}</p>
)}
</div>
{/* 이름 */}
<div className="space-y-2">
<Label htmlFor="userName"> *</Label>
<Input
id="userName"
name="userName"
type="text"
placeholder="이름을 입력하세요"
value={formData.userName}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11"
required
/>
{touchedFields?.userName && validationErrors.userName && (
2025-11-13 18:25:50 +09:00
<p className="text-destructive text-xs">{validationErrors.userName}</p>
)}
</div>
{/* 연락처 */}
<div className="space-y-2">
<Label htmlFor="phoneNumber"> *</Label>
<Input
id="phoneNumber"
name="phoneNumber"
type="text"
placeholder="010-1234-5678"
value={formData.phoneNumber}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11"
required
/>
{touchedFields?.phoneNumber && validationErrors.phoneNumber && (
2025-11-13 18:25:50 +09:00
<p className="text-destructive text-xs">{validationErrors.phoneNumber}</p>
)}
</div>
{/* 면허번호 */}
<div className="space-y-2">
<Label htmlFor="licenseNumber"> *</Label>
<Input
id="licenseNumber"
name="licenseNumber"
type="text"
placeholder="12-34-567890-12"
value={formData.licenseNumber}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11"
required
/>
{touchedFields?.licenseNumber && validationErrors.licenseNumber && (
2025-11-13 18:25:50 +09:00
<p className="text-destructive text-xs">{validationErrors.licenseNumber}</p>
)}
</div>
{/* 차량번호 */}
<div className="space-y-2">
<Label htmlFor="vehicleNumber"> *</Label>
<Input
id="vehicleNumber"
name="vehicleNumber"
type="text"
placeholder="12가1234"
value={formData.vehicleNumber}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11"
required
/>
{touchedFields?.vehicleNumber && validationErrors.vehicleNumber && (
2025-11-13 18:25:50 +09:00
<p className="text-destructive text-xs">{validationErrors.vehicleNumber}</p>
)}
</div>
{/* 차량 타입 */}
<div className="space-y-2">
<Label htmlFor="vehicleType"> *</Label>
<Input
id="vehicleType"
name="vehicleType"
type="text"
placeholder="예: 1톤, 5톤, 11톤, 25톤"
value={formData.vehicleType}
onChange={onInputChange}
onBlur={onBlur}
disabled={isLoading}
className="h-11"
required
/>
{touchedFields?.vehicleType && validationErrors.vehicleType && (
<p className="text-destructive text-xs">{validationErrors.vehicleType}</p>
)}
</div>
{/* 회원가입 버튼 */}
<Button
type="submit"
className="h-11 w-full bg-slate-900 font-medium text-white hover:bg-slate-800"
disabled={isLoading || !isFormValid}
>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
2025-11-13 18:25:50 +09:00
"회원가입(공차중계)"
)}
</Button>
{/* 로그인으로 돌아가기 버튼 */}
<Button
type="button"
variant="outline"
className="h-11 w-full font-medium"
onClick={() => router.push("/login")}
disabled={isLoading}
>
<ArrowLeft className="mr-2 h-4 w-4" />
</Button>
</form>
</CardContent>
</Card>
);
}