import { useRouter, useLocalSearchParams } from "expo-router"; import { useState } from "react"; import { View, Text } from "react-native"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { AuthLayout } from "@/components/auth/AuthLayout"; import { AuthHeader } from "@/components/auth/AuthHeader"; import { AuthCard } from "@/components/auth/AuthCard"; import { AuthFooter } from "@/components/auth/AuthFooter"; import { FormInput } from "@/components/auth/FormInput"; import { PasswordInput } from "@/components/auth/PasswordInput"; import { AuthButton } from "@/components/auth/AuthButton"; import { getApiUrl } from "@/store/api/baseApi"; const schema = z .object({ password: z.string().min(8, "Password must be at least 8 characters"), confirmPassword: z.string(), }) .refine((d) => d.password === d.confirmPassword, { path: ["confirmPassword"], message: "Passwords do not match", }); type FormVals = z.infer; const ResetPasswordScreen = () => { const router = useRouter(); const { token: tokenParam } = useLocalSearchParams<{ token?: string }>(); const [submitting, setSubmitting] = useState(false); const [message, setMessage] = useState(""); const [error, setError] = useState(""); const [tokenOverride, setTokenOverride] = useState(""); const { handleSubmit, setValue, watch, formState: { errors }, } = useForm({ resolver: zodResolver(schema), mode: "onSubmit", reValidateMode: "onChange", shouldUnregister: false, defaultValues: { password: "", confirmPassword: "" }, }); const password = watch("password"); const confirmPassword = watch("confirmPassword"); const tokenFromLink = typeof tokenParam === "string" && tokenParam.length > 0 ? tokenParam : ""; const token = tokenFromLink || tokenOverride; const onSubmit = async (vals: FormVals) => { setSubmitting(true); setError(""); setMessage(""); try { if (!token) { throw new Error("Reset link token is required"); } const res = await fetch( `${getApiUrl()?.replace(/\/$/, "")}/auth/password/reset`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token, password: vals.password }), } ); const data = await res.json().catch(() => ({})); if (!res.ok) { throw new Error(data?.error || "Failed to reset password"); } setMessage("Password has been reset. Redirecting to sign in..."); setTimeout(() => router.replace("/sign-in"), 1500); } catch (e: any) { setError(e?.message || "Failed to reset password"); } finally { setSubmitting(false); } }; return ( {!!error && ( {error} )} {!!message && ( {message} )} {!tokenFromLink && ( )} setValue("password", t, { shouldValidate: true }) } disabled={submitting} onSubmitEditing={handleSubmit(onSubmit)} returnKeyType="next" /> setValue("confirmPassword", t, { shouldValidate: true }) } disabled={submitting} onSubmitEditing={handleSubmit(onSubmit)} returnKeyType="send" submitBehavior="blurAndSubmit" /> {submitting ? "Resetting password..." : "Reset Password"} router.push("/sign-in")} disabled={submitting} /> ); }; export default ResetPasswordScreen;