-
This commit is contained in:
parent
802a81357e
commit
aa316b94ae
@ -15,5 +15,6 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Models
|
|||||||
[ForeignKey("StateId")]
|
[ForeignKey("StateId")]
|
||||||
public virtual StateModel? States { get; set; }
|
public virtual StateModel? States { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastUpdated { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
6
Areas/OTcalculate/Models/OtRegisterModel.cs
Normal file
6
Areas/OTcalculate/Models/OtRegisterModel.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
namespace PSTW_CentralSystem.Areas.OTcalculate.Models
|
||||||
|
{
|
||||||
|
public class OtRegisterModel
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,5 +18,7 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Models
|
|||||||
|
|
||||||
public virtual UserModel? Users { get; set; }
|
public virtual UserModel? Users { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastUpdated { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
Areas/OTcalculate/Models/SettingsModel.cs
Normal file
12
Areas/OTcalculate/Models/SettingsModel.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using PSTW_CentralSystem.Models;
|
||||||
|
|
||||||
|
namespace PSTW_CentralSystem.Areas.OTcalculate.Models
|
||||||
|
{
|
||||||
|
public class SettingsViewModel
|
||||||
|
{
|
||||||
|
public DateTime? LatestRateUpdate { get; set; }
|
||||||
|
public DateTime? LatestCalendarUpdate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -69,6 +69,12 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<label>State:</label>
|
<label>State:</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-check">
|
||||||
|
<input type="checkbox" class="form-check-input" v-model="selectAllChecked">
|
||||||
|
<label class="form-check-label"><strong>Select All</strong></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-md-4" v-for="state in stateList" :key="state.stateId">
|
<div class="col-md-4" v-for="state in stateList" :key="state.stateId">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="form-check-input" :value="state.stateId" v-model="selectedStates">
|
<input type="checkbox" class="form-check-input" :value="state.stateId" v-model="selectedStates">
|
||||||
@ -101,8 +107,12 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5>Holidays for Selected State</h5>
|
<h5>Holidays for Selected State</h5>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item" v-for="holiday in filteredHolidays" :key="holiday.holidayId">
|
<li class="list-group-item d-flex justify-content-between align-items-center"
|
||||||
{{ formatDate(holiday.holidayDate) }} - {{ holiday.holidayName }}
|
v-for="holiday in filteredHolidays" :key="holiday.holidayId">
|
||||||
|
<span>{{ formatDate(holiday.holidayDate) }} - {{ holiday.holidayName }}</span>
|
||||||
|
<button class="btn btn-danger btn-sm" v-on:click="deleteHoliday(holiday.holidayId)">
|
||||||
|
<i class="mdi mdi-delete"></i>
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -113,6 +123,12 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<label>State:</label>
|
<label>State:</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-check">
|
||||||
|
<input type="checkbox" class="form-check-input" v-model="selectAllChecked">
|
||||||
|
<label class="form-check-label"><strong>Select All</strong></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-md-4" v-for="state in stateList" :key="state.stateId">
|
<div class="col-md-4" v-for="state in stateList" :key="state.stateId">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="form-check-input" :value="state.stateId" v-model="selectedStates">
|
<input type="checkbox" class="form-check-input" :value="state.stateId" v-model="selectedStates">
|
||||||
@ -141,7 +157,6 @@
|
|||||||
|
|
||||||
<div v-if="activeTab === 'weekend'" class="card shadow-sm">
|
<div v-if="activeTab === 'weekend'" class="card shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5>Weekend Days per State</h5>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6" v-for="(states, day) in groupedWeekends" :key="day">
|
<div class="col-md-6" v-for="(states, day) in groupedWeekends" :key="day">
|
||||||
<div class="card p-2 mb-2 shadow-sm">
|
<div class="card p-2 mb-2 shadow-sm">
|
||||||
@ -175,7 +190,8 @@
|
|||||||
holidayList: [],
|
holidayList: [],
|
||||||
selectedDay: "",
|
selectedDay: "",
|
||||||
weekendList: [],
|
weekendList: [],
|
||||||
stateWeekends: []
|
stateWeekends: [],
|
||||||
|
selectAllChecked: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -202,6 +218,25 @@
|
|||||||
grouped[weekend.day].push(weekend.stateName);
|
grouped[weekend.day].push(weekend.stateName);
|
||||||
});
|
});
|
||||||
return grouped;
|
return grouped;
|
||||||
|
},
|
||||||
|
filteredHolidays() {
|
||||||
|
return this.selectedState
|
||||||
|
? this.holidayList
|
||||||
|
.filter(h => h.stateId === this.selectedState)
|
||||||
|
.sort((a, b) => new Date(a.holidayDate) - new Date(b.holidayDate))
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
selectAllChecked(ckeckedState) {
|
||||||
|
if (ckeckedState) {
|
||||||
|
this.selectedStates = this.stateList.map(state => state.stateId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedStates(ckeckedState) {
|
||||||
|
this.selectAllChecked = ckeckedState.length === this.stateList.length;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -278,6 +313,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async deleteHoliday(holidayId) {
|
||||||
|
if (!confirm("Are you sure you want to delete this holiday?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/OvertimeAPI/DeleteHoliday/${holidayId}`, {
|
||||||
|
method: "DELETE"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
alert("Holiday deleted successfully!");
|
||||||
|
this.fetchHolidays();
|
||||||
|
} else {
|
||||||
|
alert("Failed to delete holiday.");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting holiday:", error);
|
||||||
|
alert("An error occurred while deleting the holiday.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async fetchWeekends() {
|
async fetchWeekends() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/OvertimeAPI/GetWeekendDay");
|
const response = await fetch("/OvertimeAPI/GetWeekendDay");
|
||||||
@ -289,6 +346,7 @@
|
|||||||
alert("Failed to load weekend list.");
|
alert("Failed to load weekend list.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async fetchStateWeekends() {
|
async fetchStateWeekends() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/OvertimeAPI/GetStateWeekends");
|
const response = await fetch("/OvertimeAPI/GetStateWeekends");
|
||||||
@ -301,7 +359,8 @@
|
|||||||
alert("Failed to load state weekend data.");
|
alert("Failed to load state weekend data.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async updateWeekend() {
|
|
||||||
|
async updateWeekend() {
|
||||||
try {
|
try {
|
||||||
if (this.selectedStates.length === 0 || !this.selectedDay) {
|
if (this.selectedStates.length === 0 || !this.selectedDay) {
|
||||||
alert("Please select at least one state and a day.");
|
alert("Please select at least one state and a day.");
|
||||||
@ -355,7 +414,6 @@
|
|||||||
this.selectedDay = "";
|
this.selectedDay = "";
|
||||||
this.selectedStates = [];
|
this.selectedStates = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -177,7 +177,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Select Rate",
|
"title": "Select Rate",
|
||||||
"data": "id",
|
"data": "id",
|
||||||
|
"className": "text-center",
|
||||||
"render": function (data)
|
"render": function (data)
|
||||||
{
|
{
|
||||||
return `<input type='checkbox' class='rate-checkbox' value='${data}'>`;
|
return `<input type='checkbox' class='rate-checkbox' value='${data}'>`;
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-6 col-md-6 col-lg-3">
|
<div class="col-6 col-md-6 col-lg-3">
|
||||||
@ -36,42 +37,81 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="dateUpdate" class="card m-1">
|
<div id="app" class="card m-1">
|
||||||
<div class="row" v-if="addSection == true">
|
<div class="row">
|
||||||
<form v-on:submit.prevent="updateDate" data-aos="fade-right">
|
<div class="container updateDate justify-content-center align-items-center p-4 shadow">
|
||||||
<div class="container updateDate" data-aos="fade-right">
|
<div class="row">
|
||||||
<div class="row" data-aos="fade-right">
|
<div class="col-md-12">
|
||||||
<div class="col-md-12">
|
<div class="tab-content" id="myTabContent">
|
||||||
<div class="tab-content" id="myTabContent">
|
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
|
||||||
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
|
<div class="card-header" style="background-color: white;">
|
||||||
<div class="card-header" style="background-color: white;">
|
<h3 class="date-heading text-center">LATEST UPDATE DATES</h3>
|
||||||
<h3 class="date-heading text-center">UPDATE DATE</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="row">
|
||||||
<div class="tab-content" id="myTabContent">
|
<div class="col-md-12">
|
||||||
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
|
<div class="tab-content" id="myTabContent">
|
||||||
<div class="card-header" style="background-color: white;">
|
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
|
||||||
<lable class="date-heading text-center">Rate Latest Update:</lable>
|
<div class="card-header text-center" style="background-color: white;">
|
||||||
|
<label class="date-heading text-center">Rate Latest Update: {{ rateUpdateDate || 'N/A' }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="row">
|
||||||
<div class="tab-content" id="myTabContent">
|
<div class="col-md-12">
|
||||||
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
|
<div class="tab-content" id="myTabContent">
|
||||||
<div class="card-header" style="background-color: white;">
|
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
|
||||||
<lable class="date-heading text-center">Calendar Latest Update:</lable>
|
<div class="card-header text-center" style="background-color: white;">
|
||||||
|
<label class="date-heading text-center">Calendar Latest Update: {{ calendarUpdateDate || 'N/A' }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@section Scripts {
|
||||||
|
@{
|
||||||
|
await Html.RenderPartialAsync("_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 {
|
||||||
|
rateUpdateDate: null,
|
||||||
|
calendarUpdateDate: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchUpdateDates();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async fetchUpdateDates() {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/OvertimeAPI/GetUpdateDates", {
|
||||||
|
method: "GET",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
if (!response.ok) throw new Error("Failed to fetch update dates");
|
||||||
|
const data = await response.json();
|
||||||
|
this.rateUpdateDate = data.rateUpdateDate;
|
||||||
|
this.calendarUpdateDate = data.calendarUpdateDate;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).mount("#app");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
}
|
||||||
@ -2,13 +2,21 @@
|
|||||||
ViewData["Title"] = "Register Overtime";
|
ViewData["Title"] = "Register Overtime";
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||||
}
|
}
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
<div id="OTregister" >
|
|
||||||
<div class="row card">
|
<div id="app">
|
||||||
<div class="card-header">
|
<div class="container mt-3">
|
||||||
<p>Name:</p>
|
<div class="card m-1 shadow-sm">
|
||||||
|
<div class="card-body col-md-6">
|
||||||
|
<div class="card p-2 mb-2">
|
||||||
|
<label>Date:</label>
|
||||||
|
<input type="date" class="form-control" v-model="selectedDate">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<h4>OFFICE HOURS</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -32,6 +32,28 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
_centralDbContext = centralDbContext;
|
_centralDbContext = centralDbContext;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
[HttpGet("GetUpdateDates")]
|
||||||
|
public IActionResult GetUpdateDates()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
var latestRateUpdate = _centralDbContext.Rates.OrderByDescending(r => r.LastUpdated).FirstOrDefault()?.LastUpdated;
|
||||||
|
var latestCalendarUpdate = _centralDbContext.Holidays.OrderByDescending(c => c.LastUpdated).FirstOrDefault()?.LastUpdated;
|
||||||
|
|
||||||
|
var updateDates = new
|
||||||
|
{
|
||||||
|
rateUpdateDate = latestRateUpdate.HasValue ? latestRateUpdate.Value.ToString("dd MMMM yyyy") : null,
|
||||||
|
calendarUpdateDate = latestCalendarUpdate.HasValue ? latestCalendarUpdate.Value.ToString("dd MMMM yyyy") : null
|
||||||
|
};
|
||||||
|
|
||||||
|
return Json(updateDates);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Rate
|
#region Rate
|
||||||
[HttpPost("UpdateRates")]
|
[HttpPost("UpdateRates")]
|
||||||
@ -195,6 +217,29 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
var holidays = _centralDbContext.Holidays.ToList();
|
var holidays = _centralDbContext.Holidays.ToList();
|
||||||
return Ok(holidays);
|
return Ok(holidays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpDelete("DeleteHoliday/{id}")]
|
||||||
|
public async Task<IActionResult> DeleteHoliday(int id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var holiday = await _centralDbContext.Holidays.FindAsync(id);
|
||||||
|
if (holiday == null)
|
||||||
|
{
|
||||||
|
return NotFound("Holiday not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_centralDbContext.Holidays.Remove(holiday);
|
||||||
|
await _centralDbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Ok(new { message = "Holiday deleted successfully." });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Weekend
|
#region Weekend
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user