feat: add withdrawal requests feature and update VAT loading mechanism
Build and Deploy / build (push) Successful in 1m25s

This commit is contained in:
masoodafar-web
2025-12-20 04:03:11 +03:30
parent 9ee464b8b4
commit 025e8d3c3e
24 changed files with 961 additions and 398 deletions
@@ -0,0 +1,38 @@
@using FrontOffice.Main.Utilities
@using MudBlazor
<MudAutocomplete T="WeekDefinitionDto"
@bind-Value="_selectedWeek"
Label="@Label"
Placeholder="@Placeholder"
SearchFunc="SearchWeeksAsync"
ToStringFunc="@(w => w?.DropdownDisplay ?? string.Empty)"
Variant="@Variant"
Dense="@Dense"
Margin="@Margin"
Clearable="@Clearable"
ShowProgressIndicator="true"
ProgressIndicatorColor="Color.Primary"
AdornmentIcon="@Icons.Material.Filled.CalendarMonth"
AdornmentColor="Color.Primary"
Class="@Class"
Style="@Style">
<ItemTemplate>
<MudStack Spacing="0" Class="py-1">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<MudText Typo="Typo.body1">
@context.DisplayName
@if (context.IsCurrentWeek)
{
<MudChip T="string" Size="Size.Small" Color="Color.Primary" Class="ms-2">هفته جاری</MudChip>
}
</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary">@context.PersianYear</MudText>
</MudStack>
<MudText Typo="Typo.caption" Class="mud-text-secondary">@context.DateRangeDisplay</MudText>
</MudStack>
</ItemTemplate>
<NoItemsTemplate>
<MudText Typo="Typo.body2" Class="pa-3">هفته‌ای یافت نشد</MudText>
</NoItemsTemplate>
</MudAutocomplete>
@@ -0,0 +1,210 @@
using FrontOffice.Main.Utilities;
using Microsoft.AspNetCore.Components;
using MudBlazor;
namespace FrontOffice.Main.Shared;
public partial class WeekSelector : ComponentBase
{
[Inject] private CommissionService CommissionService { get; set; } = default!;
/// <summary>
/// Selected week definition
/// </summary>
[Parameter] public WeekDefinitionDto? Value { get; set; }
/// <summary>
/// Callback when week selection changes
/// </summary>
[Parameter] public EventCallback<WeekDefinitionDto?> ValueChanged { get; set; }
/// <summary>
/// Label for the input
/// </summary>
[Parameter] public string Label { get; set; } = "انتخاب هفته";
/// <summary>
/// Placeholder text
/// </summary>
[Parameter] public string Placeholder { get; set; } = "هفته را انتخاب کنید...";
/// <summary>
/// Input variant
/// </summary>
[Parameter] public Variant Variant { get; set; } = Variant.Outlined;
/// <summary>
/// Dense mode
/// </summary>
[Parameter] public bool Dense { get; set; } = false;
/// <summary>
/// Input margin
/// </summary>
[Parameter] public Margin Margin { get; set; } = Margin.Normal;
/// <summary>
/// Allow clearing the selection
/// </summary>
[Parameter] public bool Clearable { get; set; } = true;
/// <summary>
/// CSS class
/// </summary>
[Parameter] public string? Class { get; set; }
/// <summary>
/// Inline style
/// </summary>
[Parameter] public string? Style { get; set; }
/// <summary>
/// Persian year filter
/// </summary>
[Parameter] public int? PersianYear { get; set; }
/// <summary>
/// Gregorian year filter
/// </summary>
[Parameter] public int? GregorianYear { get; set; }
/// <summary>
/// Only show active weeks
/// </summary>
[Parameter] public bool? OnlyActive { get; set; } = true;
private WeekDefinitionDto? _selectedWeek
{
get => Value;
set
{
if (Value != value)
{
Value = value;
ValueChanged.InvokeAsync(value);
}
}
}
private List<WeekDefinitionDto> _cachedWeeks = new();
private bool _isLoading = false;
protected override async Task OnInitializedAsync()
{
// Pre-load weeks
await LoadWeeksAsync();
}
private async Task LoadWeeksAsync()
{
try
{
_isLoading = true;
_cachedWeeks = await CommissionService.GetWeekDefinitionsAsync(
searchText: null,
gregorianYear: GregorianYear,
persianYear: PersianYear,
isActive: OnlyActive,
pageSize: 100
);
}
catch
{
_cachedWeeks = new List<WeekDefinitionDto>();
}
finally
{
_isLoading = false;
}
}
private async Task<IEnumerable<WeekDefinitionDto>> SearchWeeksAsync(string searchText, CancellationToken cancellationToken)
{
// If cached weeks are empty, load them
if (!_cachedWeeks.Any())
{
await LoadWeeksAsync();
}
// Filter locally from cache
if (string.IsNullOrWhiteSpace(searchText))
return _cachedWeeks;
return _cachedWeeks.Where(w =>
w.DisplayName.Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
w.StartDatePersian.Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
w.EndDatePersian.Contains(searchText, StringComparison.OrdinalIgnoreCase));
}
private async Task OnWeekChanged(WeekDefinitionDto? week)
{
_selectedWeek = week;
}
/// <summary>
/// Get current week from cached weeks
/// </summary>
public WeekDefinitionDto? GetCurrentWeek()
{
return _cachedWeeks.FirstOrDefault(w => w.IsCurrentWeek);
}
/// <summary>
/// Select current week
/// </summary>
public async Task SelectCurrentWeekAsync()
{
var currentWeek = GetCurrentWeek();
if (currentWeek != null)
{
_selectedWeek = currentWeek;
StateHasChanged();
}
await Task.CompletedTask;
}
/// <summary>
/// Find week by WeekOrder number (e.g., 46 from ?week=46)
/// </summary>
public WeekDefinitionDto? FindByWeekOrder(int weekOrder)
{
return _cachedWeeks.FirstOrDefault(w => w.WeekOrder == weekOrder);
}
/// <summary>
/// Find week by Id
/// </summary>
public WeekDefinitionDto? FindById(long id)
{
return _cachedWeeks.FirstOrDefault(w => w.Id == id);
}
/// <summary>
/// Select week by WeekOrder
/// </summary>
public async Task SelectByWeekOrderAsync(int weekOrder)
{
var week = FindByWeekOrder(weekOrder);
if (week != null)
{
_selectedWeek = week;
StateHasChanged();
}
await Task.CompletedTask;
}
/// <summary>
/// Ensure weeks are loaded (useful for parent components)
/// </summary>
public async Task EnsureLoadedAsync()
{
if (!_cachedWeeks.Any())
{
await LoadWeeksAsync();
}
}
/// <summary>
/// Get all cached weeks
/// </summary>
public IReadOnlyList<WeekDefinitionDto> GetCachedWeeks() => _cachedWeeks.AsReadOnly();
}