Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 6m27s

This commit is contained in:
masoodafar-web
2026-08-09 02:33:27 +03:30
14 changed files with 527 additions and 162 deletions
+1
View File
@@ -1,3 +1,4 @@
# Docs moved to totalDoc
See [totalDoc/INDEX.md](../../totalDoc/INDEX.md) for all documentation.
+3
View File
@@ -429,6 +429,8 @@ else
@* ═══════════════════════════════════════════════
6. TESTIMONIALS
═══════════════════════════════════════════════ *@
@if (_testimonials.Count > 0)
{
<section class="section-landing">
<MudContainer MaxWidth="MaxWidth.Large">
<div class="text-center mb-8 fade-in-up">
@@ -465,6 +467,7 @@ else
</MudGrid>
</MudContainer>
</section>
}
@* ═══════════════════════════════════════════════
7. FAQ
+3 -2
View File
@@ -193,9 +193,10 @@ public partial class Index : IDisposable
}
// ── Testimonials ──
if (_settings?.Testimonials?.Any() == true)
// اگر تنظیمات از CMS لود شده، لیست خالی یعنی ادمین عمداً حذف کرده — بدون fallback hardcode
if (_settings is not null)
{
_testimonials = _settings.Testimonials
_testimonials = (_settings.Testimonials ?? [])
.Select((t, i) => new TestimonialItem(t.Quote ?? "", t.Name ?? "", t.Role ?? "", i * 150))
.ToList();
}
@@ -35,7 +35,23 @@
</MudAlert>
}
@if (_authLoaded && !_isClubMemberActive)
@if (_authLoaded && _redirectingToMagic)
{
<MudAlert Severity="MudBlazor.Severity.Info" Class="rounded-lg" Variant="Variant.Outlined">
<MudStack Spacing="2" AlignItems="AlignItems.Center">
<MudProgressCircular Size="Size.Small" Indeterminate="true" Color="Color.Primary" />
<MudText>
کیف پول شما در حالت جادویی است. در حال انتقال به صفحه شارژ کیف پول جادویی...
</MudText>
<MudButton Size="Size.Small" Variant="Variant.Filled" Color="Color.Primary"
Href="@RouteConstants.Profile.MagicWallet"
StartIcon="@Icons.Material.Filled.AutoAwesome">
رفتن به شارژ کیف جادویی
</MudButton>
</MudStack>
</MudAlert>
}
else if (_authLoaded && !_isClubMemberActive)
{
<MudAlert Severity="MudBlazor.Severity.Warning" Class="rounded-lg" Variant="Variant.Outlined">
<MudStack Spacing="2">
@@ -67,7 +83,35 @@
</MudStack>
</MudAlert>
}
else if (_authLoaded)
else if (_authLoaded && _needsMagicCeilingConsent && !_allowNormalDespiteMagic && !_redirectingToMagic)
{
<MudAlert Severity="MudBlazor.Severity.Warning" Class="rounded-lg" Variant="Variant.Outlined">
<MudStack Spacing="3">
<MudText Typo="Typo.subtitle1">
سقف شارژ کیف پول جادویی در این دور پر شده است.
</MudText>
<MudText Typo="Typo.body2">
شارژ از این صفحه بدون ضریب (۱:۱) به موجودی اضافه می‌شود و ضریب جادویی اعمال نمی‌شود.
برای ادامه، تأیید کنید.
</MudText>
<MudStack Row="true" Spacing="1" Class="flex-wrap">
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Check"
OnClick="AcceptMagicCeilingConsent">
ادامه شارژ بدون ضریب
</MudButton>
<MudButton Variant="Variant.Outlined"
Color="Color.Secondary"
StartIcon="@Icons.Material.Filled.AutoAwesome"
OnClick="DeclineMagicCeilingConsent">
بازگشت به کیف جادویی
</MudButton>
</MudStack>
</MudStack>
</MudAlert>
}
else if (ShowChargeForm)
{
<MudPaper Elevation="2" Class="pa-5 rounded-lg">
<MudText Typo="Typo.h6" Class="mb-3">
@@ -75,6 +119,13 @@
شارژ موجودی اصلی
</MudText>
@if (_allowNormalDespiteMagic)
{
<MudAlert Severity="MudBlazor.Severity.Warning" Dense="true" Class="mb-3" Icon="@Icons.Material.Filled.Warning">
این شارژ بدون ضریب جادویی است (۱:۱). سقف واریز جادویی شما در این دور پر شده است.
</MudAlert>
}
<MudAlert Severity="MudBlazor.Severity.Info" Dense="true" Class="mb-3" Icon="@Icons.Material.Filled.Info">
مبلغ وارد شده (به تومان) از طریق درگاه پرداخت به موجودی اصلی شما اضافه می‌شود.
از موجودی اصلی برای خرید از فروشگاه عادی و پرداخت سفارش استفاده می‌شود.
@@ -16,6 +16,9 @@ public partial class ChargeCreditWallet : ComponentBase
private bool _isClubMemberActive;
private bool _hasPurchasedPackage;
private bool _authLoaded;
private bool _redirectingToMagic;
private bool _allowNormalDespiteMagic;
private bool _needsMagicCeilingConsent;
private readonly long[] _presetAmounts = { 500_000, 1_000_000, 5_000_000, 10_000_000, 20_000_000, 50_000_000 };
@@ -28,6 +31,12 @@ public partial class ChargeCreditWallet : ComponentBase
[SupplyParameterFromQuery(Name = "returnUrl")]
public string? ReturnUrlQueryParam { get; set; }
private bool ShowChargeForm =>
_authLoaded
&& _isClubMemberActive
&& !_redirectingToMagic
&& (!_needsMagicCeilingConsent || _allowNormalDespiteMagic);
protected override async Task OnInitializedAsync()
{
_paymentResult = PaymentQueryParam;
@@ -53,18 +62,31 @@ public partial class ChargeCreditWallet : ComponentBase
{
_authLoaded = true;
}
if (_isClubMemberActive)
await EvaluateMagicWalletGateAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && !string.IsNullOrEmpty(_pendingReturnUrl) && _isClubMemberActive)
{
if (firstRender && !string.IsNullOrEmpty(_pendingReturnUrl) && _isClubMemberActive && !_redirectingToMagic)
await CreditChargeNavigation.SaveReturnUrlAsync(JSRuntime, _pendingReturnUrl);
}
await base.OnAfterRenderAsync(firstRender);
}
private void AcceptMagicCeilingConsent()
{
_allowNormalDespiteMagic = true;
_redirectingToMagic = false;
}
private void DeclineMagicCeilingConsent()
{
_redirectingToMagic = true;
Navigation.NavigateTo(RouteConstants.Profile.MagicWallet);
}
private async Task StartCreditCharge()
{
if (!_isClubMemberActive)
@@ -75,6 +97,12 @@ public partial class ChargeCreditWallet : ComponentBase
return;
}
if (await EvaluateMagicWalletGateAsync())
return;
if (_needsMagicCeilingConsent && !_allowNormalDespiteMagic)
return;
if (_chargeAmount <= 0 || _isProcessing) return;
_isProcessing = true;
@@ -113,6 +141,50 @@ public partial class ChargeCreditWallet : ComponentBase
}
}
/// <summary>
/// Magic با ظرفیت باقی‌مانده → ریدایرکت به MagicWallet.
/// Magic با سقف پر → نمایش تأیید روی صفحه برای شارژ ۱:۱.
/// true یعنی مسیر شارژ فعلی باید متوقف شود.
/// </summary>
private async Task<bool> EvaluateMagicWalletGateAsync()
{
if (_allowNormalDespiteMagic)
return false;
try
{
var status = await WalletService.GetMagicWalletStatusAsync();
if (status.WalletMode != 1)
{
_needsMagicCeilingConsent = false;
return false;
}
if (status.MagicRemainingDeposit > 0)
{
var multiplier = status.MagicMultiplier > 0 ? status.MagicMultiplier : 2.5;
var multiplierText = multiplier.ToString("0.#");
_redirectingToMagic = true;
_needsMagicCeilingConsent = false;
Snackbar.Add(
$"کیف پول شما در حالت جادویی است. شارژ از این صفحه موجودی را چندبرابر نمی‌کند. برای دریافت ضریب جادویی (×{multiplierText}) به صفحه شارژ کیف پول جادویی هدایت می‌شوید.",
Severity.Info);
Navigation.NavigateTo(RouteConstants.Profile.MagicWallet);
return true;
}
_needsMagicCeilingConsent = true;
return !_allowNormalDespiteMagic;
}
catch
{
// در صورت خطا در خواندن وضعیت، مانع شارژ عادی نشو
return false;
}
}
private async Task ContinueShoppingAsync()
{
var returnUrl = await CreditChargeNavigation.GetReturnUrlAsync(JSRuntime);
@@ -166,8 +166,23 @@
else
{
<MudAlert Severity="MudBlazor.Severity.Warning" Class="rounded-lg">
سقف شارژ جادویی در این دور پر شده است.
با خرج کردن موجودی و خرید مجدد پکیج، سقف ریست می‌شود.
<MudStack Spacing="2">
<MudText>
سقف شارژ جادویی در این دور پر شده است.
با خرج کردن موجودی و خرید مجدد پکیج، سقف ریست می‌شود.
</MudText>
<MudText Typo="Typo.body2">
اگر برای تکمیل خرید به موجودی بیشتری نیاز دارید، می‌توانید به‌صورت استثنایی کیف اصلی را بدون ضریب (۱:۱) شارژ کنید.
</MudText>
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
Size="Size.Small"
StartIcon="@Icons.Material.Filled.AccountBalanceWallet"
Href="@RouteConstants.Profile.ChargeCreditWallet"
Class="rounded-lg align-self-start">
شارژ عادی بدون ضریب
</MudButton>
</MudStack>
</MudAlert>
}
+46 -10
View File
@@ -38,18 +38,54 @@
درخواست‌های برداشت
</MudButton>
<!-- دکمه شارژ کیف‌پول اصلی -->
<!-- دکمه شارژ کیف‌پول اصلی / جادویی -->
@if (_isClubMemberActive)
{
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
Size="Size.Large"
FullWidth="true"
StartIcon="@Icons.Material.Filled.AccountBalanceWallet"
Href="@RouteConstants.Profile.ChargeCreditWallet"
Class="rounded-lg">
شارژ کیف‌پول اصلی
</MudButton>
@if (_isMagicWallet)
{
<MudButton Variant="Variant.Filled"
Color="Color.Secondary"
Size="Size.Large"
FullWidth="true"
StartIcon="@Icons.Material.Filled.AutoAwesome"
Href="@RouteConstants.Profile.MagicWallet"
Class="rounded-lg">
شارژ کیف‌پول جادویی
</MudButton>
@if (_magicCeilingFull)
{
<MudAlert Severity="Severity.Warning" Dense="true" Variant="Variant.Outlined">
سقف شارژ جادویی این دور پر است. در صورت نیاز می‌توانید به‌صورت استثنایی بدون ضریب شارژ کنید.
</MudAlert>
<MudButton Variant="Variant.Outlined"
Color="Color.Primary"
Size="Size.Large"
FullWidth="true"
StartIcon="@Icons.Material.Filled.AccountBalanceWallet"
Href="@RouteConstants.Profile.ChargeCreditWallet"
Class="rounded-lg">
شارژ عادی بدون ضریب
</MudButton>
}
else
{
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined">
کیف پول شما در حالت جادویی است؛ شارژ از مسیر جادویی با ضریب چندبرابر اعمال می‌شود.
</MudAlert>
}
}
else
{
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
Size="Size.Large"
FullWidth="true"
StartIcon="@Icons.Material.Filled.AccountBalanceWallet"
Href="@RouteConstants.Profile.ChargeCreditWallet"
Class="rounded-lg">
شارژ کیف‌پول اصلی
</MudButton>
}
}
else
{
@@ -14,6 +14,8 @@ public partial class Wallet : ComponentBase
private string _filterType = "all";
private bool _isClubMemberActive;
private bool _hasPurchasedPackage;
private bool _isMagicWallet;
private bool _magicCeilingFull;
protected override async Task OnInitializedAsync()
{
@@ -29,6 +31,18 @@ public partial class Wallet : ComponentBase
_hasPurchasedPackage = false;
}
try
{
var magicStatus = await WalletService.GetMagicWalletStatusAsync();
_isMagicWallet = magicStatus.WalletMode == 1;
_magicCeilingFull = _isMagicWallet && magicStatus.MagicRemainingDeposit <= 0;
}
catch
{
_isMagicWallet = false;
_magicCeilingFull = false;
}
var b = await WalletService.GetBalancesAsync();
_balances = (FormatPrice(b.CreditBalance), FormatPrice(b.DiscountBalance), FormatPrice(b.NetworkBalance));
_txs = await WalletService.GetTransactionsAsync();
@@ -127,6 +127,8 @@ public partial class CheckoutSummary : ComponentBase
var shortfall = totalRequired - walletBalance;
var allowCharge = false;
var hasPurchasedPackage = false;
var isMagicWallet = false;
var magicCeilingFull = false;
try
{
var userInfo = await AuthService.GetUserAuthInfo();
@@ -138,13 +140,27 @@ public partial class CheckoutSummary : ComponentBase
allowCharge = false;
}
try
{
var magicStatus = await WalletService.GetMagicWalletStatusAsync();
isMagicWallet = magicStatus.WalletMode == 1;
magicCeilingFull = isMagicWallet && magicStatus.MagicRemainingDeposit <= 0;
}
catch
{
isMagicWallet = false;
magicCeilingFull = false;
}
var parameters = new DialogParameters<InsufficientCreditDialog>
{
{ x => x.CurrentBalance, walletBalance },
{ x => x.RequiredAmount, totalRequired },
{ x => x.ShortfallAmount, shortfall },
{ x => x.AllowChargeCredit, allowCharge },
{ x => x.HasPurchasedPackage, hasPurchasedPackage }
{ x => x.HasPurchasedPackage, hasPurchasedPackage },
{ x => x.IsMagicWallet, isMagicWallet },
{ x => x.MagicCeilingFull, magicCeilingFull }
};
var dialog = await DialogService.ShowAsync<InsufficientCreditDialog>(
@@ -46,12 +46,19 @@ public partial class OrderTracking : ComponentBase
private void BuildTrackingSteps()
{
if (_order is null) return;
// Build tracking steps based on PaymentStatus
var isPaid = _order.PaymentStatus == Messages.PaymentStatus.Success;
_trackingSteps = new List<TrackingStep>
{
// Domain/public_messages: None=0, Pending=1, InTransit=2, Delivered=3, Returned=4, Cancelled=5, ReadyForOfficePickup=6
var delivery = (int)_order.DeliveryStatus;
var isCancelled = delivery == 5;
var isReturned = delivery == 4;
var isOfficePickup = delivery == 6;
var isInTransit = delivery == 2;
var isDelivered = delivery == 3;
var isPendingDelivery = delivery is 0 or 1;
_trackingSteps =
[
new()
{
Title = "ثبت سفارش",
@@ -61,45 +68,77 @@ public partial class OrderTracking : ComponentBase
},
new()
{
Title = "در انتظار پرداخت",
Description = "منتظر تایید پرداخت هستیم",
Title = "پرداخت",
Description = isPaid ? "پرداخت شما تایید شد" : "منتظر تایید پرداخت هستیم",
IsCompleted = isPaid,
IsCurrent = !isPaid,
IsCurrent = !isPaid && !isCancelled,
Date = isPaid ? FormatDate(_order.PaymentDate) : ""
},
new()
{
Title = "تایید پرداخت",
Description = "پرداخت شما تایید شد",
IsCompleted = isPaid,
IsCurrent = false,
Date = isPaid ? FormatDate(_order.PaymentDate) : ""
},
new()
{
Title = "در حال پردازش",
Description = "سفارش شما در حال آماده‌سازی است",
IsCompleted = false,
IsCurrent = isPaid,
Date = ""
},
new()
{
Title = "ارسال شده",
Description = "سفارش شما به پست تحویل داده شد",
IsCompleted = false,
IsCurrent = false,
Date = ""
},
new()
{
Title = "تحویل داده شده",
Description = "سفارش به دست شما رسید",
IsCompleted = false,
IsCurrent = false,
Date = ""
}
};
];
if (isCancelled)
{
_trackingSteps.Add(new()
{
Title = "لغو شده",
Description = "ارسال این سفارش لغو شده است",
IsCompleted = true,
IsCurrent = true,
Date = ""
});
return;
}
if (isReturned)
{
_trackingSteps.Add(new()
{
Title = "مرجوع شده",
Description = "سفارش مرجوع شده است",
IsCompleted = true,
IsCurrent = true,
Date = ""
});
return;
}
if (isOfficePickup)
{
_trackingSteps.Add(new()
{
Title = "آماده تحویل در دفتر",
Description = "سفارش برای تحویل حضوری در دفتر آماده است",
IsCompleted = true,
IsCurrent = true,
Date = ""
});
return;
}
_trackingSteps.Add(new()
{
Title = "در حال آماده‌سازی",
Description = "سفارش شما در حال آماده‌سازی است",
IsCompleted = isInTransit || isDelivered,
IsCurrent = isPaid && isPendingDelivery,
Date = ""
});
_trackingSteps.Add(new()
{
Title = "ارسال شده",
Description = "سفارش شما به پست تحویل داده شد",
IsCompleted = isDelivered,
IsCurrent = isInTransit,
Date = ""
});
_trackingSteps.Add(new()
{
Title = "تحویل داده شده",
Description = "سفارش به دست شما رسید",
IsCompleted = isDelivered,
IsCurrent = false,
Date = ""
});
}
private static string FormatDate(Google.Protobuf.WellKnownTypes.Timestamp? timestamp)
+94 -72
View File
@@ -1,80 +1,102 @@
@attribute [Route(RouteConstants.Store.Orders)]
@* Injection is handled in code-behind *@
<PageTitle>سفارشات من</PageTitle>
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
<PageHeader Title="سفارشات من" BackHref="@RouteConstants.Store.Products" />
@if (_loading)
{
<LoadingState />
}
else if (_orders.Count == 0)
{
<MudAlert Severity="Severity.Info">هنوز سفارشی ثبت نکرده‌اید.</MudAlert>
}
else
{
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert="true">
<MudTable Items="_orders" Dense="true">
<HeaderContent>
<MudTh>شناسه</MudTh>
<MudTh>تاریخ</MudTh>
<MudTh>وضعیت</MudTh>
<MudTh>مبلغ</MudTh>
<MudTh></MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Id</MudTd>
<MudTd>
@if (context.PaymentDate != null)
{
@context.PaymentDate.ToDateTime().MiladiToJalaliWithTime()
}
else
{
<text>در انتظار پرداخت</text>
}
</MudTd>
<MudTd>@GetStatusText(context.PaymentStatus)</MudTd>
<MudTd>@FormatPrice(context.FactorDetails.Sum(s=>(s.UnitPrice ?? 0) * (s.Count ?? 0)))</MudTd>
<MudTd>
<MudButton Variant="Variant.Text" Href="@($"{RouteConstants.Store.OrderDetail}{context.Id}")" StartIcon="@Icons.Material.Filled.Receipt">جزئیات</MudButton>
</MudTd>
</RowTemplate>
</MudTable>
</MudHidden>
<MudStack Spacing="3">
<PageHeader Title="سفارشات من" BackHref="@RouteConstants.Store.Products" />
<MudHidden Breakpoint="Breakpoint.MdAndUp">
<MudStack Spacing="2">
@foreach (var o in _orders)
{
<MudPaper Class="pa-3 rounded-lg" Outlined="true">
<MudStack Spacing="1">
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText>سفارش #@o.Id</MudText>
<MudText Class="mud-text-secondary">
@if (o.PaymentDate != null)
{
@o.PaymentDate.ToDateTime().MiladiToJalaliWithTime()
}
else
{
<text>در انتظار پرداخت</text>
}
</MudText>
@if (_loading)
{
<LoadingState />
}
else if (_orders.Count == 0)
{
<MudAlert Severity="Severity.Info">هنوز سفارشی ثبت نشده است.</MudAlert>
<MudButton Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Store"
Href="@RouteConstants.Store.Products">
مشاهده فروشگاه
</MudButton>
}
else
{
<!-- Desktop Table -->
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert="true">
<MudPaper Elevation="1" Class="pa-4 rounded-lg">
<MudTable Items="_orders">
<HeaderContent>
<MudTh>شماره سفارش</MudTh>
<MudTh>تعداد اقلام</MudTh>
<MudTh>مبلغ کل</MudTh>
<MudTh>وضعیت پرداخت</MudTh>
<MudTh>وضعیت ارسال</MudTh>
<MudTh>تاریخ</MudTh>
<MudTh></MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Id</MudTd>
<MudTd>@GetItemsCount(context)</MudTd>
<MudTd>@FormatPrice(GetTotalAmount(context))</MudTd>
<MudTd>
<MudChip T="string" Size="Size.Small"
Color="@GetPaymentStatusColor(context.PaymentStatus)"
Variant="Variant.Filled">
@GetPaymentStatusText(context.PaymentStatus)
</MudChip>
</MudTd>
<MudTd>
<MudChip T="string" Size="Size.Small"
Color="@GetDeliveryStatusColor((int)context.DeliveryStatus)"
Variant="Variant.Outlined">
@GetDeliveryStatusText((int)context.DeliveryStatus)
</MudChip>
</MudTd>
<MudTd>@FormatDate(context)</MudTd>
<MudTd>
<MudButton Size="Size.Small" Variant="Variant.Outlined" Color="Color.Primary"
OnClick="() => ViewOrder(context.Id)">
جزئیات
</MudButton>
</MudTd>
</RowTemplate>
</MudTable>
</MudPaper>
</MudHidden>
<!-- Mobile Cards -->
<MudHidden Breakpoint="Breakpoint.MdAndUp">
<MudStack Spacing="2">
@foreach (var order in _orders)
{
<MudPaper Class="pa-3 rounded-lg cursor-pointer" Outlined="true"
@onclick="() => ViewOrder(order.Id)">
<MudStack Spacing="1">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<MudText Typo="Typo.subtitle2">سفارش #@order.Id</MudText>
<MudChip T="string" Size="Size.Small"
Color="@GetPaymentStatusColor(order.PaymentStatus)"
Variant="Variant.Filled">
@GetPaymentStatusText(order.PaymentStatus)
</MudChip>
</MudStack>
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText Typo="Typo.caption" Class="mud-text-secondary">@FormatDate(order)</MudText>
<MudChip T="string" Size="Size.Small"
Color="@GetDeliveryStatusColor((int)order.DeliveryStatus)"
Variant="Variant.Outlined">
@GetDeliveryStatusText((int)order.DeliveryStatus)
</MudChip>
</MudStack>
<MudDivider />
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText Typo="Typo.body2">@GetItemsCount(order) قلم</MudText>
<MudText Typo="Typo.body2" Class="fw-semibold">@FormatPrice(GetTotalAmount(order)) تومان</MudText>
</MudStack>
</MudStack>
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText>وضعیت: @GetStatusText(o.PaymentStatus)</MudText>
<MudText Color="Color.Primary">@FormatPrice(o.FactorDetails.Sum(s=>(s.UnitPrice ?? 0) * (s.Count ?? 0)))</MudText>
</MudStack>
<MudStack Row="true" Justify="Justify.FlexEnd">
<MudButton Size="Size.Small" Variant="Variant.Outlined" Href="@($"{RouteConstants.Store.OrderDetail}{o.Id}")" StartIcon="@Icons.Material.Filled.Receipt">جزئیات</MudButton>
</MudStack>
</MudStack>
</MudPaper>
}
</MudStack>
</MudHidden>
}
</MudPaper>
}
</MudStack>
</MudHidden>
}
</MudStack>
</MudContainer>
@@ -1,5 +1,5 @@
using System;
using CMSMicroservice.Protobuf.Protos.UserOrder;
using DateTimeConverterCL;
using FrontOffice.Main.Utilities;
using Microsoft.AspNetCore.Components;
using Messages = CMSMicroservice.Protobuf.Protos;
@@ -10,7 +10,6 @@ namespace FrontOffice.Main.Pages.Store;
public partial class Orders : ComponentBase
{
[Inject] private OrderService OrderService { get; set; } = default!;
[Inject] private VATService VAT { get; set; } = default!;
private List<GetUserOrderResponse> _orders = new();
private bool _loading;
@@ -33,28 +32,81 @@ public partial class Orders : ComponentBase
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
private void ViewOrder(long orderId)
{
if (firstRender)
Navigation.NavigateTo($"{RouteConstants.Store.OrderDetail}{orderId}");
}
private static string FormatPrice(long price) => $"{price:N0}";
private static string FormatDate(GetUserOrderResponse order)
{
try
{
// بارگذاری نرخ VAT
await VAT.LoadAsync();
var timestamp = order.PaymentDate;
if (timestamp is null)
return "در انتظار پرداخت";
return timestamp.ToDateTime().ToLocalTime().MiladiToJalaliWithTime();
}
await base.OnAfterRenderAsync(firstRender);
}
private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price);
private string GetStatusText(Messages.PaymentStatus contextPaymentStatus)
{
return contextPaymentStatus switch
catch
{
Messages.PaymentStatus.Pending => "در انتظار پرداخت",
Messages.PaymentStatus.Success => "پرداخت شده",
Messages.PaymentStatus.Reject => "پرداخت ناموفق",
_ => "نامشخص",
};
return "—";
}
}
}
private static int GetItemsCount(GetUserOrderResponse order) =>
order.FactorDetails.Sum(f => f.Count ?? 0);
private static long GetTotalAmount(GetUserOrderResponse order)
{
if (order.VatInfo is not null && order.VatInfo.TotalAmount > 0)
return order.VatInfo.TotalAmount;
if (order.Amount > 0)
return order.Amount;
return order.FactorDetails.Sum(f => (f.UnitPrice ?? 0) * (f.Count ?? 0));
}
private static string GetPaymentStatusText(Messages.PaymentStatus status) => status switch
{
Messages.PaymentStatus.Pending => "در انتظار پرداخت",
Messages.PaymentStatus.Success => "پرداخت شده",
Messages.PaymentStatus.Reject => "پرداخت ناموفق",
_ => "نامشخص"
};
private static Color GetPaymentStatusColor(Messages.PaymentStatus status) => status switch
{
Messages.PaymentStatus.Pending => Color.Warning,
Messages.PaymentStatus.Success => Color.Success,
Messages.PaymentStatus.Reject => Color.Error,
_ => Color.Default
};
// Domain/public_messages: None=0, Pending=1, InTransit=2, Delivered=3, Returned=4, Cancelled=5, ReadyForOfficePickup=6
private static string GetDeliveryStatusText(int status) => status switch
{
0 => "بدون ارسال",
1 => "در انتظار ارسال",
2 => "ارسال شده",
3 => "تحویل داده شده",
4 => "مرجوع شده",
5 => "لغو شده",
6 => "آماده تحویل در دفتر",
_ => "نامشخص"
};
private static Color GetDeliveryStatusColor(int status) => status switch
{
0 => Color.Default,
1 => Color.Warning,
2 => Color.Primary,
3 => Color.Success,
4 => Color.Error,
5 => Color.Dark,
6 => Color.Primary,
_ => Color.Default
};
}
@@ -11,9 +11,24 @@
<MudStack Spacing="2">
@if (AllowChargeCredit)
{
<MudText Typo="Typo.body2" Class="mud-text-secondary">
برای تکمیل این سفارش، موجودی اصلی شما کافی نیست. می‌توانید کیف پول را شارژ کنید و سپس سفارش را ثبت کنید.
</MudText>
@if (IsMagicWallet && !MagicCeilingFull)
{
<MudText Typo="Typo.body2" Class="mud-text-secondary">
برای تکمیل این سفارش موجودی شما کافی نیست. کیف پول شما در حالت جادویی است؛ برای دریافت ضریب، از مسیر شارژ جادویی اقدام کنید.
</MudText>
}
else if (IsMagicWallet && MagicCeilingFull)
{
<MudAlert Severity="Severity.Warning" Dense="true" Variant="Variant.Outlined">
سقف شارژ جادویی شما در این دور پر است. می‌توانید به‌صورت استثنایی کیف اصلی را بدون ضریب (۱:۱) شارژ کنید.
</MudAlert>
}
else
{
<MudText Typo="Typo.body2" Class="mud-text-secondary">
برای تکمیل این سفارش، موجودی اصلی شما کافی نیست. می‌توانید کیف پول را شارژ کنید و سپس سفارش را ثبت کنید.
</MudText>
}
}
else
{
@@ -46,10 +61,10 @@
@if (AllowChargeCredit)
{
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Payment"
Color="@(IsMagicWallet && !MagicCeilingFull ? Color.Secondary : Color.Primary)"
StartIcon="@(IsMagicWallet && !MagicCeilingFull ? Icons.Material.Filled.AutoAwesome : Icons.Material.Filled.Payment)"
OnClick="GoToCharge">
شارژ حساب اصلی
@ChargeButtonLabel
</MudButton>
}
else if (!HasPurchasedPackage)
@@ -93,9 +108,33 @@
[Parameter]
public bool HasPurchasedPackage { get; set; }
[Parameter]
public bool IsMagicWallet { get; set; }
/// <summary>سقف واریز جادویی این دور پر شده است.</summary>
[Parameter]
public bool MagicCeilingFull { get; set; }
private string ChargeButtonLabel =>
IsMagicWallet && !MagicCeilingFull
? "شارژ کیف جادویی"
: IsMagicWallet && MagicCeilingFull
? "شارژ عادی بدون ضریب (سقف جادویی پر است)"
: "شارژ حساب اصلی";
private void Cancel() => MudDialog.Cancel();
private void GoToCharge() => MudDialog.Close(DialogResult.Ok(ShortfallAmount));
private void GoToCharge()
{
if (IsMagicWallet && !MagicCeilingFull)
{
MudDialog.Cancel();
Navigation.NavigateTo(RouteConstants.Profile.MagicWallet);
return;
}
MudDialog.Close(DialogResult.Ok(ShortfallAmount));
}
private void GoToPackages()
{
@@ -219,6 +219,8 @@ public class DiscountOrderService
2 => "ارسال شده",
3 => "تحویل داده شده",
4 => "لغو شده",
5 => "آماده تحویل در دفتر",
6 => "مرجوع شده",
_ => "نامشخص"
};
@@ -228,7 +230,9 @@ public class DiscountOrderService
1 => Color.Info,
2 => Color.Primary,
3 => Color.Success,
4 => Color.Error,
4 => Color.Dark,
5 => Color.Primary,
6 => Color.Error,
_ => Color.Default
};