303 lines
18 KiB
Plaintext
303 lines
18 KiB
Plaintext
@using Indotalent.Features.Organization.Employee
|
|
@using Indotalent.Features.Organization.Employee.Cqrs
|
|
@using Indotalent.Shared.Utils
|
|
@using MudBlazor
|
|
@implements IDisposable
|
|
@inject EmployeeService EmployeeService
|
|
@inject ISnackbar Snackbar
|
|
|
|
<style>
|
|
.field-label { font-size: 13px; font-weight: 700; color: #424242; margin-bottom: 4px; display: block; }
|
|
.section-header { font-weight: 800; color: #0D47A1; letter-spacing: 0.5px; margin-bottom: 8px; }
|
|
</style>
|
|
|
|
<MudPaper Elevation="0" Square="true" Class="pa-6 mb-3 d-flex align-center justify-space-between" Style="border: 1px solid #DCEBFA;">
|
|
<div class="d-flex align-center gap-4">
|
|
<MudIconButton Icon="@Icons.Material.Filled.ArrowBack" OnClick="() => OnCancel.InvokeAsync()" />
|
|
<div>
|
|
<MudText Typo="Typo.h5" Style="font-weight: 900; color: #1a1a1a;">Add New Employee</MudText>
|
|
<MudText Typo="Typo.body2" Style="color: #64748b;">Create a comprehensive employee profile and organizational placement.</MudText>
|
|
</div>
|
|
</div>
|
|
</MudPaper>
|
|
|
|
<MudPaper Elevation="0" Outlined="true" Class="pa-8" Style="border-radius: 0px; border: 1px solid #DCEBFA;">
|
|
@if (_isLoadingData)
|
|
{
|
|
<div class="d-flex flex-column align-center pa-10">
|
|
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
|
|
<MudText Class="mt-4">Synchronizing Records...</MudText>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<MudForm @ref="_form" Model="_model">
|
|
<MudStack Spacing="6">
|
|
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12"><div class="section-header">BASIC IDENTITY</div><MudDivider /></MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Employee Code</label>
|
|
<MudTextField @bind-Value="_model.Code" For="@(() => _model.Code)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Salary Grade</label>
|
|
<MudSelect @bind-Value="_model.GradeId"
|
|
For="@(() => _model.GradeId)"
|
|
Validation="@(_validator.ValidateValue())"
|
|
Variant="Variant.Outlined"
|
|
Margin="Margin.Dense"
|
|
Dense="true"
|
|
Placeholder="Select Grade">
|
|
@foreach (var item in _lookupData.Grades)
|
|
{
|
|
<MudSelectItem Value="@item.Id">
|
|
<div class="d-flex justify-space-between w-100 gap-4">
|
|
<MudText Typo="Typo.body2"><b>@item.Name</b> (@item.Code)</MudText>
|
|
<MudText Typo="Typo.caption" Style="color: #64748b;">
|
|
Range: @item.SalaryFrom.ToString("N0") - @item.SalaryTo.ToString("N0")
|
|
</MudText>
|
|
</div>
|
|
</MudSelectItem>
|
|
}
|
|
</MudSelect>
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">First Name</label>
|
|
<MudTextField @bind-Value="_model.FirstName" For="@(() => _model.FirstName)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Middle Name</label>
|
|
<MudTextField @bind-Value="_model.MiddleName" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Last Name</label>
|
|
<MudTextField @bind-Value="_model.LastName" For="@(() => _model.LastName)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
</MudGrid>
|
|
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12" Class="mt-2"><div class="section-header">PAYROLL & BANKING</div><MudDivider /></MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Basic Salary (Monthly)</label>
|
|
<MudNumericField @bind-Value="_model.BasicSalary"
|
|
For="@(() => _model.BasicSalary)"
|
|
HideSpinButtons="false"
|
|
Step="1"
|
|
Min="0"
|
|
Format="N0"
|
|
Adornment="Adornment.Start"
|
|
AdornmentIcon="@Icons.Material.Filled.Payments"
|
|
AdornmentColor="Color.Success"
|
|
Variant="Variant.Outlined"
|
|
Margin="Margin.Dense" />
|
|
|
|
@if (!string.IsNullOrEmpty(_model.GradeId))
|
|
{
|
|
var selectedGrade = _lookupData.Grades.FirstOrDefault(x => x.Id == _model.GradeId);
|
|
if (selectedGrade != null)
|
|
{
|
|
<MudText Typo="Typo.caption" Color="Color.Info" Class="mt-1">
|
|
Allowed range: <b>@selectedGrade.SalaryFrom.ToString("N0")</b> - <b>@selectedGrade.SalaryTo.ToString("N0")</b>
|
|
</MudText>
|
|
}
|
|
}
|
|
</MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Salary Bank Name</label>
|
|
<MudTextField @bind-Value="_model.SalaryBankName" Variant="Variant.Outlined" Margin="Margin.Dense" Placeholder="e.g. BCA" />
|
|
</MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Bank Account Name</label>
|
|
<MudTextField @bind-Value="_model.SalaryBankAccountName" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Bank Account Number</label>
|
|
<MudTextField @bind-Value="_model.SalaryBankAccountNumber" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
</MudGrid>
|
|
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12" Class="mt-2"><div class="section-header">PERSONAL DETAILS</div><MudDivider /></MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Place of Birth</label>
|
|
<MudTextField @bind-Value="_model.PlaceOfBirth" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Date of Birth</label>
|
|
<MudDatePicker @bind-Date="_model.DateOfBirth" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Gender</label>
|
|
<MudSelect @bind-Value="_model.Gender" For="@(() => _model.Gender)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" Dense="true">
|
|
<MudSelectItem Value="@("Male")">Male</MudSelectItem>
|
|
<MudSelectItem Value="@("Female")">Female</MudSelectItem>
|
|
</MudSelect>
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Marital Status</label>
|
|
<MudTextField @bind-Value="_model.MaritalStatus" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Religion</label>
|
|
<MudTextField @bind-Value="_model.Religion" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Identity Number (KTP)</label>
|
|
<MudTextField @bind-Value="_model.IdentityNumber" For="@(() => _model.IdentityNumber)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Tax Number (NPWP)</label>
|
|
<MudTextField @bind-Value="_model.TaxNumber" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Blood Type</label>
|
|
<MudTextField @bind-Value="_model.BloodType" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<label class="field-label">Last Education</label>
|
|
<MudTextField @bind-Value="_model.LastEducation" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
</MudGrid>
|
|
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12" Class="mt-2"><div class="section-header">ORGANIZATIONAL</div><MudDivider /></MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Branch</label>
|
|
<MudSelect @bind-Value="_model.BranchId" For="@(() => _model.BranchId)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" Dense="true">
|
|
@foreach (var item in _lookupData.Branches) { <MudSelectItem Value="@item.Id">@item.Name</MudSelectItem> }
|
|
</MudSelect>
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Department</label>
|
|
<MudSelect @bind-Value="_model.DepartmentId" For="@(() => _model.DepartmentId)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" Dense="true">
|
|
@foreach (var item in _lookupData.Departments) { <MudSelectItem Value="@item.Id">@item.Name</MudSelectItem> }
|
|
</MudSelect>
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Designation</label>
|
|
<MudSelect @bind-Value="_model.DesignationId" For="@(() => _model.DesignationId)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" Dense="true">
|
|
@foreach (var item in _lookupData.Designations) { <MudSelectItem Value="@item.Id">@item.Name</MudSelectItem> }
|
|
</MudSelect>
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Joined Date</label>
|
|
<MudDatePicker @bind-Date="_model.JoinedDate" For="@(() => _model.JoinedDate)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Resigned Date</label>
|
|
<MudDatePicker @bind-Date="_model.ResignedDate" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4">
|
|
<label class="field-label">Employee Status</label>
|
|
<MudTextField @bind-Value="_model.EmployeeStatus" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Employment Type</label>
|
|
<MudTextField @bind-Value="_model.EmploymentType" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<label class="field-label">Job Description</label>
|
|
<MudTextField @bind-Value="_model.JobDescription" Variant="Variant.Outlined" Margin="Margin.Dense" Lines="2" />
|
|
</MudItem>
|
|
</MudGrid>
|
|
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12" Class="mt-2"><div class="section-header">ADDRESS & CONTACT</div><MudDivider /></MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Email</label>
|
|
<MudTextField @bind-Value="_model.Email" For="@(() => _model.Email)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="6">
|
|
<label class="field-label">Phone</label>
|
|
<MudTextField @bind-Value="_model.Phone" For="@(() => _model.Phone)" Validation="@(_validator.ValidateValue())" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<label class="field-label">Street Address</label>
|
|
<MudTextField @bind-Value="_model.StreetAddress" Variant="Variant.Outlined" Margin="Margin.Dense" />
|
|
</MudItem>
|
|
<MudItem xs="4"><label class="field-label">City</label><MudTextField @bind-Value="_model.City" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">Province</label><MudTextField @bind-Value="_model.StateProvince" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">Zip Code</label><MudTextField @bind-Value="_model.ZipCode" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
</MudGrid>
|
|
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12" Class="mt-2"><div class="section-header">SOCIAL MEDIA</div><MudDivider /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">LinkedIn</label><MudTextField @bind-Value="_model.SocialMediaLinkedIn" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">Instagram</label><MudTextField @bind-Value="_model.SocialMediaInstagram" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">TikTok</label><MudTextField @bind-Value="_model.SocialMediaTikTok" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="6"><label class="field-label">Facebook</label><MudTextField @bind-Value="_model.SocialMediaFacebook" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="6"><label class="field-label">X (Twitter)</label><MudTextField @bind-Value="_model.SocialMediaX" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
</MudGrid>
|
|
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12" Class="mt-2"><div class="section-header">OTHERS</div><MudDivider /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">Other Info 1</label><MudTextField @bind-Value="_model.OtherInformation1" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">Other Info 2</label><MudTextField @bind-Value="_model.OtherInformation2" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
<MudItem xs="4"><label class="field-label">Other Info 3</label><MudTextField @bind-Value="_model.OtherInformation3" Variant="Variant.Outlined" Margin="Margin.Dense" /></MudItem>
|
|
</MudGrid>
|
|
|
|
<div class="d-flex justify-end gap-2 mt-10">
|
|
<MudButton OnClick="() => OnCancel.InvokeAsync()" Variant="Variant.Outlined" Style="border: 1px solid #e0e0e0; border-radius: 4px; text-transform: none; font-weight: 700;">Cancel</MudButton>
|
|
<MudButton Color="Color.Primary" Variant="Variant.Filled" OnClick="Submit" Disabled="_processing" Style="border-radius: 4px; text-transform: none; font-weight: 700;">
|
|
@if (_processing)
|
|
{
|
|
<MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText Class="ms-2">Creating...</MudText>
|
|
}
|
|
else
|
|
{
|
|
<MudText>Create Employee</MudText>
|
|
}
|
|
</MudButton>
|
|
</div>
|
|
</MudStack>
|
|
</MudForm>
|
|
}
|
|
</MudPaper>
|
|
|
|
@code {
|
|
[Parameter] public EventCallback OnCancel { get; set; }
|
|
[Parameter] public EventCallback OnSuccess { get; set; }
|
|
|
|
private MudForm? _form;
|
|
private CreateEmployeeRequest _model = new();
|
|
private CreateEmployeeValidator _validator = new();
|
|
private LookupResponse _lookupData = new();
|
|
private bool _processing = false;
|
|
private bool _isLoadingData = true;
|
|
private bool _isDisposed = false;
|
|
|
|
public void Dispose() => _isDisposed = true;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
try {
|
|
_isLoadingData = true;
|
|
var response = await EmployeeService.GetLookupAsync();
|
|
if (response?.IsSuccess == true)
|
|
{
|
|
_lookupData = response.Value ?? new();
|
|
}
|
|
} finally {
|
|
if (!_isDisposed) { _isLoadingData = false; StateHasChanged(); }
|
|
}
|
|
}
|
|
|
|
private async Task Submit()
|
|
{
|
|
await _form!.Validate();
|
|
if (!_form.IsValid) return;
|
|
|
|
_processing = true;
|
|
try {
|
|
var res = await EmployeeService.CreateEmployeeAsync(_model);
|
|
await Task.Delay(500);
|
|
if (res?.IsSuccess == true)
|
|
{
|
|
Snackbar.Add("Employee Created Successfully", Severity.Success);
|
|
await OnSuccess.InvokeAsync();
|
|
}
|
|
} finally { _processing = false; }
|
|
}
|
|
} |