Files
2026-07-21 14:22:06 +07:00

150 lines
7.7 KiB
Plaintext

@using Indotalent.Features.Organization.Employee
@using Indotalent.Features.Organization.Employee.Cqrs
@using Features.Root.Shared
@using MudBlazor
@inject EmployeeService EmployeeService
@inject IDialogService DialogService
@inject ISnackbar Snackbar
<MudPaper Elevation="0" Square="true" Class="pa-6 mb-3 d-flex align-center justify-space-between" Style="border: 1px solid #E5E7EB; border-radius: 12px;">
<div class="d-flex align-center gap-4">
<MudIconButton Icon="@Icons.Material.Filled.ArrowBack" OnClick="() => OnBack.InvokeAsync()" />
<div>
<MudText Typo="Typo.h5" Style="font-weight: 700; color: #111827;">Employee Income Details</MudText>
<MudText Typo="Typo.body2" Style="color: #9CA3AF;">
Manage income components for <b>@EmployeeName</b> @(!string.IsNullOrEmpty(_displayCode) ? $"({_displayCode})" : "")
</MudText>
</div>
</div>
</MudPaper>
<MudPaper Elevation="0" Outlined="true" Style="border-radius: 12px; overflow: hidden; background-color: #ffffff; border: 1px solid #E5E7EB;">
<div style="padding: 20px 24px; border-bottom: 1px solid #E5E7EB; display: flex; justify-content: space-between; align-items: center; background-color: #ffffff;">
<MudText Typo="Typo.subtitle1" Style="font-weight: 700;">List of Incomes</MudText>
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Add"
OnClick="OnAdd"
Size="Size.Small"
Style="text-transform: none; font-weight: 500; border-radius: 6px;">
Add Income
</MudButton>
</div>
@if (_isLoading)
{
<div class="d-flex justify-center pa-10">
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
</div>
}
else if (!_incomes.Any())
{
<div class="pa-10 text-center" style="border: 1px dashed #E5E7EB; margin: 24px;">
<MudText Typo="Typo.body2" Color="Color.Secondary">No income components assigned for this employee.</MudText>
</div>
}
else
{
<MudTable Items="@_incomes" Hover="true" Striped="true" Class="mud-table-styled" Elevation="0" Dense="true">
<HeaderContent>
<MudTh Style="font-weight: 600; color: #6B7280; text-transform: uppercase; font-size: 0.6875rem; letter-spacing: 0.05em; background-color: #F9FAFB; border-bottom: 1px solid #E5E7EB;">Income Component</MudTh>
<MudTh Style="font-weight: 600; color: #6B7280; text-transform: uppercase; font-size: 0.6875rem; letter-spacing: 0.05em; background-color: #F9FAFB; border-bottom: 1px solid #E5E7EB;">Type</MudTh>
<MudTh Style="font-weight: 600; color: #6B7280; text-align: right; text-transform: uppercase; font-size: 0.6875rem; letter-spacing: 0.05em; background-color: #F9FAFB; border-bottom: 1px solid #E5E7EB;">Amount</MudTh>
<MudTh Style="font-weight: 600; color: #6B7280; text-transform: uppercase; font-size: 0.6875rem; letter-spacing: 0.05em; background-color: #F9FAFB; border-bottom: 1px solid #E5E7EB;">Description</MudTh>
<MudTh Style="font-weight: 600; color: #6B7280; text-align: center; text-transform: uppercase; font-size: 0.6875rem; letter-spacing: 0.05em; background-color: #F9FAFB; border-bottom: 1px solid #E5E7EB;">Status</MudTh>
<MudTh Style="font-weight: 600; color: #6B7280; text-align: center; text-transform: uppercase; font-size: 0.6875rem; letter-spacing: 0.05em; background-color: #F9FAFB; border-bottom: 1px solid #E5E7EB;">Actions</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Income">@context.IncomeName</MudTd>
<MudTd DataLabel="Type">
<MudChip T="string" Size="Size.Small" Variant="Variant.Text" Color="@(context.IncomeType == "Fixed" ? Color.Info : Color.Warning)" Style="font-weight: 700;">
@context.IncomeType
</MudChip>
</MudTd>
<MudTd DataLabel="Amount" Style="text-align: right; font-weight: 700;">@context.Amount.ToString("N0")</MudTd>
<MudTd DataLabel="Description">@context.Description</MudTd>
<MudTd DataLabel="Status" Style="text-align: center;">
<MudIcon Icon="@(context.IsActive? Icons.Material.Filled.CheckCircle : Icons.Material.Filled.Cancel)"
Color="@(context.IsActive ? Color.Success : Color.Error)" Size="Size.Small" />
</MudTd>
<MudTd Style="text-align: center;">
<div class="d-flex justify-center gap-1">
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Small" Color="Color.Primary" OnClick="@(() => OnEdit(context))" />
<MudIconButton Icon="@Icons.Material.Filled.Delete" Size="Size.Small" Color="Color.Error" OnClick="@(() => OnDelete(context))" />
</div>
</MudTd>
</RowTemplate>
</MudTable>
}
</MudPaper>
@code {
[Parameter] public string EmployeeId { get; set; } = string.Empty;
[Parameter] public string EmployeeName { get; set; } = string.Empty;
[Parameter] public string EmployeeCode { get; set; } = string.Empty;
[Parameter] public EventCallback OnBack { get; set; }
private List<GetEmployeeIncomeListResponse> _incomes = new();
private bool _isLoading = true;
private string _displayCode = string.Empty;
protected override async Task OnInitializedAsync()
{
_displayCode = EmployeeCode;
await LoadData();
}
private async Task LoadData()
{
_isLoading = true;
StateHasChanged();
var response = await EmployeeService.GetEmployeeIncomeListAsync(EmployeeId);
if (response?.IsSuccess == true)
{
_incomes = response.Value ?? new();
if (_incomes.Any() && string.IsNullOrEmpty(_displayCode))
{
_displayCode = _incomes.First().EmployeeCode ?? string.Empty;
}
}
_isLoading = false;
StateHasChanged();
}
private async Task OnAdd()
{
var parameters = new DialogParameters { ["EmployeeId"] = EmployeeId };
var options = new DialogOptions { CloseButton = true, BackdropClick = false };
var dialog = await DialogService.ShowAsync<_EmployeeIncomeCreateForm>("Add Employee Income", parameters, options);
var result = await dialog.Result;
if (result != null && !result.Canceled) await LoadData();
}
private async Task OnEdit(GetEmployeeIncomeListResponse context)
{
var parameters = new DialogParameters { ["Id"] = context.Id };
var options = new DialogOptions { CloseButton = true, BackdropClick = false };
var dialog = await DialogService.ShowAsync<_EmployeeIncomeUpdateForm>("Edit Employee Income", parameters, options);
var result = await dialog.Result;
if (result != null && !result.Canceled) await LoadData();
}
private async Task OnDelete(GetEmployeeIncomeListResponse context)
{
var dialog = await DialogService.ShowAsync<_DeleteConfirmation>("", new DialogParameters<_DeleteConfirmation> { { x => x.ContentText, $"{context.IncomeName} from {EmployeeName}" } });
var result = await dialog.Result;
if (result != null && !result.Canceled)
{
var success = await EmployeeService.DeleteEmployeeIncomeByIdAsync(context.Id!);
if (success)
{
Snackbar.Add("Income component removed", Severity.Success);
await LoadData();
}
}
}
}