feat: Update week number handling to use WeekDefinitionId and improve UI components
Build and Deploy / build (push) Successful in 2m25s

This commit is contained in:
masoodafar-web
2025-12-20 03:17:04 +03:30
parent d1940033db
commit 869cf7e516
17 changed files with 372 additions and 353 deletions
+41 -69
View File
@@ -111,82 +111,55 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0"/> <PackageReference Include="Blazored.LocalStorage" Version="4.5.0"/>
<PackageReference Include="Foursat.BackOffice.BFF.Category.Protobuf" Version="0.0.5"/>
<PackageReference Include="Foursat.BackOffice.BFF.ClubMembership.Protobuf" Version="0.0.7"/>
<PackageReference Include="Foursat.BackOffice.BFF.Commission.Protobuf" Version="0.0.13"/>
<PackageReference Include="Foursat.BackOffice.BFF.Common.Protobuf" Version="0.0.3"/>
<PackageReference Include="Foursat.BackOffice.BFF.Configuration.Protobuf" Version="1.0.7"/>
<PackageReference Include="Foursat.BackOffice.BFF.DiscountCategory.Protobuf" Version="0.0.3"/>
<PackageReference Include="Foursat.BackOffice.BFF.DiscountOrder.Protobuf" Version="0.0.3"/>
<PackageReference Include="Foursat.BackOffice.BFF.DiscountProduct.Protobuf" Version="0.0.3"/>
<PackageReference Include="Foursat.BackOffice.BFF.DiscountShoppingCart.Protobuf" Version="0.0.3"/>
<PackageReference Include="Foursat.BackOffice.BFF.Health.Protobuf" Version="1.0.5"/>
<PackageReference Include="Foursat.BackOffice.BFF.ManualPayment.Protobuf" Version="0.0.5"/>
<PackageReference Include="Foursat.BackOffice.BFF.NetworkMembership.Protobuf" Version="0.0.11"/>
<PackageReference Include="Foursat.BackOffice.BFF.Otp.Protobuf" Version="0.0.113"/>
<PackageReference Include="FourSat.BackOffice.BFF.Package.Protobuf" Version="0.0.113"/>
<PackageReference Include="Foursat.BackOffice.BFF.Products.Protobuf" Version="0.0.11"/>
<PackageReference Include="Foursat.BackOffice.BFF.ProductTag.Protobuf" Version="0.0.3"/>
<PackageReference Include="Foursat.BackOffice.BFF.PublicMessage.Protobuf" Version="0.0.5"/>
<PackageReference Include="Foursat.BackOffice.BFF.Role.Protobuf" Version="0.0.113"/>
<PackageReference Include="Foursat.BackOffice.BFF.Tag.Protobuf" Version="0.0.4"/>
<PackageReference Include="Foursat.BackOffice.BFF.User.Protobuf" Version="0.0.114"/>
<PackageReference Include="Foursat.BackOffice.BFF.UserAddress.Protobuf" Version="0.0.113"/>
<PackageReference Include="Foursat.BackOffice.BFF.UserOrder.Protobuf" Version="0.0.116"/>
<PackageReference Include="Foursat.BackOffice.BFF.UserRole.Protobuf" Version="0.0.113"/>
<PackageReference Include="Foursat.BackOffice.BFF.Category.Protobuf" Version="0.0.4" /> <!-- Proto Projects - Using ProjectReference for latest changes -->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Category.Protobuf/BackOffice.BFF.Category.Protobuf.csproj" />-->
<PackageReference Include="Foursat.BackOffice.BFF.ClubMembership.Protobuf" Version="0.0.6" />
<PackageReference Include="Foursat.BackOffice.BFF.Commission.Protobuf" Version="0.0.12" />
<PackageReference Include="Foursat.BackOffice.BFF.Common.Protobuf" Version="0.0.2" />
<PackageReference Include="Foursat.BackOffice.BFF.Configuration.Protobuf" Version="1.0.6" />
<PackageReference Include="Foursat.BackOffice.BFF.DiscountCategory.Protobuf" Version="0.0.2" />
<PackageReference Include="Foursat.BackOffice.BFF.DiscountOrder.Protobuf" Version="0.0.2" />
<PackageReference Include="Foursat.BackOffice.BFF.DiscountProduct.Protobuf" Version="0.0.2" />
<PackageReference Include="Foursat.BackOffice.BFF.DiscountShoppingCart.Protobuf" Version="0.0.2" />
<PackageReference Include="Foursat.BackOffice.BFF.Health.Protobuf" Version="1.0.4" />
<PackageReference Include="Foursat.BackOffice.BFF.ManualPayment.Protobuf" Version="0.0.4" />
<PackageReference Include="Foursat.BackOffice.BFF.NetworkMembership.Protobuf" Version="0.0.9" />
<PackageReference Include="Foursat.BackOffice.BFF.Otp.Protobuf" Version="0.0.112" />
<PackageReference Include="FourSat.BackOffice.BFF.Package.Protobuf" Version="0.0.112" />
<PackageReference Include="Foursat.BackOffice.BFF.Products.Protobuf" Version="0.0.9" />
<PackageReference Include="Foursat.BackOffice.BFF.ProductTag.Protobuf" Version="0.0.2" />
<PackageReference Include="Foursat.BackOffice.BFF.PublicMessage.Protobuf" Version="0.0.4" />
<!-- Products: Using ProjectReference for latest proto features (ToggleProductStatus, BulkUpdate, CategoryId filter) -->
<!--<PackageReference Include="Foursat.BackOffice.BFF.Products.Protobuf" Version="0.0.8" />-->
<PackageReference Include="Foursat.BackOffice.BFF.Role.Protobuf" Version="0.0.112" />
<PackageReference Include="Foursat.BackOffice.BFF.Tag.Protobuf" Version="0.0.2" />
<PackageReference Include="Foursat.BackOffice.BFF.User.Protobuf" Version="0.0.113" />
<PackageReference Include="Foursat.BackOffice.BFF.UserRole.Protobuf" Version="0.0.112" />
<PackageReference Include="Foursat.BackOffice.BFF.UserAddress.Protobuf" Version="0.0.112" />
<PackageReference Include="Foursat.BackOffice.BFF.UserOrder.Protobuf" Version="0.0.115" />
<!-- UserOrder: Using ProjectReference for latest proto features (CancelOrder, ApplyDiscount, UpdateOrderStatus) -->
<!--<PackageReference Include="Foursat.BackOffice.BFF.UserOrder.Protobuf" Version="0.0.114" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Products.Protobuf/BackOffice.BFF.Products.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.UserOrder.Protobuf/BackOffice.BFF.UserOrder.Protobuf.csproj" />-->
<!--<PackageReference Include="Foursat.BackOffice.BFF.Commission.Protobuf" Version="0.0.2" />-->
<!--<PackageReference Include="Foursat.BackOffice.BFF.ClubMembership.Protobuf" Version="0.0.1" />-->
<!--<PackageReference Include="Foursat.BackOffice.BFF.NetworkMembership.Protobuf" Version="0.0.1" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Commission.Protobuf/BackOffice.BFF.Commission.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.ClubMembership.Protobuf/BackOffice.BFF.ClubMembership.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.ClubMembership.Protobuf/BackOffice.BFF.ClubMembership.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.NetworkMembership.Protobuf/BackOffice.BFF.NetworkMembership.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Commission.Protobuf/BackOffice.BFF.Commission.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Common.Protobuf/BackOffice.BFF.Common.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Configuration.Protobuf/BackOffice.BFF.Configuration.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Configuration.Protobuf/BackOffice.BFF.Configuration.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Health.Protobuf/BackOffice.BFF.Health.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.PublicMessage.Protobuf/BackOffice.BFF.PublicMessage.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.ManualPayment.Protobuf/BackOffice.BFF.ManualPayment.Protobuf.csproj" />-->
<!-- Proto projects for Discount Shop and Tag features -->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountProduct.Protobuf/BackOffice.BFF.DiscountProduct.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountCategory.Protobuf/BackOffice.BFF.DiscountCategory.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountCategory.Protobuf/BackOffice.BFF.DiscountCategory.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountOrder.Protobuf/BackOffice.BFF.DiscountOrder.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountOrder.Protobuf/BackOffice.BFF.DiscountOrder.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountProduct.Protobuf/BackOffice.BFF.DiscountProduct.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountShoppingCart.Protobuf/BackOffice.BFF.DiscountShoppingCart.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.DiscountShoppingCart.Protobuf/BackOffice.BFF.DiscountShoppingCart.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Tag.Protobuf/BackOffice.BFF.Tag.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Health.Protobuf/BackOffice.BFF.Health.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.ManualPayment.Protobuf/BackOffice.BFF.ManualPayment.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.NetworkMembership.Protobuf/BackOffice.BFF.NetworkMembership.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Otp.Protobuf/BackOffice.BFF.Otp.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Package.Protobuf/BackOffice.BFF.Package.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Products.Protobuf/BackOffice.BFF.Products.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.ProductTag.Protobuf/BackOffice.BFF.ProductTag.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.ProductTag.Protobuf/BackOffice.BFF.ProductTag.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Common.Protobuf/BackOffice.BFF.Common.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.PublicMessage.Protobuf/BackOffice.BFF.PublicMessage.Protobuf.csproj" />-->
<!-- --> <!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Role.Protobuf/BackOffice.BFF.Role.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.Tag.Protobuf/BackOffice.BFF.Tag.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.User.Protobuf/BackOffice.BFF.User.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.UserAddress.Protobuf/BackOffice.BFF.UserAddress.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.UserOrder.Protobuf/BackOffice.BFF.UserOrder.Protobuf.csproj" />-->
<!-- <ProjectReference Include="../../../BackOffice.BFF/src/Protobufs/BackOffice.BFF.UserRole.Protobuf/BackOffice.BFF.UserRole.Protobuf.csproj" />-->
<PackageReference Include="HtmlAgilityPack" Version="1.12.1"/> <PackageReference Include="HtmlAgilityPack" Version="1.12.1"/>
<PackageReference Include="DateTimeConverterCL" Version="1.0.0"/> <PackageReference Include="DateTimeConverterCL" Version="1.0.0"/>
<PackageReference Include="Grpc.Core" Version="2.46.6"/> <PackageReference Include="Grpc.Core" Version="2.46.6"/>
@@ -208,5 +181,4 @@
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -5,7 +5,7 @@
Value="@_selectedWeek" Value="@_selectedWeek"
DebounceInterval="300" DebounceInterval="300"
ValueChanged="@OnSelected" ValueChanged="@OnSelected"
ToStringFunc="@(e => e?.WeekNumber ?? string.Empty)" ToStringFunc="@(e => e?.DisplayName ?? string.Empty)"
SearchFunc="@Search" SearchFunc="@Search"
Variant="Variant.Outlined" Variant="Variant.Outlined"
Clearable="true" Clearable="true"
@@ -11,8 +11,15 @@ public partial class WeekNumberPicker
[Inject] public IPersianDateTimeService PersianDateTime { get; set; } = default!; [Inject] public IPersianDateTimeService PersianDateTime { get; set; } = default!;
[Parameter] public string Label { get; set; } = "انتخاب هفته"; [Parameter] public string Label { get; set; } = "انتخاب هفته";
[Parameter] public string? SelectedWeekNumber { get; set; }
[Parameter] public EventCallback<string?> SelectedWeekNumberChanged { get; set; } // WeekDefinitionId based binding (preferred)
[Parameter] public long? SelectedWeekDefinitionId { get; set; }
[Parameter] public EventCallback<long?> SelectedWeekDefinitionIdChanged { get; set; }
// Legacy string-based binding (deprecated, kept for compatibility)
// [Parameter] public long? SelectedWeekNumber { get; set; }
// [Parameter] public EventCallback<long?> SelectedWeekNumberChanged { get; set; }
[Parameter] public bool CoerceText { get; set; } = true; // اجازه ورود دستی [Parameter] public bool CoerceText { get; set; } = true; // اجازه ورود دستی
[Parameter] public int FutureWeeksCount { get; set; } = 4; [Parameter] public int FutureWeeksCount { get; set; } = 4;
[Parameter] public int PastWeeksCount { get; set; } = 12; [Parameter] public int PastWeeksCount { get; set; } = 12;
@@ -25,20 +32,30 @@ public partial class WeekNumberPicker
{ {
await LoadWeeks(); await LoadWeeks();
if (!string.IsNullOrWhiteSpace(SelectedWeekNumber) && _allWeeks.Any()) if (SelectedWeekDefinitionId.HasValue && SelectedWeekDefinitionId.Value > 0 && _allWeeks.Any())
{ {
_selectedWeek = _allWeeks.FirstOrDefault(w => w.WeekNumber == SelectedWeekNumber); _selectedWeek = _allWeeks.FirstOrDefault(w => w.WeekDefinitionId == SelectedWeekDefinitionId.Value);
} }
// else if (SelectedWeekNumber!=null && SelectedWeekNumber>0 && _allWeeks.Any())
// {
// _selectedWeek = _allWeeks.FirstOrDefault(w => w.WeekDefinitionId == SelectedWeekNumber);
// }
} }
protected override async Task OnParametersSetAsync() protected override async Task OnParametersSetAsync()
{ {
if (!string.IsNullOrWhiteSpace(SelectedWeekNumber) && if (SelectedWeekDefinitionId.HasValue && SelectedWeekDefinitionId.Value > 0 &&
_selectedWeek?.WeekNumber != SelectedWeekNumber && _selectedWeek?.WeekDefinitionId != SelectedWeekDefinitionId.Value &&
_isLoaded) _isLoaded)
{ {
_selectedWeek = _allWeeks.FirstOrDefault(w => w.WeekNumber == SelectedWeekNumber); _selectedWeek = _allWeeks.FirstOrDefault(w => w.WeekDefinitionId == SelectedWeekDefinitionId.Value);
} }
// else if (SelectedWeekNumber!=null && SelectedWeekNumber>0 &&
// _selectedWeek?.WeekDefinitionId != SelectedWeekNumber &&
// _isLoaded)
// {
// _selectedWeek = _allWeeks.FirstOrDefault(w => w.WeekDefinitionId == SelectedWeekNumber);
// }
} }
private async Task LoadWeeks() private async Task LoadWeeks()
@@ -85,23 +102,28 @@ public partial class WeekNumberPicker
if (string.IsNullOrWhiteSpace(value)) if (string.IsNullOrWhiteSpace(value))
return _allWeeks; return _allWeeks;
// جستجو در شماره هفته // جستجو در DisplayName یا DisplayText
return _allWeeks return _allWeeks
.Where(w => w.WeekNumber.Contains(value, StringComparison.OrdinalIgnoreCase)) .Where(w => w.DisplayName.Contains(value, StringComparison.OrdinalIgnoreCase) ||
w.DisplayText.Contains(value, StringComparison.OrdinalIgnoreCase))
.ToList(); .ToList();
} }
private async Task OnSelected(WeekInfo? selected) private async Task OnSelected(WeekInfo? selected)
{ {
_selectedWeek = selected; _selectedWeek = selected;
SelectedWeekNumber = selected?.WeekNumber; SelectedWeekDefinitionId = selected?.WeekDefinitionId;
await SelectedWeekNumberChanged.InvokeAsync(SelectedWeekNumber); // SelectedWeekNumber = selected.WeekDefinitionId;
await SelectedWeekDefinitionIdChanged.InvokeAsync(SelectedWeekDefinitionId);
// await SelectedWeekNumberChanged.InvokeAsync(SelectedWeekNumber);
} }
private async Task OnClear() private async Task OnClear()
{ {
_selectedWeek = null; _selectedWeek = null;
SelectedWeekNumber = null; SelectedWeekDefinitionId = null;
await SelectedWeekNumberChanged.InvokeAsync(null); // SelectedWeekNumber = null;
await SelectedWeekDefinitionIdChanged.InvokeAsync(null);
// await SelectedWeekNumberChanged.InvokeAsync(null);
} }
} }
@@ -33,7 +33,7 @@
</tr> </tr>
<tr> <tr>
<td><strong>شماره هفته:</strong></td> <td><strong>شماره هفته:</strong></td>
<td>@Payout.WeekNumber</td> <td>@Payout.WeekDisplayName</td>
</tr> </tr>
<tr> <tr>
<td><strong>تعداد بالانس:</strong></td> <td><strong>تعداد بالانس:</strong></td>
@@ -21,7 +21,7 @@
<MudCardContent> <MudCardContent>
<MudText Typo="Typo.h6" Color="Color.Primary">استخر هفتگی</MudText> <MudText Typo="Typo.h6" Color="Color.Primary">استخر هفتگی</MudText>
<MudText Typo="Typo.h4">@(_poolData?.TotalPoolAmount.ToString("N0") ?? "0") ریال</MudText> <MudText Typo="Typo.h4">@(_poolData?.TotalPoolAmount.ToString("N0") ?? "0") ریال</MudText>
<MudText Typo="Typo.body2" Color="Color.Secondary">هفته @(_currentWeekNumberPersian)</MudText> <MudText Typo="Typo.body2" Color="Color.Secondary">@_currentWeekDisplayText</MudText>
</MudCardContent> </MudCardContent>
</MudCard> </MudCard>
</MudItem> </MudItem>
@@ -79,8 +79,8 @@
@if (_allWeeks.Any()) @if (_allWeeks.Any())
{ {
<MudSelect T="string" <MudSelect T="long"
Value="_currentWeekNumber" Value="_currentWeekDefinitionId"
Label="شماره هفته" Label="شماره هفته"
Variant="Variant.Outlined" Variant="Variant.Outlined"
Margin="Margin.Dense" Margin="Margin.Dense"
@@ -90,7 +90,7 @@
@if (_availableWeeks?.CurrentWeek != null) @if (_availableWeeks?.CurrentWeek != null)
{ {
<MudSelectItem Value="@_availableWeeks.CurrentWeek.WeekNumber"> <MudSelectItem Value="@_availableWeeks.CurrentWeek.WeekDefinitionId">
<MudText> <MudText>
<MudIcon Icon="@Icons.Material.Filled.Today" Size="Size.Small" Class="ml-2" /> <MudIcon Icon="@Icons.Material.Filled.Today" Size="Size.Small" Class="ml-2" />
@_availableWeeks.CurrentWeek.DisplayText @_availableWeeks.CurrentWeek.DisplayText
@@ -104,7 +104,7 @@
<MudListSubheader>هفته‌های محاسبه شده</MudListSubheader> <MudListSubheader>هفته‌های محاسبه شده</MudListSubheader>
@foreach (var week in _availableWeeks.CalculatedWeeks) @foreach (var week in _availableWeeks.CalculatedWeeks)
{ {
<MudSelectItem Value="@week.WeekNumber"> <MudSelectItem Value="@week.WeekDefinitionId">
<MudText> <MudText>
<MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" Size="Size.Small" Class="ml-2" /> <MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" Size="Size.Small" Class="ml-2" />
@week.DisplayText @week.DisplayText
@@ -125,7 +125,7 @@
<MudListSubheader>هفته‌های محاسبه نشده</MudListSubheader> <MudListSubheader>هفته‌های محاسبه نشده</MudListSubheader>
@foreach (var week in _availableWeeks.PendingWeeks) @foreach (var week in _availableWeeks.PendingWeeks)
{ {
<MudSelectItem Value="@week.WeekNumber"> <MudSelectItem Value="@week.WeekDefinitionId">
<MudText> <MudText>
<MudIcon Icon="@Icons.Material.Filled.AccessTime" Color="Color.Warning" Size="Size.Small" Class="ml-2" /> <MudIcon Icon="@Icons.Material.Filled.AccessTime" Color="Color.Warning" Size="Size.Small" Class="ml-2" />
@week.DisplayText @week.DisplayText
@@ -140,7 +140,7 @@
<MudListSubheader>هفته‌های آینده</MudListSubheader> <MudListSubheader>هفته‌های آینده</MudListSubheader>
@foreach (var week in _availableWeeks.FutureWeeks) @foreach (var week in _availableWeeks.FutureWeeks)
{ {
<MudSelectItem Value="@week.WeekNumber"> <MudSelectItem Value="@week.WeekDefinitionId">
<MudText> <MudText>
<MudIcon Icon="@Icons.Material.Filled.CalendarMonth" Color="Color.Info" Size="Size.Small" Class="ml-2" /> <MudIcon Icon="@Icons.Material.Filled.CalendarMonth" Color="Color.Info" Size="Size.Small" Class="ml-2" />
@week.DisplayText @week.DisplayText
@@ -152,10 +152,7 @@
} }
else else
{ {
<WeekNumberPicker Label="شماره هفته" <MudText Color="Color.Warning">لیست هفته‌ها بارگذاری نشده</MudText>
@bind-SelectedWeekNumber="_currentWeekNumber"
CoerceText="true"
Style="max-width: 250px;" />
} }
<MudButton Variant="Variant.Filled" <MudButton Variant="Variant.Filled"
@@ -180,7 +177,7 @@
</tr> </tr>
<tr> <tr>
<td><strong>شماره هفته:</strong></td> <td><strong>شماره هفته:</strong></td>
<td>@_poolData.WeekNumber</td> <td>@_currentWeekDisplayName</td>
</tr> </tr>
<tr> <tr>
<td><strong>مجموع استخر:</strong></td> <td><strong>مجموع استخر:</strong></td>
@@ -14,12 +14,13 @@ public partial class Dashboard
[Inject] public NavigationManager NavigationManager { get; set; } [Inject] public NavigationManager NavigationManager { get; set; }
[SupplyParameterFromQuery(Name = "week")] [SupplyParameterFromQuery(Name = "weekId")]
public string? WeekQueryParam { get; set; } public long? WeekIdQueryParam { get; set; }
private bool _isLoading = true; private bool _isLoading = true;
private string _currentWeekNumber = string.Empty; private long _currentWeekDefinitionId;
private string _currentWeekNumberPersian = string.Empty; // هفته به شمسی private string _currentWeekDisplayName = string.Empty;
private string _currentWeekDisplayText = string.Empty; // نمایش فارسی
private GetWeeklyCommissionPoolResponse? _poolData; private GetWeeklyCommissionPoolResponse? _poolData;
// Available weeks data // Available weeks data
@@ -32,19 +33,22 @@ public partial class Dashboard
await LoadAvailableWeeks(); await LoadAvailableWeeks();
// اگر query string آمده، از آن استفاده کن // اگر query string آمده، از آن استفاده کن
if (!string.IsNullOrWhiteSpace(WeekQueryParam)) if (WeekIdQueryParam.HasValue && WeekIdQueryParam.Value > 0)
{ {
_currentWeekNumber = WeekQueryParam; _currentWeekDefinitionId = WeekIdQueryParam.Value;
// پیدا کردن نام نمایشی از لیست هفته‌ها
var weekInfo = _allWeeks.FirstOrDefault(w => w.WeekDefinitionId == _currentWeekDefinitionId);
_currentWeekDisplayName = weekInfo?.DisplayName ?? "";
_currentWeekDisplayText = weekInfo?.DisplayText ?? "";
} }
else else if (_availableWeeks?.CurrentWeek != null)
{ {
// محاسبه شماره هفته جاری (میلادی برای API) // استفاده از هفته جاری
_currentWeekNumber = GetCurrentWeekNumber(); _currentWeekDefinitionId = _availableWeeks.CurrentWeek.WeekDefinitionId;
_currentWeekDisplayName = _availableWeeks.CurrentWeek.DisplayName;
_currentWeekDisplayText = _availableWeeks.CurrentWeek.DisplayText;
} }
// تبدیل به شمسی برای نمایش
_currentWeekNumberPersian = PersianDateTime.ConvertWeekNumberToPersian(_currentWeekNumber);
await LoadPoolData(); await LoadPoolData();
} }
@@ -71,18 +75,18 @@ public partial class Dashboard
catch (Exception ex) catch (Exception ex)
{ {
Snackbar.Add($"خطا در بارگذاری لیست هفته‌ها: {ex.Message}", Severity.Warning); Snackbar.Add($"خطا در بارگذاری لیست هفته‌ها: {ex.Message}", Severity.Warning);
// Fallback to current week
_currentWeekNumber = GetCurrentWeekNumber();
} }
} }
private async Task OnWeekChanged(string weekNumber) private async Task OnWeekChanged(long weekDefinitionId)
{ {
_currentWeekNumber = weekNumber; _currentWeekDefinitionId = weekDefinitionId;
_currentWeekNumberPersian = PersianDateTime.ConvertWeekNumberToPersian(weekNumber); var weekInfo = _allWeeks.FirstOrDefault(w => w.WeekDefinitionId == weekDefinitionId);
_currentWeekDisplayName = weekInfo?.DisplayName ?? "";
_currentWeekDisplayText = weekInfo?.DisplayText ?? "";
// به‌روزرسانی URL با query string // به‌روزرسانی URL با query string
var uri = NavigationManager.GetUriWithQueryParameter("week", weekNumber); var uri = NavigationManager.GetUriWithQueryParameter("weekId", weekDefinitionId.ToString());
NavigationManager.NavigateTo(uri, false); NavigationManager.NavigateTo(uri, false);
await LoadPoolData(); await LoadPoolData();
@@ -90,6 +94,12 @@ public partial class Dashboard
private async Task LoadPoolData() private async Task LoadPoolData()
{ {
if (_currentWeekDefinitionId <= 0)
{
Snackbar.Add("هفته انتخاب نشده است", Severity.Warning);
return;
}
try try
{ {
_isLoading = true; _isLoading = true;
@@ -97,12 +107,12 @@ public partial class Dashboard
var request = new GetWeeklyCommissionPoolRequest var request = new GetWeeklyCommissionPoolRequest
{ {
WeekNumber = _currentWeekNumber WeekDefinitionId = _currentWeekDefinitionId
}; };
_poolData = await CommissionContract.GetWeeklyCommissionPoolAsync(request); _poolData = await CommissionContract.GetWeeklyCommissionPoolAsync(request);
Console.WriteLine(JsonSerializer.Serialize(_poolData)); Console.WriteLine(JsonSerializer.Serialize(_poolData));
Snackbar.Add($"اطلاعات Pool هفته {_currentWeekNumber} بارگذاری شد", Severity.Success); Snackbar.Add($"اطلاعات Pool هفته {_currentWeekDisplayName} بارگذاری شد", Severity.Success);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -120,7 +130,7 @@ public partial class Dashboard
{ {
var confirmed = await DialogService.ShowMessageBox( var confirmed = await DialogService.ShowMessageBox(
"تایید", "تایید",
$"آیا از اجرای محاسبه دستی برای هفته {_currentWeekNumber} مطمئن هستید؟", $"آیا از اجرای محاسبه دستی برای هفته {_currentWeekDisplayName} مطمئن هستید؟",
yesText: "بله", cancelText: "خیر"); yesText: "بله", cancelText: "خیر");
if (confirmed == true) if (confirmed == true)
@@ -129,7 +139,7 @@ public partial class Dashboard
{ {
await CommissionContract.TriggerWeeklyCalculationAsync(new TriggerWeeklyCalculationRequest() await CommissionContract.TriggerWeeklyCalculationAsync(new TriggerWeeklyCalculationRequest()
{ {
WeekNumber = _currentWeekNumber, WeekDefinitionId = _currentWeekDefinitionId,
ForceRecalculate = true, ForceRecalculate = true,
SkipBalances = false, SkipBalances = false,
SkipPayouts = false, SkipPayouts = false,
@@ -147,12 +157,4 @@ public partial class Dashboard
} }
} }
} }
private string GetCurrentWeekNumber()
{
var today = DateTime.Now;
var calendar = CultureInfo.CurrentCulture.Calendar;
var weekOfYear = calendar.GetWeekOfYear(today, CalendarWeekRule.FirstDay, DayOfWeek.Saturday);
return $"{today.Year}-W{weekOfYear:D2}";
}
} }
@@ -20,10 +20,8 @@
<MudStack Row="true" Spacing="2"> <MudStack Row="true" Spacing="2">
<UserAutoComplete Label="جستجوی کاربر" <UserAutoComplete Label="جستجوی کاربر"
@bind-SelectedUserId="_filterUserId" /> @bind-SelectedUserId="_filterUserId" />
<WeekNumberPicker Label="شماره هفته" <WeekNumberPicker Label="انتخاب هفته"
@bind-SelectedWeekNumber="_filterWeekNumber" @bind-SelectedWeekDefinitionId="_filterWeekDefinitionId" />
CoerceText="true"
/>
<MudSelect @bind-Value="_filterStatus" <MudSelect @bind-Value="_filterStatus"
Label="وضعیت" Label="وضعیت"
Variant="Variant.Outlined" Variant="Variant.Outlined"
@@ -55,12 +53,9 @@
</CellTemplate> </CellTemplate>
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="x => x.WeekNumber" Title="هفته"> <PropertyColumn Property="x => x.WeekDisplayName" Title="هفته">
<CellTemplate> <CellTemplate>
@{ <MudText Typo="Typo.body2">@context.Item.WeekDisplayName</MudText>
var persianWeek = PersianDateTime.ConvertWeekNumberToPersian(context.Item.WeekNumber);
}
<MudText Typo="Typo.body2">@persianWeek</MudText>
</CellTemplate> </CellTemplate>
</PropertyColumn> </PropertyColumn>
@@ -15,7 +15,7 @@ public partial class UserPayouts
private MudDataGrid<UserCommissionPayoutModel> _gridData; private MudDataGrid<UserCommissionPayoutModel> _gridData;
private long? _filterUserId; private long? _filterUserId;
private string? _filterWeekNumber; private long? _filterWeekDefinitionId;
private int? _filterStatus; private int? _filterStatus;
private async Task<GridData<UserCommissionPayoutModel>> ServerReload(GridState<UserCommissionPayoutModel> state) private async Task<GridData<UserCommissionPayoutModel>> ServerReload(GridState<UserCommissionPayoutModel> state)
@@ -37,9 +37,9 @@ public partial class UserPayouts
request.Filter.UserId = _filterUserId.Value; request.Filter.UserId = _filterUserId.Value;
} }
if (!string.IsNullOrWhiteSpace(_filterWeekNumber)) if (_filterWeekDefinitionId.HasValue && _filterWeekDefinitionId.Value > 0)
{ {
request.Filter.WeekNumber = _filterWeekNumber; request.Filter.WeekDefinitionId = _filterWeekDefinitionId.Value;
} }
if (_filterStatus.HasValue) if (_filterStatus.HasValue)
@@ -60,7 +60,7 @@
Filterable="true" Filterable="true"
SortMode="SortMode.Multiple"> SortMode="SortMode.Multiple">
<Columns> <Columns>
<PropertyColumn Property="x => x.WeekNumber" Title="هفته" /> <PropertyColumn Property="x => x.WeekDisplayName" Title="هفته" />
<PropertyColumn Property="x => x.TotalPoolAmount" Title="مبلغ کل استخر" Format="N0"> <PropertyColumn Property="x => x.TotalPoolAmount" Title="مبلغ کل استخر" Format="N0">
<CellTemplate> <CellTemplate>
<MudText>@context.Item.TotalPoolAmount.ToString("N0") ریال</MudText> <MudText>@context.Item.TotalPoolAmount.ToString("N0") ریال</MudText>
@@ -106,7 +106,7 @@
Variant="Variant.Text" Variant="Variant.Text"
Color="Color.Info" Color="Color.Info"
StartIcon="@Icons.Material.Filled.People" StartIcon="@Icons.Material.Filled.People"
Href="@($"/commission/payouts?week={context.Item.WeekNumber}")"> Href="@($"/commission/payouts?weekDefinitionId={context.Item.WeekDefinitionId}")">
پرداخت‌ها پرداخت‌ها
</MudButton> </MudButton>
</CellTemplate> </CellTemplate>
@@ -197,7 +197,8 @@
_reports = response.Models.Select(x => new WeeklyPoolReportModel _reports = response.Models.Select(x => new WeeklyPoolReportModel
{ {
WeekNumber = x.WeekNumber, WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName = x.WeekDisplayName,
TotalPoolAmount = x.TotalPoolAmount, TotalPoolAmount = x.TotalPoolAmount,
TotalBalances = x.TotalBalances, TotalBalances = x.TotalBalances,
ValuePerBalance = x.ValuePerBalance, ValuePerBalance = x.ValuePerBalance,
@@ -224,7 +225,7 @@
private void ViewDetails(WeeklyPoolReportModel report) private void ViewDetails(WeeklyPoolReportModel report)
{ {
Navigation.NavigateTo($"/commission/dashboard?week={report.WeekNumber}"); Navigation.NavigateTo($"/commission/dashboard?weekId={report.WeekDefinitionId}");
} }
private void CalculateStatistics() private void CalculateStatistics()
@@ -242,7 +243,8 @@
// Model for weekly pool reports // Model for weekly pool reports
private class WeeklyPoolReportModel private class WeeklyPoolReportModel
{ {
public string WeekNumber { get; set; } public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = "";
public long TotalPoolAmount { get; set; } public long TotalPoolAmount { get; set; }
public int TotalBalances { get; set; } public int TotalBalances { get; set; }
public long ValuePerBalance { get; set; } public long ValuePerBalance { get; set; }
@@ -41,7 +41,7 @@
<MudCardContent> <MudCardContent>
<MudStack Spacing="1"> <MudStack Spacing="1">
<MudText Typo="Typo.body2" Color="Color.Secondary">هفته جاری</MudText> <MudText Typo="Typo.body2" Color="Color.Secondary">هفته جاری</MudText>
<MudText Typo="Typo.h5">@_currentWeek</MudText> <MudText Typo="Typo.h5">@_currentWeekDisplayName</MudText>
</MudStack> </MudStack>
</MudCardContent> </MudCardContent>
</MudCard> </MudCard>
@@ -219,7 +219,8 @@
[Inject] public ClubMembershipContract.ClubMembershipContractClient ClubClient { get; set; } [Inject] public ClubMembershipContract.ClubMembershipContractClient ClubClient { get; set; }
private bool _loading = false; private bool _loading = false;
private string _currentWeek = ""; private long _currentWeekDefinitionId = 0;
private string _currentWeekDisplayName = string.Empty;
private GetWeeklyCommissionPoolResponse? _currentPool; private GetWeeklyCommissionPoolResponse? _currentPool;
private long _totalClubMembers = 0; private long _totalClubMembers = 0;
@@ -236,15 +237,31 @@
_loading = true; _loading = true;
try try
{ {
// Get current week in ISO 8601 format // Get current week from available weeks API
_currentWeek = GetCurrentWeekNumber(); try
{
var availableWeeksRequest = new GetAvailableWeeksRequest
{
FutureWeeksCount = 0,
PastWeeksCount = 0
};
var availableWeeksResponse = await CommissionClient.GetAvailableWeeksAsync(availableWeeksRequest);
if (availableWeeksResponse?.CurrentWeek != null)
{
_currentWeekDefinitionId = availableWeeksResponse.CurrentWeek.WeekDefinitionId;
_currentWeekDisplayName = availableWeeksResponse.CurrentWeek.DisplayName;
}
}
catch { /* Ignore - will skip pool loading */ }
// Load Commission data // Load Commission data
if (_currentWeekDefinitionId > 0)
{
try try
{ {
var commissionRequest = new GetWeeklyCommissionPoolRequest var commissionRequest = new GetWeeklyCommissionPoolRequest
{ {
WeekNumber = _currentWeek WeekDefinitionId = _currentWeekDefinitionId
}; };
var commissionResponse = await CommissionClient.GetWeeklyCommissionPoolAsync(commissionRequest); var commissionResponse = await CommissionClient.GetWeeklyCommissionPoolAsync(commissionRequest);
_currentPool = commissionResponse; _currentPool = commissionResponse;
@@ -253,6 +270,7 @@
{ {
Snackbar.Add($"خطا در بارگذاری داده‌های کمیسیون: {ex.Message}", Severity.Warning); Snackbar.Add($"خطا در بارگذاری داده‌های کمیسیون: {ex.Message}", Severity.Warning);
} }
}
// Load Club membership data // Load Club membership data
try try
@@ -23,7 +23,7 @@
</MudItem> </MudItem>
<MudItem xs="12" md="3"> <MudItem xs="12" md="3">
<WeekNumberPicker Label="شماره هفته" <WeekNumberPicker Label="شماره هفته"
@bind-SelectedWeekNumber="_filterWeekNumber" @bind-SelectedWeekDefinitionId="_filterWeekDefinitionId"
CoerceText="true" /> CoerceText="true" />
</MudItem> </MudItem>
<MudItem xs="12" md="2"> <MudItem xs="12" md="2">
@@ -69,7 +69,7 @@
Hover="true"> Hover="true">
<Columns> <Columns>
<PropertyColumn Property="x => x.UserId" Title="شناسه کاربر" /> <PropertyColumn Property="x => x.UserId" Title="شناسه کاربر" />
<PropertyColumn Property="x => x.WeekNumber" Title="هفته" /> <PropertyColumn Property="x => x.WeekDisplayName" Title="هفته" />
<PropertyColumn Property="x => x.LeftBalance" Title="موجودی چپ"> <PropertyColumn Property="x => x.LeftBalance" Title="موجودی چپ">
<CellTemplate> <CellTemplate>
<MudChip T="string" Color="Color.Success" Size="Size.Small"> <MudChip T="string" Color="Color.Success" Size="Size.Small">
@@ -153,7 +153,7 @@
[Inject] public CommissionContract.CommissionContractClient CommissionClient { get; set; } [Inject] public CommissionContract.CommissionContractClient CommissionClient { get; set; }
private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; } private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
private long? _filterUserId = null; private long? _filterUserId = null;
private string _filterWeekNumber = ""; private long? _filterWeekDefinitionId = null;
private int? _minBalance = null; private int? _minBalance = null;
private int? _maxBalance = null; private int? _maxBalance = null;
private bool _onlyActive = false; private bool _onlyActive = false;
@@ -178,9 +178,9 @@ private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
request.UserId = _filterUserId.Value; request.UserId = _filterUserId.Value;
} }
if (!string.IsNullOrWhiteSpace(_filterWeekNumber)) if (_filterWeekDefinitionId.HasValue && _filterWeekDefinitionId.Value > 0)
{ {
request.WeekNumber = _filterWeekNumber; request.WeekDefinitionId = _filterWeekDefinitionId.Value;
} }
var response = await CommissionClient.GetUserWeeklyBalancesAsync(request); var response = await CommissionClient.GetUserWeeklyBalancesAsync(request);
@@ -188,7 +188,7 @@ private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
var items = response.Models.Select(b => new UserWeeklyBalanceModel var items = response.Models.Select(b => new UserWeeklyBalanceModel
{ {
UserId = b.UserId, UserId = b.UserId,
WeekNumber = b.WeekNumber, WeekDisplayName = b.WeekDisplayName,
LeftBalance = b.LeftLegBalances, LeftBalance = b.LeftLegBalances,
RightBalance = b.RightLegBalances, RightBalance = b.RightLegBalances,
MatchedBalance = b.TotalBalances, MatchedBalance = b.TotalBalances,
@@ -247,7 +247,7 @@ private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
private class UserWeeklyBalanceModel private class UserWeeklyBalanceModel
{ {
public long UserId { get; set; } public long UserId { get; set; }
public string WeekNumber { get; set; } public string WeekDisplayName { get; set; }
public int LeftBalance { get; set; } public int LeftBalance { get; set; }
public int RightBalance { get; set; } public int RightBalance { get; set; }
public int MatchedBalance { get; set; } public int MatchedBalance { get; set; }
@@ -34,7 +34,7 @@
<div style="max-width: 200px; min-width: 150px;"> <div style="max-width: 200px; min-width: 150px;">
<WeekNumberPicker Label="هفته فعالسازی" <WeekNumberPicker Label="هفته فعالسازی"
@bind-SelectedWeekNumber="_activationWeekFilter" /> @bind-SelectedWeekDefinitionId="_activationWeekFilter" />
</div> </div>
<MudSpacer /> <MudSpacer />
<MudStack Row="true" Spacing="2"> <MudStack Row="true" Spacing="2">
@@ -118,11 +118,11 @@
</CellTemplate> </CellTemplate>
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="x => x.ActivationWeekNumber" Title="هفته فعالسازی"> <PropertyColumn Property="x => x.ActivationWeekDefinitionId" Title="هفته فعالسازی">
<CellTemplate> <CellTemplate>
@if (!string.IsNullOrEmpty(context.Item.ActivationWeekNumber)) @if (context.Item.ActivationWeekDefinitionId != null)
{ {
<MudText Typo="Typo.body2">@context.Item.ActivationWeekNumber</MudText> <MudText Typo="Typo.body2">@context.Item.ActivationWeekDefinitionId</MudText>
} }
else else
{ {
@@ -180,7 +180,7 @@
private int _rightCount; private int _rightCount;
private DotNetObjectReference<NetworkTreeViewer> _dotNetRef; private DotNetObjectReference<NetworkTreeViewer> _dotNetRef;
private bool? _clubActiveFilter; private bool? _clubActiveFilter;
private string? _activationWeekFilter; private long? _activationWeekFilter;
protected override void OnInitialized() protected override void OnInitialized()
{ {
@@ -213,7 +213,7 @@
UserId = _searchUserId.Value, UserId = _searchUserId.Value,
MaxDepth = 20, MaxDepth = 20,
IsClubActive = _clubActiveFilter.HasValue ? _clubActiveFilter.Value : null, IsClubActive = _clubActiveFilter.HasValue ? _clubActiveFilter.Value : null,
ActivationWeekNumber = !string.IsNullOrEmpty(_activationWeekFilter) ? _activationWeekFilter : null ActivationWeekDefinitionId = _activationWeekFilter!=null ? _activationWeekFilter : null
}; };
_treeData = await NetworkContract.GetNetworkTreeAsync(request); _treeData = await NetworkContract.GetNetworkTreeAsync(request);
@@ -248,7 +248,7 @@
isActive = n.IsClubActive, isActive = n.IsClubActive,
isClubActive = n.IsClubActive, isClubActive = n.IsClubActive,
isActivatedInTargetWeek = n.IsActivatedInTargetWeek, isActivatedInTargetWeek = n.IsActivatedInTargetWeek,
activationWeekNumber = _activationWeekFilter ?? "", // فیلتر UI activationWeekNumber = _activationWeekFilter ?? 0, // فیلتر UI
clubActivatedAt = n.ClubActivatedAt?.ToDateTime().ToLocalTime().ToString("yyyy/MM/dd") ?? "", clubActivatedAt = n.ClubActivatedAt?.ToDateTime().ToLocalTime().ToString("yyyy/MM/dd") ?? "",
userCreated = n.UserCreated?.ToDateTime().ToLocalTime().ToString("yyyy/MM/dd") ?? "" userCreated = n.UserCreated?.ToDateTime().ToLocalTime().ToString("yyyy/MM/dd") ?? ""
}).ToArray(); }).ToArray();
@@ -56,7 +56,14 @@
</MudItem> </MudItem>
</MudStack> </MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.Discount" Disabled="_isLoading" Label="تخفیف (%)" Variant="Variant.Outlined" Margin="Margin.Dense" /> <MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.Discount" Disabled="_isLoading" Label="تخفیف (%)" Variant="Variant.Outlined" Margin="Margin.Dense" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.RemainingCount" Disabled="_isLoading" Label="تعداد موجودی" Variant="Variant.Outlined" Margin="Margin.Dense" />
</MudItem>
</MudStack>
<MudTextField T="string" @bind-Value="Model.ShortInfomation" Disabled="_isLoading" Label="خلاصه" Variant="Variant.Outlined" Margin="Margin.Dense" /> <MudTextField T="string" @bind-Value="Model.ShortInfomation" Disabled="_isLoading" Label="خلاصه" Variant="Variant.Outlined" Margin="Margin.Dense" />
@@ -42,7 +42,14 @@
</MudItem> </MudItem>
</MudStack> </MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.Discount" Disabled="_isLoading" Label="تخفیف (%)" Variant="Variant.Outlined" Margin="Margin.Dense" /> <MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.Discount" Disabled="_isLoading" Label="تخفیف (%)" Variant="Variant.Outlined" Margin="Margin.Dense" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.RemainingCount" Disabled="_isLoading" Label="تعداد موجودی" Variant="Variant.Outlined" Margin="Margin.Dense" />
</MudItem>
</MudStack>
<MudTextField T="string" @bind-Value="Model.ShortInfomation" Disabled="_isLoading" Label="خلاصه" Variant="Variant.Outlined" Margin="Margin.Dense" /> <MudTextField T="string" @bind-Value="Model.ShortInfomation" Disabled="_isLoading" Label="خلاصه" Variant="Variant.Outlined" Margin="Margin.Dense" />
@@ -142,6 +142,23 @@
<PropertyColumn Property="x => x.Price" Title="قیمت" /> <PropertyColumn Property="x => x.Price" Title="قیمت" />
<TemplateColumn Title="موجودی" CellStyle="text-wrap: nowrap;">
<CellTemplate>
@if (context.Item.RemainingCount <= 0)
{
<MudChip T="string" Color="Color.Error" Size="Size.Small">ناموجود</MudChip>
}
else if (context.Item.RemainingCount < 10)
{
<MudChip T="string" Color="Color.Warning" Size="Size.Small">@context.Item.RemainingCount</MudChip>
}
else
{
<MudChip T="string" Color="Color.Success" Size="Size.Small">@context.Item.RemainingCount</MudChip>
}
</CellTemplate>
</TemplateColumn>
<TemplateColumn StickyLeft="true" Title="عملیات" CellStyle="text-wrap: nowrap;" HeaderStyle="text-wrap: nowrap;"> <TemplateColumn StickyLeft="true" Title="عملیات" CellStyle="text-wrap: nowrap;" HeaderStyle="text-wrap: nowrap;">
<CellTemplate> <CellTemplate>
<MudStack Row="true" AlignItems="AlignItems.Center"> <MudStack Row="true" AlignItems="AlignItems.Center">
@@ -2,8 +2,7 @@ using BackOffice.BFF.Products.Protobuf.Protos.Products;
using BackOffice.BFF.Protobuf.Common; using BackOffice.BFF.Protobuf.Common;
using BackOffice.Common.BaseComponents; using BackOffice.Common.BaseComponents;
using BackOffice.Common.Utilities; using BackOffice.Common.Utilities;
// TODO: Uncomment when Tag proto project is created using BackOffice.Pages.Tag.Components;
// using BackOffice.Pages.Tag.Components;
using BackOffice.Pages.Products.Components; using BackOffice.Pages.Products.Components;
using Mapster; using Mapster;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
@@ -163,9 +162,6 @@ public partial class ProductsMainPage
} }
} }
// TODO: Re-enable when CreateProductDialog and UpdateProductDialog are available
// These dialogs need ImageFile/ThumbnailFile fields in proto
/*
public async Task Update(DataModel model) public async Task Update(DataModel model)
{ {
var parameters = new DialogParameters<UpdateDialog> { { x => x.Model, model.Adapt<UpdateProductsRequest>() } }; var parameters = new DialogParameters<UpdateDialog> { { x => x.Model, model.Adapt<UpdateProductsRequest>() } };
@@ -179,12 +175,6 @@ public partial class ProductsMainPage
Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success); Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success);
} }
} }
*/
public async Task Update(DataModel model)
{
Snackbar.Add("ویرایش محصول موقتاً غیرفعال است - در حال توسعه", Severity.Warning);
}
private async Task OnDelete(DataModel model) private async Task OnDelete(DataModel model)
{ {
@@ -208,8 +198,6 @@ public partial class ProductsMainPage
await _gridData.ReloadServerData(); await _gridData.ReloadServerData();
} }
// TODO: Re-enable when CreateProductDialog is available
/*
public async Task CreateNew() public async Task CreateNew()
{ {
var dialog = await DialogService.ShowAsync<CreateDialog>("افزودن محصول", new DialogParameters<CreateDialog> { { x => x.Model, new CreateNewProductsRequest() } }, new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small }); var dialog = await DialogService.ShowAsync<CreateDialog>("افزودن محصول", new DialogParameters<CreateDialog> { { x => x.Model, new CreateNewProductsRequest() } }, new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small });
@@ -220,12 +208,6 @@ public partial class ProductsMainPage
Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success); Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success);
} }
} }
*/
public async Task CreateNew()
{
Snackbar.Add("افزودن محصول موقتاً غیرفعال است - در حال توسعه", Severity.Warning);
}
public async Task OnFilterSubmit() public async Task OnFilterSubmit()
{ {
@@ -245,15 +227,13 @@ public partial class ProductsMainPage
// TODO: Enable when GalleryDialog is working (needs AddProductImageAsync/RemoveProductImageAsync in proto) // TODO: Enable when GalleryDialog is working (needs AddProductImageAsync/RemoveProductImageAsync in proto)
public async Task OpenGallery(DataModel model) public async Task OpenGallery(DataModel model)
{ {
// var parameters = new DialogParameters<GalleryDialog> var parameters = new DialogParameters<GalleryDialog>
// { {
// { x => x.ProductId, model.Id }, { x => x.ProductId, model.Id },
// { x => x.ProductTitle, model.Title } { x => x.ProductTitle, model.Title }
// }; };
// await DialogService.ShowAsync<GalleryDialog>("گالری تصاویر", parameters, await DialogService.ShowAsync<GalleryDialog>("گالری تصاویر", parameters,
// new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Medium }); new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Medium });
Snackbar.Add("گالری تصاویر در حال توسعه است", Severity.Info);
await Task.CompletedTask;
} }
public void OpenCategoryMapping(DataModel model) public void OpenCategoryMapping(DataModel model)
@@ -261,20 +241,16 @@ public partial class ProductsMainPage
Navigation.NavigateTo($"{RouteConstance.ProductCategories}{model.Id}"); Navigation.NavigateTo($"{RouteConstance.ProductCategories}{model.Id}");
} }
// TODO: Enable when Tag proto project is created
public async Task OpenTagAssignment(DataModel model) public async Task OpenTagAssignment(DataModel model)
{ {
// var parameters = new DialogParameters<AssignTagsDialog> var parameters = new DialogParameters<AssignTagsDialog>
// { {
// { x => x.ProductId, model.Id }, { x => x.ProductId, model.Id },
// { x => x.ProductTitle, model.Title } { x => x.ProductTitle, model.Title }
// }; };
// await DialogService.ShowAsync<AssignTagsDialog>("مدیریت تگ‌های محصول", parameters, await DialogService.ShowAsync<AssignTagsDialog>("مدیریت تگ‌های محصول", parameters,
// new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true }); new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true });
await Task.CompletedTask;
Snackbar.Add("قابلیت تگ‌گذاری در حال توسعه است", Severity.Info);
} }
public async Task OpenImagePreview(string imagePath, string title) public async Task OpenImagePreview(string imagePath, string title)
@@ -61,7 +61,8 @@
<MudCardContent> <MudCardContent>
<MudStack Spacing="3"> <MudStack Spacing="3">
<WeekNumberPicker Label="شماره هفته برای اجرای دستی" <WeekNumberPicker Label="شماره هفته برای اجرای دستی"
@bind-SelectedWeekNumber="_manualWeekNumber" @bind-SelectedWeekDefinitionId="_manualWeekDefinitionId"
@* @bind-SelectedWeekNumber="_manualWeekDisplayName" *@
CoerceText="true" /> CoerceText="true" />
<MudButton Variant="Variant.Filled" <MudButton Variant="Variant.Filled"
@@ -144,7 +145,7 @@
</HeaderContent> </HeaderContent>
<RowTemplate> <RowTemplate>
<MudTd DataLabel="زمان">@PersianDateTime.ConvertToPersianDateTime(context.ExecutionTime)</MudTd> <MudTd DataLabel="زمان">@PersianDateTime.ConvertToPersianDateTime(context.ExecutionTime)</MudTd>
<MudTd DataLabel="هفته">@PersianDateTime.ConvertWeekNumberToPersian(context.WeekNumber)</MudTd> <MudTd DataLabel="هفته">@context.WeekDisplayName</MudTd>
<MudTd DataLabel="وضعیت"> <MudTd DataLabel="وضعیت">
<MudChip T="string" <MudChip T="string"
Color="@(context.Status == "موفق" ? Color.Success : Color.Error)" Color="@(context.Status == "موفق" ? Color.Success : Color.Error)"
@@ -184,7 +185,8 @@
private DateTime _nextRunTime = DateTime.Now.AddDays(1); private DateTime _nextRunTime = DateTime.Now.AddDays(1);
private int _successfulRuns = 45; private int _successfulRuns = 45;
private int _failedRuns = 2; private int _failedRuns = 2;
private string _manualWeekNumber = ""; private long? _manualWeekDefinitionId;
private string _manualWeekDisplayName = "";
private bool _isProcessing = false; private bool _isProcessing = false;
private List<ExecutionLogModel> _executionLog = new(); private List<ExecutionLogModel> _executionLog = new();
@@ -210,15 +212,15 @@
private async Task RunManualCalculation() private async Task RunManualCalculation()
{ {
if (string.IsNullOrWhiteSpace(_manualWeekNumber)) if (!_manualWeekDefinitionId.HasValue || _manualWeekDefinitionId.Value <= 0)
{ {
Snackbar.Add("لطفا شماره هفته را وارد کنید", Severity.Warning); Snackbar.Add("لطفا هفته را انتخاب کنید", Severity.Warning);
return; return;
} }
var confirmed = await DialogService.ShowMessageBox( var confirmed = await DialogService.ShowMessageBox(
"اجرای دستی محاسبات", "اجرای دستی محاسبات",
$"آیا از اجرای محاسبات برای هفته {PersianDateTime.ConvertWeekNumberToPersian(_manualWeekNumber)} اطمینان دارید؟", $"آیا از اجرای محاسبات برای هفته {_manualWeekDisplayName} اطمینان دارید؟",
yesText: "بله، اجرا شود", cancelText: "لغو"); yesText: "بله، اجرا شود", cancelText: "لغو");
if (confirmed == true) if (confirmed == true)
@@ -228,13 +230,13 @@
{ {
var request = new Foursat.BackOffice.BFF.Commission.Protos.TriggerWeeklyCalculationRequest var request = new Foursat.BackOffice.BFF.Commission.Protos.TriggerWeeklyCalculationRequest
{ {
WeekNumber = _manualWeekNumber WeekDefinitionId = _manualWeekDefinitionId.Value
}; };
await CommissionClient.TriggerWeeklyCalculationAsync(request); await CommissionClient.TriggerWeeklyCalculationAsync(request);
var persianWeek = PersianDateTime.ConvertWeekNumberToPersian(_manualWeekNumber); Snackbar.Add($"محاسبات هفته {_manualWeekDisplayName} با موفقیت آغاز شد", Severity.Success);
Snackbar.Add($"محاسبات هفته {persianWeek} با موفقیت آغاز شد", Severity.Success); _manualWeekDefinitionId = null;
_manualWeekNumber = ""; _manualWeekDisplayName = "";
await RefreshLog(); await RefreshLog();
} }
catch (Exception ex) catch (Exception ex)
@@ -283,7 +285,8 @@
_executionLog = response.Models.Select(log => new ExecutionLogModel _executionLog = response.Models.Select(log => new ExecutionLogModel
{ {
ExecutionTime = log.StartedAt?.ToDateTime() ?? DateTime.MinValue, ExecutionTime = log.StartedAt?.ToDateTime() ?? DateTime.MinValue,
WeekNumber = log.WeekNumber, WeekDefinitionId = log.WeekDefinitionId,
WeekDisplayName = log.WeekDisplayName,
Status = log.Success ? "موفق" : "ناموفق", Status = log.Success ? "موفق" : "ناموفق",
Duration = $"{log.DurationMs / 1000.0:F1} ثانیه", Duration = $"{log.DurationMs / 1000.0:F1} ثانیه",
ProcessedCount = log.RecordsProcessed, ProcessedCount = log.RecordsProcessed,
@@ -319,7 +322,8 @@
private class ExecutionLogModel private class ExecutionLogModel
{ {
public DateTime ExecutionTime { get; set; } public DateTime ExecutionTime { get; set; }
public string WeekNumber { get; set; } = ""; public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = "";
public string Status { get; set; } = ""; public string Status { get; set; } = "";
public string Duration { get; set; } = ""; public string Duration { get; set; } = "";
public int ProcessedCount { get; set; } public int ProcessedCount { get; set; }