initial commit
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Email Confirm";
|
||||
}
|
||||
<div id="app" class="container-fluid" v-cloak>
|
||||
|
||||
<div class="card-body register-card-body">
|
||||
<p class="login-box-msg">@ViewData["Title"]</p>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center mb-3">
|
||||
<h3 class="text-dark">Email Confirm</h3>
|
||||
<a asp-page="/Index" class="">
|
||||
<p><i class="fas fa-home me-2 text-warning"></i><span class="text-dark">INDOTALENT</span></p>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<p>Please wait...</p>
|
||||
<p>Email confirmation is in progress.</p>
|
||||
<span class="spinner-border spinner-border-sm me-2"
|
||||
v-if="state.isSubmitting"
|
||||
role="status"
|
||||
aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@section scripts {
|
||||
<script src="~/FrontEnd/Pages/Accounts/EmailConfirm.cshtml.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
const App = {
|
||||
setup() {
|
||||
const state = Vue.reactive({
|
||||
isSubmitting: false,
|
||||
});
|
||||
|
||||
const emailConfirmation = async (email, code) => {
|
||||
try {
|
||||
const response = await AxiosManager.get(`/Security/ConfirmEmail?email=${email}&code=${code}`, {});
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('Error during emailConfirmation:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vue.onMounted(async () => {
|
||||
try {
|
||||
state.isSubmitting = true;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const email = params.get('email');
|
||||
const code = params.get('code');
|
||||
|
||||
if (email && code) {
|
||||
const response = await emailConfirmation(email, code);
|
||||
if (response.data.code === 200) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Email Confirmation Successful',
|
||||
text: 'You are being redirected...',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.href = '/Accounts/Login';
|
||||
}, 2000);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Email Confirmation Failed',
|
||||
text: response.data.message ?? 'Please check your data.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Email Confirmation Failed',
|
||||
text: 'Email or code is missing in the URL query string.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error('page init error:', e);
|
||||
} finally {
|
||||
state.isSubmitting = false;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
state
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Vue.createApp(App).mount('#app');
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Forgot Password";
|
||||
}
|
||||
|
||||
<div class="container-fluid" id="app" v-cloak>
|
||||
<div class="card-body register-card-body">
|
||||
<p class="login-box-msg">@ViewData["Title"]</p>
|
||||
|
||||
<form v-on:submit.prevent="handleSubmit">
|
||||
<div class="input-group mb-3">
|
||||
<input id="Email"
|
||||
name="Email"
|
||||
type="email"
|
||||
class="form-control"
|
||||
placeholder="name@example.com"
|
||||
v-model="state.email"
|
||||
v-on:input="state.errors.email = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-envelope"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.email" class="text-danger">{{ state.errors.email }}</label>
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-4">
|
||||
<button type="submit"
|
||||
v-bind:disabled="state.isSubmitting"
|
||||
class="btn btn-primary btn-block">
|
||||
<span class="spinner-border spinner-border-sm me-2"
|
||||
v-if="state.isSubmitting"
|
||||
role="status"
|
||||
aria-hidden="true"></span>
|
||||
<span>{{ state.isSubmitting ? '...' : 'Reset' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="social-auth-links text-center">
|
||||
<p>- OR -</p>
|
||||
<a href="#" class="btn btn-block btn-primary">
|
||||
<i class="fab fa-facebook mr-2"></i>
|
||||
Sign up using Facebook
|
||||
</a>
|
||||
<a href="#" class="btn btn-block btn-danger">
|
||||
<i class="fab fa-google-plus mr-2"></i>
|
||||
Sign up using Google+
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p class="mb-1">
|
||||
<a asp-page="/Accounts/Login" class="text-center">I already have a membership</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@section scripts {
|
||||
<script src="~/FrontEnd/Pages/Accounts/ForgotPassword.cshtml.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
const App = {
|
||||
setup() {
|
||||
const state = Vue.reactive({
|
||||
email: '',
|
||||
isSubmitting: false,
|
||||
errors: {
|
||||
email: ''
|
||||
}
|
||||
});
|
||||
|
||||
const validateForm = () => {
|
||||
state.errors.email = '';
|
||||
let isValid = true;
|
||||
|
||||
if (!state.email) {
|
||||
state.errors.email = 'Email is required.';
|
||||
isValid = false;
|
||||
} else if (!/\S+@\S+\.\S+/.test(state.email)) {
|
||||
state.errors.email = 'Please enter a valid email address.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
|
||||
const forgotPassword = async (email) => {
|
||||
try {
|
||||
const response = await AxiosManager.post('/Security/ForgotPassword', {
|
||||
email
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
|
||||
try {
|
||||
state.isSubmitting = true;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
if (!validateForm()) return;
|
||||
|
||||
const response = await forgotPassword(state.email);
|
||||
if (response.data.code === 200) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Reset Password Successful',
|
||||
text: 'Please check your email. You are being redirected...',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 2000);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Reset Password Failed',
|
||||
text: response.data.message ?? 'Please check your data.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'An Error Occurred',
|
||||
text: error.response?.data?.message || 'Please try again.',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
} finally {
|
||||
state.isSubmitting = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
state,
|
||||
handleSubmit
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Vue.createApp(App).mount('#app');
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Forgot Password Confirmation";
|
||||
}
|
||||
<div class="container-fluid" id="app" v-cloak>
|
||||
|
||||
<div class="card-body register-card-body">
|
||||
<p class="login-box-msg">@ViewData["Title"]</p>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center mb-3">
|
||||
<h3 class="text-dark">Forgot Password Confirm</h3>
|
||||
<a asp-page="/Index" class="">
|
||||
<p><i class="fas fa-home me-2 text-warning"></i><span class="text-dark">INDOTALENT</span></p>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<p>Please wait...</p>
|
||||
<p>Password reset is in progress.</p>
|
||||
<span class="spinner-border spinner-border-sm me-2"
|
||||
v-if="state.isSubmitting"
|
||||
role="status"
|
||||
aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@section scripts {
|
||||
<script src="~/FrontEnd/Pages/Accounts/ForgotPasswordConfirmation.cshtml.js"></script>
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
const App = {
|
||||
setup() {
|
||||
const state = Vue.reactive({
|
||||
isSubmitting: false,
|
||||
});
|
||||
|
||||
const forgotPasswordConfirmation = async (email, code, tempPassword) => {
|
||||
try {
|
||||
const response = await AxiosManager.get(`/Security/ForgotPasswordConfirmation?email=${email}&code=${code}&tempPassword=${tempPassword}`, {});
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('Error during ForgotPasswordConfirmation:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vue.onMounted(async () => {
|
||||
try {
|
||||
state.isSubmitting = true;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const email = params.get('email');
|
||||
const code = params.get('code');
|
||||
const tempPassword = params.get('tempPassword');
|
||||
|
||||
if (email && code && tempPassword) {
|
||||
const response = await forgotPasswordConfirmation(email, code, tempPassword);
|
||||
if (response.data.code === 200) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Password Reset Successful',
|
||||
text: 'You are being redirected...',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.href = '/Accounts/Login';
|
||||
}, 2000);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Password Reset Failed',
|
||||
text: response.data.message ?? 'Please check your data.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Password Reset Failed',
|
||||
text: 'Email or code is missing in the URL query string.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error('page init error:', e);
|
||||
} finally {
|
||||
state.isSubmitting = false;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
state
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Vue.createApp(App).mount('#app');
|
||||
@@ -0,0 +1,91 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Login";
|
||||
}
|
||||
|
||||
<div id="app" class="container-fluid" v-cloak>
|
||||
|
||||
<div class="card-body login-card-body">
|
||||
<p class="login-box-msg">@ViewData["Title"]</p>
|
||||
|
||||
<form v-on:submit.prevent="handleSubmit">
|
||||
<div class="input-group mb-3">
|
||||
<input id="Email"
|
||||
name="Email"
|
||||
type="email"
|
||||
class="form-control"
|
||||
placeholder="name@example.com"
|
||||
v-model="state.email"
|
||||
v-on:input="state.errors.email = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-envelope"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.email" class="text-danger">{{ state.errors.email }}</label>
|
||||
<div class="input-group mb-3">
|
||||
<input id="Password"
|
||||
name="Password"
|
||||
type="password"
|
||||
class="form-control"
|
||||
placeholder="Password"
|
||||
v-model="state.password"
|
||||
v-on:input="state.errors.password = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.password" class="text-danger">{{ state.errors.password }}</label>
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="icheck-primary">
|
||||
<input type="checkbox">
|
||||
<label for="remember">
|
||||
Remember Me
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-4">
|
||||
<button type="submit"
|
||||
v-bind:disabled="state.isSubmitting"
|
||||
class="btn btn-primary btn-block">
|
||||
<span class="spinner-border spinner-border-sm me-2"
|
||||
v-if="state.isSubmitting"
|
||||
role="status"
|
||||
aria-hidden="true"></span>
|
||||
<span>{{ state.isSubmitting ? '...' : 'Log In' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="social-auth-links text-center mb-3">
|
||||
<p>- OR -</p>
|
||||
<a href="#" class="btn btn-block btn-primary">
|
||||
<i class="fab fa-facebook mr-2"></i> Sign in using Facebook
|
||||
</a>
|
||||
<a href="#" class="btn btn-block btn-danger">
|
||||
<i class="fab fa-google-plus mr-2"></i> Sign in using Google+
|
||||
</a>
|
||||
</div>
|
||||
<!-- /.social-auth-links -->
|
||||
|
||||
<p class="mb-1">
|
||||
<a asp-page="/Accounts/ForgotPassword">Forgot Password</a>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<a asp-page="/Accounts/Register" class="text-center">Register a new membership</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@section scripts {
|
||||
<script type ="module" src="~/FrontEnd/Pages/Accounts/Login.cshtml.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
const App = {
|
||||
setup() {
|
||||
const state = Vue.reactive({
|
||||
email: '',
|
||||
password: '',
|
||||
isSubmitting: false,
|
||||
errors: {
|
||||
email: '',
|
||||
password: ''
|
||||
}
|
||||
});
|
||||
|
||||
const validateForm = () => {
|
||||
state.errors.email = '';
|
||||
state.errors.password = '';
|
||||
let isValid = true;
|
||||
|
||||
if (!state.email) {
|
||||
state.errors.email = 'Email is required.';
|
||||
isValid = false;
|
||||
} else if (!/\S+@\S+\.\S+/.test(state.email)) {
|
||||
state.errors.email = 'Please enter a valid email address.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!state.password) {
|
||||
state.errors.password = 'Password is required.';
|
||||
isValid = false;
|
||||
} else if (state.password.length < 6) {
|
||||
state.errors.password = 'Password must be at least 6 characters.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
|
||||
try {
|
||||
state.isSubmitting = true;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
if (!validateForm()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await AxiosManager.post('/Security/Login', {
|
||||
email: state.email,
|
||||
password: state.password
|
||||
});
|
||||
|
||||
if (response.data.code === 200) {
|
||||
StorageManager.saveLoginResult(response.data);
|
||||
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Login Successful',
|
||||
text: 'You are being redirected...',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/Profiles/MyProfile';
|
||||
}, 2000);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Login Failed',
|
||||
text: response.data.message || 'Please check your credentials.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'An Error Occurred',
|
||||
text: error.response?.data?.message || 'Please try again.',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
} finally {
|
||||
state.isSubmitting = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
state,
|
||||
handleSubmit
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Vue.createApp(App).mount('#app');
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Logout";
|
||||
}
|
||||
|
||||
<div class="container-fluid" id="app" v-cloak>
|
||||
|
||||
<div class="card-body login-card-body">
|
||||
<p class="login-box-msg">@ViewData["Title"]</p>
|
||||
|
||||
|
||||
|
||||
<div class="social-auth-links text-center mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<form v-on:submit.prevent="handleSubmit">
|
||||
<div class="form-group mb-2 text-center">
|
||||
<p>Are you sure you want to log out?</p>
|
||||
<p>Click the button below to confirm and log out completely.</p>
|
||||
</div>
|
||||
<button type="submit"
|
||||
v-bind:disabled="state.isSubmitting"
|
||||
class="btn btn-primary w-100 mb-2">
|
||||
<span class="spinner-border spinner-border-sm me-2"
|
||||
v-if="state.isSubmitting"
|
||||
role="status"
|
||||
aria-hidden="true"></span>
|
||||
<span>{{ state.isSubmitting ? '...' : 'Log Out' }}</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@section scripts {
|
||||
<script src="~/FrontEnd/Pages/Accounts/Logout.cshtml.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
const App = {
|
||||
setup() {
|
||||
const state = Vue.reactive({
|
||||
isSubmitting: false,
|
||||
});
|
||||
|
||||
const logout = async () => {
|
||||
try {
|
||||
const response = await AxiosManager.post('/Security/Logout', {
|
||||
userId: StorageManager.getUserId()
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
|
||||
try {
|
||||
state.isSubmitting = true;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
const response = await logout();
|
||||
if (response.data.code === 200) {
|
||||
StorageManager.clearStorage();
|
||||
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Logout Successful',
|
||||
text: 'You are being redirected...',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 2000);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Logout Failed',
|
||||
text: response.data.message ?? 'Logout Failed.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'An Error Occurred',
|
||||
text: error.response?.data?.message || 'Please try again.',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
} finally {
|
||||
state.isSubmitting = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
state,
|
||||
handleSubmit
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Vue.createApp(App).mount('#app');
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Register";
|
||||
}
|
||||
<div id="app" class="container-fluid" v-cloak>
|
||||
|
||||
<div class="card-body register-card-body">
|
||||
<p class="login-box-msg">@ViewData["Title"]</p>
|
||||
|
||||
<form v-on:submit.prevent="handleSubmit">
|
||||
<div class="input-group mb-3">
|
||||
<input id="Email"
|
||||
name="Email"
|
||||
type="email"
|
||||
placeholder="Enter Email"
|
||||
class="form-control"
|
||||
v-model="state.email"
|
||||
v-on:input="state.errors.email = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-envelope"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.email" class="text-danger small">{{ state.errors.email }}</label>
|
||||
<div class="input-group mb-3">
|
||||
<input id="CompanyName"
|
||||
name="CompanyName"
|
||||
type="text"
|
||||
placeholder="Enter Company Name"
|
||||
class="form-control"
|
||||
v-model="state.companyName">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-edit"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<input id="FirstName"
|
||||
name="FirstName"
|
||||
type="text"
|
||||
placeholder="Enter First Name"
|
||||
class="form-control"
|
||||
v-model="state.firstName"
|
||||
v-on:input="state.errors.firstName = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-edit"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.firstName" class="text-danger small">{{ state.errors.firstName }}</label>
|
||||
<div class="input-group mb-3">
|
||||
<input id="LastName"
|
||||
name="LastName"
|
||||
type="text"
|
||||
placeholder="Enter Last Name"
|
||||
class="form-control"
|
||||
v-model="state.lastName"
|
||||
v-on:input="state.errors.lastName = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-edit"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.lastName" class="text-danger small">{{ state.errors.lastName }}</label>
|
||||
<div class="input-group mb-3">
|
||||
<input id="Password"
|
||||
name="Password"
|
||||
type="password"
|
||||
placeholder="Enter Password"
|
||||
class="form-control"
|
||||
v-model="state.password"
|
||||
v-on:input="state.errors.password = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.password" class="text-danger small">{{ state.errors.password }}</label>
|
||||
<div class="input-group mb-3">
|
||||
<input id="ConfirmPassword"
|
||||
name="ConfirmPassword"
|
||||
type="password"
|
||||
placeholder="Re-type Password"
|
||||
class="form-control"
|
||||
v-model="state.confirmPassword"
|
||||
v-on:input="state.errors.confirmPassword = ''">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="state.errors.confirmPassword" class="text-danger small">{{ state.errors.confirmPassword }}</label>
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="icheck-primary">
|
||||
<input type="checkbox">
|
||||
<label for="remember">
|
||||
Remember Me
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-4">
|
||||
<button type="submit"
|
||||
v-bind:disabled="state.isSubmitting"
|
||||
class="btn btn-primary btn-block">
|
||||
<span class="spinner-border spinner-border-sm me-2"
|
||||
v-if="state.isSubmitting"
|
||||
role="status"
|
||||
aria-hidden="true"></span>
|
||||
<span>{{ state.isSubmitting ? '...' : 'Register' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="social-auth-links text-center">
|
||||
<p>- OR -</p>
|
||||
<a href="#" class="btn btn-block btn-primary">
|
||||
<i class="fab fa-facebook mr-2"></i>
|
||||
Sign up using Facebook
|
||||
</a>
|
||||
<a href="#" class="btn btn-block btn-danger">
|
||||
<i class="fab fa-google-plus mr-2"></i>
|
||||
Sign up using Google+
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p class="mb-1">
|
||||
<a asp-page="/Accounts/ForgotPassword">I forgot my password</a>
|
||||
</p>
|
||||
<p class="mb-1">
|
||||
<a asp-page="/Accounts/Login" class="text-center">I already have a membership</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@section scripts {
|
||||
<script type="module" src="~/FrontEnd/Pages/Accounts/Register.cshtml.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
const App = {
|
||||
setup() {
|
||||
const state = Vue.reactive({
|
||||
email: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
companyName: '',
|
||||
isSubmitting: false,
|
||||
errors: {
|
||||
email: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
firstName: '',
|
||||
lastName: ''
|
||||
}
|
||||
});
|
||||
|
||||
const validateForm = () => {
|
||||
// Reset errors
|
||||
state.errors.email = '';
|
||||
state.errors.password = '';
|
||||
state.errors.confirmPassword = '';
|
||||
state.errors.firstName = '';
|
||||
state.errors.lastName = '';
|
||||
|
||||
let isValid = true;
|
||||
|
||||
if (!state.email) {
|
||||
state.errors.email = 'Email is required.';
|
||||
isValid = false;
|
||||
} else if (!/\S+@\S+\.\S+/.test(state.email)) {
|
||||
state.errors.email = 'Please enter a valid email address.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!state.password) {
|
||||
state.errors.password = 'Password is required.';
|
||||
isValid = false;
|
||||
} else if (state.password.length < 6) {
|
||||
state.errors.password = 'Password must be at least 6 characters.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!state.confirmPassword) {
|
||||
state.errors.confirmPassword = 'Confirm Password is required.';
|
||||
isValid = false;
|
||||
} else if (state.password !== state.confirmPassword) {
|
||||
state.errors.confirmPassword = 'Passwords do not match.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!state.firstName) {
|
||||
state.errors.firstName = 'First Name is required.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!state.lastName) {
|
||||
state.errors.lastName = 'Last Name is required.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
|
||||
try {
|
||||
state.isSubmitting = true;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
if (!validateForm()) return;
|
||||
|
||||
const response = await AxiosManager.post('/Security/Register', {
|
||||
email: state.email,
|
||||
password: state.password,
|
||||
confirmPassword: state.confirmPassword,
|
||||
firstName: state.firstName,
|
||||
lastName: state.lastName,
|
||||
companyName: state.companyName
|
||||
});
|
||||
|
||||
if (response.data.code === 200) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Register Successful',
|
||||
text: 'Please check your email. You are being redirected...',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 2000);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Register Failed',
|
||||
text: response.data.message || 'Please check your data.',
|
||||
confirmButtonText: 'Try Again'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'An Error Occurred',
|
||||
text: error.response?.data?.message || 'Please try again.',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
} finally {
|
||||
state.isSubmitting = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
state,
|
||||
handleSubmit
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Vue.createApp(App).mount('#app');
|
||||
@@ -0,0 +1,3 @@
|
||||
@{
|
||||
Layout = "~/FrontEnd/Pages/Shared/AdminLTE/_Auth.cshtml";
|
||||
}
|
||||
Reference in New Issue
Block a user