diff --git a/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor b/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor
index 96da6a3..abea33f 100644
--- a/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor
+++ b/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor
@@ -11,35 +11,73 @@
- ثبت درخواست برداشت جدید
-
-
-
- برداشت نقدی (نیاز به شبا)
- الماس/غیرنقدی
-
-
-
- حداقل مبلغ برداشت: @FormatPrice(_minWithdrawalAmount)
-
-
- @(_isSubmittingWithdrawal ? "در حال ثبت..." : "ثبت درخواست برداشت")
-
-
+ ثبت درخواست برداشت جدید
+
+ @if (!_availablePayouts.Any())
+ {
+
+ در حال حاضر واریزی برای برداشت وجود ندارد.
+
+ }
+ else
+ {
+
+
+ @foreach (var payout in _availablePayouts)
+ {
+
+
+ @payout.WeekDisplayName
+
+ @payout.AmountFormatted
+
+
+
+ }
+
+
+ @if (_selectedPayout != null)
+ {
+
+ مبلغ قابل برداشت: @_selectedPayout.AmountFormatted
+
+ }
+
+
+
+ برداشت نقدی (نیاز به شبا)
+
+
+ الماس/غیرنقدی
+
+
+
+
+
+
+ حداقل مبلغ برداشت: @FormatPrice(_minWithdrawalAmount)
+
+
+
+ @(_isSubmittingWithdrawal ? "در حال ثبت..." : "ثبت درخواست برداشت")
+
+
+ }
diff --git a/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs b/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs
index 3473f3e..abd9568 100644
--- a/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs
+++ b/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs
@@ -6,12 +6,15 @@ namespace FrontOffice.Main.Pages.Profile;
public partial class WithdrawalRequests : ComponentBase
{
+ [Inject] private CommissionService CommissionService { get; set; } = default!;
+
private long _minWithdrawalAmount = 1_000_000;
private List _withdrawals = new();
+ private List _availablePayouts = new();
private string _statusFilter = "all";
private bool _isLoading = true;
private bool _isSubmittingWithdrawal;
- private long _withdrawPayoutId;
+ private CommissionPayoutDto? _selectedPayout;
private WithdrawalMethodClient _withdrawMethod = WithdrawalMethodClient.Cash;
private string? _withdrawIban;
@@ -26,6 +29,7 @@ public partial class WithdrawalRequests : ComponentBase
try
{
_withdrawals = await WalletService.GetWithdrawalsAsync();
+ _availablePayouts = await CommissionService.GetWithdrawablePayoutsAsync();
var settings = await WalletService.GetWithdrawalSettingsAsync();
if (settings.MinWithdrawalAmount > 0)
_minWithdrawalAmount = settings.MinWithdrawalAmount;
@@ -40,9 +44,9 @@ public partial class WithdrawalRequests : ComponentBase
private async Task SubmitWithdrawal()
{
- if (_withdrawPayoutId <= 0)
+ if (_selectedPayout == null)
{
- Snackbar.Add("شناسه واریز (PayoutId) الزامی است.", Severity.Warning);
+ Snackbar.Add("لطفاً یک واریز را انتخاب کنید.", Severity.Warning);
return;
}
if (_withdrawMethod == WithdrawalMethodClient.Cash && string.IsNullOrWhiteSpace(_withdrawIban))
@@ -54,14 +58,14 @@ public partial class WithdrawalRequests : ComponentBase
try
{
_isSubmittingWithdrawal = true;
- await WalletService.RequestWithdrawalAsync(_withdrawPayoutId, _withdrawMethod, _withdrawIban);
+ await WalletService.RequestWithdrawalAsync(_selectedPayout.Id, _withdrawMethod, _withdrawIban);
Snackbar.Add("درخواست برداشت ثبت شد.", Severity.Success);
// بروزرسانی لیست
await LoadData();
// ریست فرم
- _withdrawPayoutId = 0;
+ _selectedPayout = null;
_withdrawIban = null;
}
catch (Exception ex)
diff --git a/src/FrontOffice.Main/Pages/Store/Products.razor b/src/FrontOffice.Main/Pages/Store/Products.razor
index 4207ed2..88d5cca 100644
--- a/src/FrontOffice.Main/Pages/Store/Products.razor
+++ b/src/FrontOffice.Main/Pages/Store/Products.razor
@@ -3,37 +3,91 @@
محصولات
-
-
+
+
-
+ @* ردیف اول: جستجو و دکمهها *@
+
+ Variant="Variant.Outlined"
+ Margin="Margin.Dense"/>
-
-
+
+
دستهبندیها
-
- سبد خرید (@Cart.Count)
+ سبد خرید
+ @if (Cart.Count > 0)
+ {
+
+ }
+
+ @* ردیف دوم: فیلترها و مرتبسازی *@
+
+
+
+
+
+
+
+
+ گرانترین
+
+
+
+
+
+ ارزانترین
+
+
+
+
+
+ جدیدترین
+
+
+
+
+
+ الفبایی
+
+
+
+
+
+ @if (_activeCategoryId.HasValue)
+ {
+
+ @(_activeCategoryTitle ?? $"دستهبندی #{_activeCategoryId}")
+
+ }
+ else
+ {
+
+
+ @(_products.Count) محصول
+
+ }
+
- @if (_activeCategoryId.HasValue)
- {
-
-
- @(_activeCategoryTitle ?? $"دستهبندی #{_activeCategoryId}")
-
-
- }
@if (_loading)
diff --git a/src/FrontOffice.Main/Pages/Store/Products.razor.cs b/src/FrontOffice.Main/Pages/Store/Products.razor.cs
index 7156e3f..5c8163d 100644
--- a/src/FrontOffice.Main/Pages/Store/Products.razor.cs
+++ b/src/FrontOffice.Main/Pages/Store/Products.razor.cs
@@ -7,6 +7,14 @@ using FrontOffice.Main.Utilities;
namespace FrontOffice.Main.Pages.Store;
+public enum ProductSortOption
+{
+ PriceDesc, // گرانترین (پیشفرض)
+ PriceAsc, // ارزانترین
+ Newest, // جدیدترین
+ Title // الفبایی
+}
+
public partial class Products : ComponentBase, IDisposable
{
[Inject] private ProductService ProductService { get; set; } = default!;
@@ -19,6 +27,8 @@ public partial class Products : ComponentBase, IDisposable
private List _products = new();
private long? _activeCategoryId;
private string? _activeCategoryTitle;
+
+ private ProductSortOption _sortOption = ProductSortOption.PriceDesc; // پیشفرض: گرانترین
protected override async Task OnInitializedAsync()
{
@@ -43,13 +53,31 @@ public partial class Products : ComponentBase, IDisposable
{
_loading = true;
UpdateCategoryFilterFromUri();
- _products = await ProductService.GetProductsAsync(_query, _activeCategoryId);
+ var sortBy = GetSortByValue();
+ _products = await ProductService.GetProductsAsync(_query, _activeCategoryId, sortBy);
_activeCategoryTitle = _activeCategoryId is { } categoryId
? (await CategoryService.GetByIdAsync(categoryId))?.Title
: null;
_loading = false;
}
+ private string GetSortByValue()
+ {
+ return _sortOption switch
+ {
+ ProductSortOption.PriceDesc => "price desc",
+ ProductSortOption.PriceAsc => "price asc",
+ ProductSortOption.Newest => "id desc",
+ ProductSortOption.Title => "title asc",
+ _ => "price desc"
+ };
+ }
+
+ private async Task OnSortChanged()
+ {
+ await Load();
+ }
+
private async Task OnQueryChanged(KeyboardEventArgs _)
{
await Load();
diff --git a/src/FrontOffice.Main/Pages/_Host.cshtml b/src/FrontOffice.Main/Pages/_Host.cshtml
index 6925fc6..e22f5de 100644
--- a/src/FrontOffice.Main/Pages/_Host.cshtml
+++ b/src/FrontOffice.Main/Pages/_Host.cshtml
@@ -4,7 +4,7 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
-
+
diff --git a/src/FrontOffice.Main/Shared/ReleaseNotesDialog.razor b/src/FrontOffice.Main/Shared/ReleaseNotesDialog.razor
index 7446e0b..508c10a 100644
--- a/src/FrontOffice.Main/Shared/ReleaseNotesDialog.razor
+++ b/src/FrontOffice.Main/Shared/ReleaseNotesDialog.razor
@@ -21,7 +21,7 @@
@* اطلاعات نسخه با انیمیشن *@
+ Style="">
diff --git a/src/FrontOffice.Main/Utilities/CommissionService.cs b/src/FrontOffice.Main/Utilities/CommissionService.cs
index b45c498..bee9bfe 100644
--- a/src/FrontOffice.Main/Utilities/CommissionService.cs
+++ b/src/FrontOffice.Main/Utilities/CommissionService.cs
@@ -191,6 +191,46 @@ public class CommissionService
#region Helper Methods
+ ///
+ /// Get payouts that are eligible for withdrawal (all statuses except Withdrawn=3)
+ ///
+ public async Task> GetWithdrawablePayoutsAsync()
+ {
+ try
+ {
+ // Get all payouts that are not yet withdrawn
+ // We'll get all and filter out Withdrawn (status=3) on client side
+ var request = new GetMyCommissionPayoutsRequest
+ {
+ PageNumber = 1,
+ PageSize = 100
+ // No status filter - get all
+ };
+
+ var response = await _client.GetMyCommissionPayoutsAsync(request);
+
+ // Filter: exclude already withdrawn (status text contains "برداشت" or status=3)
+ return response.Payouts
+ .Where(p => !p.Status.Contains("برداشت") && p.Status != "Withdrawn")
+ .Select(p => new CommissionPayoutDto
+ {
+ Id = p.Id,
+ WeekDefinitionId = p.WeekDefinitionId,
+ WeekDisplayName = p.WeekDisplayName,
+ BalancesEarned = p.BalancesEarned,
+ TotalAmount = p.TotalAmount,
+ AmountFormatted = p.AmountFormatted,
+ Status = p.Status,
+ StatusBadgeColor = p.StatusBadgeColor,
+ DatePersian = p.DatePersian
+ }).ToList();
+ }
+ catch
+ {
+ return new List();
+ }
+ }
+
private static WeeklyBalanceDto CreateEmptyWeeklyBalance()
{
return new WeeklyBalanceDto
diff --git a/src/FrontOffice.Main/Utilities/ProductService.cs b/src/FrontOffice.Main/Utilities/ProductService.cs
index 28451b3..f8a0c1b 100644
--- a/src/FrontOffice.Main/Utilities/ProductService.cs
+++ b/src/FrontOffice.Main/Utilities/ProductService.cs
@@ -58,7 +58,7 @@ public class ProductService
_client = client;
}
- public async Task> GetProductsAsync(string? query = null, long? categoryId = null)
+ public async Task> GetProductsAsync(string? query = null, long? categoryId = null, string? sortBy = null)
{
try
{
@@ -75,7 +75,12 @@ public class ProductService
if (categoryId is { } value)
{
- request.Filter.CategoryId = value ;
+ request.Filter.CategoryId = value;
+ }
+
+ if (!string.IsNullOrEmpty(sortBy))
+ {
+ request.SortBy = sortBy;
}
var resp = await _client.GetAllProductsByFilterAsync(request);
diff --git a/src/FrontOffice.Main/wwwroot/css/site.css b/src/FrontOffice.Main/wwwroot/css/site.css
index b983cb2..9735a1a 100644
--- a/src/FrontOffice.Main/wwwroot/css/site.css
+++ b/src/FrontOffice.Main/wwwroot/css/site.css
@@ -49,6 +49,8 @@ html, body {
font-weight: 400;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
+ direction: rtl;
+ text-align: right;
}
/* Apply Vazir to common Mud components */
diff --git a/src/FrontOffice.Main/wwwroot/js/print-utils.js b/src/FrontOffice.Main/wwwroot/js/print-utils.js
index 98f58f1..b3e1818 100644
--- a/src/FrontOffice.Main/wwwroot/js/print-utils.js
+++ b/src/FrontOffice.Main/wwwroot/js/print-utils.js
@@ -27,7 +27,7 @@
var doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
- doc.write(""+
+ doc.write(""+
""+ title +""+
""+
""+