feat: داشبورد — لیست کاشی پکیج‌ها + مدال انتخاب روش پرداخت

- حذف متن hardcoded 'پکیج پایه ۵۶ میلیون تومان' و دیالوگ inline
- ایجاد PackagePurchaseDialog — کامپوننت مستقل 2 مرحله‌ای:
  مرحله ۱: نمایش کاشی‌های پکیج (ریسپانسیو ۲-۳ تایی)
  مرحله ۲: انتخاب روش پرداخت (درگاه بانکی / دایا الماس)
- دایا الماس فقط برای پکیج پایه + دور اول نمایش داده میشه
- پکیج‌ها داینامیک از API بارگذاری میشن
- تغییر متن CTA از 'شروع فرآیند تامین اعتبار' به 'تهیه پکیج'
- تغییر متن راهنما از 'پکیج پایه را تهیه کنید' به 'یکی از پکیج‌ها را تهیه کنید'
- CSS: hover effects + badge + responsive tiles
This commit is contained in:
masoodafar-web
2026-02-27 20:14:40 +03:30
parent ecc4f447ba
commit a3681a8bcd
4 changed files with 311 additions and 130 deletions
@@ -42,8 +42,7 @@ public partial class Index
private bool _isClubMemberActive;
private bool CanShowReferralLink => _hasPurchasedPackage && _isClubMemberActive;
// Purchase Options Bottom Sheet
private bool _showPurchaseBottomSheet;
// Purchase flow
private bool _isProcessingPayment;
private int _purchaseCycleCount; // تعداد دورهای خرید — اگر > 0 فقط IPG مجاز
@@ -394,53 +393,65 @@ 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()
{
_showPurchaseBottomSheet = false;
}
private async Task DirectPayment()
private async Task ProcessDirectPayment(long packageId)
{
if (_isProcessingPayment) return;
_isProcessingPayment = true;
_showPurchaseBottomSheet = false;
StateHasChanged();
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 response = await PackageContract.CustomerPurchasePackageAsync(new CustomerPurchasePackageRequest
{
PackageId = selectedPackage.Id,
PackageId = packageId,
CallbackUrl = callbackUrl,
PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway
});
if (!response.Success)
{
Snackbar.Add(response.Message ?? "خطا در آغاز فرآیند پرداخت", Severity.Error);
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))
{
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))
{
_showPurchaseBottomSheet = false;
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (نام وارد نشده)", Severity.Error);
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (نام وارد نشده)", Severity.Error);
return;
}
if (string.IsNullOrWhiteSpace(_updateUserRequest.LastName))
{
_showPurchaseBottomSheet = false;
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (نام خانوادگی وارد نشده)", Severity.Error);
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (نام خانوادگی وارد نشده)", Severity.Error);
return;
}
if (string.IsNullOrWhiteSpace(_updateUserRequest.NationalCode))
{
_showPurchaseBottomSheet = false;
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (کدملی وارد نشده)", Severity.Error);
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (کدملی وارد نشده)", Severity.Error);
return;
}
if (_updateUserRequest.BirthDate == null)
{
_showPurchaseBottomSheet = false;
Snackbar.Add($"لطفا اطلاعات شخصی خود را تکمیل کنید. (تاریخ تولد وارد نشده)", Severity.Error);
Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (تاریخ تولد وارد نشده)", Severity.Error);
return;
}
if (!_addresses.Any())
{
_showPurchaseBottomSheet = false;
Snackbar.Add($"آدرس محل سکونت شما الزامی است!", Severity.Error);
Snackbar.Add("آدرس محل سکونت شما الزامی است!", Severity.Error);
return;
}
_showPurchaseBottomSheet = false;
var url = "https://dayadiamond.ir/profile/creditpurchase/?merchantcode=56146364";
await JSRuntime.InvokeVoidAsync("open", url, "_blank");
}