@using Indotalent.ConfigBackEnd.Extensions @using Indotalent.Features.Organization.Employee @using Indotalent.Features.Organization.Employee.Cqrs @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using MudBlazor @using Features.Root.Shared @using ClosedXML.Excel @using System.IO @inject EmployeeService EmployeeService @inject IDialogService DialogService @inject ISnackbar Snackbar @inject IJSRuntime JSRuntime
Employee Directory Manage human resources and organizational structure.
/ Organization / Employee
Search
@if (_isExporting) { Processing... } else { Excel } @if (_isRefreshing) { Refreshing... } else { Refresh } @if (_selectedEmp != null) { Income Deduction View Edit } else { Add Employee }
Code Full Name Grade Salary Designation Department @context.Code
@(!string.IsNullOrWhiteSpace(context.FullName) ? context.FullName.Substring(0, 1) : "?") @context.FullName
@context.GradeName @context.BasicSalary?.ToString("N0") @context.DesignationName @context.DepartmentName
Rows per page: Showing @(GetFilteredData().Count() == 0 ? 0 : _skip + 1)-@Math.Min(_skip + _top, GetFilteredData().Count()) of @GetFilteredData().Count()
Prev @{ var totalPages = _totalPage == 0 ? 1 : _totalPage; var maxVisible = 5; var startPage = Math.Max(1, _currentPage - maxVisible / 2); var endPage = Math.Min(totalPages, startPage + maxVisible - 1); if (endPage - startPage < maxVisible - 1) { startPage = Math.Max(1, endPage - maxVisible + 1); } } @for (int i = startPage; i <= endPage; i++) { var pageNum = i; var isActive = pageNum == _currentPage; @pageNum } Next
@code { [Parameter] public EventCallback OnAdd { get; set; } [Parameter] public EventCallback OnEdit { get; set; } [Parameter] public EventCallback OnView { get; set; } [Parameter] public EventCallback<(string Id, string Name, string Code)> OnIncome { get; set; } [Parameter] public EventCallback<(string Id, string Name, string Code)> OnDeduction { get; set; } private List _employees = new(); private GetEmployeeListResponse? _selectedEmp; private string _searchString = ""; private int _skip = 0; private int _top = 5; private int _totalPage => GetFilteredData().Count() == 0 ? 0 : (int)Math.Ceiling((double)GetFilteredData().Count() / (_top == 0 ? 1 : _top)); private int _currentPage => (_top >= GetFilteredData().Count() || _top == 0) ? 1 : (_skip / _top) + 1; private bool _isRefreshing = false; private bool _isExporting = false; protected override async Task OnInitializedAsync() => await LoadData(); private async Task LoadData() { _isRefreshing = true; _selectedEmp = null; StateHasChanged(); try { var response = await EmployeeService.GetEmployeeListAsync(); await Task.Delay(800); if (response?.IsSuccess == true) { _employees = response.Value ?? new(); } } finally { _isRefreshing = false; StateHasChanged(); } } private IEnumerable GetFilteredData() { if (string.IsNullOrWhiteSpace(_searchString)) return _employees; return _employees.Where(x => (x.FullName?.Contains(_searchString, StringComparison.OrdinalIgnoreCase) ?? false) || (x.Code?.Contains(_searchString, StringComparison.OrdinalIgnoreCase) ?? false) || (x.DesignationName?.Contains(_searchString, StringComparison.OrdinalIgnoreCase) ?? false) || (x.DepartmentName?.Contains(_searchString, StringComparison.OrdinalIgnoreCase) ?? false) || (x.BranchName?.Contains(_searchString, StringComparison.OrdinalIgnoreCase) ?? false) ); } private IEnumerable GetPagedData() => GetFilteredData().Skip(_skip).Take(_top); private async Task ExportToExcel() { _isExporting = true; StateHasChanged(); try { await Task.Delay(1000); using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("Employees"); var currentRow = 1; worksheet.Cell(currentRow, 1).Value = "Code"; worksheet.Cell(currentRow, 2).Value = "Full Name"; worksheet.Cell(currentRow, 3).Value = "Grade"; worksheet.Cell(currentRow, 4).Value = "Basic Salary"; worksheet.Cell(currentRow, 5).Value = "Designation"; worksheet.Cell(currentRow, 6).Value = "Department"; worksheet.Cell(currentRow, 7).Value = "Branch"; var headerRange = worksheet.Range(1, 1, 1, 7); headerRange.Style.Font.Bold = true; headerRange.Style.Fill.BackgroundColor = XLColor.FromHtml("#0D47A1"); headerRange.Style.Font.FontColor = XLColor.White; foreach (var item in GetFilteredData()) { currentRow++; worksheet.Cell(currentRow, 1).Value = item.Code; worksheet.Cell(currentRow, 2).Value = item.FullName; worksheet.Cell(currentRow, 3).Value = item.GradeName; worksheet.Cell(currentRow, 4).Value = item.BasicSalary; worksheet.Cell(currentRow, 5).Value = item.DesignationName; worksheet.Cell(currentRow, 6).Value = item.DepartmentName; worksheet.Cell(currentRow, 7).Value = item.BranchName; worksheet.Cell(currentRow, 4).Style.NumberFormat.Format = "#,##0"; } worksheet.Columns().AdjustToContents(); using (var stream = new MemoryStream()) { workbook.SaveAs(stream); var content = Convert.ToBase64String(stream.ToArray()); await JSRuntime.InvokeVoidAsync("downloadFile", "Employee_Registry.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", content); Snackbar.Add("Excel exported successfully", Severity.Success); } } } catch (Exception ex) { Snackbar.Add($"Export failed: {ex.Message}", Severity.Error); } finally { _isExporting = false; StateHasChanged(); } } private void OnSearchClick() { _skip = 0; _selectedEmp = null; StateHasChanged(); } private void HandleSearchKeyDown(KeyboardEventArgs e) { if (e.Key == "Enter") OnSearchClick(); } private void OnPageChanged(int page) { if (page >= 1 && page <= _totalPage) { _skip = (page - 1) * _top; _selectedEmp = null; StateHasChanged(); } } private void OnPageSizeChanged(int size) { _top = size; _skip = 0; _selectedEmp = null; StateHasChanged(); } private async Task InvokeIncome() { if (_selectedEmp == null) return; await OnIncome.InvokeAsync((_selectedEmp.Id!, _selectedEmp.FullName!, _selectedEmp.Code!)); } private async Task InvokeDeduction() { if (_selectedEmp == null) return; await OnDeduction.InvokeAsync((_selectedEmp.Id!, _selectedEmp.FullName!, _selectedEmp.Code!)); } private async Task InvokeView() { if (_selectedEmp == null) return; var res = await EmployeeService.GetEmployeeByIdAsync(_selectedEmp.Id); if (res?.Value != null) await OnView.InvokeAsync(Map(res.Value)); } private async Task InvokeEdit() { if (_selectedEmp == null) return; var res = await EmployeeService.GetEmployeeByIdAsync(_selectedEmp.Id); if (res?.Value != null) await OnEdit.InvokeAsync(Map(res.Value)); } private UpdateEmployeeRequest Map(GetEmployeeByIdResponse d) => new UpdateEmployeeRequest { Id = d.Id, Code = d.Code, FirstName = d.FirstName, MiddleName = d.MiddleName, LastName = d.LastName, JobDescription = d.JobDescription, GradeId = d.GradeId, BasicSalary = d.BasicSalary, SalaryBankName = d.SalaryBankName, SalaryBankAccountName = d.SalaryBankAccountName, SalaryBankAccountNumber = d.SalaryBankAccountNumber, PlaceOfBirth = d.PlaceOfBirth, DateOfBirth = d.DateOfBirth, Gender = d.Gender, MaritalStatus = d.MaritalStatus, Religion = d.Religion, BloodType = d.BloodType, IdentityNumber = d.IdentityNumber, TaxNumber = d.TaxNumber, LastEducation = d.LastEducation, JoinedDate = d.JoinedDate, ResignedDate = d.ResignedDate, EmployeeStatus = d.EmployeeStatus, EmploymentType = d.EmploymentType, StreetAddress = d.StreetAddress, City = d.City, StateProvince = d.StateProvince, ZipCode = d.ZipCode, Phone = d.Phone, Email = d.Email, BranchId = d.BranchId, DepartmentId = d.DepartmentId, DesignationId = d.DesignationId, SocialMediaLinkedIn = d.SocialMediaLinkedIn, SocialMediaX = d.SocialMediaX, SocialMediaFacebook = d.SocialMediaFacebook, SocialMediaInstagram = d.SocialMediaInstagram, SocialMediaTikTok = d.SocialMediaTikTok, OtherInformation1 = d.OtherInformation1, OtherInformation2 = d.OtherInformation2, OtherInformation3 = d.OtherInformation3, CreatedAt = d.CreatedAt, CreatedBy = d.CreatedBy, UpdatedAt = d.UpdatedAt, UpdatedBy = d.UpdatedBy }; private async Task OnDelete() { if (_selectedEmp == null) return; var diag = await DialogService.ShowAsync<_DeleteConfirmation>("", new DialogParameters<_DeleteConfirmation> { { x => x.ContentText, _selectedEmp.FullName } }); if (!(await diag.Result).Canceled) { if (await EmployeeService.DeleteEmployeeByIdAsync(_selectedEmp.Id)) { await LoadData(); Snackbar.Add("Employee deleted successfully", Severity.Success); } } } }