Compare commits

...

5 Commits

Author SHA1 Message Date
masoodafar-web e0203541bf feat(F2+T4.13): ChangeNetworkParent dialog + PackageFeature checkbox matrix
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 2m32s
F2: ChangeNetworkParent UI
- Add ChangeParentDialog with parent ID, leg, reason fields
- Add 'تغییر والد' button to UserNetworkInfo operations

T4.13: PackageFeature checkbox matrix
- Update NuGet to v0.0.188
- Add ClubFeature checkbox list to CreateDialog and UpdateDialog
- Load features via ConfigClient.GetClubFeaturesAsync
- Sync selected FeatureIds to proto request on save
2026-02-26 22:00:20 +03:30
masoodafar-web 8be98ae33e feat(commission): add per-package filtering to commission pages
- New PackageSelect component: reusable dropdown for package filtering
- UserPayouts: add package filter + package column with MudChip
- BalancesReport: add package filter + package column with MudChip
- Update NuGet Foursat.CMSMicroservice.Protobuf to v0.0.187
2026-02-26 21:08:16 +03:30
masoodafar-web c96377a674 Phase 8d: NuGet bump 0.0.185 → 0.0.186 (proto cleanup) 2026-02-26 18:00:47 +03:30
masoodafar-web 89f5241680 Phase 8b: Expand Package CRUD with all package-based fields
- CreateDialog: Add 12 new fields (SortOrder, ActivationFee, DiscountMultiplier,
  MagicWalletMultiplier, MagicWalletMaxDeposit, MagicWalletMaxCredit,
  MaxBalancesPerLeg, MaxNetworkLevel, IsActive, IsBasePackage,
  SupportsDirectPurchase, SupportsDayaPurchase)
- UpdateDialog: Same 12 new fields added
- PackageMainPage grid: Add Price, SortOrder, IsActive, IsBasePackage columns
- Dialog size: Small → Medium for expanded forms
- CreateNew defaults: IsActive=true, DiscountMultiplier=2.0, etc.
- Fix HasPurchasedGoldenPackage → HasPurchasedPackage in UserNetworkInfo
- NuGet: 0.0.184 → 0.0.185 + local feed source
2026-02-26 17:44:53 +03:30
masoodafar-web f1b0085181 Cleanup: Rename 'پکیج طلایی' → 'خرید پکیج' in UserNetworkInfo 2026-02-26 02:03:26 +03:30
16 changed files with 493 additions and 29 deletions
+1 -1
View File
@@ -138,7 +138,7 @@
<!-- CMS Protobuf NuGet package (used for both local dev and Docker builds) -->
<ItemGroup>
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.184" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.188" />
</ItemGroup>
<!-- ============================================================ -->
+2
View File
@@ -2,6 +2,8 @@
<configuration>
<packageSources>
<clear />
<!-- Local packages (dev builds) -->
<add key="Local" value="/home/masoud/Apps/project/FourSat/nupkg" />
<!-- Nexus (hosts FourSat packages + proxies nuget.org) -->
<add key="Nexus" value="http://194.5.195.53:32081/repository/nuget-all/index.json" allowInsecureConnections="true" />
</packageSources>
@@ -0,0 +1,16 @@
@using CMSMicroservice.Protobuf.Protos.Package
<MudSelect T="long?"
Label="@Label"
Value="@SelectedPackageId"
ValueChanged="OnValueChanged"
Variant="Variant.Outlined"
Margin="Margin.Dense"
Clearable="true"
Style="min-width: 160px;">
<MudSelectItem T="long?" Value="@((long?)null)">همه پکیج‌ها</MudSelectItem>
@foreach (var pkg in _packages)
{
<MudSelectItem T="long?" Value="@((long?)pkg.Id)">@pkg.Title</MudSelectItem>
}
</MudSelect>
@@ -0,0 +1,46 @@
using CMSMicroservice.Protobuf.Protos.Package;
using Microsoft.AspNetCore.Components;
namespace BackOffice.Pages.AutoComplete;
public partial class PackageSelect
{
[Inject] public PackageContract.PackageContractClient PackageClient { get; set; }
[Parameter] public string Label { get; set; } = "پکیج";
[Parameter] public long? SelectedPackageId { get; set; }
[Parameter] public EventCallback<long?> SelectedPackageIdChanged { get; set; }
private List<GetAllPackageByFilterResponseModel> _packages = new();
protected override async Task OnInitializedAsync()
{
await LoadPackages();
}
private async Task LoadPackages()
{
try
{
var request = new GetAllPackageByFilterRequest
{
PaginationState = new() { PageNumber = 1, PageSize = 100 },
Filter = new()
};
var result = await PackageClient.GetAllPackageByFilterAsync(request);
_packages = result.Models?.OrderBy(p => p.SortOrder).ToList()
?? new List<GetAllPackageByFilterResponseModel>();
}
catch
{
_packages = new List<GetAllPackageByFilterResponseModel>();
}
}
private async Task OnValueChanged(long? value)
{
SelectedPackageId = value;
await SelectedPackageIdChanged.InvokeAsync(value);
}
}
@@ -36,6 +36,8 @@
<MudSelectItem T="int?" Value="@((int?)4)">شکست خورده</MudSelectItem>
<MudSelectItem T="int?" Value="@((int?)5)">لغو شده</MudSelectItem>
</MudSelect>
<PackageSelect Label="پکیج"
@bind-SelectedPackageId="_filterPackageId" />
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
OnClick="ApplyFilter"
@@ -64,6 +66,14 @@
</CellTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.PackageTitle" Title="پکیج">
<CellTemplate>
<MudChip T="string" Color="Color.Tertiary" Size="Size.Small">
@(string.IsNullOrEmpty(context.Item.PackageTitle) ? "-" : context.Item.PackageTitle)
</MudChip>
</CellTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.BalancesEarned" Title="بالانس‌ها">
<CellTemplate>
<MudChip T="string" Color="Color.Info" Size="Size.Small">
@@ -17,6 +17,7 @@ public partial class UserPayouts
private long? _filterUserId;
private long? _filterWeekDefinitionId;
private int? _filterStatus;
private long? _filterPackageId;
private async Task<GridData<UserCommissionPayoutModel>> ServerReload(GridState<UserCommissionPayoutModel> state)
{
@@ -44,6 +45,11 @@ public partial class UserPayouts
request.Status = _filterStatus.Value;
}
if (_filterPackageId.HasValue && _filterPackageId.Value > 0)
{
request.PackageId = _filterPackageId.Value;
}
var result = await CommissionContract.GetUserCommissionPayoutsAsync(request);
if (result?.Models != null && result.Models.Any())
@@ -33,10 +33,8 @@
Min="0" />
</MudItem>
<MudItem xs="12" md="2">
<MudNumericField @bind-Value="_maxBalance"
Label="حداکثر موجودی"
Variant="Variant.Outlined"
Min="0" />
<PackageSelect Label="پکیج"
@bind-SelectedPackageId="_filterPackageId" />
</MudItem>
<MudItem xs="12" md="2" Class="d-flex align-center">
<MudButton Variant="Variant.Filled"
@@ -72,6 +70,14 @@
<PropertyColumn Property="x => x.UserFullName" Title="نام کاربر" />
<PropertyColumn Property="x => x.WeekDisplayName" Title="هفته" />
<PropertyColumn Property="x => x.PackageTitle" Title="پکیج">
<CellTemplate>
<MudChip T="string" Color="Color.Tertiary" Size="Size.Small">
@(string.IsNullOrEmpty(context.Item.PackageTitle) ? "-" : context.Item.PackageTitle)
</MudChip>
</CellTemplate>
</PropertyColumn>
<TemplateColumn Title="چپ (جدید + قبلی = مجموع)">
<CellTemplate>
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
@@ -193,6 +199,7 @@
private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
private long? _filterUserId = null;
private long? _filterWeekDefinitionId = null;
private long? _filterPackageId = null;
private int? _minBalance = null;
private int? _maxBalance = null;
private bool _onlyActive = false;
@@ -222,6 +229,11 @@ private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
request.WeekDefinitionId = _filterWeekDefinitionId.Value;
}
if (_filterPackageId.HasValue && _filterPackageId.Value > 0)
{
request.PackageId = _filterPackageId.Value;
}
var response = await CommissionClient.GetUserWeeklyBalancesAsync(request);
var items = response.Models.Select(b => new UserWeeklyBalanceModel
@@ -238,7 +250,8 @@ private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
MatchedBalance = b.TotalBalances,
PoolContribution = b.WeeklyPoolContribution,
CalculatedAt = b.CalculatedAt?.ToDateTime(),
IsExpired = b.IsExpired
IsExpired = b.IsExpired,
PackageTitle = b.PackageTitle
}).ToList();
// Apply balance range filter if specified
@@ -308,5 +321,6 @@ private MudDataGrid <UserWeeklyBalanceModel> _grid { get; set; }
public long PoolContribution { get; set; }
public DateTime? CalculatedAt { get; set; }
public bool IsExpired { get; set; }
public string PackageTitle { get; set; } = string.Empty;
}
}
@@ -0,0 +1,78 @@
@using CMSMicroservice.Protobuf.Protos.NetworkMembership
<MudDialog>
<TitleContent>
<MudText Typo="Typo.h6">
<MudIcon Icon="@Icons.Material.Filled.SwapHoriz" Class="ml-1" />
تغییر والد در شبکه
</MudText>
</TitleContent>
<DialogContent>
<MudAlert Severity="Severity.Warning" Dense="true" Class="mb-4">
⚠️ این عملیات حساس است و ساختار درخت شبکه را تغییر می‌دهد.
تاریخچه تغییر ثبت خواهد شد.
</MudAlert>
<MudForm @ref="_form">
<MudStack Spacing="3">
<MudTextField T="string"
Label="کاربر فعلی"
Value="@UserDisplayName"
ReadOnly="true"
Variant="Variant.Outlined"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Person" />
<MudNumericField T="long"
@bind-Value="_newParentId"
Label="شناسه والد جدید"
Required="true"
RequiredError="شناسه والد جدید الزامی است"
Variant="Variant.Outlined"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.PersonSearch"
Min="1" />
<MudSelect T="int"
@bind-Value="_newLeg"
Label="ساق جدید"
Required="true"
Variant="Variant.Outlined"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.AccountTree">
<MudSelectItem T="int" Value="0">چپ (تیم اول)</MudSelectItem>
<MudSelectItem T="int" Value="1">راست (تیم دوم)</MudSelectItem>
</MudSelect>
<MudTextField T="string"
@bind-Value="_reason"
Label="دلیل تغییر"
Required="true"
RequiredError="دلیل تغییر الزامی است"
Variant="Variant.Outlined"
Lines="3"
Placeholder="دلیل جابجایی کاربر در شبکه را وارد کنید..."
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Description" />
</MudStack>
</MudForm>
</DialogContent>
<DialogActions>
<MudButton OnClick="Cancel" Color="Color.Default">انصراف</MudButton>
<MudButton OnClick="Submit"
Color="Color.Error"
Variant="Variant.Filled"
Disabled="_isSubmitting"
StartIcon="@Icons.Material.Filled.SwapHoriz">
@if (_isSubmitting)
{
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="ml-2" />
<span>در حال انجام...</span>
}
else
{
<span>تغییر والد</span>
}
</MudButton>
</DialogActions>
</MudDialog>
@@ -0,0 +1,66 @@
using CMSMicroservice.Protobuf.Protos.NetworkMembership;
using Microsoft.AspNetCore.Components;
using MudBlazor;
namespace BackOffice.Pages.Network.Components;
public partial class ChangeParentDialog
{
[Parameter] public long UserId { get; set; }
[Parameter] public string UserDisplayName { get; set; } = "";
[CascadingParameter] IMudDialogInstance MudDialog { get; set; } = default!;
[Inject] public NetworkMembershipContract.NetworkMembershipContractClient NetworkContract { get; set; } = default!;
private MudForm _form = default!;
private long _newParentId;
private int _newLeg;
private string _reason = "";
private bool _isSubmitting;
private async Task Submit()
{
await _form.Validate();
if (!_form.IsValid)
return;
if (_newParentId == UserId)
{
Snackbar.Add("والد جدید نمی‌تواند خود کاربر باشد.", Severity.Error);
return;
}
_isSubmitting = true;
StateHasChanged();
try
{
var request = new ChangeNetworkParentRequest
{
UserId = UserId,
NewParentId = _newParentId,
NewLeg = _newLeg,
Reason = _reason
};
await NetworkContract.ChangeNetworkParentAsync(request);
Snackbar.Add("والد کاربر با موفقیت تغییر کرد.", Severity.Success);
MudDialog.Close(DialogResult.Ok(true));
}
catch (Grpc.Core.RpcException ex)
{
Snackbar.Add($"خطا: {ex.Status.Detail}", Severity.Error);
}
catch (Exception ex)
{
Snackbar.Add($"خطا در تغییر والد: {ex.Message}", Severity.Error);
}
finally
{
_isSubmitting = false;
StateHasChanged();
}
}
private void Cancel() => MudDialog.Cancel();
}
@@ -300,9 +300,9 @@
<MudSimpleTable Dense="true">
<tbody>
<tr>
<td><strong>پکیج طلایی:</strong></td>
<td><strong>خرید پکیج:</strong></td>
<td>
@if (_userInfo.HasPurchasedGoldenPackage)
@if (_userInfo.HasPurchasedPackage)
{
<MudChip T="string" Color="Color.Success" Size="Size.Small" Icon="@Icons.Material.Filled.CheckCircle">
خریداری شده
@@ -434,6 +434,12 @@
OnClick="@(() => NavigationManager.NavigateTo($"/commission/payouts?userId={UserId}"))">
پرداخت‌های کاربر
</MudButton>
<MudButton Variant="Variant.Outlined"
Color="Color.Warning"
StartIcon="@Icons.Material.Filled.SwapHoriz"
OnClick="OpenChangeParentDialog">
تغییر والد
</MudButton>
<MudButton Variant="Variant.Outlined"
Color="Color.Secondary"
StartIcon="@Icons.Material.Filled.Refresh"
@@ -537,4 +543,28 @@
_ => "نامشخص"
};
}
private async Task OpenChangeParentDialog()
{
var displayName = $"{_userInfo.UserName} (ID: {UserId})";
var parameters = new DialogParameters<Network.Components.ChangeParentDialog>
{
{ x => x.UserId, UserId },
{ x => x.UserDisplayName, displayName }
};
var options = new DialogOptions
{
MaxWidth = MaxWidth.Small,
FullWidth = true,
CloseOnEscapeKey = true
};
var dialog = await DialogService.ShowAsync<Network.Components.ChangeParentDialog>("تغییر والد شبکه", parameters, options);
var result = await dialog.Result;
if (result is { Canceled: false })
{
await LoadUserInfo();
await LoadNetworkHistory();
}
}
}
@@ -1,4 +1,5 @@
@using CMSMicroservice.Protobuf.Protos.Package
@using CMSMicroservice.Protobuf.Protos.Configuration
@using BackOffice.Common.BaseComponents
@using Microsoft.AspNetCore.Components.Forms
@using Tizzani.MudBlazor.HtmlEditor
@@ -41,12 +42,77 @@
<MudTextField T="string" @bind-Value="Model.Title" Disabled="_isLoading" Label="عنوان" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.Price" Format="N0" Immediate="true" Disabled="_isLoading" Label="قیمت" Variant="Variant.Outlined" />
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.Price" Format="N0" Immediate="true" Disabled="_isLoading" Label="قیمت (ریال)" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="4">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.SortOrder" Disabled="_isLoading" Label="ترتیب نمایش" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.ActivationFee" Format="N0" Immediate="true" Disabled="_isLoading" Label="هزینه فعال‌سازی (ریال)" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="double" HideSpinButtons="true" @bind-Value="Model.DiscountMultiplier" Disabled="_isLoading" Label="ضریب تخفیف" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="4">
<MudNumericField T="double" HideSpinButtons="true" @bind-Value="Model.MagicWalletMultiplier" Disabled="_isLoading" Label="ضریب کیف پول جادویی" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.MagicWalletMaxDeposit" Format="N0" Immediate="true" Disabled="_isLoading" Label="سقف واریز جادویی" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.MagicWalletMaxCredit" Format="N0" Immediate="true" Disabled="_isLoading" Label="سقف اعتبار جادویی" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.MaxBalancesPerLeg" Disabled="_isLoading" Label="حداکثر تعادل هر پا" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.MaxNetworkLevel" Disabled="_isLoading" Label="حداکثر سطح شبکه" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.IsActive" Disabled="_isLoading" Label="فعال" Color="Color.Success" />
</MudItem>
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.IsBasePackage" Disabled="_isLoading" Label="پکیج پایه" Color="Color.Primary" />
</MudItem>
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.SupportsDirectPurchase" Disabled="_isLoading" Label="پرداخت مستقیم" Color="Color.Info" />
</MudItem>
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.SupportsDayaPurchase" Disabled="_isLoading" Label="اعتبار دایا" Color="Color.Warning" />
</MudItem>
</MudStack>
@if (_features.Any())
{
<MudText Typo="Typo.subtitle1" Class="mt-4 mb-2"><strong>ویژگی‌های پکیج</strong></MudText>
<MudStack Row="true" Wrap="Wrap.Wrap">
@foreach (var feature in _features)
{
<MudCheckBox T="bool"
Value="@(_selectedFeatureIds.Contains(feature.Id))"
ValueChanged="@((bool v) => ToggleFeature(feature.Id, v))"
Disabled="_isLoading"
Label="@feature.Title"
Color="Color.Primary" />
}
</MudStack>
}
<MudItem xs="12">
<MudHtmlEditor @bind-Html="Model.Description" MinHeight="300px">
<MudHtmlToolbarOptions InsertImage="false" /> <!-- This will exclude the "insert image" toolbar option -->
<MudHtmlToolbarOptions InsertImage="false" />
</MudHtmlEditor>
</MudItem>
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
@using CMSMicroservice.Protobuf.Protos.Package
@using CMSMicroservice.Protobuf.Protos.Configuration
@using BackOffice.Common.BaseComponents
@using Microsoft.AspNetCore.Components.Forms
@using Tizzani.MudBlazor.HtmlEditor
@@ -42,12 +43,77 @@
<MudTextField T="string" @bind-Value="Model.Title" Disabled="_isLoading" Label="عنوان" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.Price" Disabled="_isLoading" Label="قیمت" Variant="Variant.Outlined" />
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.Price" Disabled="_isLoading" Label="قیمت (ریال)" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="4">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.SortOrder" Disabled="_isLoading" Label="ترتیب نمایش" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.ActivationFee" Format="N0" Immediate="true" Disabled="_isLoading" Label="هزینه فعال‌سازی (ریال)" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="double" HideSpinButtons="true" @bind-Value="Model.DiscountMultiplier" Disabled="_isLoading" Label="ضریب تخفیف" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="4">
<MudNumericField T="double" HideSpinButtons="true" @bind-Value="Model.MagicWalletMultiplier" Disabled="_isLoading" Label="ضریب کیف پول جادویی" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.MagicWalletMaxDeposit" Format="N0" Immediate="true" Disabled="_isLoading" Label="سقف واریز جادویی" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="4">
<MudNumericField T="long" HideSpinButtons="true" @bind-Value="Model.MagicWalletMaxCredit" Format="N0" Immediate="true" Disabled="_isLoading" Label="سقف اعتبار جادویی" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.MaxBalancesPerLeg" Disabled="_isLoading" Label="حداکثر تعادل هر پا" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="6">
<MudNumericField T="int" HideSpinButtons="true" @bind-Value="Model.MaxNetworkLevel" Disabled="_isLoading" Label="حداکثر سطح شبکه" Variant="Variant.Outlined" />
</MudItem>
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.IsActive" Disabled="_isLoading" Label="فعال" Color="Color.Success" />
</MudItem>
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.IsBasePackage" Disabled="_isLoading" Label="پکیج پایه" Color="Color.Primary" />
</MudItem>
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.SupportsDirectPurchase" Disabled="_isLoading" Label="پرداخت مستقیم" Color="Color.Info" />
</MudItem>
<MudItem xs="3">
<MudCheckBox T="bool" @bind-Value="Model.SupportsDayaPurchase" Disabled="_isLoading" Label="اعتبار دایا" Color="Color.Warning" />
</MudItem>
</MudStack>
@if (_features.Any())
{
<MudText Typo="Typo.subtitle1" Class="mt-4 mb-2"><strong>ویژگی‌های پکیج</strong></MudText>
<MudStack Row="true" Wrap="Wrap.Wrap">
@foreach (var feature in _features)
{
<MudCheckBox T="bool"
Value="@(_selectedFeatureIds.Contains(feature.Id))"
ValueChanged="@((bool v) => ToggleFeature(feature.Id, v))"
Disabled="_isLoading"
Label="@feature.Title"
Color="Color.Primary" />
}
</MudStack>
}
<MudItem xs="12">
<MudHtmlEditor @bind-Html="Model.Description" MinHeight="300px">
<MudHtmlToolbarOptions InsertImage="false" /> <!-- This will exclude the "insert image" toolbar option -->
<MudHtmlToolbarOptions InsertImage="false" />
</MudHtmlEditor>
</MudItem>
</MudStack>
File diff suppressed because one or more lines are too long
@@ -18,7 +18,11 @@
<col />
<col />
<col />
<col style="width: 58px;" />
<col />
<col />
<col />
<col />
<col style="width: 80px;" />
</ColGroup>
<ToolBarContent>
<MudText>مدیریت پکیج</MudText>
@@ -51,31 +55,42 @@
</CellTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.Description" Title="توضیحات" CellStyle="text-wrap: nowrap;" HeaderStyle="text-wrap: nowrap;">
<PropertyColumn Property="x => x.Price" Title="قیمت" CellStyle="text-wrap: nowrap;" HeaderStyle="text-wrap: nowrap;">
<CellTemplate>
@if (string.IsNullOrWhiteSpace(context.Item.Description))
<MudText Typo="Typo.inherit">@context.Item.Price.ToString("N0")</MudText>
</CellTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.SortOrder" Title="ترتیب" />
<PropertyColumn Property="x => x.IsActive" Title="وضعیت" CellStyle="text-wrap: nowrap;" HeaderStyle="text-wrap: nowrap;">
<CellTemplate>
@if (context.Item.IsActive)
{
<MudText Typo="Typo.inherit">-</MudText>
<MudChip T="string" Color="Color.Success" Variant="Variant.Filled" Size="Size.Small">فعال</MudChip>
}
else
{
<MudTooltip Text="@(context.Item.Description.HtmlToText())" Arrow="true" Style="@($"{(context.Item.Description.Length < 70 ? string.Empty : "width:600px;")}")">
<MudText Typo="Typo.inherit" Style="text-wrap: nowrap;">
@(context.Item.Description.HtmlToText().Truncate(20, true))
</MudText>
</MudTooltip>
<MudChip T="string" Color="Color.Default" Variant="Variant.Filled" Size="Size.Small">غیرفعال</MudChip>
}
</CellTemplate>
</PropertyColumn>
<TemplateColumn StickyLeft="true" Title="عملیات" CellStyle="text-wrap: nowrap;" HeaderStyle="text-wrap: nowrap;">
<PropertyColumn Property="x => x.IsBasePackage" Title="نوع" CellStyle="text-wrap: nowrap;" HeaderStyle="text-wrap: nowrap;">
<CellTemplate>
<MudStack Row="true" AlignItems="AlignItems.Center">
@if (context.Item.IsBasePackage)
{
<MudChip T="string" Color="Color.Primary" Variant="Variant.Filled" Size="Size.Small">پایه</MudChip>
}
else
{
<MudChip T="string" Color="Color.Info" Variant="Variant.Outlined" Size="Size.Small">عادی</MudChip>
}
</CellTemplate>
</PropertyColumn>
<TemplateColumn Title="">
<CellTemplate>
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
<MudTooltip Text="ویرایش">
<MudIconButton Icon="@Icons.Material.Filled.EditNote" Size="Size.Small" ButtonType="ButtonType.Button" OnClick="@(() => Update(context.Item.Adapt<DataModel>()))" />
<MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Small" ButtonType="ButtonType.Button" OnClick="@(() => Update(context.Item))" />
</MudTooltip>
<MudTooltip Text="آرشیو">
<MudIconButton Icon="@Icons.Material.Filled.DeleteOutline" Size="Size.Small" ButtonType="ButtonType.Button" OnClick="@(() => OnDelete(context.Item))" />
</MudTooltip>
@@ -33,7 +33,7 @@ public partial class PackageMainPage
{
var parameters = new DialogParameters<UpdateDialog> { { x => x.Model, model.Adapt<UpdatePackageRequest>() } };
var dialog = await DialogService.ShowAsync<UpdateDialog>($"ویرایش پکیج", parameters, new DialogOptions() { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small });
var dialog = await DialogService.ShowAsync<UpdateDialog>($"ویرایش پکیج", parameters, new DialogOptions() { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Medium });
var result = await dialog.Result;
if (!result.Canceled)
@@ -70,7 +70,7 @@ public partial class PackageMainPage
public async Task CreateNew()
{
var dialog = await DialogService.ShowAsync<CreateDialog>($"افزودن پکیج", new DialogParameters<CreateDialog>() { { x => x.Model, new CreateNewPackageRequest() } }, new DialogOptions() { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small });
var dialog = await DialogService.ShowAsync<CreateDialog>($"افزودن پکیج", new DialogParameters<CreateDialog>() { { x => x.Model, new CreateNewPackageRequest() { IsActive = true, SupportsDirectPurchase = true, DiscountMultiplier = 2.0, MagicWalletMultiplier = 2.5, MaxBalancesPerLeg = 300, MaxNetworkLevel = 15, MagicWalletMaxDeposit = 1_000_000_000, MagicWalletMaxCredit = 2_500_000_000 } } }, new DialogOptions() { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Medium });
var result = await dialog.Result;
if (!result.Canceled)
{