Compare commits

..

6 Commits

Author SHA1 Message Date
masoodafar-web 230453e491 feat(config): add production configuration for gateway URL and authentication
Build and Deploy to Production / build-and-deploy (push) Successful in 4m5s
2025-12-27 07:46:54 +03:30
masoodafar-web 1a65babb9d feat(UserPayouts): update status options and colors for user payouts
Build and Deploy / build (push) Successful in 2m8s
2025-12-27 07:34:38 +03:30
masoodafar-web bbe783dc83 feat(UserPayouts): implement withdrawal approval and rejection functionality
Build and Deploy / build (push) Successful in 2m6s
2025-12-27 06:22:11 +03:30
masoodafar-web 6f5bfba0a5 feat(AppVersionEditDialog): replace ReleaseNotes text field with HTML editor for enhanced formatting
Build and Deploy / build (push) Successful in 2m9s
2025-12-27 05:08:14 +03:30
masoodafar-web 98a4ba9e99 feat(config): Add staging configuration for backend URL and authentication
Build and Deploy / build (push) Has been cancelled
2025-12-27 05:07:50 +03:30
masoodafar-web ece29956b2 feat(app-versions): Add functionality to create new app versions and update UI components
Build and Deploy / build (push) Successful in 2m26s
2025-12-27 02:45:47 +03:30
8 changed files with 186 additions and 40 deletions
@@ -31,7 +31,10 @@
<MudSelectItem Value="@((int?)null)">همه</MudSelectItem>
<MudSelectItem Value="@((int?)0)">در انتظار</MudSelectItem>
<MudSelectItem Value="@((int?)1)">پرداخت شده</MudSelectItem>
<MudSelectItem Value="@((int?)2)">شکست خورده</MudSelectItem>
<MudSelectItem Value="@((int?)2)">درخواست برداشت</MudSelectItem>
<MudSelectItem Value="@((int?)3)">برداشت شده</MudSelectItem>
<MudSelectItem Value="@((int?)4)">شکست خورده</MudSelectItem>
<MudSelectItem Value="@((int?)5)">لغو شده</MudSelectItem>
</MudSelect>
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
@@ -109,13 +112,19 @@
Color="Color.Info"
OnClick="@(() => ViewDetails(context.Item))" />
</MudTooltip>
@if (context.Item.Status == 0)
@if (context.Item.Status == 2) @* WithdrawRequested *@
{
<MudTooltip Text="پردازش برداشت">
<MudIconButton Icon="@Icons.Material.Filled.Payment"
<MudTooltip Text="تایید برداشت">
<MudIconButton Icon="@Icons.Material.Filled.CheckCircle"
Size="Size.Small"
Color="Color.Success"
OnClick="@(() => ProcessWithdrawal(context.Item))" />
OnClick="@(() => ApproveWithdrawal(context.Item))" />
</MudTooltip>
<MudTooltip Text="رد برداشت">
<MudIconButton Icon="@Icons.Material.Filled.Cancel"
Size="Size.Small"
Color="Color.Error"
OnClick="@(() => RejectWithdrawal(context.Item))" />
</MudTooltip>
}
</MudStack>
@@ -79,9 +79,12 @@ public partial class UserPayouts
{
return status switch
{
0 => Color.Warning, // Pending
1 => Color.Success, // Paid
2 => Color.Error, // Failed
0 => Color.Warning, // Pending - در انتظار
1 => Color.Success, // Paid - پرداخت شده
2 => Color.Info, // WithdrawRequested - درخواست برداشت
3 => Color.Primary, // Withdrawn - برداشت شده
4 => Color.Error, // PaymentFailed - شکست خورده
5 => Color.Dark, // Cancelled - لغو شده
_ => Color.Default
};
}
@@ -92,7 +95,10 @@ public partial class UserPayouts
{
0 => "در انتظار",
1 => "پرداخت شده",
2 => "شکست خورده",
2 => "درخواست برداشت",
3 => "برداشت شده",
4 => "شکست خورده",
5 => "لغو شده",
_ => "نامشخص"
};
}
@@ -112,24 +118,55 @@ public partial class UserPayouts
});
}
private async Task ProcessWithdrawal(UserCommissionPayoutModel payout)
private async Task ApproveWithdrawal(UserCommissionPayoutModel payout)
{
var confirmed = await DialogService.ShowMessageBox(
"تایید پردازش برداشت",
$"آیا از پردازش برداشت برای کاربر {payout.UserName} (مبلغ: {payout.TotalAmount:N0} ریال) مطمئن هستید؟",
"تایید برداشت",
$"آیا از تایید برداشت برای کاربر {payout.UserName} (مبلغ: {payout.TotalAmount:N0} ریال) مطمئن هستید؟",
yesText: "تایید", cancelText: "لغو");
if (confirmed == true)
{
try
{
// TODO: Call ProcessWithdrawal API
Snackbar.Add("درخواست برداشت با موفقیت پردازش شد", Severity.Success);
await CommissionContract.ProcessWithdrawalAsync(new ProcessWithdrawalRequest
{
PayoutId = payout.Id,
IsApproved = true
});
Snackbar.Add("درخواست برداشت با موفقیت تایید شد", Severity.Success);
await ApplyFilter();
}
catch (Exception ex)
{
Snackbar.Add($"خطا در پردازش: {ex.Message}", Severity.Error);
Snackbar.Add($"خطا در تایید: {ex.Message}", Severity.Error);
}
}
}
private async Task RejectWithdrawal(UserCommissionPayoutModel payout)
{
var reason = await DialogService.ShowMessageBox(
"رد برداشت",
$"آیا از رد برداشت برای کاربر {payout.UserName} مطمئن هستید؟",
yesText: "رد کردن", cancelText: "لغو");
if (reason == true)
{
try
{
await CommissionContract.ProcessWithdrawalAsync(new ProcessWithdrawalRequest
{
PayoutId = payout.Id,
IsApproved = false,
Reason = "رد شده توسط ادمین"
});
Snackbar.Add("درخواست برداشت رد شد", Severity.Warning);
await ApplyFilter();
}
catch (Exception ex)
{
Snackbar.Add($"خطا در رد: {ex.Message}", Severity.Error);
}
}
}
@@ -26,6 +26,13 @@
T="bool"
ValueChanged="@(async (bool val) => { _includeInactive = val; await LoadVersions(); })" />
<MudStack Row="true" Spacing="2">
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Add"
OnClick="@OpenCreateDialog">
افزودن نسخه جدید
</MudButton>
<MudButton Variant="Variant.Outlined"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Refresh"
@@ -33,6 +40,7 @@
بارگذاری مجدد
</MudButton>
</MudStack>
</MudStack>
@if (_loading)
{
@@ -61,7 +69,7 @@
<TemplateColumn Title="نسخه فعلی">
<CellTemplate>
<MudChip T="string" Color="Color.Primary" Size="Size.Small" Variant="Variant.Outlined">
v@context.Item.CurrentVersion
@context.Item.CurrentVersion
</MudChip>
</CellTemplate>
</TemplateColumn>
@@ -71,7 +79,7 @@
@if (!string.IsNullOrEmpty(context.Item.MinRequiredVersion))
{
<MudChip T="string" Color="Color.Warning" Size="Size.Small" Variant="Variant.Outlined">
v@context.Item.MinRequiredVersion
@context.Item.MinRequiredVersion
</MudChip>
}
else
@@ -151,14 +159,14 @@
<MudStack Spacing="2">
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText Typo="Typo.body2">نسخه فعلی:</MudText>
<MudChip T="string" Color="Color.Primary" Size="Size.Small">v@version.CurrentVersion</MudChip>
<MudChip T="string" Color="Color.Primary" Size="Size.Small">@version.CurrentVersion</MudChip>
</MudStack>
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText Typo="Typo.body2">حداقل نسخه:</MudText>
@if (!string.IsNullOrEmpty(version.MinRequiredVersion))
{
<MudChip T="string" Color="Color.Warning" Size="Size.Small">v@version.MinRequiredVersion</MudChip>
<MudChip T="string" Color="Color.Warning" Size="Size.Small">@version.MinRequiredVersion</MudChip>
}
else
{
@@ -215,6 +223,52 @@
}
}
private async Task OpenCreateDialog()
{
var parameters = new DialogParameters<AppVersionEditDialog>
{
{ x => x.Model, new UpdateAppVersionDto
{
AppName = "",
CurrentVersion = "1.0.0",
MinRequiredVersion = null,
RequiresFullCacheClear = false,
UpdateMessage = null,
ReleaseNotes = null
}
},
{ x => x.IsNew, true }
};
var options = new DialogOptions
{
CloseButton = true,
MaxWidth = MaxWidth.Medium,
FullWidth = true
};
var dialog = await DialogService.ShowAsync<AppVersionEditDialog>(
"افزودن نسخه جدید",
parameters,
options);
var result = await dialog.Result;
if (result is { Canceled: false, Data: UpdateAppVersionDto dto })
{
try
{
await AppVersionService.UpdateAsync(dto);
Snackbar.Add("نسخه جدید با موفقیت ایجاد شد", Severity.Success);
await LoadVersions();
}
catch (Exception ex)
{
Snackbar.Add($"خطا در ایجاد: {ex.Message}", Severity.Error);
}
}
}
private async Task OpenEditDialog(AppVersionDto version)
{
var parameters = new DialogParameters<AppVersionEditDialog>
@@ -296,15 +350,15 @@
private string GetAppIcon(string appName) => appName switch
{
"FoursatMarketApp" => Icons.Material.Filled.ShoppingCart,
"FoursatClubApp" => Icons.Material.Filled.Groups,
"KaraBazarApp" => Icons.Material.Filled.ShoppingCart,
"KaraBazarAdminApp" => Icons.Material.Filled.AdminPanelSettings,
_ => Icons.Material.Filled.PhoneAndroid
};
private Color GetAppColor(string appName) => appName switch
{
"FoursatMarketApp" => Color.Primary,
"FoursatClubApp" => Color.Secondary,
"KaraBazarApp" => Color.Primary,
"KaraBazarAdminApp" => Color.Secondary,
_ => Color.Default
};
}
@@ -1,15 +1,30 @@
@using BackOffice.Services.AppVersion
@using Tizzani.MudBlazor.HtmlEditor
@inject ISnackbar Snackbar
<MudDialog>
<DialogContent>
<MudForm @ref="_form" @bind-IsValid="_isValid">
<MudStack Spacing="3">
@if (IsNew)
{
<MudSelect @bind-Value="Model.AppName"
Label="نام اپلیکیشن"
Variant="Variant.Outlined"
Required="true"
RequiredError="انتخاب اپلیکیشن اجباری است">
<MudSelectItem Value="@("KaraBazarApp")">کارابازار</MudSelectItem>
<MudSelectItem Value="@("KaraBazarAdminApp")">ادمین کارابازار</MudSelectItem>
</MudSelect>
}
else
{
<MudTextField @bind-Value="Model.AppName"
Label="نام اپلیکیشن"
Variant="Variant.Outlined"
ReadOnly="true"
Disabled="true" />
}
<MudTextField @bind-Value="Model.CurrentVersion"
Label="نسخه فعلی"
@@ -33,11 +48,11 @@
Lines="2"
HelperText="پیامی که به کاربر نمایش داده می‌شود" />
<MudTextField @bind-Value="Model.ReleaseNotes"
Label="یادداشت‌های انتشار"
Variant="Variant.Outlined"
Lines="4"
HelperText="توضیحات تغییرات این نسخه" />
<MudText Typo="Typo.subtitle2" Class="mt-2">یادداشت‌های انتشار (HTML)</MudText>
<MudHtmlEditor @bind-Html="Model.ReleaseNotes"
Placeholder="توضیحات تغییرات این نسخه..."
MinHeight="150px">
</MudHtmlEditor>
<MudDivider Class="my-2" />
@@ -68,6 +83,9 @@
[Parameter]
public UpdateAppVersionDto Model { get; set; } = new();
[Parameter]
public bool IsNew { get; set; } = false;
private MudForm? _form;
private bool _isValid;
+11
View File
@@ -252,6 +252,15 @@
تنظیمات سیستم
</MudNavLink>
}
@if (CanViewSettings)
{
<MudNavLink Match="NavLinkMatch.Prefix"
Href="/settings/app-versions"
Icon="@Icons.Material.Filled.PhoneAndroid">
نسخه اپلیکیشن‌ها
</MudNavLink>
}
</Authorized>
</AuthorizeView>
@@ -295,6 +304,7 @@
private bool CanViewSystemAlerts;
private bool CanViewSystemHealth;
private bool CanManageSystemConfiguration;
private bool CanViewSettings;
protected override async Task OnInitializedAsync()
{
@@ -323,6 +333,7 @@
CanViewSystemAlerts = await AuthorizationService.HasPermissionAsync("system.alerts.view");
CanViewSystemHealth = await AuthorizationService.HasPermissionAsync("system.health.view");
CanManageSystemConfiguration = await AuthorizationService.HasPermissionAsync("settings.manage_configuration");
CanViewSettings = await AuthorizationService.HasPermissionAsync("settings.view");
_initialized = true;
StateHasChanged();
@@ -0,0 +1,8 @@
{
// "GwUrl": "https://localhost:6468",
"GwUrl": "https://bogw.kbs2.ir",
"Authentication": {
"Authority": "https://ids.afrino.co/",
"ClientId": "client_backoffice_spa"
}
}
@@ -0,0 +1,8 @@
{
// "GwUrl": "https://localhost:6468",
"GwUrl": "https://backoffice-bff.foursat.afrino.co",
"Authentication": {
"Authority": "https://ids.afrino.co/",
"ClientId": "client_backoffice_spa"
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
{
"GwUrl": "https://bogw.kbs2.ir",
// "GwUrl": "https://localhost:6468",
"GwUrl": "https://backoffice-bff.foursat.afrino.co",
"Authentication": {
"Authority": "https://ids.afrino.co/",
"ClientId": "client_backoffice_spa"