import { o as __toESM } from "../_runtime.mjs"; import { h as require_react, m as require_jsx_runtime } from "../_libs/react+tanstack__react-query.mjs"; import { a as p, i as MyButton, o as pInput, s as MyTouchableOpacity } from "./src-u_N1opJl.mjs"; import { n as trpc } from "./trpc-client-CQOIB5UU.mjs"; import { l as useNavigate } from "../_libs/@tanstack/react-router+[...].mjs"; import { n as useAuth } from "./auth-context-DzjwonUC.mjs"; import { n as useForm, t as Controller } from "../_libs/react-hook-form.mjs"; //#region node_modules/.nitro/vite/services/ssr/assets/login-QH2hpwxi.js var import_react = /* @__PURE__ */ __toESM(require_react()); var import_jsx_runtime = require_jsx_runtime(); function LoginPage() { const { loginWithToken } = useAuth(); const navigate = useNavigate(); const [step, setStep] = (0, import_react.useState)("mobile"); const [selectedMobile, setSelectedMobile] = (0, import_react.useState)(""); const [canResend, setCanResend] = (0, import_react.useState)(false); const [resendCountdown, setResendCountdown] = (0, import_react.useState)(0); const intervalRef = (0, import_react.useRef)(); const [otpCells, setOtpCells] = (0, import_react.useState)([ "", "", "", "" ]); const inputRefs = (0, import_react.useRef)([ null, null, null, null ]); const loginMutation = trpc.user.auth.login.useMutation(); const sendOtpMutation = trpc.user.auth.sendOtp.useMutation({ onSuccess: (data) => { if (data.success) { setResendCountdown(120); setCanResend(false); setStep("otp"); } } }); const verifyOtpMutation = trpc.user.auth.verifyOtp.useMutation({ onSuccess: (data) => { if (data.success && data.token && data.user) { loginWithToken(data.token, data.user); navigate({ to: "/home" }); } } }); (0, import_react.useEffect)(() => { return () => { if (intervalRef.current) clearInterval(intervalRef.current); }; }, []); (0, import_react.useEffect)(() => { if (intervalRef.current) clearInterval(intervalRef.current); if (resendCountdown > 0) intervalRef.current = setInterval(() => { setResendCountdown((prev) => { if (prev <= 1) { setCanResend(true); return 0; } return prev - 1; }); }, 1e3); return () => { if (intervalRef.current) clearInterval(intervalRef.current); }; }, [resendCountdown]); const { control, handleSubmit, setValue, clearErrors, setError } = useForm({ defaultValues: { mobile: "", otp: "", password: "" } }); const validateMobile = (mobile) => { const clean = mobile.replace(/\D/g, ""); return clean.length === 10 && /^[6-9]/.test(clean); }; const handleOtpChange = (index, text) => { if (text.length > 1) { const digits = text.replace(/\D/g, "").slice(0, 4); const newCells = digits.split("").concat([ "", "", "", "" ]).slice(0, 4); setOtpCells(newCells); setValue("otp", newCells.join("")); const lastIndex = Math.min(digits.length - 1, 3); inputRefs.current[lastIndex]?.focus(); return; } const newCells = [...otpCells]; newCells[index] = text; setOtpCells(newCells); setValue("otp", newCells.join("")); if (text && index < 3) inputRefs.current[index + 1]?.focus(); else if (!text && index > 0) inputRefs.current[index - 1]?.focus(); }; const onSubmit = (data) => { if (step === "mobile") { const mobile = data.mobile.trim(); if (!validateMobile(mobile)) { setError("mobile", { message: "Enter a valid 10-digit mobile number" }); return; } setSelectedMobile(mobile.replace(/\D/g, "")); sendOtpMutation.mutate({ mobile }); } else if (step === "otp") { if (!data.otp || data.otp.length < 4) { setError("otp", { message: "Enter a valid OTP" }); return; } verifyOtpMutation.mutate({ mobile: selectedMobile, otp: data.otp }); } else if (step === "password") loginMutation.mutate({ identifier: selectedMobile, password: data.password }, { onSuccess: (res) => { loginWithToken(res.data.token, res.data.user); navigate({ to: "/home" }); } }); }; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-h-screen items-center justify-center bg-gradient-to-b from-brand-400 to-brand-700 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full max-w-md", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, { weight: "bold", className: "mb-2 text-center text-4xl text-white", children: "Welcome" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, { className: "mb-8 text-center text-lg text-blue-100", children: "Sign in to continue your journey" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-2xl bg-white p-8 shadow-xl", children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: handleSubmit(onSubmit), children: [ step === "mobile" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Controller, { control, name: "mobile", render: ({ field: { onChange, value } }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(pInput, { placeholder: "Enter your mobile number", value, onChange: (e) => { const clean = e.target.value.replace(/\D/g, ""); if (clean.length <= 10) onChange(clean); }, className: "bg-gray-50" }) }), step === "otp" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-6", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, { weight: "semibold", className: "mb-3 text-center text-base text-gray-800", children: "Enter 4-digit OTP" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex justify-center gap-2", children: [ 0, 1, 2, 3 ].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { ref: (el) => { inputRefs.current[i] = el; }, className: "h-14 w-14 rounded-xl border-2 text-center text-2xl font-bold", style: { borderColor: otpCells[i] ? "#E63946" : "#E5E7EB", backgroundColor: otpCells[i] ? "#FFF5F6" : "#F9FAFB" }, type: "text", inputMode: "numeric", maxLength: 1, value: otpCells[i], onChange: (e) => handleOtpChange(i, e.target.value) }, i)) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-4 flex items-center justify-between border-t border-gray-100 pt-4", children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MyTouchableOpacity, { onClick: () => { setStep("choice"); setOtpCells([ "", "", "", "" ]); }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, { weight: "medium", className: "text-gray-500", children: "Back" }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MyTouchableOpacity, { onClick: () => sendOtpMutation.mutate({ mobile: selectedMobile }), disabled: !canResend, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, { weight: "semibold", className: canResend ? "text-brand-600" : "text-gray-400", children: canResend ? "Resend OTP" : `Resend in ${resendCountdown}s` }) })] }) ] }), step === "password" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Controller, { control, name: "password", render: ({ field: { onChange, value } }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(pInput, { placeholder: "Enter your password", value, onChange: (e) => onChange(e.target.value), type: "password", className: "bg-gray-50" }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MyButton, { type: "submit", fullWidth: true, className: "h-12 rounded-xl bg-brand-600 text-white shadow-lg", disabled: sendOtpMutation.isPending || verifyOtpMutation.isPending || loginMutation.isPending, textContent: step === "otp" ? "Verify & Login" : step === "password" ? "Login" : "Continue" }) }) ] }), step === "otp" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MyTouchableOpacity, { onClick: () => { setStep("password"); setOtpCells([ "", "", "", "" ]); }, className: "mt-4 block text-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, { weight: "semibold", className: "text-brand-600", children: "Or login with Password" }) })] }) ] }) }); } //#endregion export { LoginPage as component };