Files
SweetHome/app/components/LoginComponent/LoginForm.js

125 lines
5.5 KiB
JavaScript

import { EyeOff, Mail, Phone, Eye, LogIn, Lock, Loader2, CheckCircle } from "lucide-react";
import { useTranslation } from "react-i18next";
import { motion } from "framer-motion";
import Link from "next/link";
import { useState } from "react";
export default function LoginForm({ loginMethod, errors, formData, isLoading, isSuccess, setFormData, handleCredentialChange }) {
const { t } = useTranslation();
const [showPassword, setShowPassword] = useState(false);
return (
<>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">{loginMethod === "email" ? t("emailLabel") : t("phoneLabel")}</label>
<div className="relative group">
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
{loginMethod === "email" ? (
<Mail className={`w-5 h-5 transition-colors ${errors.credential ? "text-red-500" : "text-gray-400 group-focus-within:text-amber-500"}`} />
) : (
<Phone className={`w-5 h-5 transition-colors ${errors.credential ? "text-red-500" : "text-gray-400 group-focus-within:text-amber-500"}`} />
)}
</div>
<input
type="text"
// type={loginMethod === 'email' ? 'email' : 'tel'}
value={formData.credential}
onChange={(e) => handleCredentialChange(e.target.value)}
className={`w-full pr-12 pl-4 py-4 bg-white/5 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent text-amber-50 placeholder-gray-500 transition-all ${
errors.credential ? "border-red-500" : "border-gray-700"
}`}
placeholder={loginMethod === "email" ? t("emailPlaceholder") : t("phonePlaceholder")}
dir="ltr"
/>
</div>
{errors.credential && (
<motion.p initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }} className="text-red-500 text-sm mt-1">
{errors.credential}
</motion.p>
)}
</div>
{/* Password */}
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">{t("password")}</label>
<div className="relative group">
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
<Lock className={`w-5 h-5 transition-colors ${errors.password ? "text-red-500" : "text-gray-400 group-focus-within:text-amber-500"}`} />
</div>
<input
type={showPassword ? "text" : "password"}
value={formData.password}
onChange={(e) => {
setFormData({
...formData,
password: e.target.value,
});
if (errors.password) setErrors({ ...errors, password: null });
}}
className={`w-full pr-12 pl-12 py-4 bg-white/5 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent text-amber-50 placeholder-gray-500 transition-all ${
errors.password ? "border-red-500" : "border-gray-700"
}`}
placeholder={t("passwordPlaceholder")}
/>
<button type="button" onClick={() => setShowPassword(!showPassword)} className="absolute inset-y-0 left-0 pl-3 flex items-center">
{showPassword ? <EyeOff className="w-5 h-5 text-gray-400 hover:text-gray-300 transition-colors" /> : <Eye className="w-5 h-5 text-gray-400 hover:text-gray-300 transition-colors" />}
</button>
</div>
{errors.password && (
<motion.p initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }} className="text-red-500 text-sm mt-1">
{errors.password}
</motion.p>
)}
</div>
{/* Remember + Forgot */}
<div className="flex items-center justify-between">
<label className="flex items-center gap-2 cursor-pointer group">
<input
type="checkbox"
checked={formData.rememberMe}
onChange={(e) =>
setFormData({
...formData,
rememberMe: e.target.checked,
})
}
className="w-4 h-4 rounded border-gray-600 bg-white/5 text-amber-500 focus:ring-amber-500 focus:ring-offset-0"
/>
<span className="text-sm text-gray-400 group-hover:text-white transition-colors">{t("rememberMe")}</span>
</label>
<Link href="/forgot-password" className="text-sm text-amber-400 hover:text-amber-300 transition-colors">
{t("forgotPassword")}
</Link>
</div>
{/* Submit */}
<motion.button
type="submit"
disabled={isLoading || isSuccess}
className="relative w-full bg-gradient-to-r from-amber-500 to-amber-600 text-white py-4 rounded-xl font-bold text-lg overflow-hidden group disabled:opacity-50 disabled:cursor-not-allowed"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
<span className="relative z-10 flex items-center justify-center gap-2">
{isLoading ? (
<>
<Loader2 className="w-5 h-5 animate-spin" />
{t("loggingIn")}{" "}
</>
) : isSuccess ? (
<>
<CheckCircle className="w-5 h-5" /> {t("success")}{" "}
</>
) : (
<>
{" "}
<LogIn className="w-5 h-5" />
{t("login")}
</>
)}
</span>
</motion.button>
</>
);
}