383 lines
18 KiB
Plaintext
383 lines
18 KiB
Plaintext
@{
|
|
ViewBag.Title = "User Settings";
|
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
|
}
|
|
|
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
|
|
|
<div class="container">
|
|
<div class="row justify-content-center">
|
|
<div class="col-6 col-md-6 col-lg-3">
|
|
<div class="card card-hover">
|
|
<a asp-area="OTcalculate" asp-controller="HrDashboard" asp-action="Rate">
|
|
<div class="box bg-success text-center">
|
|
<h1 class="font-light text-white"><i class="mdi mdi-currency-usd"></i></h1>
|
|
<h6 class="text-white">Rate</h6>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-6 col-md-6 col-lg-3">
|
|
<div class="card card-hover">
|
|
<a asp-area="OTcalculate" asp-controller="HrDashboard" asp-action="Calendar">
|
|
<div class="box bg-purple text-center">
|
|
<h1 class="font-light text-white"><i class="mdi mdi-calendar"></i></h1>
|
|
<h6 class="text-white">Calendar</h6>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-6 col-md-6 col-lg-3">
|
|
<div class="card card-hover">
|
|
<a asp-area="OTcalculate" asp-controller="HrDashboard" asp-action="HrUserSetting">
|
|
<div class="box bg-megna text-center">
|
|
<h1 class="font-light text-white"><i class="mdi mdi-account-settings"></i></h1>
|
|
<h6 class="text-white">User Setting</h6>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container mt-4" id="app">
|
|
<ul class="nav nav-tabs">
|
|
<li class="nav-item">
|
|
<a class="nav-link" :class="{ 'bg-purple text-white': activeTab === 'flexi', 'bg-light text-dark': activeTab !== 'flexi' }"
|
|
style="border: 1px solid #ddd;" v-on:click="changeTab('flexi')">
|
|
Flexi Hour Settings
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" :class="{ 'bg-purple text-white': activeTab === 'state', 'bg-light text-dark': activeTab !== 'state' }"
|
|
style="border: 1px solid #ddd;" v-on:click="changeTab('state')">
|
|
Region Update
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="tab-content mt-3">
|
|
<div v-if="activeTab === 'flexi'" class="card shadow-sm">
|
|
<div class="card m-1">
|
|
<form v-on:submit.prevent="updateFlexiHours" data-aos="fade-right">
|
|
<div class="d-flex justify-content-center align-items-center mt-3">
|
|
<div class="card-body d-flex justify-content-center align-items-center gap-3">
|
|
<label for="flexiHour" class="mb-0">Flexi Hour</label>
|
|
<select id="flexiHour" class="form-select" v-model="selectedFlexiHourId" style="max-width: 150px;">
|
|
<option disabled value="">--Select--</option>
|
|
<option v-for="option in flexiHours" :value="option.flexiHourId">{{ option.flexiHour }}</option>
|
|
</select>
|
|
<button type="button" class="btn btn-danger" v-on:click="clearForm">Clear</button>
|
|
<button type="submit" class="btn btn-success">Update Flexi Hour</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<table id="userDatatable" class="table table-bordered table-hover table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Full Name</th>
|
|
<th>Department</th>
|
|
<th>Current Flexi Hour</th>
|
|
<th class="text-center">Select</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-center gap-2 my-3">
|
|
<button type="button" class="btn btn-danger" v-on:click="clearForm">Clear</button>
|
|
<button type="submit" class="btn btn-success">Update Flexi Hour</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="activeTab === 'state'" class="card shadow-sm">
|
|
<div class="card-body d-flex justify-content-center align-items-center gap-3">
|
|
<label class="mb-0">Select State:</label>
|
|
<select class="form-select" v-model="selectedStateAll" style="max-width: 150px;">
|
|
<option disabled value="">--Select--</option>
|
|
<option v-for="state in stateList" :value="state.stateId">{{ state.stateName }}</option>
|
|
</select>
|
|
<button class="btn btn-danger" v-on:click="clearStateSelection">Cancel</button>
|
|
<button class="btn btn-success" v-on:click="saveState">Update State</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<table id="stateUpdateTable" class="table table-bordered table-hover table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Full Name</th>
|
|
<th>Department</th>
|
|
<th>Current State</th>
|
|
<th class="text-center">Select</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
<div class="card-body text-center">
|
|
<button class="btn btn-danger" v-on:click="clearStateSelection">Clear Selection</button>
|
|
<button class="btn btn-success ms-3" v-on:click="saveState">Update User State</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@section Scripts {
|
|
@await Html.PartialAsync("_ValidationScriptsPartial")
|
|
<script src="https://unpkg.com/vue@3.2.37/dist/vue.global.js"></script>
|
|
|
|
|
|
<script>
|
|
window.onload = function () {
|
|
const app = Vue.createApp({
|
|
data() {
|
|
return {
|
|
activeTab: 'flexi',
|
|
flexiHours: [],
|
|
selectedFlexiHourId: '',
|
|
selectedUsers: [],
|
|
userList: [],
|
|
stateList: [],
|
|
selectedStateAll: '',
|
|
selectedUsersState: [],
|
|
stateUserList: [],
|
|
userDatatable: null,
|
|
stateDatatable: null
|
|
};
|
|
},
|
|
mounted() {
|
|
console.log("Vue App Mounted Successfully");
|
|
this.fetchFlexiHours();
|
|
this.fetchStates();
|
|
this.changeTab('flexi'); // Initialize the default tab
|
|
},
|
|
methods: {
|
|
changeTab(tab) {
|
|
this.activeTab = tab;
|
|
if (tab === 'flexi') {
|
|
this.clearForm();
|
|
if (!this.userList.length) {
|
|
this.fetchUsers().then(() => this.initiateTable());
|
|
} else {
|
|
this.initiateTable();
|
|
}
|
|
} else if (tab === 'state') {
|
|
this.clearStateSelection();
|
|
if (!this.stateUserList.length) {
|
|
this.fetchUsersState().then(() => this.initiateStateTable());
|
|
}
|
|
else{
|
|
this.initiateStateTable();
|
|
}
|
|
}
|
|
},
|
|
|
|
async updateUserSettings(apiUrl, selectedUsers, selectedValue, successMessage, clearCallback, fetchCallback, valueKey) {
|
|
if (!selectedUsers.length || !selectedValue) {
|
|
alert("Please select at least one user and a value.");
|
|
return;
|
|
}
|
|
|
|
const payload = selectedUsers.map(userId => ({ UserId: userId, [valueKey]: selectedValue }));
|
|
|
|
try {
|
|
const response = await fetch(apiUrl, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(payload)
|
|
});
|
|
|
|
if (response.ok) {
|
|
alert(successMessage);
|
|
clearCallback(); // Clears form selections
|
|
await fetchCallback(); // Fetches the updated data
|
|
} else {
|
|
const errorData = await response.json();
|
|
alert(errorData.message || "Failed to update. Please try again.");
|
|
}
|
|
} catch (error) {
|
|
console.error("Error updating:", error);
|
|
}
|
|
},
|
|
|
|
|
|
async fetchFlexiHours() {
|
|
try {
|
|
const response = await fetch("/OvertimeAPI/GetFlexiHours");
|
|
this.flexiHours = await response.json();
|
|
console.log("Fetched flexi hours:", this.flexiHours);
|
|
} catch (error) {
|
|
console.error("Error fetching Flexi Hours:", error);
|
|
}
|
|
},
|
|
|
|
async fetchUsers() {
|
|
try {
|
|
const response = await fetch("/OvertimeAPI/GetUserFlexiHours", { method: "GET" });
|
|
if (!response.ok) {
|
|
throw new Error('Failed to fetch users');
|
|
}
|
|
const data = await response.json();
|
|
this.userList = data.filter(e => e.fullName !== "MAAdmin" && e.fullName !== "SysAdmin");
|
|
console.log("Fetched User data", this.userList);
|
|
|
|
// Reinitialize DataTable with updated data
|
|
this.initiateTable();
|
|
|
|
} catch (error) {
|
|
console.error("Error fetching users:", error);
|
|
}
|
|
},
|
|
|
|
|
|
async fetchStates() {
|
|
try {
|
|
const response = await fetch("/OvertimeAPI/GetStatesName");
|
|
this.stateList = await response.json();
|
|
} catch (error) {
|
|
console.error("Error fetching States:", error);
|
|
}
|
|
},
|
|
|
|
async fetchUsersState() {
|
|
try {
|
|
const response = await fetch("/OvertimeAPI/GetUserStates", { method: "GET" });
|
|
const data = await response.json();
|
|
this.stateUserList = data.filter(e => e.fullName !== "MAAdmin" && e.fullName !== "SysAdmin");
|
|
console.log("Fetched state users", this.stateUserList);
|
|
|
|
// Reinitialize the state table to reflect updated data
|
|
this.initiateStateTable();
|
|
|
|
} catch (error) {
|
|
console.error("Error fetching users for State:", error);
|
|
}
|
|
},
|
|
|
|
|
|
initiateTable() {
|
|
if (this.userDatatable) {
|
|
this.userDatatable.destroy();
|
|
this.userDatatable = null;
|
|
}
|
|
const self = this;
|
|
this.$nextTick(() => {
|
|
self.userDatatable = $('#userDatatable').DataTable({
|
|
data: self.userList,
|
|
columns: [
|
|
{ data: "fullName" },
|
|
{ data: "departmentName" },
|
|
{ data: "flexiHour", defaultContent: "N/A" },
|
|
{
|
|
data: "userId",
|
|
className: "text-center",
|
|
render: data => `<input type='checkbox' class='user-checkbox' value='${data}'>`
|
|
}
|
|
],
|
|
destroy: true,
|
|
responsive: true
|
|
});
|
|
|
|
$('#userDatatable tbody').off('change').on('change', '.user-checkbox', (e) => {
|
|
const userId = $(e.target).val();
|
|
if (e.target.checked) {
|
|
self.selectedUsers.push(userId);
|
|
} else {
|
|
self.selectedUsers = self.selectedUsers.filter(id => id !== userId);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
initiateStateTable() {
|
|
if (this.stateDatatable) {
|
|
this.stateDatatable.destroy();
|
|
this.stateDatatable = null;
|
|
}
|
|
const self = this;
|
|
this.$nextTick(() => {
|
|
self.stateDatatable = $('#stateUpdateTable').DataTable({
|
|
data: self.stateUserList,
|
|
columns: [
|
|
{ data: "fullName" },
|
|
{ data: "departmentName" },
|
|
{ data: "state", defaultContent: "N/A" },
|
|
{
|
|
data: "id",
|
|
className: "text-center",
|
|
render: data => `<input type='checkbox' class='state-checkbox' value='${data || ""}'>`
|
|
}
|
|
],
|
|
destroy: true,
|
|
responsive: true
|
|
});
|
|
|
|
$('#stateUpdateTable tbody').off('change').on('change', '.state-checkbox', (e) => {
|
|
const userId = $(e.target).val();
|
|
if (e.target.checked) {
|
|
self.selectedUsersState.push(userId);
|
|
} else {
|
|
self.selectedUsersState = self.selectedUsersState.filter(id => id !== userId);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
clearForm() {
|
|
this.selectedFlexiHourId = '';
|
|
this.selectedUsers = [];
|
|
if (this.userDatatable) {
|
|
this.userDatatable.rows().every(function () {
|
|
$(this.node()).find('input[type="checkbox"]').prop('checked', false);
|
|
});
|
|
}
|
|
},
|
|
|
|
clearStateSelection() {
|
|
this.selectedUsersState = [];
|
|
if (this.stateDatatable) {
|
|
this.stateDatatable.rows().every(function () {
|
|
$(this.node()).find('input[type="checkbox"]').prop('checked', false);
|
|
});
|
|
}
|
|
},
|
|
|
|
async saveState() {
|
|
await this.updateUserSettings(
|
|
"/OvertimeAPI/UpdateUserStates",
|
|
this.selectedUsersState,
|
|
this.selectedStateAll,
|
|
"State updated successfully!",
|
|
this.clearStateSelection,
|
|
this.fetchUsersState, // This will fetch the updated state users after the update
|
|
"StateId"
|
|
);
|
|
|
|
// Fetch the updated state list to ensure the page reflects the new state data
|
|
await this.fetchUsersState(); // This fetch will make sure stateUserList is updated
|
|
this.initiateStateTable(); // Reinitialize the state table with new data
|
|
},
|
|
|
|
|
|
async updateFlexiHours() {
|
|
await this.updateUserSettings(
|
|
"/OvertimeAPI/UpdateUserFlexiHours",
|
|
this.selectedUsers,
|
|
this.selectedFlexiHourId,
|
|
"Flexi Hours updated successfully!",
|
|
this.clearForm,
|
|
this.fetchUsers,
|
|
"FlexiHourId"
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
app.mount('#app');
|
|
};
|
|
</script>
|
|
}
|