169 lines
6.9 KiB
Plaintext
169 lines
6.9 KiB
Plaintext
|
|
: (
|
||
|
|
// /* OTP Verification Step */
|
||
|
|
// <motion.form key="otp" initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -20 }} onSubmit={handleVerifyOTP} className="space-y-6">
|
||
|
|
// <div className="text-center mb-4">
|
||
|
|
// <Shield className="w-12 h-12 text-amber-500 mx-auto mb-3" />
|
||
|
|
// <p className="text-gray-300 text-sm">
|
||
|
|
// {t("sendOTPTo")}{" "}
|
||
|
|
// <span className="text-white font-medium" dir="ltr">
|
||
|
|
// {formData.credential}
|
||
|
|
// </span>
|
||
|
|
// </p>
|
||
|
|
// </div>
|
||
|
|
|
||
|
|
// <div>
|
||
|
|
// <label className="block text-sm font-medium text-gray-300 mb-2">{t("otpLabel")}</label>
|
||
|
|
// <input
|
||
|
|
// type="text"
|
||
|
|
// value={otpCode}
|
||
|
|
// onChange={(e) => {
|
||
|
|
// setOtpCode(e.target.value);
|
||
|
|
// if (otpError) setOtpError("");
|
||
|
|
// }}
|
||
|
|
// className={`w-full px-4 py-4 bg-white/5 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent text-white text-center text-2xl tracking-[0.5em] placeholder-gray-500 transition-all ${
|
||
|
|
// otpError ? "border-red-500" : "border-gray-700"
|
||
|
|
// }`}
|
||
|
|
// placeholder="______"
|
||
|
|
// maxLength={6}
|
||
|
|
// dir="ltr"
|
||
|
|
// />
|
||
|
|
// {otpError && (
|
||
|
|
// <motion.p initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }} className="text-red-500 text-sm mt-1 text-center">
|
||
|
|
// {otpError}
|
||
|
|
// </motion.p>
|
||
|
|
// )}
|
||
|
|
// </div>
|
||
|
|
|
||
|
|
// <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 disabled:opacity-50 disabled:cursor-not-allowed"
|
||
|
|
// whileHover={{ scale: 1.02 }}
|
||
|
|
// whileTap={{ scale: 0.98 }}
|
||
|
|
// >
|
||
|
|
// <span className="flex items-center justify-center gap-2">
|
||
|
|
// {isLoading ? (
|
||
|
|
// <>
|
||
|
|
// <Loader2 className="w-5 h-5 animate-spin" />
|
||
|
|
// {t("verifying")}
|
||
|
|
// </>
|
||
|
|
// ) : isSuccess ? (
|
||
|
|
// <>
|
||
|
|
// <CheckCircle className="w-5 h-5" />
|
||
|
|
// {t("success")}
|
||
|
|
// </>
|
||
|
|
// ) : (
|
||
|
|
// <>
|
||
|
|
// <KeyRound className="w-5 h-5" />
|
||
|
|
// {t("verify")}
|
||
|
|
// </>
|
||
|
|
// )}
|
||
|
|
// </span>
|
||
|
|
// </motion.button>
|
||
|
|
|
||
|
|
// <div className="flex items-center justify-between text-sm">
|
||
|
|
// <button
|
||
|
|
// type="button"
|
||
|
|
// onClick={() => {
|
||
|
|
// setStep("login");
|
||
|
|
// setOtpCode("");
|
||
|
|
// setOtpError("");
|
||
|
|
// }}
|
||
|
|
// className="text-gray-400 hover:text-white transition-colors"
|
||
|
|
// >
|
||
|
|
// ← {t("back")}
|
||
|
|
// </button>
|
||
|
|
// <button type="button" onClick={resendOTP} className="text-amber-400 hover:text-amber-300 transition-colors">
|
||
|
|
// {t("resendCode")}
|
||
|
|
// </button>
|
||
|
|
// </div>
|
||
|
|
// </motion.form>
|
||
|
|
<></>
|
||
|
|
// )}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// Send OTP
|
||
|
|
try {
|
||
|
|
if (loginMethod === "email") {
|
||
|
|
await sendEmailOTP();
|
||
|
|
} else {
|
||
|
|
await sendPhoneOTP();
|
||
|
|
}
|
||
|
|
} catch (otpErr) {
|
||
|
|
console.warn("[Login] OTP send failed, proceeding anyway:", otpErr);
|
||
|
|
}
|
||
|
|
|
||
|
|
setStep("otp");
|
||
|
|
} else if (result.status >= 500) {
|
||
|
|
console.error("[Login] Server error:", result.status, result.data);
|
||
|
|
toast.error(t("serverError"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
} else if (result.status === 404) {
|
||
|
|
console.error("[Login] API endpoint not found:", result.status);
|
||
|
|
toast.error(t("apiNotFound"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
} else if (result.status === 429) {
|
||
|
|
toast.error(t("tooManyRequests"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
console.error("[Login] Unexpected status:", result.status, result.data);
|
||
|
|
toast.error(result.data?.message || result.data || t("invalidCredentials"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
console.error("[Login] Error:", err);
|
||
|
|
toast.error(err.message || t("connectionError"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
toast(t("otpRequired"), {
|
||
|
|
icon: "🔐",
|
||
|
|
style: { background: "#fef3c7", color: "#92400e" },
|
||
|
|
});
|
||
|
|
|
||
|
|
// Send OTP
|
||
|
|
try {
|
||
|
|
if (loginMethod === "email") {
|
||
|
|
await sendEmailOTP();
|
||
|
|
} else {
|
||
|
|
await sendPhoneOTP();
|
||
|
|
}
|
||
|
|
} catch (otpErr) {
|
||
|
|
console.warn("[Login] OTP send failed, proceeding anyway:", otpErr);
|
||
|
|
}
|
||
|
|
|
||
|
|
setStep("otp");
|
||
|
|
} else if (result.status >= 500) {
|
||
|
|
console.error("[Login] Server error:", result.status, result.data);
|
||
|
|
toast.error(t("serverError"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
} else if (result.status === 404) {
|
||
|
|
console.error("[Login] API endpoint not found:", result.status);
|
||
|
|
toast.error(t("apiNotFound"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
} else if (result.status === 429) {
|
||
|
|
toast.error(t("tooManyRequests"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
console.error("[Login] Unexpected status:", result.status, result.data);
|
||
|
|
toast.error(result.data?.message || result.data || t("invalidCredentials"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
console.error("[Login] Error:", err);
|
||
|
|
toast.error(err.message || t("connectionError"), {
|
||
|
|
style: { background: "#fee2e2", color: "#991b1b" },
|
||
|
|
});
|
||
|
|
} finally {
|
||
|
|
setIsLoading(false);
|
||
|
|
}
|