Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c1a8ffd53 | |||
| a3681a8bcd |
@@ -89,7 +89,7 @@
|
|||||||
{
|
{
|
||||||
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
|
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
|
||||||
<MudIcon Icon="@Icons.Material.Filled.Check" Size="Size.Small" Color="Color.Primary" />
|
<MudIcon Icon="@Icons.Material.Filled.Check" Size="Size.Small" Color="Color.Primary" />
|
||||||
<MudText Typo="Typo.caption">ضریب تخفیف: @package.DiscountMultiplier.ToString("F1")x</MudText>
|
<MudText Typo="Typo.caption">ضریب اعتبار: @package.DiscountMultiplier.ToString("F1")x</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
}
|
}
|
||||||
@if (package.MagicWalletMultiplier > 0)
|
@if (package.MagicWalletMultiplier > 0)
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
لینک دعوت شما هنوز فعال نشده است
|
لینک دعوت شما هنوز فعال نشده است
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudText Typo="Typo.body2" Class="mud-text-secondary mb-1" Style="max-width:560px; margin:0 auto;">
|
<MudText Typo="Typo.body2" Class="mud-text-secondary mb-1" Style="max-width:560px; margin:0 auto;">
|
||||||
برای فعالسازی لینک دعوت، ابتدا <strong>پکیج پایه</strong> را تهیه کنید و سپس در <strong>باشگاه مشتریان</strong> عضو شوید.
|
برای فعالسازی لینک دعوت، ابتدا یکی از <strong>پکیجها</strong> را تهیه کنید و سپس در <strong>باشگاه مشتریان</strong> عضو شوید.
|
||||||
</MudText>
|
</MudText>
|
||||||
<MudText Typo="Typo.body2" Class="mud-text-secondary mb-4" Style="max-width:560px; margin:0 auto;">
|
<MudText Typo="Typo.body2" Class="mud-text-secondary mb-4" Style="max-width:560px; margin:0 auto;">
|
||||||
از مزایای ویژه عضویت بهرهمند شده و با فعالیت در زمینه توسعه فروشگاهها پاداش دریافت کنید.
|
از مزایای ویژه عضویت بهرهمند شده و با فعالیت در زمینه توسعه فروشگاهها پاداش دریافت کنید.
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
Class="rounded-pill"
|
Class="rounded-pill"
|
||||||
StartIcon="@Icons.Material.Filled.ShoppingCart"
|
StartIcon="@Icons.Material.Filled.ShoppingCart"
|
||||||
OnClick="OpenPurchaseOptions">
|
OnClick="OpenPurchaseOptions">
|
||||||
شروع فرآیند تامین اعتبار
|
تهیه پکیج
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
}
|
}
|
||||||
@@ -195,88 +195,4 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
|
|
||||||
@* ── Purchase Options Dialog ── *@
|
|
||||||
<MudDialog @bind-Visible="_showPurchaseBottomSheet">
|
|
||||||
<DialogContent>
|
|
||||||
<MudStack Spacing="3" Class="pa-2">
|
|
||||||
<MudText Typo="Typo.h6" Align="Align.Center">
|
|
||||||
خرید پکیج پایه ۵۶ میلیون تومان
|
|
||||||
</MudText>
|
|
||||||
<MudDivider />
|
|
||||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">
|
|
||||||
برای خرید پکیج پایه، یکی از روشهای زیر را انتخاب کنید:
|
|
||||||
</MudText>
|
|
||||||
|
|
||||||
<MudPaper Elevation="0" Class="pa-4 rounded-lg" Style="border: 2px solid var(--mud-palette-primary);">
|
|
||||||
<MudStack Spacing="2">
|
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
|
||||||
<MudIcon Icon="@Icons.Material.Filled.CreditCard" Color="Color.Primary" Size="Size.Medium" />
|
|
||||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary"><b>پرداخت مستقیم</b></MudText>
|
|
||||||
</MudStack>
|
|
||||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">پرداخت آنی از طریق درگاه بانکی</MudText>
|
|
||||||
@if (_purchaseCycleCount > 0)
|
|
||||||
{
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
|
||||||
Disabled="@_isProcessingPayment"
|
|
||||||
StartIcon="@Icons.Material.Filled.Payment"
|
|
||||||
OnClick="DirectPayment">
|
|
||||||
@if (_isProcessingPayment)
|
|
||||||
{
|
|
||||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="me-2" />
|
|
||||||
<span>در حال انتقال به درگاه...</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span>پرداخت با کارت بانکی</span>
|
|
||||||
}
|
|
||||||
</MudButton>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
|
||||||
Disabled="@_isProcessingPayment"
|
|
||||||
StartIcon="@Icons.Material.Filled.Payment"
|
|
||||||
OnClick="DirectPayment">
|
|
||||||
@if (_isProcessingPayment)
|
|
||||||
{
|
|
||||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="me-2" />
|
|
||||||
<span>در حال انتقال به درگاه...</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span>پرداخت با کارت بانکی</span>
|
|
||||||
}
|
|
||||||
</MudButton>
|
|
||||||
}
|
|
||||||
</MudStack>
|
|
||||||
</MudPaper>
|
|
||||||
|
|
||||||
@if (_purchaseCycleCount == 0)
|
|
||||||
{
|
|
||||||
<MudPaper Elevation="0" Class="pa-4 rounded-lg" Style="border: 2px solid var(--mud-palette-tertiary);">
|
|
||||||
<MudStack Spacing="2">
|
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
|
||||||
<MudIcon Icon="@Icons.Material.Filled.Diamond" Color="Color.Tertiary" Size="Size.Medium" />
|
|
||||||
<MudText Typo="Typo.subtitle1" Color="Color.Tertiary"><b>اعتبار الماسی دایا</b></MudText>
|
|
||||||
</MudStack>
|
|
||||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">تأمین اعتبار از طریق خرید توکن الماس و دریافت وام</MudText>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Tertiary" FullWidth="true"
|
|
||||||
StartIcon="@Icons.Material.Filled.AccountBalance" OnClick="DayaLoanPayment">
|
|
||||||
تأمین اعتبار الماسی
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
</MudPaper>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudAlert Severity="Severity.Info" Dense="true" Class="mt-1">
|
|
||||||
از دور دوم به بعد، خرید پکیج فقط از طریق درگاه بانکی امکانپذیر است.
|
|
||||||
</MudAlert>
|
|
||||||
}
|
|
||||||
|
|
||||||
<MudButton Variant="Variant.Text" Color="Color.Default" FullWidth="true" OnClick="ClosePurchaseOptions">
|
|
||||||
بستن
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
</DialogContent>
|
|
||||||
</MudDialog>
|
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ public partial class Index
|
|||||||
private bool _isClubMemberActive;
|
private bool _isClubMemberActive;
|
||||||
private bool CanShowReferralLink => _hasPurchasedPackage && _isClubMemberActive;
|
private bool CanShowReferralLink => _hasPurchasedPackage && _isClubMemberActive;
|
||||||
|
|
||||||
// Purchase Options Bottom Sheet
|
// Purchase flow
|
||||||
private bool _showPurchaseBottomSheet;
|
|
||||||
private bool _isProcessingPayment;
|
private bool _isProcessingPayment;
|
||||||
private int _purchaseCycleCount; // تعداد دورهای خرید — اگر > 0 فقط IPG مجاز
|
private int _purchaseCycleCount; // تعداد دورهای خرید — اگر > 0 فقط IPG مجاز
|
||||||
|
|
||||||
@@ -394,40 +393,55 @@ public partial class Index
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenPurchaseOptions()
|
private async Task OpenPurchaseOptions()
|
||||||
{
|
{
|
||||||
_showPurchaseBottomSheet = true;
|
var options = new DialogOptions
|
||||||
|
{
|
||||||
|
MaxWidth = MaxWidth.Small,
|
||||||
|
FullWidth = true,
|
||||||
|
CloseOnEscapeKey = true,
|
||||||
|
BackdropClick = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var parameters = new DialogParameters<Shared.PackagePurchaseDialog>
|
||||||
|
{
|
||||||
|
{ x => x.PurchaseCycleCount, _purchaseCycleCount }
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialog = await DialogService.ShowAsync<Shared.PackagePurchaseDialog>(
|
||||||
|
string.Empty, parameters, options);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
|
||||||
|
if (result.Canceled) return;
|
||||||
|
|
||||||
|
if (result.Data is Shared.PackagePurchaseDialog.PackagePurchaseResult purchase)
|
||||||
|
{
|
||||||
|
switch (purchase.Method)
|
||||||
|
{
|
||||||
|
case Shared.PackagePurchaseDialog.PaymentMethodType.DirectPayment:
|
||||||
|
await ProcessDirectPayment(purchase.Package.Id);
|
||||||
|
break;
|
||||||
|
case Shared.PackagePurchaseDialog.PaymentMethodType.DayaLoan:
|
||||||
|
await ProcessDayaLoanPayment();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClosePurchaseOptions()
|
private async Task ProcessDirectPayment(long packageId)
|
||||||
{
|
|
||||||
_showPurchaseBottomSheet = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DirectPayment()
|
|
||||||
{
|
{
|
||||||
if (_isProcessingPayment) return;
|
if (_isProcessingPayment) return;
|
||||||
|
|
||||||
_isProcessingPayment = true;
|
_isProcessingPayment = true;
|
||||||
_showPurchaseBottomSheet = false;
|
StateHasChanged();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Get available packages and pick the first one
|
|
||||||
var packages = await PackageContract.GetCustomerPackagesAsync(new GetCustomerPackagesRequest());
|
|
||||||
var selectedPackage = packages?.Models?.FirstOrDefault();
|
|
||||||
if (selectedPackage == null)
|
|
||||||
{
|
|
||||||
Snackbar.Add("پکیجی برای خرید یافت نشد", Severity.Error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call CMS to initiate purchase (UserId from JWT, PackageId explicit)
|
|
||||||
var callbackUrl = $"{Navigation.BaseUri}profile/payment-callback";
|
var callbackUrl = $"{Navigation.BaseUri}profile/payment-callback";
|
||||||
|
|
||||||
var response = await PackageContract.CustomerPurchasePackageAsync(new CustomerPurchasePackageRequest
|
var response = await PackageContract.CustomerPurchasePackageAsync(new CustomerPurchasePackageRequest
|
||||||
{
|
{
|
||||||
PackageId = selectedPackage.Id,
|
PackageId = packageId,
|
||||||
CallbackUrl = callbackUrl,
|
CallbackUrl = callbackUrl,
|
||||||
PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway
|
PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway
|
||||||
});
|
});
|
||||||
@@ -438,9 +452,6 @@ public partial class Index
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to payment gateway
|
|
||||||
// ZarinPal appends ?Authority=...&Status=... to callback URL
|
|
||||||
// PaymentCallback uses Authority+Status to verify via CustomerVerifyPackagePurchase
|
|
||||||
if (!string.IsNullOrEmpty(response.PaymentGatewayUrl))
|
if (!string.IsNullOrEmpty(response.PaymentGatewayUrl))
|
||||||
{
|
{
|
||||||
Navigation.NavigateTo(response.PaymentGatewayUrl, forceLoad: true);
|
Navigation.NavigateTo(response.PaymentGatewayUrl, forceLoad: true);
|
||||||
@@ -461,41 +472,34 @@ public partial class Index
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DayaLoanPayment()
|
private async Task ProcessDayaLoanPayment()
|
||||||
{
|
{
|
||||||
// Validate user info before redirecting
|
|
||||||
if (string.IsNullOrWhiteSpace(_updateUserRequest.FirstName))
|
if (string.IsNullOrWhiteSpace(_updateUserRequest.FirstName))
|
||||||
{
|
{
|
||||||
_showPurchaseBottomSheet = false;
|
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (نام وارد نشده)", Severity.Error);
|
||||||
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (نام وارد نشده)", Severity.Error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (string.IsNullOrWhiteSpace(_updateUserRequest.LastName))
|
if (string.IsNullOrWhiteSpace(_updateUserRequest.LastName))
|
||||||
{
|
{
|
||||||
_showPurchaseBottomSheet = false;
|
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (نام خانوادگی وارد نشده)", Severity.Error);
|
||||||
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (نام خانوادگی وارد نشده)", Severity.Error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (string.IsNullOrWhiteSpace(_updateUserRequest.NationalCode))
|
if (string.IsNullOrWhiteSpace(_updateUserRequest.NationalCode))
|
||||||
{
|
{
|
||||||
_showPurchaseBottomSheet = false;
|
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (کدملی وارد نشده)", Severity.Error);
|
||||||
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (کدملی وارد نشده)", Severity.Error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_updateUserRequest.BirthDate == null)
|
if (_updateUserRequest.BirthDate == null)
|
||||||
{
|
{
|
||||||
_showPurchaseBottomSheet = false;
|
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (تاریخ تولد وارد نشده)", Severity.Error);
|
||||||
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (تاریخ تولد وارد نشده)", Severity.Error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!_addresses.Any())
|
if (!_addresses.Any())
|
||||||
{
|
{
|
||||||
_showPurchaseBottomSheet = false;
|
Snackbar.Add("آدرس محل سکونت شما الزامی است!", Severity.Error);
|
||||||
Snackbar.Add($"آدرس محل سکونت شما الزامی است!", Severity.Error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_showPurchaseBottomSheet = false;
|
|
||||||
var url = "https://dayadiamond.ir/profile/creditpurchase/?merchantcode=56146364";
|
var url = "https://dayadiamond.ir/profile/creditpurchase/?merchantcode=56146364";
|
||||||
await JSRuntime.InvokeVoidAsync("open", url, "_blank");
|
await JSRuntime.InvokeVoidAsync("open", url, "_blank");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,234 @@
|
|||||||
|
@using FrontOffice.Main.Utilities
|
||||||
|
@inject PackageService PackageService
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
|
||||||
|
<MudDialog>
|
||||||
|
<TitleContent>
|
||||||
|
@if (_selectedPackage != null)
|
||||||
|
{
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.ArrowForward"
|
||||||
|
Size="Size.Small"
|
||||||
|
OnClick="BackToList" />
|
||||||
|
<MudText Typo="Typo.h6">انتخاب روش پرداخت</MudText>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.ShoppingCart" Color="Color.Primary" />
|
||||||
|
<MudText Typo="Typo.h6">انتخاب پکیج</MudText>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
</TitleContent>
|
||||||
|
<DialogContent>
|
||||||
|
@if (_isLoading)
|
||||||
|
{
|
||||||
|
<MudStack AlignItems="AlignItems.Center" Class="py-8">
|
||||||
|
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
|
||||||
|
<MudText Typo="Typo.body2" Class="mud-text-secondary mt-2">در حال بارگذاری پکیجها...</MudText>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
else if (_selectedPackage != null)
|
||||||
|
{
|
||||||
|
@* ── Step 2: Payment method selection ── *@
|
||||||
|
<MudStack Spacing="3">
|
||||||
|
@* Selected Package Summary *@
|
||||||
|
<MudPaper Elevation="0" Class="pa-3 rounded-lg" Style="background:rgba(99,102,241,.06);">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudAvatar Size="Size.Medium" Style="background:rgba(99,102,241,.15); color:#6366f1;">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Inventory2" />
|
||||||
|
</MudAvatar>
|
||||||
|
<MudStack Spacing="0" Class="flex-grow-1">
|
||||||
|
<MudText Typo="Typo.subtitle1"><b>@_selectedPackage.Title</b></MudText>
|
||||||
|
<MudText Typo="Typo.body2" Color="Color.Success">@_selectedPackage.FormattedPrice</MudText>
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
</MudPaper>
|
||||||
|
|
||||||
|
<MudDivider />
|
||||||
|
|
||||||
|
<MudText Typo="Typo.body2" Class="mud-text-secondary">
|
||||||
|
روش پرداخت خود را انتخاب کنید:
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
@* Direct Payment — always available *@
|
||||||
|
<MudPaper Elevation="0" Class="pa-4 rounded-lg pkg-payment-option"
|
||||||
|
Style="border:2px solid var(--mud-palette-primary); cursor:pointer;"
|
||||||
|
@onclick="() => SelectPaymentMethod(PaymentMethodType.DirectPayment)">
|
||||||
|
<MudStack Spacing="2">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.CreditCard" Color="Color.Primary" Size="Size.Medium" />
|
||||||
|
<MudStack Spacing="0" Class="flex-grow-1">
|
||||||
|
<MudText Typo="Typo.subtitle1" Color="Color.Primary"><b>پرداخت مستقیم</b></MudText>
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">پرداخت آنی از طریق درگاه بانکی</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.ArrowBack" Color="Color.Primary" Size="Size.Small" />
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
</MudPaper>
|
||||||
|
|
||||||
|
@* Daya Loan — only for base package AND first purchase cycle *@
|
||||||
|
@if (_selectedPackage.SupportsDayaPurchase && PurchaseCycleCount == 0)
|
||||||
|
{
|
||||||
|
<MudPaper Elevation="0" Class="pa-4 rounded-lg pkg-payment-option"
|
||||||
|
Style="border:2px solid var(--mud-palette-tertiary); cursor:pointer;"
|
||||||
|
@onclick="() => SelectPaymentMethod(PaymentMethodType.DayaLoan)">
|
||||||
|
<MudStack Spacing="2">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Diamond" Color="Color.Tertiary" Size="Size.Medium" />
|
||||||
|
<MudStack Spacing="0" Class="flex-grow-1">
|
||||||
|
<MudText Typo="Typo.subtitle1" Color="Color.Tertiary"><b>اعتبار الماسی دایا</b></MudText>
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">تأمین اعتبار از طریق خرید توکن الماس</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.ArrowBack" Color="Color.Tertiary" Size="Size.Small" />
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
</MudPaper>
|
||||||
|
}
|
||||||
|
else if (!_selectedPackage.SupportsDayaPurchase)
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Text" Class="mt-1">
|
||||||
|
اعتبار الماسی دایا فقط برای پکیج پایه قابل استفاده است.
|
||||||
|
</MudAlert>
|
||||||
|
}
|
||||||
|
else if (PurchaseCycleCount > 0)
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Text" Class="mt-1">
|
||||||
|
از دور دوم به بعد، خرید پکیج فقط از طریق درگاه بانکی امکانپذیر است.
|
||||||
|
</MudAlert>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@* ── Step 1: Package tile grid ── *@
|
||||||
|
<MudStack Spacing="3">
|
||||||
|
<MudText Typo="Typo.body2" Class="mud-text-secondary">
|
||||||
|
پکیج مورد نظر خود را انتخاب کنید:
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudGrid Spacing="3">
|
||||||
|
@foreach (var pkg in _packages)
|
||||||
|
{
|
||||||
|
<MudItem xs="12" sm="6" md="@(_packages.Count <= 2 ? 6 : 4)">
|
||||||
|
<MudPaper Elevation="0" Class="pa-4 rounded-xl pkg-tile text-center"
|
||||||
|
Style="@GetTileStyle(pkg)"
|
||||||
|
@onclick="() => SelectPackage(pkg)">
|
||||||
|
@if (pkg.IsBasePackage)
|
||||||
|
{
|
||||||
|
<MudChip T="string" Size="Size.Small" Color="Color.Primary" Variant="Variant.Filled"
|
||||||
|
Class="pkg-tile-badge">پایه</MudChip>
|
||||||
|
}
|
||||||
|
<MudStack Spacing="1" AlignItems="AlignItems.Center">
|
||||||
|
<MudAvatar Size="Size.Large" Style="@GetAvatarStyle(pkg)" Class="mb-1">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Inventory2" Size="Size.Large" />
|
||||||
|
</MudAvatar>
|
||||||
|
<MudText Typo="Typo.subtitle1"><b>@pkg.Title</b></MudText>
|
||||||
|
<MudText Typo="Typo.h6" Color="Color.Success">@pkg.FormattedPrice</MudText>
|
||||||
|
@if (!string.IsNullOrWhiteSpace(pkg.Description))
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary"
|
||||||
|
Style="display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;">
|
||||||
|
@((MarkupString)pkg.Description)
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
@* Key features *@
|
||||||
|
<MudStack Spacing="0" Class="mt-2" Style="width:100%;">
|
||||||
|
@if (pkg.MagicWalletMultiplier > 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.AutoAwesome" Size="Size.Small" Class="me-1" Style="font-size:.85rem;vertical-align:middle;" />
|
||||||
|
ضریب جادویی: @pkg.MagicWalletMultiplier.ToString("F1")x
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
@if (pkg.DiscountMultiplier > 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Discount" Size="Size.Small" Class="me-1" Style="font-size:.85rem;vertical-align:middle;" />
|
||||||
|
ضریب اعتبار: @pkg.DiscountMultiplier.ToString("F1")x
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
@if (pkg.SupportsDayaPurchase)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.caption" Color="Color.Tertiary">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Diamond" Size="Size.Small" Class="me-1" Style="font-size:.85rem;vertical-align:middle;" />
|
||||||
|
قابل خرید با دایا
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
}
|
||||||
|
</MudGrid>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="Cancel" Variant="Variant.Text" Color="Color.Default">بستن</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
|
/// <summary>Number of previous purchase cycles — controls Daya eligibility</summary>
|
||||||
|
[Parameter] public int PurchaseCycleCount { get; set; }
|
||||||
|
|
||||||
|
private List<PackageDto> _packages = new();
|
||||||
|
private PackageDto? _selectedPackage;
|
||||||
|
private bool _isLoading = true;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
_isLoading = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_packages = await PackageService.GetAllPackagesAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Snackbar.Add("خطا در بارگذاری پکیجها", MudBlazor.Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectPackage(PackageDto package)
|
||||||
|
{
|
||||||
|
_selectedPackage = package;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BackToList()
|
||||||
|
{
|
||||||
|
_selectedPackage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectPaymentMethod(PaymentMethodType method)
|
||||||
|
{
|
||||||
|
var result = new PackagePurchaseResult(_selectedPackage!, method);
|
||||||
|
MudDialog.Close(DialogResult.Ok(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel() => MudDialog.Cancel();
|
||||||
|
|
||||||
|
private static string GetTileStyle(PackageDto pkg)
|
||||||
|
{
|
||||||
|
return pkg.IsBasePackage
|
||||||
|
? "border:2px solid var(--mud-palette-primary); background:rgba(99,102,241,.04); cursor:pointer;"
|
||||||
|
: "border:2px solid var(--mud-palette-lines-default); background:var(--mud-palette-surface); cursor:pointer;";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetAvatarStyle(PackageDto pkg)
|
||||||
|
{
|
||||||
|
return pkg.IsBasePackage
|
||||||
|
? "background:rgba(99,102,241,.15); color:#6366f1;"
|
||||||
|
: "background:rgba(16,185,129,.12); color:#10b981;";
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PaymentMethodType { DirectPayment, DayaLoan }
|
||||||
|
public record PackagePurchaseResult(PackageDto Package, PaymentMethodType Method);
|
||||||
|
}
|
||||||
@@ -20,7 +20,8 @@ public record PackageDto(
|
|||||||
bool SupportsDayaPurchase = false,
|
bool SupportsDayaPurchase = false,
|
||||||
bool SupportsDirectPurchase = false)
|
bool SupportsDirectPurchase = false)
|
||||||
{
|
{
|
||||||
public string FormattedPrice => string.Format("{0:N0} تومان", Price);
|
/// <summary>قیمت به تومان — مقدار Price از سرور به ریال است</summary>
|
||||||
|
public string FormattedPrice => string.Format("{0:N0} تومان", Price / 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1611,3 +1611,30 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*#endregion*/
|
/*#endregion*/
|
||||||
|
|
||||||
|
/* ── Package Purchase Dialog tiles ── */
|
||||||
|
.pkg-tile {
|
||||||
|
transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.pkg-tile:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 6px 20px rgba(0,0,0,.08);
|
||||||
|
border-color: var(--mud-palette-primary) !important;
|
||||||
|
}
|
||||||
|
.pkg-tile-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
|
.pkg-payment-option {
|
||||||
|
transition: transform .15s ease, box-shadow .15s ease;
|
||||||
|
}
|
||||||
|
.pkg-payment-option:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,.06);
|
||||||
|
}
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.pkg-tile { padding: .8rem !important; }
|
||||||
|
.pkg-tile .mud-avatar-large { width: 48px !important; height: 48px !important; }
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user