initial commit

This commit is contained in:
2026-07-21 15:03:40 +07:00
commit 5c20bb8a9e
2752 changed files with 864209 additions and 0 deletions
@@ -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>
}
@@ -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";
}