Compare commits
11 Commits
764742dbe7
...
f5bfdba124
| Author | SHA1 | Date | |
|---|---|---|---|
| f5bfdba124 | |||
| c2c07c6b89 | |||
| 955736d345 | |||
| ea357e9865 | |||
| a4061c041b | |||
| a108f89213 | |||
| c71062decf | |||
| c815f8d358 | |||
| 27a3ea76c5 | |||
| 0d0ca252a6 | |||
| aedf312812 |
@@ -73,10 +73,10 @@ jobs:
|
|||||||
|
|
||||||
# Apply manifests and restart
|
# Apply manifests and restart
|
||||||
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
|
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
|
||||||
kubectl apply -f /tmp/frontoffice-deployment.yaml &&
|
kubectl apply -n kbs-stage -f /tmp/frontoffice-deployment.yaml &&
|
||||||
crictl rmi ${REGISTRY}/${IMAGE_NAME}:latest 2>/dev/null || true &&
|
crictl rmi ${REGISTRY}/${IMAGE_NAME}:latest 2>/dev/null || true &&
|
||||||
kubectl rollout restart deployment/frontoffice &&
|
kubectl -n kbs-stage rollout restart deployment/frontoffice &&
|
||||||
kubectl rollout status deployment/frontoffice --timeout=180s &&
|
kubectl -n kbs-stage rollout status deployment/frontoffice --timeout=180s &&
|
||||||
rm -f /tmp/frontoffice-deployment.yaml
|
rm -f /tmp/frontoffice-deployment.yaml
|
||||||
"
|
"
|
||||||
echo "✅ Deployed!"
|
echo "✅ Deployed!"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: frontoffice
|
name: frontoffice
|
||||||
namespace: default
|
namespace: kbs-stage
|
||||||
labels:
|
labels:
|
||||||
app: frontoffice
|
app: frontoffice
|
||||||
environment: staging
|
environment: staging
|
||||||
@@ -21,7 +21,7 @@ spec:
|
|||||||
containers:
|
containers:
|
||||||
- name: frontoffice
|
- name: frontoffice
|
||||||
image: 185.252.31.44:30080/admin/frontoffice:latest
|
image: 185.252.31.44:30080/admin/frontoffice:latest
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 80
|
- containerPort: 80
|
||||||
name: http
|
name: http
|
||||||
@@ -43,7 +43,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: frontoffice-svc
|
name: frontoffice-svc
|
||||||
namespace: default
|
namespace: kbs-stage
|
||||||
labels:
|
labels:
|
||||||
app: frontoffice
|
app: frontoffice
|
||||||
spec:
|
spec:
|
||||||
@@ -54,3 +54,31 @@ spec:
|
|||||||
targetPort: 80
|
targetPort: 80
|
||||||
name: http
|
name: http
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
||||||
|
---
|
||||||
|
# FrontOffice Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: frontoffice-ingress
|
||||||
|
namespace: kbs-stage
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- frontoffice.se.kbs1.ir
|
||||||
|
secretName: frontoffice-tls
|
||||||
|
rules:
|
||||||
|
- host: frontoffice.se.kbs1.ir
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: frontoffice-svc
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|||||||
@@ -10,8 +10,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DateTimeConverterCL" Version="1.0.0" />
|
<PackageReference Include="DateTimeConverterCL" Version="1.0.0" />
|
||||||
<!-- Replace all FrontOffice.BFF protobuf packages with CMS protobuf (CI/CD packs → Nexus) -->
|
|
||||||
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.211" />
|
|
||||||
<PackageReference Include="MudBlazor" Version="8.14.0" />
|
<PackageReference Include="MudBlazor" Version="8.14.0" />
|
||||||
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||||
@@ -23,6 +22,19 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- ============================================================ -->
|
||||||
|
<!-- Proto References: Direct reference to CMS Protobuf project -->
|
||||||
|
<!-- This enables direct communication with CMS (no BFF needed) -->
|
||||||
|
<!-- ============================================================ -->
|
||||||
|
|
||||||
|
<!-- CMS Protobuf: NuGet in CI/Docker; ProjectReference for local monorepo dev -->
|
||||||
|
<ItemGroup Condition="Exists('../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj')">
|
||||||
|
<ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup Condition="!Exists('../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj')">
|
||||||
|
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.213" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Local Proto Project Reference for development -->
|
<!-- Local Proto Project Reference for development -->
|
||||||
<!-- <ItemGroup>-->
|
<!-- <ItemGroup>-->
|
||||||
<!-- <ProjectReference Include="..\..\..\FrontOffice.BFF\src\Protobufs\FrontOffice.BFF.Package.Protobuf\FrontOffice.BFF.Package.Protobuf.csproj" />-->
|
<!-- <ProjectReference Include="..\..\..\FrontOffice.BFF\src\Protobufs\FrontOffice.BFF.Package.Protobuf\FrontOffice.BFF.Package.Protobuf.csproj" />-->
|
||||||
|
|||||||
@@ -140,7 +140,18 @@
|
|||||||
OnClick="ProcessPayment"
|
OnClick="ProcessPayment"
|
||||||
Disabled="@(!CanProceedToPayment || _isProcessingPayment || !_selectedPackage.SupportsDirectPurchase)"
|
Disabled="@(!CanProceedToPayment || _isProcessingPayment || !_selectedPackage.SupportsDirectPurchase)"
|
||||||
Class="mt-2">
|
Class="mt-2">
|
||||||
@(_isProcessingPayment ? "در حال پردازش..." : "پرداخت آنلاین")
|
@(_isProcessingPayment ? "در حال پردازش..." : "پرداخت آنلاین (زرینپال)")
|
||||||
|
</MudButton>
|
||||||
|
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Info"
|
||||||
|
Size="Size.Large"
|
||||||
|
FullWidth="true"
|
||||||
|
StartIcon="@Icons.Material.Filled.AccountBalance"
|
||||||
|
OnClick="ProcessTwentyCardPayment"
|
||||||
|
Disabled="@(!CanProceedToPayment || _isProcessingPayment || !_selectedPackage.SupportsDirectPurchase)"
|
||||||
|
Class="mt-2">
|
||||||
|
پرداخت با ۲۰کارت
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
|
||||||
@if (_selectedPackage.SupportsDayaPurchase)
|
@if (_selectedPackage.SupportsDayaPurchase)
|
||||||
|
|||||||
@@ -107,6 +107,33 @@ public partial class Checkout
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessPayment()
|
private async Task ProcessPayment()
|
||||||
|
=> await StartGatewayPayment(gatewayProvider: null);
|
||||||
|
|
||||||
|
private async Task ProcessTwentyCardPayment()
|
||||||
|
{
|
||||||
|
if (!CanProceedToPayment || _selectedPackage == null)
|
||||||
|
{
|
||||||
|
Snackbar.Add("لطفاً پکیج را انتخاب کنید.", Severity.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = new DialogOptions
|
||||||
|
{
|
||||||
|
MaxWidth = MaxWidth.Small,
|
||||||
|
FullWidth = true,
|
||||||
|
CloseOnEscapeKey = true,
|
||||||
|
BackdropClick = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialog = await DialogService.ShowAsync<Shared.TwentyCardCreditDialog>(
|
||||||
|
string.Empty, options);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
if (result.Canceled) return;
|
||||||
|
|
||||||
|
await StartGatewayPayment(gatewayProvider: "20card");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartGatewayPayment(string? gatewayProvider)
|
||||||
{
|
{
|
||||||
if (_isProcessingPayment) return;
|
if (_isProcessingPayment) return;
|
||||||
|
|
||||||
@@ -120,11 +147,15 @@ public partial class Checkout
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await PackageClient.CustomerPurchasePackageAsync(new CustomerPurchasePackageRequest
|
var request = new CustomerPurchasePackageRequest
|
||||||
{
|
{
|
||||||
PackageId = _selectedPackage.Id,
|
PackageId = _selectedPackage.Id,
|
||||||
PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway
|
PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway
|
||||||
});
|
};
|
||||||
|
if (!string.IsNullOrWhiteSpace(gatewayProvider))
|
||||||
|
request.GatewayProvider = gatewayProvider;
|
||||||
|
|
||||||
|
var response = await PackageClient.CustomerPurchasePackageAsync(request);
|
||||||
|
|
||||||
if (!response.Success)
|
if (!response.Success)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public partial class Index : IDisposable
|
|||||||
(Icons.Material.Outlined.VerifiedUser, "ثبتنام سریع و ساده", "در چند گام کوتاه حساب بسازید و شروع کنید.", 0),
|
(Icons.Material.Outlined.VerifiedUser, "ثبتنام سریع و ساده", "در چند گام کوتاه حساب بسازید و شروع کنید.", 0),
|
||||||
(Icons.Material.Outlined.StarBorder, "پاداشهای شفاف", "قوانین روشن، دسترسی آسان به سوابق و گزارشها.", 100),
|
(Icons.Material.Outlined.StarBorder, "پاداشهای شفاف", "قوانین روشن، دسترسی آسان به سوابق و گزارشها.", 100),
|
||||||
(Icons.Material.Outlined.Devices, "طراحی واکنشگرا", "تجربهای روان در موبایل و دسکتاپ.", 200),
|
(Icons.Material.Outlined.Devices, "طراحی واکنشگرا", "تجربهای روان در موبایل و دسکتاپ.", 200),
|
||||||
(Icons.Material.Outlined.Groups, "تیمسازی هوشمند", "ساختار درختی شبکه و مدیریت تیمهای فروش.", 300),
|
(Icons.Material.Outlined.Groups, "تیمسازی هوشمند", "ساختار درختی سازمان و مدیریت تیمهای فروش.", 300),
|
||||||
(Icons.Material.Outlined.Insights, "گزارشهای لحظهای", "داشبورد پویا برای مشاهده عملکرد و کمیسیون.", 400),
|
(Icons.Material.Outlined.Insights, "گزارشهای لحظهای", "داشبورد پویا برای مشاهده عملکرد و کمیسیون.", 400),
|
||||||
(Icons.Material.Outlined.Lock, "امنیت بالا", "رمزنگاری اطلاعات و احراز هویت چندمرحلهای.", 500),
|
(Icons.Material.Outlined.Lock, "امنیت بالا", "رمزنگاری اطلاعات و احراز هویت چندمرحلهای.", 500),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,6 +46,21 @@
|
|||||||
</MudPaper>
|
</MudPaper>
|
||||||
</MudLink>
|
</MudLink>
|
||||||
|
|
||||||
|
<MudLink Href="@RouteConstants.Profile.Invitees" Underline="Underline.None">
|
||||||
|
<MudPaper Elevation="0" Class="pa-4 rounded-xl profile-hub-item">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="3">
|
||||||
|
<MudIcon Icon="@Icons.Material.Outlined.GroupAdd" Color="Color.Info" />
|
||||||
|
<MudStack Spacing="0">
|
||||||
|
<MudText Typo="Typo.subtitle2">دعوتشدگان من</MudText>
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">کسانی که با موبایل شما ثبتنام کردهاند</MudText>
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.ChevronLeft" Class="mud-text-secondary" />
|
||||||
|
</MudStack>
|
||||||
|
</MudPaper>
|
||||||
|
</MudLink>
|
||||||
|
|
||||||
<MudLink Href="@RouteConstants.Profile.Settings" Underline="Underline.None">
|
<MudLink Href="@RouteConstants.Profile.Settings" Underline="Underline.None">
|
||||||
<MudPaper Elevation="0" Class="pa-4 rounded-xl profile-hub-item">
|
<MudPaper Elevation="0" Class="pa-4 rounded-xl profile-hub-item">
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
|
||||||
|
|||||||
@@ -109,6 +109,13 @@
|
|||||||
{
|
{
|
||||||
<MudText Typo="Typo.caption" Color="Color.Success" Class="mt-2">@(_copyMessage)</MudText>
|
<MudText Typo="Typo.caption" Color="Color.Success" Class="mt-2">@(_copyMessage)</MudText>
|
||||||
}
|
}
|
||||||
|
<MudButton Variant="Variant.Text"
|
||||||
|
Color="Color.Primary"
|
||||||
|
Class="mt-3"
|
||||||
|
Href="@RouteConstants.Profile.Invitees"
|
||||||
|
StartIcon="@Icons.Material.Filled.GroupAdd">
|
||||||
|
مشاهده دعوتشدگان من
|
||||||
|
</MudButton>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -121,6 +128,13 @@
|
|||||||
<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>
|
||||||
|
<MudButton Variant="Variant.Outlined"
|
||||||
|
Color="Color.Primary"
|
||||||
|
Class="mt-3"
|
||||||
|
Href="@RouteConstants.Profile.Invitees"
|
||||||
|
StartIcon="@Icons.Material.Filled.GroupAdd">
|
||||||
|
دعوتشدگان من
|
||||||
|
</MudButton>
|
||||||
<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;">
|
||||||
از مزایای ویژه عضویت بهرهمند شده و با فعالیت در زمینه توسعه فروشگاهها پاداش دریافت کنید.
|
از مزایای ویژه عضویت بهرهمند شده و با فعالیت در زمینه توسعه فروشگاهها پاداش دریافت کنید.
|
||||||
</MudText>
|
</MudText>
|
||||||
|
|||||||
@@ -421,7 +421,10 @@ public partial class Index
|
|||||||
switch (purchase.Method)
|
switch (purchase.Method)
|
||||||
{
|
{
|
||||||
case Shared.PackagePurchaseDialog.PaymentMethodType.DirectPayment:
|
case Shared.PackagePurchaseDialog.PaymentMethodType.DirectPayment:
|
||||||
await ProcessDirectPayment(purchase.Package.Id);
|
await ProcessDirectPayment(purchase.Package.Id, gatewayProvider: null);
|
||||||
|
break;
|
||||||
|
case Shared.PackagePurchaseDialog.PaymentMethodType.TwentyCard:
|
||||||
|
await ProcessTwentyCardPayment(purchase.Package.Id);
|
||||||
break;
|
break;
|
||||||
case Shared.PackagePurchaseDialog.PaymentMethodType.DayaLoan:
|
case Shared.PackagePurchaseDialog.PaymentMethodType.DayaLoan:
|
||||||
await ProcessDayaLoanPayment();
|
await ProcessDayaLoanPayment();
|
||||||
@@ -430,7 +433,25 @@ public partial class Index
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessDirectPayment(long packageId)
|
private async Task ProcessTwentyCardPayment(long packageId)
|
||||||
|
{
|
||||||
|
var options = new DialogOptions
|
||||||
|
{
|
||||||
|
MaxWidth = MaxWidth.Small,
|
||||||
|
FullWidth = true,
|
||||||
|
CloseOnEscapeKey = true,
|
||||||
|
BackdropClick = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialog = await DialogService.ShowAsync<Shared.TwentyCardCreditDialog>(
|
||||||
|
string.Empty, options);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
if (result.Canceled) return;
|
||||||
|
|
||||||
|
await ProcessDirectPayment(packageId, gatewayProvider: "20card");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessDirectPayment(long packageId, string? gatewayProvider = null)
|
||||||
{
|
{
|
||||||
if (_isProcessingPayment) return;
|
if (_isProcessingPayment) return;
|
||||||
|
|
||||||
@@ -439,11 +460,15 @@ public partial class Index
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await PackageContract.CustomerPurchasePackageAsync(new CustomerPurchasePackageRequest
|
var request = new CustomerPurchasePackageRequest
|
||||||
{
|
{
|
||||||
PackageId = packageId,
|
PackageId = packageId,
|
||||||
PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway
|
PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway
|
||||||
});
|
};
|
||||||
|
if (!string.IsNullOrWhiteSpace(gatewayProvider))
|
||||||
|
request.GatewayProvider = gatewayProvider;
|
||||||
|
|
||||||
|
var response = await PackageContract.CustomerPurchasePackageAsync(request);
|
||||||
|
|
||||||
if (!response.Success)
|
if (!response.Success)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
@attribute [Authorize]
|
||||||
|
@attribute [Route(RouteConstants.Profile.Invitees)]
|
||||||
|
@using CMSMicroservice.Protobuf.Protos.User
|
||||||
|
@using CMSMicroservice.Protobuf.Protos.City
|
||||||
|
@inject UserContract.UserContractClient UserClient
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
|
||||||
|
<PageTitle>دعوتشدگان من | کارا بازار سلامت</PageTitle>
|
||||||
|
|
||||||
|
<MudContainer MaxWidth="MaxWidth.Medium" Class="py-6">
|
||||||
|
<PageHeader Title="دعوتشدگان من" BackHref="@RouteConstants.Profile.Index" />
|
||||||
|
|
||||||
|
<MudText Typo="Typo.body2" Class="mud-text-secondary mb-4">
|
||||||
|
افرادی که با شماره موبایل شما بهعنوان دعوتکننده ثبتنام کردهاند (متفاوت از سازمان فروش).
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
@if (_loading)
|
||||||
|
{
|
||||||
|
<MudStack AlignItems="AlignItems.Center" Class="py-8">
|
||||||
|
<MudProgressCircular Indeterminate="true" Color="Color.Primary" />
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudGrid Spacing="3" Class="mb-4">
|
||||||
|
<MudItem xs="12" sm="4">
|
||||||
|
<MudPaper Class="pa-4 rounded-xl" Elevation="1">
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">کل دعوتها</MudText>
|
||||||
|
<MudText Typo="Typo.h5">@_stats.TotalInvitees</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="4">
|
||||||
|
<MudPaper Class="pa-4 rounded-xl" Elevation="1">
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">فعال در باشگاه</MudText>
|
||||||
|
<MudText Typo="Typo.h5" Color="Color.Success">@_stats.ClubActiveCount</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="4">
|
||||||
|
<MudPaper Class="pa-4 rounded-xl" Elevation="1">
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">غیرفعال باشگاه</MudText>
|
||||||
|
<MudText Typo="Typo.h5" Color="Color.Warning">@_stats.ClubInactiveCount</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
|
||||||
|
<MudPaper Class="pa-3 rounded-xl mb-3" Elevation="0">
|
||||||
|
<MudSelect T="string" Label="فیلتر وضعیت باشگاه" Value="_clubFilter" ValueChanged="OnFilterChanged"
|
||||||
|
Variant="Variant.Outlined" Dense="true" Margin="Margin.Dense">
|
||||||
|
<MudSelectItem Value="@("ALL")">همه</MudSelectItem>
|
||||||
|
<MudSelectItem Value="@("ACTIVE")">فعال باشگاه</MudSelectItem>
|
||||||
|
<MudSelectItem Value="@("INACTIVE")">غیرفعال باشگاه</MudSelectItem>
|
||||||
|
</MudSelect>
|
||||||
|
</MudPaper>
|
||||||
|
|
||||||
|
@if (!_invitees.Any())
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Info" Dense="true">هنوز کسی با کد دعوت شما ثبتنام نکرده است.</MudAlert>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudTable Items="_invitees" Hover="true" Dense="true" Breakpoint="Breakpoint.Sm" Class="rounded-xl">
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>نام</MudTh>
|
||||||
|
<MudTh>تاریخ ثبتنام</MudTh>
|
||||||
|
<MudTh>باشگاه</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="نام">
|
||||||
|
@(string.IsNullOrWhiteSpace($"{context.FirstName} {context.LastName}".Trim())
|
||||||
|
? "—"
|
||||||
|
: $"{context.FirstName} {context.LastName}".Trim())
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="تاریخ ثبتنام">
|
||||||
|
@FormatDate(context.RegisteredAt)
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="باشگاه">
|
||||||
|
@if (context.IsClubActive)
|
||||||
|
{
|
||||||
|
<MudChip T="string" Size="Size.Small" Color="Color.Success" Variant="Variant.Filled">فعال</MudChip>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudChip T="string" Size="Size.Small" Color="Color.Default" Variant="Variant.Outlined">غیرفعال</MudChip>
|
||||||
|
}
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
|
||||||
|
@if (_totalPages > 1)
|
||||||
|
{
|
||||||
|
<MudStack AlignItems="AlignItems.Center" Class="mt-4">
|
||||||
|
<MudPagination Count="_totalPages" Selected="_page" SelectedChanged="OnPageChanged" Color="Color.Primary" />
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</MudContainer>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _loading = true;
|
||||||
|
private string _clubFilter = "ALL";
|
||||||
|
private int _page = 1;
|
||||||
|
private const int PageSize = 10;
|
||||||
|
private int _totalPages;
|
||||||
|
private InviteeStats _stats = new();
|
||||||
|
private List<InviteeModel> _invitees = new();
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await LoadAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnFilterChanged(string value)
|
||||||
|
{
|
||||||
|
_clubFilter = value;
|
||||||
|
_page = 1;
|
||||||
|
await LoadAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnPageChanged(int page)
|
||||||
|
{
|
||||||
|
_page = page;
|
||||||
|
await LoadAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadAsync()
|
||||||
|
{
|
||||||
|
_loading = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await UserClient.GetMyInviteesAsync(new GetMyInviteesRequest
|
||||||
|
{
|
||||||
|
PaginationState = new PaginationState { PageNumber = _page, PageSize = PageSize },
|
||||||
|
ClubStatusFilter = _clubFilter
|
||||||
|
});
|
||||||
|
|
||||||
|
_stats = response.Stats ?? new InviteeStats();
|
||||||
|
_invitees = response.Invitees.ToList();
|
||||||
|
_totalPages = (int)(response.MetaData?.TotalPage ?? 0);
|
||||||
|
if (_totalPages < 1 && _invitees.Count > 0) _totalPages = 1;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Snackbar.Add($"خطا در بارگذاری دعوتشدگان: {ex.Message}", Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatDate(Google.Protobuf.WellKnownTypes.Timestamp? ts)
|
||||||
|
{
|
||||||
|
if (ts == null) return "—";
|
||||||
|
return ts.ToDateTime().ToLocalTime().MiladiToJalali();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -86,6 +86,10 @@
|
|||||||
[SupplyParameterFromQuery(Name = "Status")]
|
[SupplyParameterFromQuery(Name = "Status")]
|
||||||
private string? Status { get; set; }
|
private string? Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>۲۰کارت callback — هممعنی Status زرینپال</summary>
|
||||||
|
[SupplyParameterFromQuery(Name = "PaymentStatus")]
|
||||||
|
private string? PaymentStatus { get; set; }
|
||||||
|
|
||||||
private bool _isLoading = true;
|
private bool _isLoading = true;
|
||||||
private bool _isSuccess;
|
private bool _isSuccess;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
@@ -132,6 +136,10 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// ۲۰کارت: PaymentStatus؛ زرینپال: Status
|
||||||
|
if (string.IsNullOrWhiteSpace(Status) && !string.IsNullOrWhiteSpace(PaymentStatus))
|
||||||
|
Status = PaymentStatus;
|
||||||
|
|
||||||
// تعیین نوع پرداخت — اگر type نباشد، پیشفرض خرید پکیج
|
// تعیین نوع پرداخت — اگر type نباشد، پیشفرض خرید پکیج
|
||||||
var type = PaymentType?.ToLowerInvariant() ?? "package";
|
var type = PaymentType?.ToLowerInvariant() ?? "package";
|
||||||
|
|
||||||
|
|||||||
@@ -319,17 +319,17 @@ public partial class RegisterWizard
|
|||||||
$"<p><span class='field-label'>شماره ملی:</span> {_model.NationalCode?.PersianToEnglish()}</p>" +
|
$"<p><span class='field-label'>شماره ملی:</span> {_model.NationalCode?.PersianToEnglish()}</p>" +
|
||||||
$"<p><span class='field-label'>شماره تماس:</span> {_userAuthInfo.MobileNumber?.PersianToEnglish()}</p></div>" +
|
$"<p><span class='field-label'>شماره تماس:</span> {_userAuthInfo.MobileNumber?.PersianToEnglish()}</p></div>" +
|
||||||
"<p>کارابازار و کاربر که در این قرارداد جداگانه «طرف» و مجموعاً «طرفین» نامیده میشوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا مینمایند.</p></div><div><p class='section-title'>ماده ۱ - موضوع قرارداد</p>" +
|
"<p>کارابازار و کاربر که در این قرارداد جداگانه «طرف» و مجموعاً «طرفین» نامیده میشوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا مینمایند.</p></div><div><p class='section-title'>ماده ۱ - موضوع قرارداد</p>" +
|
||||||
"<p>موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر ازخدمات، باشگاه مشتریان، مزایا، طرحهای همکاری، شبکه معرفی، خرید از فروشگاههای طرفقراردادو هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرمها و شرکتهایهمکار در اختیار کاربر قرار میگیرد، بدون اینکه جزئیات مدل کسبوکار، شیوه تأمین منابع مالی،شبکه همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.</p>" +
|
"<p>موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر ازخدمات، باشگاه مشتریان، مزایا، طرحهای همکاری، سازمان معرفی، خرید از فروشگاههای طرفقراردادو هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرمها و شرکتهایهمکار در اختیار کاربر قرار میگیرد، بدون اینکه جزئیات مدل کسبوکار، شیوه تأمین منابع مالی،سازمان همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.</p>" +
|
||||||
"<p class='section-title'>ماده ۲ - اقرار و آگاهی کاربر</p><p>۲-۱. کاربر اقرار مینماید که کلیه اطلاعات کلی لازم در خصوص نحوه فعالیت، مزایا، ریسکهای احتمالی," +
|
"<p class='section-title'>ماده ۲ - اقرار و آگاهی کاربر</p><p>۲-۱. کاربر اقرار مینماید که کلیه اطلاعات کلی لازم در خصوص نحوه فعالیت، مزایا، ریسکهای احتمالی," +
|
||||||
"سازوکار کلی استفاده از خدمات، و چارچوب کلی همکاری را از مراجع رسمی معرفیشده توسط کارابازاردریافت کرده، سؤالات خود را مطرح نموده و پاسخ مناسب را دریافت نموده است.</p><p>۲-۲. کاربر با امضای این قرارداد اقرار مینماید که:</p><ul><li>با اراده آزاد و بدون هرگونه اجبار، اکراه، فریب یا سوءاستفاده از ناآگاهی وارد این همکاری شده است.</li><li>از احتمال وجود ریسکهای مالی، اعتباری، قانونی و شبکهای مرتبط با فعالیت خود آگاه بوده و آن را میپذیرد.</li>" +
|
"سازوکار کلی استفاده از خدمات، و چارچوب کلی همکاری را از مراجع رسمی معرفیشده توسط کارابازاردریافت کرده، سؤالات خود را مطرح نموده و پاسخ مناسب را دریافت نموده است.</p><p>۲-۲. کاربر با امضای این قرارداد اقرار مینماید که:</p><ul><li>با اراده آزاد و بدون هرگونه اجبار، اکراه، فریب یا سوءاستفاده از ناآگاهی وارد این همکاری شده است.</li><li>از احتمال وجود ریسکهای مالی، اعتباری، قانونی و شبکهای مرتبط با فعالیت خود آگاه بوده و آن را میپذیرد.</li>" +
|
||||||
"<li>هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در شبکه معرفی، خرید از فروشگاهها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و بهعنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمیشود.</li></ul>" +
|
"<li>هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در سازمان معرفی، خرید از فروشگاهها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و بهعنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمیشود.</li></ul>" +
|
||||||
"<p class='section-title'>ماده ۳ - سلب مسئولیت کارابازار</p><p>۳-۱. کاربر صراحتاً میپذیرد که کارابازار صرفاً در چارچوب قوانین و مقررات حاکم و مطابق قراردادها و تفاهمنامههای خود با شرکای تجاری و پلتفرمهای همکار، خدمات و امکانات مشخصی را در اختیار کاربر قرار میدهد و هیچگونه تعهدی نسبت به:</p><ul><li>تحقق سود یا بازده مالی مشخص،</li><li>ثبات ارزش هرگونه اعتبار، امتیاز، یا منافع غیرنقدی که ممکن است در قالب طرحها به کاربر تخصیص یابد،</li>" +
|
"<p class='section-title'>ماده ۳ - سلب مسئولیت کارابازار</p><p>۳-۱. کاربر صراحتاً میپذیرد که کارابازار صرفاً در چارچوب قوانین و مقررات حاکم و مطابق قراردادها و تفاهمنامههای خود با شرکای تجاری و پلتفرمهای همکار، خدمات و امکانات مشخصی را در اختیار کاربر قرار میدهد و هیچگونه تعهدی نسبت به:</p><ul><li>تحقق سود یا بازده مالی مشخص،</li><li>ثبات ارزش هرگونه اعتبار، امتیاز، یا منافع غیرنقدی که ممکن است در قالب طرحها به کاربر تخصیص یابد،</li>" +
|
||||||
"<li>عملکرد اشخاص ثالث (از جمله پلتفرمها، فروشگاهها، شرکتهای بیمه، ارائهدهندگان خدمات سلامت و هر شخص حقیقی یا حقوقی همکار)،</li><li>تصمیمات و اقدامات کاربر در جذب افراد جدید و ایجاد زیرمجموعه،</li></ul><p>نداشته و نخواهد داشت مگر در حدودی که بهصراحت در قرارداد یا قوانین آمره بر عهده کارابازار گذاشته شده است.</p><p>" +
|
"<li>عملکرد اشخاص ثالث (از جمله پلتفرمها، فروشگاهها، شرکتهای بیمه، ارائهدهندگان خدمات سلامت و هر شخص حقیقی یا حقوقی همکار)،</li><li>تصمیمات و اقدامات کاربر در جذب افراد جدید و ایجاد زیرمجموعه،</li></ul><p>نداشته و نخواهد داشت مگر در حدودی که بهصراحت در قرارداد یا قوانین آمره بر عهده کارابازار گذاشته شده است.</p><p>" +
|
||||||
"۳-۲. هرگونه خسارت، دعوی، تهدید، مطالبه، ادعا، شکایت یا پیگیری حقوقی که ناشی از تصمیمات شخصی کاربر،نحوه استفاده وی از تسهیلات و مزایا، جذب دیگران، خرید کالا و خدمات، یا تعاملات او با اشخاص ثالث باشد،مستقیماً متوجه خود کاربر است و کارابازار نسبت به آن هیچگونه مسئولیت مدنی، کیفری، مالی یا قراردادی ندارد," +
|
"۳-۲. هرگونه خسارت، دعوی، تهدید، مطالبه، ادعا، شکایت یا پیگیری حقوقی که ناشی از تصمیمات شخصی کاربر،نحوه استفاده وی از تسهیلات و مزایا، جذب دیگران، خرید کالا و خدمات، یا تعاملات او با اشخاص ثالث باشد،مستقیماً متوجه خود کاربر است و کارابازار نسبت به آن هیچگونه مسئولیت مدنی، کیفری، مالی یا قراردادی ندارد," +
|
||||||
"مگر در مواردی که طبق قوانین آمره، مسئولیت صریح و غیرقابلاسقاط بر عهده کارابازار قرار گرفته باشد.</p><p>۳-۳. کاربر میپذیرد که هیچگونه ادعایی مبنی بر فریب، اغفال، ارائه اطلاعات نادرست یا وعدههای خارج ازچهارچوب رسمی از سوی کارابازار یا نمایندگان رسمی آن، پس از امضای این قرارداد، از وی مسموع نخواهد بود،مگر آنکه طبق رأی قطعی مرجع قضایی صالح، خلاف آن ثابت شود.</p><p class='section-title'>ماده ۴ - مسئولیت کاربر در قبال تهدید، ادعا و شکایت</p>" +
|
"مگر در مواردی که طبق قوانین آمره، مسئولیت صریح و غیرقابلاسقاط بر عهده کارابازار قرار گرفته باشد.</p><p>۳-۳. کاربر میپذیرد که هیچگونه ادعایی مبنی بر فریب، اغفال، ارائه اطلاعات نادرست یا وعدههای خارج ازچهارچوب رسمی از سوی کارابازار یا نمایندگان رسمی آن، پس از امضای این قرارداد، از وی مسموع نخواهد بود،مگر آنکه طبق رأی قطعی مرجع قضایی صالح، خلاف آن ثابت شود.</p><p class='section-title'>ماده ۴ - مسئولیت کاربر در قبال تهدید، ادعا و شکایت</p>" +
|
||||||
"<p>۴-۱. کاربر متعهد است در صورت طرح هرگونه تهدید، ادعا، مطالبه، شکایت یا پیگیری حقوقی از سوی اشخاص ثالث(از جمله افراد جذبشده توسط کاربر، زیرمجموعهها، خریداران معرفیشده یا سایر اشخاص)، که ناشی از عملکردشخصی کاربر، معرفیهای وی، شیوه تبلیغ، وعدههای خارج از چارچوب رسمی کارابازار، یا نقض قوانین و مقرراتباشد، خود رأساً پاسخگو باشد و کارابازار را از هرگونه مسئولیت و هزینه احتمالی در این خصوص مصون بدارد.</p><p>۴-۲. کاربر میپذیرد که:</p><ul><li>هرگونه تهدید یا ادعای بیجا، غیرمنطقی، غیرمستند یا مغایر با مفاد این قرارداد، متوجه شخص کاربر است.</li>" +
|
"<p>۴-۱. کاربر متعهد است در صورت طرح هرگونه تهدید، ادعا، مطالبه، شکایت یا پیگیری حقوقی از سوی اشخاص ثالث(از جمله افراد جذبشده توسط کاربر، زیرمجموعهها، خریداران معرفیشده یا سایر اشخاص)، که ناشی از عملکردشخصی کاربر، معرفیهای وی، شیوه تبلیغ، وعدههای خارج از چارچوب رسمی کارابازار، یا نقض قوانین و مقرراتباشد، خود رأساً پاسخگو باشد و کارابازار را از هرگونه مسئولیت و هزینه احتمالی در این خصوص مصون بدارد.</p><p>۴-۲. کاربر میپذیرد که:</p><ul><li>هرگونه تهدید یا ادعای بیجا، غیرمنطقی، غیرمستند یا مغایر با مفاد این قرارداد، متوجه شخص کاربر است.</li>" +
|
||||||
"<li>در صورت وارد آمدن خسارت مادی یا معنوی به کارابازار ناشی از چنین تهدیدات یا ادعاهایی، کارابازار حق دارد نسبت به مطالبه خسارت از کاربر، طبق قوانین و از طریق مراجع صالح اقدام نماید.</li></ul>" +
|
"<li>در صورت وارد آمدن خسارت مادی یا معنوی به کارابازار ناشی از چنین تهدیدات یا ادعاهایی، کارابازار حق دارد نسبت به مطالبه خسارت از کاربر، طبق قوانین و از طریق مراجع صالح اقدام نماید.</li></ul>" +
|
||||||
"<p class='section-title'>ماده ۵ - محرمانگی و عدم افشای جزئیات کسبوکار</p><p>۵-۱. کاربر میپذیرد که جزئیات فنی، مالی، ساختار شبکه، شیوه توزیع مزایا، قراردادهای داخلی کارابازار باشرکای تجاری و پلتفرمهای همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آنهاتوسط کاربر بدون مجوز کتبی کارابازار، مجاز نمیباشد.</p><p>۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسبوکار در این قرارداد را بهعنوان دلیل بطلان، فسخ یاادعای فریب علیه کارابازار از خود سلب مینماید.</p>" +
|
"<p class='section-title'>ماده ۵ - محرمانگی و عدم افشای جزئیات کسبوکار</p><p>۵-۱. کاربر میپذیرد که جزئیات فنی، مالی، ساختار سازمان، شیوه توزیع مزایا، قراردادهای داخلی کارابازار باشرکای تجاری و پلتفرمهای همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آنهاتوسط کاربر بدون مجوز کتبی کارابازار، مجاز نمیباشد.</p><p>۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسبوکار در این قرارداد را بهعنوان دلیل بطلان، فسخ یاادعای فریب علیه کارابازار از خود سلب مینماید.</p>" +
|
||||||
"<p class='section-title'>ماده ۶ - کد تأیید یکبارمصرف (OTP) و شناسه قرارداد</p><p>۶-۱. به منظور تأیید هویت کاربر و جایگزین کردن امضا در محیط غیرحضوری، برای این قرارداد یک شناسه یکتا(GUID) تولید شده و از طریق سامانه کارابازار، کد تأیید یکبارمصرف (OTP) مرتبط با آن برای کاربر ارسالمیگردد.</p>" +
|
"<p class='section-title'>ماده ۶ - کد تأیید یکبارمصرف (OTP) و شناسه قرارداد</p><p>۶-۱. به منظور تأیید هویت کاربر و جایگزین کردن امضا در محیط غیرحضوری، برای این قرارداد یک شناسه یکتا(GUID) تولید شده و از طریق سامانه کارابازار، کد تأیید یکبارمصرف (OTP) مرتبط با آن برای کاربر ارسالمیگردد.</p>" +
|
||||||
"<p>۶-۲. کاربر با وارد کردن صحیح کد تأیید (OTP) در سامانه، اقرار مینماید که:</p><ul><li>مالک شماره تماس ثبتشده در این قرارداد است یا با اجازه قانونی مالک از آن استفاده میکند،</li><li>از محتوای قرارداد بهطور کامل آگاه است و آن را بدون ابهام و با رضایت کامل میپذیرد،</li><li>شناسه یکتا و OTP ارسالشده، معادل امضای الکترونیکی معتبر وی بر روی این قرارداد است.</li></ul>" +
|
"<p>۶-۲. کاربر با وارد کردن صحیح کد تأیید (OTP) در سامانه، اقرار مینماید که:</p><ul><li>مالک شماره تماس ثبتشده در این قرارداد است یا با اجازه قانونی مالک از آن استفاده میکند،</li><li>از محتوای قرارداد بهطور کامل آگاه است و آن را بدون ابهام و با رضایت کامل میپذیرد،</li><li>شناسه یکتا و OTP ارسالشده، معادل امضای الکترونیکی معتبر وی بر روی این قرارداد است.</li></ul>" +
|
||||||
"<p class='section-title'>ماده ۷ - مدت، اصلاح و حاکمیت قانون</p>" +
|
"<p class='section-title'>ماده ۷ - مدت، اصلاح و حاکمیت قانون</p>" +
|
||||||
|
|||||||
@@ -24,7 +24,9 @@
|
|||||||
OnChangePhone="ChangePhoneAsync"
|
OnChangePhone="ChangePhoneAsync"
|
||||||
OnResendOtp="ResendOtpAsync"
|
OnResendOtp="ResendOtpAsync"
|
||||||
ReferralCode="@_referralCode"
|
ReferralCode="@_referralCode"
|
||||||
ReferralCodeChanged="OnReferralCodeChanged" />
|
ReferralCodeChanged="OnReferralCodeChanged"
|
||||||
|
InviterMobile="@_inviterMobile"
|
||||||
|
InviterMobileChanged="OnInviterMobileChanged" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -55,7 +57,9 @@ else
|
|||||||
OnChangePhone="ChangePhoneAsync"
|
OnChangePhone="ChangePhoneAsync"
|
||||||
OnResendOtp="ResendOtpAsync"
|
OnResendOtp="ResendOtpAsync"
|
||||||
ReferralCode="@_referralCode"
|
ReferralCode="@_referralCode"
|
||||||
ReferralCodeChanged="OnReferralCodeChanged" />
|
ReferralCodeChanged="OnReferralCodeChanged"
|
||||||
|
InviterMobile="@_inviterMobile"
|
||||||
|
InviterMobileChanged="OnInviterMobileChanged" />
|
||||||
|
|
||||||
<MudStack Class="mt-4" Spacing="2">
|
<MudStack Class="mt-4" Spacing="2">
|
||||||
@if (_currentStep == AuthStep.Phone)
|
@if (_currentStep == AuthStep.Phone)
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ public partial class AuthDialog : IDisposable
|
|||||||
|
|
||||||
// Referral code field
|
// Referral code field
|
||||||
private string? _referralCode;
|
private string? _referralCode;
|
||||||
|
// Inviter mobile (دعوتکننده)
|
||||||
|
private string? _inviterMobile;
|
||||||
|
|
||||||
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
||||||
[Inject] private UserContract.UserContractClient UserClient { get; set; } = default!;
|
[Inject] private UserContract.UserContractClient UserClient { get; set; } = default!;
|
||||||
@@ -71,6 +73,7 @@ public partial class AuthDialog : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_referralCode = await LocalStorage.GetItemAsync<string>("referral:code");
|
_referralCode = await LocalStorage.GetItemAsync<string>("referral:code");
|
||||||
|
_inviterMobile = await LocalStorage.GetItemAsync<string>("inviter:mobile");
|
||||||
// await LocalStorage.RemoveItemAsync(TokenStorageKey);
|
// await LocalStorage.RemoveItemAsync(TokenStorageKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +86,15 @@ public partial class AuthDialog : IDisposable
|
|||||||
await LocalStorage.RemoveItemAsync("referral:code");
|
await LocalStorage.RemoveItemAsync("referral:code");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task OnInviterMobileChanged(string? value)
|
||||||
|
{
|
||||||
|
_inviterMobile = value;
|
||||||
|
if (!string.IsNullOrWhiteSpace(value))
|
||||||
|
await LocalStorage.SetItemAsync("inviter:mobile", value);
|
||||||
|
else
|
||||||
|
await LocalStorage.RemoveItemAsync("inviter:mobile");
|
||||||
|
}
|
||||||
|
|
||||||
private void GenerateCaptcha()
|
private void GenerateCaptcha()
|
||||||
{
|
{
|
||||||
_captchaCode = Guid.NewGuid().ToString("N")[..6].ToUpperInvariant();
|
_captchaCode = Guid.NewGuid().ToString("N")[..6].ToUpperInvariant();
|
||||||
@@ -204,6 +216,15 @@ public partial class AuthDialog : IDisposable
|
|||||||
_verifyRequest.ParentReferralCode = effectiveReferralCode;
|
_verifyRequest.ParentReferralCode = effectiveReferralCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var storedInviterMobile = await LocalStorage.GetItemAsync<string>("inviter:mobile");
|
||||||
|
var effectiveInviterMobile = !string.IsNullOrWhiteSpace(_inviterMobile)
|
||||||
|
? _inviterMobile
|
||||||
|
: storedInviterMobile;
|
||||||
|
if (!string.IsNullOrWhiteSpace(effectiveInviterMobile))
|
||||||
|
{
|
||||||
|
_verifyRequest.InviterMobile = effectiveInviterMobile;
|
||||||
|
}
|
||||||
|
|
||||||
var validationResult = true; // _verifyRequestValidator.Validate(_verifyRequest);
|
var validationResult = true; // _verifyRequestValidator.Validate(_verifyRequest);
|
||||||
if (!validationResult)
|
if (!validationResult)
|
||||||
{
|
{
|
||||||
@@ -236,6 +257,7 @@ public partial class AuthDialog : IDisposable
|
|||||||
await LocalStorage.RemoveItemAsync(PhoneStorageKey);
|
await LocalStorage.RemoveItemAsync(PhoneStorageKey);
|
||||||
await LocalStorage.RemoveItemAsync(RedirectStorageKey);
|
await LocalStorage.RemoveItemAsync(RedirectStorageKey);
|
||||||
await LocalStorage.RemoveItemAsync("referral:code");
|
await LocalStorage.RemoveItemAsync("referral:code");
|
||||||
|
await LocalStorage.RemoveItemAsync("inviter:mobile");
|
||||||
|
|
||||||
_attemptsLeft = MaxVerificationAttempts;
|
_attemptsLeft = MaxVerificationAttempts;
|
||||||
_verifyRequest.Code = string.Empty;
|
_verifyRequest.Code = string.Empty;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
روش پرداخت خود را انتخاب کنید:
|
روش پرداخت خود را انتخاب کنید:
|
||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
@* Direct Payment — always available *@
|
@* Direct Payment (ZarinPal) — always available *@
|
||||||
<MudPaper Elevation="0" Class="pa-4 rounded-lg pkg-payment-option"
|
<MudPaper Elevation="0" Class="pa-4 rounded-lg pkg-payment-option"
|
||||||
Style="border:2px solid var(--mud-palette-primary); cursor:pointer;"
|
Style="border:2px solid var(--mud-palette-primary); cursor:pointer;"
|
||||||
@onclick="() => SelectPaymentMethod(PaymentMethodType.DirectPayment)">
|
@onclick="() => SelectPaymentMethod(PaymentMethodType.DirectPayment)">
|
||||||
@@ -61,13 +61,29 @@
|
|||||||
<MudIcon Icon="@Icons.Material.Filled.CreditCard" Color="Color.Primary" Size="Size.Medium" />
|
<MudIcon Icon="@Icons.Material.Filled.CreditCard" Color="Color.Primary" Size="Size.Medium" />
|
||||||
<MudStack Spacing="0" Class="flex-grow-1">
|
<MudStack Spacing="0" Class="flex-grow-1">
|
||||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary"><b>پرداخت مستقیم</b></MudText>
|
<MudText Typo="Typo.subtitle1" Color="Color.Primary"><b>پرداخت مستقیم</b></MudText>
|
||||||
<MudText Typo="Typo.caption" Class="mud-text-secondary">پرداخت آنی از طریق درگاه بانکی</MudText>
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">پرداخت آنی از طریق درگاه بانکی (زرینپال)</MudText>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
<MudIcon Icon="@Icons.Material.Filled.ArrowBack" Color="Color.Primary" Size="Size.Small" />
|
<MudIcon Icon="@Icons.Material.Filled.ArrowBack" Color="Color.Primary" Size="Size.Small" />
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
|
@* TwentyCard IPG *@
|
||||||
|
<MudPaper Elevation="0" Class="pa-4 rounded-lg pkg-payment-option"
|
||||||
|
Style="border:2px solid var(--mud-palette-info); cursor:pointer;"
|
||||||
|
@onclick="() => SelectPaymentMethod(PaymentMethodType.TwentyCard)">
|
||||||
|
<MudStack Spacing="2">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.AccountBalance" Color="Color.Info" Size="Size.Medium" />
|
||||||
|
<MudStack Spacing="0" Class="flex-grow-1">
|
||||||
|
<MudText Typo="Typo.subtitle1" Color="Color.Info"><b>پرداخت با ۲۰کارت</b></MudText>
|
||||||
|
<MudText Typo="Typo.caption" Class="mud-text-secondary">پرداخت از طریق درگاه ۲۰کارت (نیاز به تأمین اعتبار)</MudText>
|
||||||
|
</MudStack>
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.ArrowBack" Color="Color.Info" Size="Size.Small" />
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
</MudPaper>
|
||||||
|
|
||||||
@* Daya Loan — only for base package AND first purchase cycle *@
|
@* Daya Loan — only for base package AND first purchase cycle *@
|
||||||
@if (_selectedPackage.SupportsDayaPurchase && PurchaseCycleCount == 0)
|
@if (_selectedPackage.SupportsDayaPurchase && PurchaseCycleCount == 0)
|
||||||
{
|
{
|
||||||
@@ -229,6 +245,6 @@
|
|||||||
: "background:rgba(16,185,129,.12); color:#10b981;";
|
: "background:rgba(16,185,129,.12); color:#10b981;";
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PaymentMethodType { DirectPayment, DayaLoan }
|
public enum PaymentMethodType { DirectPayment, TwentyCard, DayaLoan }
|
||||||
public record PackagePurchaseResult(PackageDto Package, PaymentMethodType Method);
|
public record PackagePurchaseResult(PackageDto Package, PaymentMethodType Method);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,11 +38,21 @@
|
|||||||
|
|
||||||
<MudTextField Value="ReferralCode"
|
<MudTextField Value="ReferralCode"
|
||||||
ValueChanged="@((string? v) => ReferralCodeChanged.InvokeAsync(v))"
|
ValueChanged="@((string? v) => ReferralCodeChanged.InvokeAsync(v))"
|
||||||
Label="کد معرف (اختیاری)"
|
Label="کد معرف سازمان (اختیاری)"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Immediate="true"
|
Immediate="true"
|
||||||
Placeholder="کد معرف را وارد کنید"
|
Placeholder="کد معرف ۱۰ رقمی"
|
||||||
Class="mb-3" />
|
Class="mb-3"
|
||||||
|
HelperText="جایگاه شما در سازمان — با لینک معرف پر میشود" />
|
||||||
|
|
||||||
|
<MudTextField Value="InviterMobile"
|
||||||
|
ValueChanged="@((string? v) => InviterMobileChanged.InvokeAsync(v))"
|
||||||
|
Label="شماره موبایل دعوتکننده (اختیاری)"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Immediate="true"
|
||||||
|
Placeholder="مثلاً 0912xxxxxxx"
|
||||||
|
Class="mb-3"
|
||||||
|
HelperText="کسی که شما را به کارابازار معرفی کرده — متفاوت از معرف سازمان" />
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(ErrorMessage))
|
@if (!string.IsNullOrWhiteSpace(ErrorMessage))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ public partial class PhoneVerifyForm
|
|||||||
[Parameter] public string? ReferralCode { get; set; }
|
[Parameter] public string? ReferralCode { get; set; }
|
||||||
[Parameter] public EventCallback<string?> ReferralCodeChanged { get; set; }
|
[Parameter] public EventCallback<string?> ReferralCodeChanged { get; set; }
|
||||||
|
|
||||||
|
// ── Inviter (دعوتکننده) ──
|
||||||
|
[Parameter] public string? InviterMobile { get; set; }
|
||||||
|
[Parameter] public EventCallback<string?> InviterMobileChanged { get; set; }
|
||||||
|
|
||||||
// ── Verify actions ──
|
// ── Verify actions ──
|
||||||
[Parameter] public EventCallback OnChangePhone { get; set; }
|
[Parameter] public EventCallback OnChangePhone { get; set; }
|
||||||
[Parameter] public EventCallback OnResendOtp { get; set; }
|
[Parameter] public EventCallback OnResendOtp { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
@inject IConfiguration Configuration
|
||||||
|
@inject IJSRuntime JSRuntime
|
||||||
|
|
||||||
|
<MudDialog>
|
||||||
|
<TitleContent>
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.AccountBalance" Color="Color.Primary" />
|
||||||
|
<MudText Typo="Typo.h6">تأمین اعتبار ۲۰کارت</MudText>
|
||||||
|
</MudStack>
|
||||||
|
</TitleContent>
|
||||||
|
<DialogContent>
|
||||||
|
<MudStack Spacing="3">
|
||||||
|
<MudText Typo="Typo.body2" Class="mud-text-secondary">
|
||||||
|
برای پرداخت از طریق درگاه ۲۰کارت، ابتدا باید اعتبار حساب ۲۰کارت خود را تأمین کنید.
|
||||||
|
پس از تأمین اعتبار، روی «ادامه پرداخت» بزنید تا به درگاه هدایت شوید.
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined">
|
||||||
|
اگر قبلاً اعتبار را تأمین کردهاید، میتوانید مستقیم ادامه دهید.
|
||||||
|
</MudAlert>
|
||||||
|
</MudStack>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="Cancel" Variant="Variant.Text">انصراف</MudButton>
|
||||||
|
<MudButton Variant="Variant.Outlined"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.OpenInNew"
|
||||||
|
OnClick="OpenCreditPortal"
|
||||||
|
Disabled="@string.IsNullOrWhiteSpace(_creditPortalUrl)">
|
||||||
|
تأمین اعتبار
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.Payment"
|
||||||
|
OnClick="ContinuePayment">
|
||||||
|
ادامه پرداخت
|
||||||
|
</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
|
private string _creditPortalUrl = string.Empty;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_creditPortalUrl = Configuration["TwentyCard:CreditPortalUrl"] ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OpenCreditPortal()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(_creditPortalUrl)) return;
|
||||||
|
await JSRuntime.InvokeVoidAsync("open", _creditPortalUrl, "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ContinuePayment() => MudDialog.Close(DialogResult.Ok(true));
|
||||||
|
|
||||||
|
private void Cancel() => MudDialog.Cancel();
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ public static class RouteConstants
|
|||||||
public const string Settings = "/profile/settings";
|
public const string Settings = "/profile/settings";
|
||||||
public const string ChangePassword = "/profile/change-password";
|
public const string ChangePassword = "/profile/change-password";
|
||||||
public const string Tree = "/profile/tree";
|
public const string Tree = "/profile/tree";
|
||||||
|
public const string Invitees = "/profile/invitees";
|
||||||
public const string Wallet = "/profile/wallet";
|
public const string Wallet = "/profile/wallet";
|
||||||
public const string MagicWallet = "/profile/magic-wallet";
|
public const string MagicWallet = "/profile/magic-wallet";
|
||||||
public const string ChargeDiscountWallet = "/profile/charge-discount-wallet";
|
public const string ChargeDiscountWallet = "/profile/charge-discount-wallet";
|
||||||
|
|||||||
@@ -208,6 +208,6 @@ public class SeoMetadataProvider
|
|||||||
|
|
||||||
private static string GetHomeCrawlableContent() =>
|
private static string GetHomeCrawlableContent() =>
|
||||||
"کارابازار سلامت (KBS) — باشگاه مشتریان و فروشگاه محصولات سلامت. " +
|
"کارابازار سلامت (KBS) — باشگاه مشتریان و فروشگاه محصولات سلامت. " +
|
||||||
"با عضویت در باشگاه مشتریان KBS از پاداش شفاف، کیف پول جادویی، فروشگاه اعتباری و شبکه فروش بهرهمند شوید. " +
|
"با عضویت در باشگاه مشتریان KBS از پاداش شفاف، کیف پول جادویی، فروشگاه اعتباری و سازمان فروش بهرهمند شوید. " +
|
||||||
"ثبتنام رایگان در kbs2.ir.";
|
"ثبتنام رایگان در kbs2.ir.";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ public class SeoSettings
|
|||||||
public string SiteUrl { get; set; } = "https://kbs2.ir";
|
public string SiteUrl { get; set; } = "https://kbs2.ir";
|
||||||
public string SiteName { get; set; } = "کارابازار سلامت";
|
public string SiteName { get; set; } = "کارابازار سلامت";
|
||||||
public string DefaultDescription { get; set; } =
|
public string DefaultDescription { get; set; } =
|
||||||
"باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و شبکه فروش.";
|
"باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و سازمان فروش.";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
"Seo": {
|
"Seo": {
|
||||||
"SiteUrl": "https://kbs1.ir",
|
"SiteUrl": "https://kbs1.ir",
|
||||||
"SiteName": "کارابازار سلامت",
|
"SiteName": "کارابازار سلامت",
|
||||||
"DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و شبکه فروش."
|
"DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و سازمان فروش."
|
||||||
},
|
},
|
||||||
"GwUrl": "https://cms.se.kbs1.ir",
|
"GwUrl": "https://cms.se.kbs1.ir",
|
||||||
"DownloadUrl": "",
|
"DownloadUrl": "",
|
||||||
|
"TwentyCard": {
|
||||||
|
"CreditPortalUrl": "https://userpanel.20card.ir/"
|
||||||
|
},
|
||||||
"EncryptionSettings": {
|
"EncryptionSettings": {
|
||||||
"Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
|
"Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
|
||||||
"IV": "1wyF3Tt142MOkCpIyCxh/g=="
|
"IV": "1wyF3Tt142MOkCpIyCxh/g=="
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
"Seo": {
|
"Seo": {
|
||||||
"SiteUrl": "http://localhost:5268",
|
"SiteUrl": "http://localhost:5268",
|
||||||
"SiteName": "کارابازار سلامت",
|
"SiteName": "کارابازار سلامت",
|
||||||
"DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و شبکه فروش."
|
"DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و سازمان فروش."
|
||||||
},
|
},
|
||||||
"GwUrl": "https://cms.se.kbs1.ir",
|
"GwUrl": "https://cms.se.kbs1.ir",
|
||||||
"DownloadUrl": "",
|
"DownloadUrl": "",
|
||||||
|
"TwentyCard": {
|
||||||
|
"CreditPortalUrl": "https://userpanel.20card.ir/"
|
||||||
|
},
|
||||||
"EncryptionSettings": {
|
"EncryptionSettings": {
|
||||||
"Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
|
"Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
|
||||||
"IV": "1wyF3Tt142MOkCpIyCxh/g=="
|
"IV": "1wyF3Tt142MOkCpIyCxh/g=="
|
||||||
|
|||||||
Reference in New Issue
Block a user