feat: Add manual membership payment page and week picker component
All checks were successful
Build and Deploy / build (push) Successful in 2m36s

This commit is contained in:
masoodafar-web
2025-12-12 10:24:43 +03:30
parent 2fc7733c84
commit cc721da65f
16 changed files with 448 additions and 66 deletions

View File

@@ -0,0 +1,131 @@
@page "/payment/membership"
@using BackOffice.BFF.ManualPayment.Protobuf
@using BackOffice.Main.Pages.AutoComplete
@attribute [Authorize(Roles = "Admin,SuperAdmin")]
<PageTitle>پرداخت دستی عضویت</PageTitle>
<MudContainer MaxWidth="MaxWidth.Large" Class="mt-4">
<MudCard>
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h5">
<MudIcon Icon="@Icons.Material.Filled.Payment" Class="ml-2" />
پرداخت دستی عضویت
</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudGrid>
<!-- انتخاب کاربر -->
<MudItem xs="12" md="6">
<UserAutoComplete
Label="انتخاب کاربر *"
@bind-SelectedUserId="_userId"
HelperText="جستجو با نام، موبایل یا شناسه" />
</MudItem>
<!-- مبلغ -->
<MudItem xs="12" md="6">
<MudNumericField
@bind-Value="_amount"
Label="مبلغ (ریال) *"
Min="0"
Step="10000"
Format="N0"
Variant="Variant.Outlined"
HelperText="مبلغ پرداختی به ریال" />
</MudItem>
<!-- شماره مرجع -->
<MudItem xs="12" md="6">
<MudTextField
@bind-Value="_referenceNumber"
Label="شماره مرجع *"
Variant="Variant.Outlined"
MaxLength="50"
HelperText="شماره مرجع تراکنش یا فیش" />
</MudItem>
<!-- توضیحات -->
<MudItem xs="12" md="6">
<MudTextField
@bind-Value="_description"
Label="توضیحات"
Variant="Variant.Outlined"
Lines="3"
MaxLength="500"
HelperText="توضیحات اختیاری" />
</MudItem>
</MudGrid>
@if (_showResult)
{
<MudAlert Severity="Severity.Success" Class="mt-4" ShowCloseIcon CloseIconClicked="@(() => _showResult = false)">
<MudText>@_resultMessage</MudText>
<MudText Typo="Typo.caption">شماره تراکنش: @_transactionId</MudText>
<MudText Typo="Typo.caption">شماره سفارش: @_orderId</MudText>
<MudText Typo="Typo.caption">موجودی جدید کیف پول: @_newWalletBalance.ToString("N0") ریال</MudText>
</MudAlert>
}
</MudCardContent>
<MudCardActions>
<MudButton
Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Check"
OnClick="ProcessPayment"
Disabled="@_isProcessing">
@if (_isProcessing)
{
<MudProgressCircular Class="ml-2" Size="Size.Small" Indeterminate="true" />
<MudText>در حال ثبت...</MudText>
}
else
{
<MudText>ثبت پرداخت</MudText>
}
</MudButton>
<MudButton
Variant="Variant.Outlined"
Color="Color.Default"
StartIcon="@Icons.Material.Filled.Clear"
OnClick="ResetForm"
Disabled="@_isProcessing">
پاک کردن فرم
</MudButton>
</MudCardActions>
</MudCard>
<!-- راهنما -->
<MudCard Class="mt-4">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6">
<MudIcon Icon="@Icons.Material.Filled.Info" Class="ml-2" />
راهنما
</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudText Typo="Typo.body2" Class="mb-2">این صفحه برای ثبت پرداخت‌های دستی عضویت استفاده می‌شود. پس از ثبت:</MudText>
<MudList Dense="true">
<MudListItem Icon="@Icons.Material.Filled.AccountBalance">
<MudText Typo="Typo.body2">مبلغ به کیف پول کاربر (Balance و DiscountBalance) اضافه می‌شود</MudText>
</MudListItem>
<MudListItem Icon="@Icons.Material.Filled.History">
<MudText Typo="Typo.body2">لاگ تغییرات کیف پول ثبت می‌شود</MudText>
</MudListItem>
<MudListItem Icon="@Icons.Material.Filled.Receipt">
<MudText Typo="Typo.body2">تراکنش با وضعیت موفق ثبت می‌شود</MudText>
</MudListItem>
<MudListItem Icon="@Icons.Material.Filled.ShoppingCart">
<MudText Typo="Typo.body2">سفارش خرید پکیج عضویت ثبت می‌شود</MudText>
</MudListItem>
</MudList>
</MudCardContent>
</MudCard>
</MudContainer>

View File

@@ -0,0 +1,103 @@
using BackOffice.BFF.ManualPayment.Protobuf;
using BackOffice.Main.Components;
using Grpc.Core;
using Microsoft.AspNetCore.Components;
namespace BackOffice.Main.Pages.Payment;
public partial class ManualMembershipPayment
{
[Inject] private ManualPaymentContract.ManualPaymentContractClient ManualPaymentClient { get; set; } = default!;
[Inject] private ISnackbar Snackbar { get; set; } = default!;
private long? _userId;
private long _amount = 0;
private string _referenceNumber = string.Empty;
private string? _description;
private bool _isProcessing = false;
private bool _showResult = false;
private string _resultMessage = string.Empty;
private long _transactionId = 0;
private long _orderId = 0;
private long _newWalletBalance = 0;
private async Task ProcessPayment()
{
// Validation
if (!_userId.HasValue || _userId.Value <= 0)
{
Snackbar.Add("لطفا کاربر را انتخاب کنید", Severity.Warning);
return;
}
if (_amount <= 0)
{
Snackbar.Add("لطفا مبلغ معتبری وارد کنید", Severity.Warning);
return;
}
if (string.IsNullOrWhiteSpace(_referenceNumber))
{
Snackbar.Add("لطفا شماره مرجع را وارد کنید", Severity.Warning);
return;
}
try
{
_isProcessing = true;
_showResult = false;
var request = new ProcessManualMembershipPaymentRequest
{
UserId = _userId.Value,
Amount = _amount,
ReferenceNumber = _referenceNumber
};
if (!string.IsNullOrWhiteSpace(_description))
{
request.Description = _description;
}
var response = await ManualPaymentClient.ProcessManualMembershipPaymentAsync(request);
_resultMessage = response.Message;
_transactionId = response.TransactionId;
_orderId = response.OrderId;
_newWalletBalance = response.NewWalletBalance;
_showResult = true;
Snackbar.Add("پرداخت دستی با موفقیت ثبت شد", Severity.Success);
// Reset form
await Task.Delay(2000);
ResetForm();
}
catch (RpcException ex)
{
Snackbar.Add($"خطا در ثبت پرداخت: {ex.Status.Detail}", Severity.Error);
}
catch (Exception ex)
{
Snackbar.Add($"خطای غیرمنتظره: {ex.Message}", Severity.Error);
}
finally
{
_isProcessing = false;
}
}
private void ResetForm()
{
_userId = null;
_amount = 0;
_referenceNumber = string.Empty;
_description = null;
_showResult = false;
_resultMessage = string.Empty;
_transactionId = 0;
_orderId = 0;
_newWalletBalance = 0;
}
}