Debugging Reset Password Form

User
<script>
import { ref, inject, onMounted } from "vue";
import { useForm, useField } from "vee-validate";
import { useAuthStore } from "@/stores/auth";
import { useRouter } from "vue-router";
import publicApi from "@/publicApi";
import SingleColumn from "@/layouts/SingleColumn.vue";

const authStore = useAuthStore();
const router = useRouter();
const apiUrl = inject<string>("apiUrl");

const showPassword = ref(false);
const alertMessage = ref("");
const alertColor = ref("");
const step = ref(1);
const loading = ref(false);
const otp = ref("");

const items = ["Forget Password", "Reset Password"];

onMounted(() => {
  if (authStore.isAuthenticated) {
    router.push("/dashboard"); // Redirect if already logged in
  }
});

// **Email Form Validation**
const { handleSubmit, handleReset } = useForm({
  validationSchema: {
    email(value: string) {
      return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value) || "Must be a valid e-mail.";
    },
  },
});
const email = useField("email");

const password = useField("password");
const confirmPassword = useField("confirmPassword");
const otpField = useField("otp");
// **Password Reset Form Validation**
const { handleSubmit: handleResetSubmit } = useForm({
  validationSchema: {
    password(value: string) {
      return value?.length >= 6 || "Password must be at least 6 characters long.";
    },
    confirmPassword(value: string) {
      return password.value?.value && value === password.value.value || "Passwords do not match.";
    }
  },
});



// **Submit Forgot Password**
const submit = handleSubmit(async (values) => {
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/send-otp-password`, {
      email: values.email,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "OTP has been sent successfully!";
      alertColor.value = "success";
      step.value = 2;
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error sending OTP.";
    alertColor.value = "error";
  }
});
// **Submit OTP and Reset Password**
const resetPassword = handleResetSubmit(async (values) => {
  alert("sfaff")
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
      email: email.value.value,
      otp: otp.value,
      password: values.password,
      confirmPassword: values.confirmPassword,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "Password reset successfully!";
      alertColor.value = "success";
      router.push("/login");
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error resetting password.";
    alertColor.value = "error";
  }
});
</script>

Forget Password

Submit
Clear

Reset Password

We sent a verification code to {{ email.value.value || "your email" }}.
Please check your email and paste the code below.

Verify

Didn't receive the code? Resend

when click verify
const resetPassword = handleResetSubmit(async (values) => {
alert("sfaff")
loading.value = true;
alertMessage.value = "";
alertColor.value = "";

try {
const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
email: email.value.value,
otp: otp.value,
password: values.password,
confirmPassword: values.confirmPassword,
});

loading.value = false;
if (response.data.success) {
alertMessage.value = "Password reset successfully!";
alertColor.value = "success";
router.push("/login");
} else {
alertMessage.value = response.data.message;
alertColor.value = "error";
}
} catch (error: any) {
loading.value = false;
alertMessage.value = error.response?.data.message || "Error resetting password.";
alertColor.value = "error";
}
});
nothing happens

Assistant
It looks like your `resetPassword` function is not executing properly. Here are a few debugging steps to identify and fix the issue:

### **Potential Issues & Fixes**
1. **Check if the function is being triggered**
– You added `alert("sfaff")` at the start of `resetPassword`. If the alert is not showing, it means the function is not being called.
– Try adding a `console.log("resetPassword triggered")` inside the function and check the browser console.

2. **Check Form Submission**
– Ensure the `@submit.prevent="resetPassword"` is correctly attached to the form.
– Vue's `useForm()` and `handleSubmit()` return a new function that must be executed. Try updating the form like this:

<form @submit.prevent="resetPassword()">

instead of

<form @submit.prevent="resetPassword">

3. **Check if OTP is Being Collected**
– `otp` is a separate `ref("")`, but you are not binding it to any input field. Add an input field for OTP:

<v-text-field
       v-model="otp"
       label="OTP"
       required
     ></v-text-field>

4. **Validate API Response**
– Add `console.log(response.data);` inside the `try` block after the API call to inspect the response:

console.log("API Response:", response.data);

5. **Ensure `apiUrl` is Injected**
– `const apiUrl = inject("apiUrl");`
– If `apiUrl` is `undefined`, the API request won't work. Add a check:

console.log("apiUrl:", apiUrl);

6. **Check Console for Errors**
– Open the **browser console** (`F12 > Console`) and check if any Vue or API errors appear.

### **Final Debugging Version**
Modify your `resetPassword` function:

const resetPassword = handleResetSubmit(async (values) => {
  console.log("resetPassword triggered");
  if (!apiUrl) {
    alert("API URL is missing");
    return;
  }
  if (!otp.value) {
    alert("OTP is required");
    return;
  }

  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
      email: email.value.value,
      otp: otp.value,
      password: values.password,
      confirmPassword: values.confirmPassword,
    });

    console.log("API Response:", response.data);

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "Password reset successfully!";
      alertColor.value = "success";
      router.push("/login");
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    console.error("API Error:", error.response?.data || error);
    alertMessage.value = error.response?.data.message || "Error resetting password.";
    alertColor.value = "error";
  }
});

### **Summary of Fixes**
✅ Ensure function is actually triggered
✅ Ensure `@submit.prevent="resetPassword()"` in “
✅ Add an OTP input field
✅ Debug API response with `console.log(response.data);`
✅ Verify `apiUrl` is not `undefined`

Try these fixes and let me know what happens! 🚀

User
<script>
import { ref, inject, onMounted } from "vue";
import { useForm, useField } from "vee-validate";
import { useAuthStore } from "@/stores/auth";
import { useRouter } from "vue-router";
import publicApi from "@/publicApi";
import SingleColumn from "@/layouts/SingleColumn.vue";

const authStore = useAuthStore();
const router = useRouter();
const apiUrl = inject<string>("apiUrl");

const showPassword = ref(false);
const alertMessage = ref("");
const alertColor = ref("");
const step = ref(1);
const loading = ref(false);

const items = ["Forget Password", "Reset Password"];

onMounted(() => {
  if (authStore.isAuthenticated) {
    router.push("/dashboard"); // Redirect if already logged in
  }
});

// **Email Form Validation**
const { handleSubmit, handleReset } = useForm({
  validationSchema: {
    email(value: string) {
      return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value) || "Must be a valid e-mail.";
    },
  },
});
const email = useField("email");

const password = useField("password");
const confirmPassword = useField("confirmPassword");
const otp = useField("otp");
// **Password Reset Form Validation**
const { handleSubmit: handleResetSubmit } = useForm({
  validationSchema: {
    password(value: string) {
      return value?.length >= 6 || "Password must be at least 6 characters long.";
    },
    confirmPassword(value: string) {
      return password.value?.value && value === password.value.value || "Passwords do not match.";
    },
    otp(value: string) {
      return value?.length === 6 || "OTP must be 6 digits.";
    },
  },
});



// **Submit Forgot Password**
const submit = handleSubmit(async (values) => {
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/send-otp-password`, {
      email: values.email,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "OTP has been sent successfully!";
      alertColor.value = "success";
      step.value = 2;
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error sending OTP.";
    alertColor.value = "error";
  }
});
// **Submit OTP and Reset Password**
const resetPassword = handleResetSubmit(async (values) => {
  alert("sfaff")
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
      email: email.value.value,
      otp: otp.value,
      password: values.password,
      confirmPassword: values.confirmPassword,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "Password reset successfully!";
      alertColor.value = "success";
      router.push("/login");
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error resetting password.";
    alertColor.value = "error";
  }
});
</script>

Forget Password

Submit
Clear

Reset Password

We sent a verification code to {{ email.value.value || "your email" }}.
Please check your email and paste the code below.

Verify

Didn't receive the code? Resend

click on verify still not work

Assistant
It looks like your `resetPassword` function isn't executing properly. Here are some potential issues and fixes:

### Possible Issues:
1. **`otp.value` is an object, not a string**
– You're passing `otp.value` directly in the API request. Since `useField()` returns an object with `.value`, you should use `otp.value.value`.

2. **Fix for OTP field binding**

const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
     email: email.value.value,
   - otp: otp.value,
   + otp: otp.value.value,
     password: values.password,
     confirmPassword: values.confirmPassword,
   });

3. **Check for API Errors**
– Add `console.log` to check if the function is executing properly.

4. **Ensure `step` is updating properly**
– Your `resetPassword` form will not trigger unless `step.value === 2`. Double-check if `step.value` is updating after OTP submission.

### Debugging Steps:
1. **Check if `resetPassword` is triggered**
Add a `console.log` at the beginning of the `resetPassword` function:

const resetPassword = handleResetSubmit(async (values) => {
     console.log("Reset Password function triggered", values);

2. **Verify if API is receiving the right data**

console.log({
     email: email.value.value,
     otp: otp.value.value,
     password: values.password,
     confirmPassword: values.confirmPassword,
   });

3. **Check for Errors in API Call**

try {
     const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
       email: email.value.value,
       otp: otp.value.value,
       password: values.password,
       confirmPassword: values.confirmPassword,
     });
     console.log("API Response:", response.data);
   } catch (error: any) {
     console.error("API Error:", error.response?.data);
   }

Let me know what you find after adding these logs! 🚀

User
<script>
import { ref, inject, onMounted } from "vue";
import { useForm, useField } from "vee-validate";
import { useAuthStore } from "@/stores/auth";
import { useRouter } from "vue-router";
import publicApi from "@/publicApi";
import SingleColumn from "@/layouts/SingleColumn.vue";

const authStore = useAuthStore();
const router = useRouter();
const apiUrl = inject<string>("apiUrl");

const showPassword = ref(false);
const alertMessage = ref("");
const alertColor = ref("");
const step = ref(1);
const loading = ref(false);

const items = ["Forget Password", "Reset Password"];

onMounted(() => {
  if (authStore.isAuthenticated) {
    router.push("/dashboard"); // Redirect if already logged in
  }
});

// **Email Form Validation**
const { handleSubmit, handleReset } = useForm({
  validationSchema: {
    email(value: string) {
      return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value) || "Must be a valid e-mail.";
    },
  },
});
const email = useField("email");

const password = useField("password");
const confirmPassword = useField("confirmPassword");
const otp = useField("otp");
// **Password Reset Form Validation**
const { handleSubmit: handleResetSubmit } = useForm({
  validationSchema: {
    password(value: string) {
      return value?.length >= 6 || "Password must be at least 6 characters long.";
    },
    confirmPassword(value: string) {
      return password.value?.value && value === password.value.value || "Passwords do not match.";
    },
    otp(value: string) {
      return value?.length === 6 || "OTP must be 6 digits.";
    },
  },
});



// **Submit Forgot Password**
const submit = handleSubmit(async (values) => {
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/send-otp-password`, {
      email: values.email,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "OTP has been sent successfully!";
      alertColor.value = "success";
      step.value = 2;
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error sending OTP.";
    alertColor.value = "error";
  }
});
// **Submit OTP and Reset Password**
const resetPassword = handleResetSubmit(async (values) => {
  alert("sfaff")
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
      email: email.value.value,
      otp: otp.value,
      password: values.password,
      confirmPassword: values.confirmPassword,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "Password reset successfully!";
      alertColor.value = "success";
      router.push("/login");
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error resetting password.";
    alertColor.value = "error";
  }
});
</script>

Forget Password

Submit
Clear

Reset Password

We sent a verification code to {{ email.value.value || "your email" }}.
Please check your email and paste the code below.

Verify

Didn't receive the code? Resend

correct above code

Assistant
Here are the issues I found in your code and the necessary corrections:

### **Issues & Fixes**
1. **Incorrect `useField` Usage:**
– `useField` should be used inside `useForm`, but you've used it outside.
– **Fix:** Move `useField` inside the respective `useForm` instances.

2. **Incorrect Form Submission:**
– `otp.value`, `password.value.value`, and `confirmPassword.value.value` are accessed incorrectly.
– **Fix:** Use `values` from `handleSubmit`.

3. **Resend OTP Link Issue:**
– You're trying to clear `otp` using `@click.prevent="otp = ''"` directly.
– **Fix:** Use `otp.value.value = ""`.

4. **Alert Debugging (`alert("sfaff")` in `resetPassword`)**
– Remove `alert("sfaff")` from `resetPassword`.

5. **Proper OTP Resend Handling**
– Add an API call for resending OTP.

### **Updated Code**

<script setup lang="ts">
import { ref, inject, onMounted } from "vue";
import { useForm, useField } from "vee-validate";
import { useAuthStore } from "@/stores/auth";
import { useRouter } from "vue-router";
import publicApi from "@/publicApi";
import SingleColumn from "@/layouts/SingleColumn.vue";

const authStore = useAuthStore();
const router = useRouter();
const apiUrl = inject<string>("apiUrl");

const showPassword = ref(false);
const alertMessage = ref("");
const alertColor = ref("");
const step = ref(1);
const loading = ref(false);
const items = ["Forget Password", "Reset Password"];

onMounted(() => {
  if (authStore.isAuthenticated) {
    router.push("/dashboard"); // Redirect if already logged in
  }
});

// **Forgot Password Form Validation**
const { handleSubmit, handleReset } = useForm({
  validationSchema: {
    email(value: string) {
      return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value) || "Must be a valid e-mail.";
    },
  },
});
const email = useField("email");

// **Password Reset Form Validation**
const { handleSubmit: handleResetSubmit } = useForm({
  validationSchema: {
    password(value: string) {
      return value?.length >= 6 || "Password must be at least 6 characters long.";
    },
    confirmPassword(value: string) {
      return password.value?.value && value === password.value.value || "Passwords do not match.";
    },
    otp(value: string) {
      return value?.length === 6 || "OTP must be 6 digits.";
    },
  },
});
const password = useField("password");
const confirmPassword = useField("confirmPassword");
const otp = useField("otp");

// **Submit Forgot Password**
const submit = handleSubmit(async (values) => {
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/send-otp-password`, {
      email: values.email,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "OTP has been sent successfully!";
      alertColor.value = "success";
      step.value = 2;
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error sending OTP.";
    alertColor.value = "error";
  }
});

// **Submit OTP and Reset Password**
const resetPassword = handleResetSubmit(async (values) => {
  loading.value = true;
  alertMessage.value = "";
  alertColor.value = "";

  try {
    const response = await publicApi.post(`${apiUrl}/verify-otp-password`, {
      email: email.value.value,
      otp: values.otp,
      password: values.password,
      confirmPassword: values.confirmPassword,
    });

    loading.value = false;
    if (response.data.success) {
      alertMessage.value = "Password reset successfully!";
      alertColor.value = "success";
      router.push("/login");
    } else {
      alertMessage.value = response.data.message;
      alertColor.value = "error";
    }
  } catch (error: any) {
    loading.value = false;
    alertMessage.value = error.response?.data.message || "Error resetting password.";
    alertColor.value = "error";
  }
});

// **Resend OTP**
const resendOtp = async () => {
  try {
    await publicApi.post(`${apiUrl}/send-otp-password`, { email: email.value.value });
    alertMessage.value = "OTP has been resent!";
    alertColor.value = "success";
  } catch (error: any) {
    alertMessage.value = "Error resending OTP.";
    alertColor.value = "error";
  }
};
</script>

<template>
  <SingleColumn :md="12" :mt="4">
    <OverlayLoading :overlay="loading" />

    <v-stepper v-model="step" :items="items" hide-actions>
      <!-- Step 1: Enter Email -->
      <template v-slot:item.1>
        <v-card class="py-8 px-6 text-center mx-auto ma-4" elevation="12" max-width="600">
          <h3 class="text-h6 mb-4">Forget Password</h3>

          <v-sheet class="mx-auto mt-4 mb-4" max-width="600">
            <form @submit.prevent="submit">
              <v-text-field
                v-model="email.value.value"
                :error-messages="email.errorMessage.value"
                label="E-mail"
              ></v-text-field>

              <v-btn class="me-4" type="submit"> Submit </v-btn>
              <v-btn @click="handleReset"> Clear </v-btn>
            </form>
          </v-sheet>
        </v-card>
      </template>

      <!-- Step 2: OTP Verification & Password Reset -->
      <template v-slot:item.2>
        <v-card class="py-8 px-6 text-center mx-auto ma-4" elevation="12" max-width="400">
          <h3 class="text-h6 mb-4">Reset Password</h3>

          <div class="text-body-2">
            We sent a verification code to {{ email.value.value || "your email" }}. <br />
            Please check your email and paste the code below.
          </div>

          <v-sheet color="surface">
            <form @submit.prevent="resetPassword">
              <v-text-field
                v-model="otp.value.value"
                :error-messages="otp.errorMessage.value"
                label="OTP"
                required
              ></v-text-field>

              <v-text-field
                v-model="password.value.value"
                :type="showPassword ? 'text' : 'password'"
                :error-messages="password.errorMessage.value"
                prepend-inner-icon="mdi-lock"
                :append-inner-icon="showPassword ? 'mdi-eye-off' : 'mdi-eye'"
                @click:append-inner="showPassword = !showPassword"
                label="Password"
              ></v-text-field>

              <v-text-field
                v-model="confirmPassword.value.value"
                :type="showPassword ? 'text' : 'password'"
                :error-messages="confirmPassword.errorMessage.value"
                prepend-inner-icon="mdi-lock"
                :append-inner-icon="showPassword ? 'mdi-eye-off' : 'mdi-eye'"
                @click:append-inner="showPassword = !showPassword"
                label="Confirm Password"
              ></v-text-field>

              <v-btn class="my-4" color="purple" height="40" variant="flat" type="submit" width="70%">
                Verify
              </v-btn>

              <div class="text-caption">
                Didn't receive the code?
                <a href="#" @click.prevent="resendOtp">Resend</a>
              </div>
            </form>
          </v-sheet>
        </v-card>
      </template>
    </v-stepper>

    <TheAlert v-if="alertMessage" :title="alertMessage" :color="alertColor" :icon="alertColor" />
  </SingleColumn>
</template>

### **Key Fixes**
✅ Moved `useField` inside `useForm` correctly.
✅ Fixed `otp.value` access.
✅ Implemented proper OTP resend functionality.
✅ Removed debugging `alert("sfaff")`.

This should now work without errors. 🚀

Leave a Comment

Your email address will not be published. Required fields are marked *