Files
sweekar-app/pages/login/changePassword.vue
T
2026-01-21 11:34:37 +08:00

307 lines
8.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { ref } from 'vue';
import { forgetPassword, sendCodeToEmail } from './api';
// Password reset related variables
const email = ref('');
const newPassword = ref('');
const confirmPassword = ref('');
const verificationCode = ref('');
const codeBtnText = ref('Get Code');
const codeBtnDisabled = ref(false);
let countdownTimer = null;
// Email format validation
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
// Get verification code
const getVerificationCode = async () => {
if (!email.value) {
uni.showToast({
title: 'Please enter email',
icon: 'none',
});
return;
}
if (!validateEmail(email.value)) {
uni.showToast({
title: 'Please enter a valid email',
icon: 'none',
});
return;
}
// Send verification code
try {
uni.showLoading({
title: 'Sending...',
mask: true,
});
const params = {
email: email.value,
register: false // Not for registration, but for password reset
};
const res = await sendCodeToEmail(params);
if (res && res.code === 0) {
uni.hideLoading();
uni.showToast({
title: 'Verification code sent',
icon: 'success',
});
// Start countdown
let timeLeft = 60;
codeBtnDisabled.value = true;
codeBtnText.value = `${timeLeft}s`;
countdownTimer = setInterval(() => {
timeLeft--;
codeBtnText.value = `${timeLeft}s`;
if (timeLeft <= 0) {
clearInterval(countdownTimer);
codeBtnText.value = 'Resend';
codeBtnDisabled.value = false;
}
}, 1000);
} else {
uni.hideLoading();
uni.showToast({
title: res.msg || 'Send failed',
icon: 'error',
});
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: error.message || 'Send failed, please try again',
icon: 'error',
});
}
};
// Submit password reset
const onResetPassword = async () => {
if (!email.value) {
uni.showToast({
title: 'Please enter email',
icon: 'none',
});
return;
}
if (!validateEmail(email.value)) {
uni.showToast({
title: 'Please enter a valid email',
icon: 'none',
});
return;
}
if (!verificationCode.value) {
uni.showToast({
title: 'Please enter verification code',
icon: 'none',
});
return;
}
if (!newPassword.value) {
uni.showToast({
title: 'Please enter new password',
icon: 'none',
});
return;
}
if (newPassword.value !== confirmPassword.value) {
uni.showToast({
title: 'Passwords do not match',
icon: 'none',
});
return;
}
if (newPassword.value.length < 6) {
uni.showToast({
title: 'Password must be at least 6 characters',
icon: 'none',
});
return;
}
try {
uni.showLoading({
title: 'Resetting password...',
mask: true,
});
// Call password reset API
const resetParams = {
email: email.value,
verificationCode: verificationCode.value,
password: newPassword.value,
confirmPassword: confirmPassword.value
};
const res = await forgetPassword(resetParams);
if (res && res.code === 0) {
uni.hideLoading();
uni.showToast({
title: 'Password reset successful',
icon: 'success',
});
// Navigate back to login page after success
setTimeout(() => {
uni.navigateBack();
}, 1500);
} else {
uni.hideLoading();
uni.showToast({
title: res.msg || 'Password reset failed',
icon: 'error',
});
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: error.message || 'Password reset failed, please try again',
icon: 'error',
});
}
};
// Clear input field
const clearInput = (type) => {
if (type === 'email') {
email.value = '';
} else if (type === 'newPassword') {
newPassword.value = '';
} else if (type === 'confirmPassword') {
confirmPassword.value = '';
} else if (type === 'verificationCode') {
verificationCode.value = '';
}
};
// Go back to login page
const goLoginPage = function() {
uni.navigateTo({
url: '/pages/login/index'
})
}
</script>
<template>
<view class="p-4 min-h-screen bg-white flex flex-col justify-center">
<!-- Title -->
<view class="mb-12 text-center">
<image src="/static/tabbar/find.png" class="w-20 h-20 mb-8" mode="aspectFit"></image>
<text class="block text-3xl font-bold text-gray-800 mb-4">RESET PASSWORD</text>
<text class="text-sm text-gray-500">Enter your email and new password</text>
</view>
<!-- Email input -->
<view class="mb-6">
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
<u-icon name="email" class="h-10" color="black" bold="true"></u-icon>
<input
class="w-full text-base text-gray-800 bg-transparent"
type="email"
placeholder="Email Address"
v-model="email"
/>
<view
v-if="email"
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-black font-bold"
@tap="clearInput('email')"
>
×
</view>
</view>
</view>
<!-- Verification code input -->
<view class="mb-6 relative">
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
<u-icon name="chat" class="h-10" color="black" bold="true"></u-icon>
<input
class="w-full text-base text-gray-800 bg-transparent pr-32"
type="text"
placeholder="Verification Code"
v-model="verificationCode"
/>
</view>
<button
class="absolute right-2 top-1/2 transform -translate-y-1/2 h-10 px-4 bg-theme text-white text-xs rounded-full disabled:bg-gray-400 disabled:text-gray-300 flex items-center justify-center"
:disabled="codeBtnDisabled"
@tap="getVerificationCode"
>
{{ codeBtnText }}
</button>
</view>
<!-- New password input -->
<view class="mb-6">
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
<u-icon name="lock" class="h-10" color="black" bold="true"></u-icon>
<input
class="w-full text-base text-gray-800 bg-transparent"
type="password"
placeholder="New Password"
v-model="newPassword"
/>
<view
v-if="newPassword"
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-white font-bold"
@tap="clearInput('newPassword')"
>
×
</view>
</view>
</view>
<!-- Confirm password input -->
<view class="mb-8">
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
<u-icon name="lock" class="h-10" color="black" bold="true"></u-icon>
<input
class="w-full text-base text-gray-800 bg-transparent"
type="password"
placeholder="Confirm Password"
v-model="confirmPassword"
/>
<view
v-if="confirmPassword"
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-white font-bold"
@tap="clearInput('confirmPassword')"
>
×
</view>
</view>
</view>
<!-- Reset password button -->
<view
class="w-full h-12 bg-theme rounded-lg text-white text-xl flex items-center justify-center"
@click="onResetPassword"
>
<text>RESET PASSWORD</text>
</view>
<!-- Back to login link -->
<view class="flex justify-center items-center my-8 text-gray-500 text-sm">
<text>Remember your password?</text>
<text class="text-green-500 ml-2" @click="goLoginPage">Back to Sign in</text>
</view>
</view>
</template>