feat: integrate "IsInvalid" filter and dropdown functionality in leave management

This commit is contained in:
2025-10-07 12:51:18 +03:30
parent dbbee73e2a
commit 7b3d1f527c
4 changed files with 171 additions and 64 deletions

View File

@@ -305,6 +305,11 @@ public class LeaveRepository : RepositoryBase<long, Leave>, ILeaveRepository
if (searchModel.LeaveType == "sickLeave")
leaveMainList = leaveMainList.Where(x => x.LeaveType == "استعلاجی");
if (searchModel.IsInvalid)
{
leaveMainList = leaveMainList.IgnoreQueryFilters().Where(x => x.IsInvalid);
}
if (!string.IsNullOrWhiteSpace(searchModel.StartLeave) && !string.IsNullOrWhiteSpace(searchModel.EndLeave))
{
var start = searchModel.StartLeave.ToGeorgianDateTime();
@@ -341,6 +346,7 @@ public class LeaveRepository : RepositoryBase<long, Leave>, ILeaveRepository
Month = item.Month,
MonthStr = item.Month.ToFarsiMonthByIntNumber(),
CreationDate = item.CreationDate,
IsInvalid = item.IsInvalid
}).OrderByDescending(x => x.CreationDate).Skip(searchModel.PageIndex).Take(30).ToList();
return leaveList;

View File

@@ -252,6 +252,8 @@
<input type="hidden" name="leaveType" id="leaveType" asp-for="SearchModel.LeaveType" />
<input type="hidden" name="start" id="start" asp-for="SearchModel.StartLeave" />
<input type="hidden" name="end" id="end" asp-for="SearchModel.EndLeave" />
<input type="hidden" name="isInvalid" id="isInvalid" asp-for="SearchModel.IsInvalid" />
<div class="container-fluid d-none d-lg-block">
<div class="row px-2">
@@ -260,66 +262,80 @@
<div class="col-12">
<div class="d-grid search-section gap-2">
<div class="d-grid grid-cols-3 gap-2 col-span-4">
@{
var gridCols = Model.HasCustomizeCheckout ? "4" : "3";
}
<div class="d-grid grid-cols-@gridCols gap-2 col-span-4">
<div class="wrapper-dropdown-normal btn-dropdown" id="dropdown-normal">
<span class="selected-display" id="destination-normal">هر دو</span>
<svg id="drp-arrow" class="arrow transition-all ml-auto rotate-180" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 14.5l5-5 5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<ul class="dropdown-normal boxes">
<li class="item" value-data-normal="both">هر دو</li>
<li class="item" value-data-normal="paidLeave">استحقاقی</li>
<li class="item" value-data-normal="sickLeave">استعلاجی</li>
</ul>
<input type="hidden" id="sendSorting" asp-for="SearchModel.LeaveType"/>
</div>
<div class="wrapper-dropdown-year btn-dropdown" id="dropdown-year">
<span class="selected-display" id="destination-year">سال</span>
<svg class="arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="transition-all ml-auto rotate-180">
<path d="M7 14.5l5-5 5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<ul class="dropdown-year boxes" id="my-scrollbar">
<li class="item" value-data-year="0">سال</li>
@foreach (string year in @Model.YearlyList)
{
<li class="item" value-data-year="@year">@year</li>
}
</ul>
<input type="hidden" id="sendDropdownYear" asp-for="SearchModel.Year"/>
</div>
<div class="wrapper-dropdown-month btn-dropdown" id="dropdown-month">
<span class="selected-display" id="destination-month">ماه</span>
<svg class="arrow" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="transition-all ml-auto rotate-180">
<path d="M7 14.5l5-5 5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<ul class="dropdown-month boxes">
<li class="item" value-data-month="0">ماه</li>
<li class="item" value-data-month="01">فروردین</li>
<li class="item" value-data-month="02">اردیبهشت</li>
<li class="item" value-data-month="03">خرداد</li>
<li class="item" value-data-month="04">تیر</li>
<li class="item" value-data-month="05">مرداد</li>
<li class="item" value-data-month="06">شهریور</li>
<li class="item" value-data-month="07">مهر</li>
<li class="item" value-data-month="08">آبان</li>
<li class="item" value-data-month="09">آذر</li>
<li class="item" value-data-month="10">دی</li>
<li class="item" value-data-month="11">بهمن</li>
<li class="item" value-data-month="12">اسفند</li>
</ul>
<input type="hidden" id="sendDropdownMonth" asp-for="SearchModel.Month"/>
<span class="selected-display" id="destination-normal">هر دو</span>
<svg id="drp-arrow" class="arrow transition-all ml-auto rotate-180" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 14.5l5-5 5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<ul class="dropdown-normal boxes">
<li class="item" value-data-normal="both">هر دو</li>
<li class="item" value-data-normal="paidLeave">استحقاقی</li>
<li class="item" value-data-normal="sickLeave">استعلاجی</li>
</ul>
<input type="hidden" id="sendSorting" asp-for="SearchModel.LeaveType"/>
</div>
</div>
<div class="wrapper-dropdown-year btn-dropdown" id="dropdown-year">
<span class="selected-display" id="destination-year">سال</span>
<svg class="arrow transition-all ml-auto rotate-180" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 14.5l5-5 5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<ul class="dropdown-year boxes" id="my-scrollbar">
<li class="item" value-data-year="0">سال</li>
@foreach (string year in @Model.YearlyList)
{
<li class="item" value-data-year="@year">@year</li>
}
</ul>
<input type="hidden" id="sendDropdownYear" asp-for="SearchModel.Year"/>
</div>
<div class="wrapper-dropdown-month btn-dropdown" id="dropdown-month">
<span class="selected-display" id="destination-month">ماه</span>
<svg class="arrow transition-all ml-auto rotate-180" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 14.5l5-5 5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<ul class="dropdown-month boxes">
<li class="item" value-data-month="0">ماه</li>
<li class="item" value-data-month="01">فروردین</li>
<li class="item" value-data-month="02">اردیبهشت</li>
<li class="item" value-data-month="03">خرداد</li>
<li class="item" value-data-month="04">تیر</li>
<li class="item" value-data-month="05">مرداد</li>
<li class="item" value-data-month="06">شهریور</li>
<li class="item" value-data-month="07">مهر</li>
<li class="item" value-data-month="08">آبان</li>
<li class="item" value-data-month="09">آذر</li>
<li class="item" value-data-month="10">دی</li>
<li class="item" value-data-month="11">بهمن</li>
<li class="item" value-data-month="12">اسفند</li>
</ul>
<input type="hidden" id="sendDropdownMonth" asp-for="SearchModel.Month"/>
</div>
@if (Model.HasCustomizeCheckout)
{
<div class="wrapper-dropdown-invalid btn-dropdown" id="dropdown-invalid">
<span class="selected-display" id="destination-invalid">دارای اعتبار</span>
<svg class="arrow transition-all ml-auto rotate-180" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 14.5l5-5 5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<ul class="dropdown-invalid boxes">
<li class="item" value-data-invalid="false">دارای اعتبار</li>
<li class="item" value-data-invalid="true">فاقد اعتبار</li>
</ul>
<input type="hidden" id="sendDropdownInvalid" asp-for="SearchModel.IsInvalid"/>
</div>
}
</div>
<div class="col-span-1 md-col-span-2"><input type="text" class="form-control date start-date" asp-for="SearchModel.StartLeave" placeholder="تاریخ شروع"></div>
<div class="col-span-2 md-col-span-2"><input type="text" class="form-control date end-date" asp-for="SearchModel.EndLeave" placeholder="تاریخ پایان"></div>
<select asp-for="SearchModel.IsInvalid" class="form-select wrapper-dropdown-normal">
<option class="item" value="false">دارای اعتبار</option>
<option class="item" value="true">فاقد اعتبار</option>
</select>
<div class="col-span-2 md-col-span-3">
<div class="employeeSelect">
<select class="form-select select2Option" aria-label="انتخاب پرسنل ..." asp-for="SearchModel.EmployeeId" id="employeeSelect">
@@ -890,13 +906,20 @@
</select>
</div>
<div class="mb-2">
<select class="form-select" asp-for="SearchModel.LeaveType">
<option value="both" selected>هر دو</option>
<option value="paidLeave">استحقاقی</option>
<option value="sickLeave">استعلاجی</option>
</select>
</div>
<div class="mb-2">
<select class="form-select" asp-for="SearchModel.LeaveType">
<option value="both" selected>هر دو</option>
<option value="paidLeave">استحقاقی</option>
<option value="sickLeave">استعلاجی</option>
</select>
</div>
<div class="mb-2">
<select class="form-select" asp-for="SearchModel.IsInvalid">
<option value="true">دارای اعتبار</option>
<option value="false">فاقد اعتبار</option>
</select>
</div>
<div>
<span class="form-control text-center persianDateInputStartDate" id="start-date">تاریخ شروع</span>
@@ -1221,6 +1244,12 @@
$('#sendDropdownMonth').val(dataVal);
});
$('.dropdown-invalid .item').on("click", function () {
let dataVal = $(this).attr("value-data-invalid");
$('#sendDropdownInvalid').val(dataVal === 'both' ? '' : dataVal);
$('#isInvalid').val(dataVal === 'both' ? '' : dataVal)
});
var sendDropdownNormal = $("#sendSorting").val();
if (sendDropdownNormal) {
let itemDropdownNormal = $(".dropdown-normal").find(".item[value-data-normal='" + sendDropdownNormal + "']");
@@ -1245,6 +1274,21 @@
selectedMonthDisplay.text(itemDropdownMonth.text());
}
// Initialize invalid dropdown display
var sendDropdownInvalid = $("#sendDropdownInvalid").val();
if (!sendDropdownInvalid) {
let itemInvalidBoth = $(".dropdown-invalid").find(".item[value-data-invalid='both']");
itemInvalidBoth.addClass("active");
var selectedInvalidDisplay = $(".wrapper-dropdown-invalid").find(".selected-display");
selectedInvalidDisplay.text(itemInvalidBoth.text());
} else {
let invalidVal = sendDropdownInvalid.toString().toLowerCase();
let itemInvalid = $(".dropdown-invalid").find(".item[value-data-invalid='" + invalidVal + "']");
itemInvalid.addClass("active");
var selectedInvalidDisplay = $(".wrapper-dropdown-invalid").find(".selected-display");
selectedInvalidDisplay.text(itemInvalid.text());
}
// check if anything else ofther than the dropdown is clicked
window.addEventListener("click", function (e) {
if (e.target.closest(".wrapper-dropdown") === null) {
@@ -2754,7 +2798,8 @@
'searchModel.LeaveType': $('#leaveType').val(),
'searchModel.StartLeave': $('#start').val(),
'searchModel.EndLeave': $('#end').val(),
'searchModel.PageIndex': $('#pageIndex').val()
'searchModel.PageIndex': $('#pageIndex').val(),
'searchModel.IsInvalid': $('#isInvalid').val(),
};

View File

@@ -54,8 +54,9 @@ namespace ServiceHost.Areas.Client.Pages.Company.Employees
private readonly IHolidayItemApplication _holidayItemApplication;
private readonly IRollCallServiceApplication _rollCallServiceApplication;
public int PageIndex;
public bool HasCustomizeCheckout { get; set; }
#region Initial Data
#region Initial Data
public LeaveModel(IWorkshopApplication workshopApplication, IEmployeeApplication employeeApplication, IAuthHelper authHelper, ILeaveApplication leaveApplication, IYearlySalaryApplication yearlySalaryApplication, IPasswordHasher passwordHasher, IHttpContextAccessor contextAccessor, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, ICustomizeWorkshopSettingsApplication customizeWorkshopSettingsApplication, IHolidayItemApplication holidayItemApplication, IRollCallServiceApplication rollCallServiceApplication)
{
_workshopApplication = workshopApplication;
@@ -86,6 +87,8 @@ namespace ServiceHost.Areas.Client.Pages.Company.Employees
{
//long employeeId = _passwordHasher.SlugDecrypt(employeeHash);
long employeeId = searchModel.EmployeeId;
var rollCallServiceViewModel = _rollCallServiceApplication.GetActiveServiceByWorkshopId(_workshopId);
HasCustomizeCheckout = rollCallServiceViewModel is { HasCustomizeCheckoutService: "true" };
if (employeeId >= 0)
{
var workshop = _workshopApplication.GetDetails(_workshopId);
@@ -97,7 +100,8 @@ namespace ServiceHost.Areas.Client.Pages.Company.Employees
Year = searchModel.Year,
Month = searchModel.Month,
StartLeave = searchModel.StartLeave,
EndLeave = searchModel.EndLeave
EndLeave = searchModel.EndLeave,
IsInvalid = searchModel.IsInvalid
};
Year = searchModel.Year;
Month = searchModel.Month;

View File

@@ -215,6 +215,58 @@ $(document).ready(function () {
});
}
/* --------------------------------------------------------------------------------Invalid-------------------------------------------------------------------------------------- */
// dropdown invalid
const selectedAllInvalid = document.querySelectorAll(".wrapper-dropdown-invalid");
selectedAllInvalid.forEach((selected) => {
const optionsContainer = selected.children[2];
const optionsList = selected.querySelectorAll("div.wrapper-dropdown-invalid li");
selected.addEventListener("click", () => {
let arrow = selected.children[1];
let currentActive = document.querySelector(".wrapper-dropdown-invalid.active");
if (currentActive) {
let anotherArrow = currentActive.children[1];
handleDropdown(currentActive, anotherArrow, false);
}
handleDropdown(selected, arrow, true);
});
// update the display of the dropdown invalid
for (let o of optionsList) {
o.addEventListener("click", () => {
selected.querySelector(".selected-display").innerHTML = o.innerHTML;
});
}
$(document).on("click", '.dropdown-invalid .item', function (e) {
$('.dropdown-invalid .item').removeClass("active");
$(this).addClass("active");
closeAllDropdownsInvalid();
});
});
// check if anything else other than the dropdown invalid is clicked
window.addEventListener("click", function (e) {
if (e.target.closest(".wrapper-dropdown-invalid") === null) {
closeAllDropdownsInvalid();
}
});
// close all the dropdowns invalid
function closeAllDropdownsInvalid() {
const selectedInvalid = document.querySelectorAll(".wrapper-dropdown-invalid");
selectedInvalid.forEach((selected) => {
const optionsContainer = selected.children[2];
let arrow = selected.children[1];
handleDropdown(selected, arrow, false);
});
}
// open all the dropdowns
function handleDropdown(dropdown, arrow, open) {