From aedf31281263384013b7f89c9792d8d1436bd055 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Sun, 20 Sep 2026 22:17:39 +0330 Subject: [PATCH 01/10] feat(payment): integrate TwentyCard payment option and enhance checkout flow - Added a new payment method for TwentyCard in the checkout process, allowing users to select it alongside direct payment options. - Implemented the logic for processing TwentyCard payments, including user feedback and dialog interactions for payment confirmation. - Updated the appsettings files to include configuration for the new payment method. - Enhanced the user interface in the PackagePurchaseDialog to reflect the new payment option and its requirements. These changes improve the payment flexibility in the checkout process, providing users with additional options for completing their transactions. --- .gitattributes | 2 +- .gitignore | 2 +- src/FrontOffice.Main/FrontOffice.Main.csproj | 8 ++- src/FrontOffice.Main/Pages/Checkout.razor | 13 +++- src/FrontOffice.Main/Pages/Checkout.razor.cs | 35 ++++++++++- .../Pages/Profile/Index.razor.cs | 33 ++++++++-- .../Pages/Profile/PaymentCallback.razor | 8 +++ .../Shared/PackagePurchaseDialog.razor | 22 ++++++- .../Shared/TwentyCardCreditDialog.razor | 60 +++++++++++++++++++ .../appsettings.Production.json | 3 + src/FrontOffice.Main/appsettings.Staging.json | 3 + src/FrontOffice.Main/appsettings.json | 3 + 12 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 src/FrontOffice.Main/Shared/TwentyCardCreditDialog.razor diff --git a/.gitattributes b/.gitattributes index 82b5185..679f26c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ -# Keep production config from current branch during merges — never overwrite +# Keep production config from current branch during merges — never ov erwrite src/FrontOffice.Main/appsettings.Production.json merge=ours diff --git a/.gitignore b/.gitignore index 0f13c79..28a74b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # ---> VisualStudio ## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. +## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore diff --git a/src/FrontOffice.Main/FrontOffice.Main.csproj b/src/FrontOffice.Main/FrontOffice.Main.csproj index 8d8f9e7..eac8e04 100644 --- a/src/FrontOffice.Main/FrontOffice.Main.csproj +++ b/src/FrontOffice.Main/FrontOffice.Main.csproj @@ -10,8 +10,8 @@ - - + + @@ -23,6 +23,10 @@ + + + + diff --git a/src/FrontOffice.Main/Pages/Checkout.razor b/src/FrontOffice.Main/Pages/Checkout.razor index f138e5b..c268589 100644 --- a/src/FrontOffice.Main/Pages/Checkout.razor +++ b/src/FrontOffice.Main/Pages/Checkout.razor @@ -140,7 +140,18 @@ OnClick="ProcessPayment" Disabled="@(!CanProceedToPayment || _isProcessingPayment || !_selectedPackage.SupportsDirectPurchase)" Class="mt-2"> - @(_isProcessingPayment ? "در حال پردازش..." : "پرداخت آنلاین") + @(_isProcessingPayment ? "در حال پردازش..." : "پرداخت آنلاین (زرین‌پال)") + + + + پرداخت با ۲۰کارت @if (_selectedPackage.SupportsDayaPurchase) diff --git a/src/FrontOffice.Main/Pages/Checkout.razor.cs b/src/FrontOffice.Main/Pages/Checkout.razor.cs index 5e30af5..a15bf17 100644 --- a/src/FrontOffice.Main/Pages/Checkout.razor.cs +++ b/src/FrontOffice.Main/Pages/Checkout.razor.cs @@ -107,6 +107,33 @@ public partial class Checkout } 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( + 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; @@ -120,11 +147,15 @@ public partial class Checkout try { - var response = await PackageClient.CustomerPurchasePackageAsync(new CustomerPurchasePackageRequest + var request = new CustomerPurchasePackageRequest { PackageId = _selectedPackage.Id, PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway - }); + }; + if (!string.IsNullOrWhiteSpace(gatewayProvider)) + request.GatewayProvider = gatewayProvider; + + var response = await PackageClient.CustomerPurchasePackageAsync(request); if (!response.Success) { diff --git a/src/FrontOffice.Main/Pages/Profile/Index.razor.cs b/src/FrontOffice.Main/Pages/Profile/Index.razor.cs index 2f4a266..09708a7 100644 --- a/src/FrontOffice.Main/Pages/Profile/Index.razor.cs +++ b/src/FrontOffice.Main/Pages/Profile/Index.razor.cs @@ -421,7 +421,10 @@ public partial class Index switch (purchase.Method) { 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; case Shared.PackagePurchaseDialog.PaymentMethodType.DayaLoan: 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( + 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; @@ -439,11 +460,15 @@ public partial class Index try { - var response = await PackageContract.CustomerPurchasePackageAsync(new CustomerPurchasePackageRequest + var request = new CustomerPurchasePackageRequest { PackageId = packageId, PurchaseMethod = PurchaseMethodEnum.PurchaseMethodGateway - }); + }; + if (!string.IsNullOrWhiteSpace(gatewayProvider)) + request.GatewayProvider = gatewayProvider; + + var response = await PackageContract.CustomerPurchasePackageAsync(request); if (!response.Success) { diff --git a/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor b/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor index c70178f..3ca2632 100644 --- a/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor +++ b/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor @@ -85,6 +85,10 @@ [SupplyParameterFromQuery(Name = "Status")] private string? Status { get; set; } + + /// ۲۰کارت callback — هم‌معنی Status زرین‌پال + [SupplyParameterFromQuery(Name = "PaymentStatus")] + private string? PaymentStatus { get; set; } private bool _isLoading = true; private bool _isSuccess; @@ -132,6 +136,10 @@ { try { + // ۲۰کارت: PaymentStatus؛ زرین‌پال: Status + if (string.IsNullOrWhiteSpace(Status) && !string.IsNullOrWhiteSpace(PaymentStatus)) + Status = PaymentStatus; + // تعیین نوع پرداخت — اگر type نباشد، پیش‌فرض خرید پکیج var type = PaymentType?.ToLowerInvariant() ?? "package"; diff --git a/src/FrontOffice.Main/Shared/PackagePurchaseDialog.razor b/src/FrontOffice.Main/Shared/PackagePurchaseDialog.razor index c997ff1..5230825 100644 --- a/src/FrontOffice.Main/Shared/PackagePurchaseDialog.razor +++ b/src/FrontOffice.Main/Shared/PackagePurchaseDialog.razor @@ -52,7 +52,7 @@ روش پرداخت خود را انتخاب کنید: - @* Direct Payment — always available *@ + @* Direct Payment (ZarinPal) — always available *@ @@ -61,13 +61,29 @@ پرداخت مستقیم - پرداخت آنی از طریق درگاه بانکی + پرداخت آنی از طریق درگاه بانکی (زرین‌پال) + @* TwentyCard IPG *@ + + + + + + پرداخت با ۲۰کارت + پرداخت از طریق درگاه ۲۰کارت (نیاز به تأمین اعتبار) + + + + + + @* Daya Loan — only for base package AND first purchase cycle *@ @if (_selectedPackage.SupportsDayaPurchase && PurchaseCycleCount == 0) { @@ -229,6 +245,6 @@ : "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); } diff --git a/src/FrontOffice.Main/Shared/TwentyCardCreditDialog.razor b/src/FrontOffice.Main/Shared/TwentyCardCreditDialog.razor new file mode 100644 index 0000000..1f9b13f --- /dev/null +++ b/src/FrontOffice.Main/Shared/TwentyCardCreditDialog.razor @@ -0,0 +1,60 @@ +@inject IConfiguration Configuration +@inject IJSRuntime JSRuntime + + + + + + تأمین اعتبار ۲۰کارت + + + + + + برای پرداخت از طریق درگاه ۲۰کارت، ابتدا باید اعتبار حساب ۲۰کارت خود را تأمین کنید. + پس از تأمین اعتبار، روی «ادامه پرداخت» بزنید تا به درگاه هدایت شوید. + + + + اگر قبلاً اعتبار را تأمین کرده‌اید، می‌توانید مستقیم ادامه دهید. + + + + + انصراف + + تأمین اعتبار + + + ادامه پرداخت + + + + +@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(); +} diff --git a/src/FrontOffice.Main/appsettings.Production.json b/src/FrontOffice.Main/appsettings.Production.json index 6f08557..3411fe9 100644 --- a/src/FrontOffice.Main/appsettings.Production.json +++ b/src/FrontOffice.Main/appsettings.Production.json @@ -1,6 +1,9 @@ { "GwUrl": "https://cms.kbs1.ir", "DownloadUrl": "", + "TwentyCard": { + "CreditPortalUrl": "https://20card.ir" + }, "EncryptionSettings": { "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", "IV": "1wyF3Tt142MOkCpIyCxh/g==" diff --git a/src/FrontOffice.Main/appsettings.Staging.json b/src/FrontOffice.Main/appsettings.Staging.json index f07c714..038c752 100644 --- a/src/FrontOffice.Main/appsettings.Staging.json +++ b/src/FrontOffice.Main/appsettings.Staging.json @@ -6,6 +6,9 @@ }, "GwUrl": "https://cms.se.kbs1.ir", "DownloadUrl": "", + "TwentyCard": { + "CreditPortalUrl": "https://20card.ir" + }, "EncryptionSettings": { "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", "IV": "1wyF3Tt142MOkCpIyCxh/g==" diff --git a/src/FrontOffice.Main/appsettings.json b/src/FrontOffice.Main/appsettings.json index a8b7510..9ecc7ab 100644 --- a/src/FrontOffice.Main/appsettings.json +++ b/src/FrontOffice.Main/appsettings.json @@ -6,6 +6,9 @@ }, "GwUrl": "https://cms.se.kbs1.ir", "DownloadUrl": "", + "TwentyCard": { + "CreditPortalUrl": "https://20card.ir" + }, "EncryptionSettings": { "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", "IV": "1wyF3Tt142MOkCpIyCxh/g==" From 0d0ca252a6bc650936d637df4c4fecc9c39f478a Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Sun, 20 Sep 2026 22:41:49 +0330 Subject: [PATCH 02/10] fix(project): restore PackageReference and comment out ProjectReference for Protobuf - Reinstated the PackageReference for Foursat.CMSMicroservice.Protobuf version 0.0.212, ensuring the project can utilize the necessary protobuf functionalities. - Commented out the ProjectReference for the CMSMicroservice.Protobuf project to prevent build issues during development. These changes ensure proper package management and maintain project stability during development. --- src/FrontOffice.Main/FrontOffice.Main.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FrontOffice.Main/FrontOffice.Main.csproj b/src/FrontOffice.Main/FrontOffice.Main.csproj index eac8e04..689439a 100644 --- a/src/FrontOffice.Main/FrontOffice.Main.csproj +++ b/src/FrontOffice.Main/FrontOffice.Main.csproj @@ -11,7 +11,7 @@ - + @@ -24,7 +24,7 @@ - + From 27a3ea76c5458de8625eaadca92f4a88aabce798 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Sun, 20 Sep 2026 23:33:18 +0330 Subject: [PATCH 03/10] feat(profile): add invitees section and inviter mobile functionality - Introduced a new section in the Profile hub for viewing invitees, enhancing user engagement and tracking of referrals. - Added buttons for accessing the invitees page from the Profile index, improving navigation. - Enhanced the AuthDialog and PhoneVerifyForm components to support inviter mobile input, allowing users to specify who referred them. - Updated RouteConstants to include a new route for invitees, ensuring proper navigation within the application. These changes improve the user experience by facilitating better referral tracking and enhancing the profile management features. --- src/FrontOffice.Main/FrontOffice.Main.csproj | 2 +- src/FrontOffice.Main/Pages/Profile/Hub.razor | 15 ++ .../Pages/Profile/Index.razor | 14 ++ .../Pages/Profile/Invitees.razor | 159 ++++++++++++++++++ src/FrontOffice.Main/Shared/AuthDialog.razor | 8 +- .../Shared/AuthDialog.razor.cs | 22 +++ .../Shared/PhoneVerifyForm.razor | 16 +- .../Shared/PhoneVerifyForm.razor.cs | 4 + .../Utilities/RouteConstants.cs | 1 + 9 files changed, 235 insertions(+), 6 deletions(-) create mode 100644 src/FrontOffice.Main/Pages/Profile/Invitees.razor diff --git a/src/FrontOffice.Main/FrontOffice.Main.csproj b/src/FrontOffice.Main/FrontOffice.Main.csproj index 689439a..7ef57ee 100644 --- a/src/FrontOffice.Main/FrontOffice.Main.csproj +++ b/src/FrontOffice.Main/FrontOffice.Main.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/FrontOffice.Main/Pages/Profile/Hub.razor b/src/FrontOffice.Main/Pages/Profile/Hub.razor index 83f24db..7e38ce3 100644 --- a/src/FrontOffice.Main/Pages/Profile/Hub.razor +++ b/src/FrontOffice.Main/Pages/Profile/Hub.razor @@ -46,6 +46,21 @@ + + + + + + + دعوت‌شدگان من + کسانی که با موبایل شما ثبت‌نام کرده‌اند + + + + + + + diff --git a/src/FrontOffice.Main/Pages/Profile/Index.razor b/src/FrontOffice.Main/Pages/Profile/Index.razor index 0189e5b..462721f 100644 --- a/src/FrontOffice.Main/Pages/Profile/Index.razor +++ b/src/FrontOffice.Main/Pages/Profile/Index.razor @@ -109,6 +109,13 @@ { @(_copyMessage) } + + مشاهده دعوت‌شدگان من + } else @@ -121,6 +128,13 @@ برای فعال‌سازی لینک دعوت، ابتدا یکی از پکیج‌ها را تهیه کنید و سپس در باشگاه مشتریان عضو شوید. + + دعوت‌شدگان من + از مزایای ویژه عضویت بهره‌مند شده و با فعالیت در زمینه توسعه فروشگاه‌ها پاداش دریافت کنید. diff --git a/src/FrontOffice.Main/Pages/Profile/Invitees.razor b/src/FrontOffice.Main/Pages/Profile/Invitees.razor new file mode 100644 index 0000000..601b4b0 --- /dev/null +++ b/src/FrontOffice.Main/Pages/Profile/Invitees.razor @@ -0,0 +1,159 @@ +@page "/profile/invitees" +@attribute [Authorize] +@attribute [Route(RouteConstants.Profile.Invitees)] +@using CMSMicroservice.Protobuf.Protos.User +@using CMSMicroservice.Protobuf.Protos.City +@using DateTimeConverterCL +@inject UserContract.UserContractClient UserClient +@inject ISnackbar Snackbar + +دعوت‌شدگان من | کارا بازار سلامت + + + + + + افرادی که با شماره موبایل شما به‌عنوان دعوت‌کننده ثبت‌نام کرده‌اند (متفاوت از زیرمجموعه شبکه). + + + @if (_loading) + { + + + + } + else + { + + + + کل دعوت‌ها + @_stats.TotalInvitees + + + + + فعال در باشگاه + @_stats.ClubActiveCount + + + + + غیرفعال باشگاه + @_stats.ClubInactiveCount + + + + + + + همه + فعال باشگاه + غیرفعال باشگاه + + + + @if (!_invitees.Any()) + { + هنوز کسی با کد دعوت شما ثبت‌نام نکرده است. + } + else + { + + + نام + تاریخ ثبت‌نام + باشگاه + + + + @(string.IsNullOrWhiteSpace($"{context.FirstName} {context.LastName}".Trim()) + ? "—" + : $"{context.FirstName} {context.LastName}".Trim()) + + + @FormatDate(context.RegisteredAt) + + + @if (context.IsClubActive) + { + فعال + } + else + { + غیرفعال + } + + + + + @if (_totalPages > 1) + { + + + + } + } + } + + +@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 _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(); + } +} diff --git a/src/FrontOffice.Main/Shared/AuthDialog.razor b/src/FrontOffice.Main/Shared/AuthDialog.razor index d4e7b30..a99e45a 100644 --- a/src/FrontOffice.Main/Shared/AuthDialog.razor +++ b/src/FrontOffice.Main/Shared/AuthDialog.razor @@ -24,7 +24,9 @@ OnChangePhone="ChangePhoneAsync" OnResendOtp="ResendOtpAsync" ReferralCode="@_referralCode" - ReferralCodeChanged="OnReferralCodeChanged" /> + ReferralCodeChanged="OnReferralCodeChanged" + InviterMobile="@_inviterMobile" + InviterMobileChanged="OnInviterMobileChanged" /> } else @@ -55,7 +57,9 @@ else OnChangePhone="ChangePhoneAsync" OnResendOtp="ResendOtpAsync" ReferralCode="@_referralCode" - ReferralCodeChanged="OnReferralCodeChanged" /> + ReferralCodeChanged="OnReferralCodeChanged" + InviterMobile="@_inviterMobile" + InviterMobileChanged="OnInviterMobileChanged" /> @if (_currentStep == AuthStep.Phone) diff --git a/src/FrontOffice.Main/Shared/AuthDialog.razor.cs b/src/FrontOffice.Main/Shared/AuthDialog.razor.cs index 0ce1755..23da086 100644 --- a/src/FrontOffice.Main/Shared/AuthDialog.razor.cs +++ b/src/FrontOffice.Main/Shared/AuthDialog.razor.cs @@ -44,6 +44,8 @@ public partial class AuthDialog : IDisposable // Referral code field private string? _referralCode; + // Inviter mobile (دعوت‌کننده) + private string? _inviterMobile; [Inject] private ILocalStorageService LocalStorage { get; set; } = default!; [Inject] private UserContract.UserContractClient UserClient { get; set; } = default!; @@ -71,6 +73,7 @@ public partial class AuthDialog : IDisposable } _referralCode = await LocalStorage.GetItemAsync("referral:code"); + _inviterMobile = await LocalStorage.GetItemAsync("inviter:mobile"); // await LocalStorage.RemoveItemAsync(TokenStorageKey); } @@ -83,6 +86,15 @@ public partial class AuthDialog : IDisposable 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() { _captchaCode = Guid.NewGuid().ToString("N")[..6].ToUpperInvariant(); @@ -204,6 +216,15 @@ public partial class AuthDialog : IDisposable _verifyRequest.ParentReferralCode = effectiveReferralCode; } + var storedInviterMobile = await LocalStorage.GetItemAsync("inviter:mobile"); + var effectiveInviterMobile = !string.IsNullOrWhiteSpace(_inviterMobile) + ? _inviterMobile + : storedInviterMobile; + if (!string.IsNullOrWhiteSpace(effectiveInviterMobile)) + { + _verifyRequest.InviterMobile = effectiveInviterMobile; + } + var validationResult = true; // _verifyRequestValidator.Validate(_verifyRequest); if (!validationResult) { @@ -236,6 +257,7 @@ public partial class AuthDialog : IDisposable await LocalStorage.RemoveItemAsync(PhoneStorageKey); await LocalStorage.RemoveItemAsync(RedirectStorageKey); await LocalStorage.RemoveItemAsync("referral:code"); + await LocalStorage.RemoveItemAsync("inviter:mobile"); _attemptsLeft = MaxVerificationAttempts; _verifyRequest.Code = string.Empty; diff --git a/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor b/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor index 3ca37a4..d6ea5ae 100644 --- a/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor +++ b/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor @@ -38,11 +38,21 @@ + Placeholder="کد معرف ۱۰ رقمی" + Class="mb-3" + HelperText="جایگاه شما در شبکه — با لینک معرف پر می‌شود" /> + + @if (!string.IsNullOrWhiteSpace(ErrorMessage)) { diff --git a/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor.cs b/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor.cs index e7f353e..f917d88 100644 --- a/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor.cs +++ b/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor.cs @@ -33,6 +33,10 @@ public partial class PhoneVerifyForm [Parameter] public string? ReferralCode { get; set; } [Parameter] public EventCallback ReferralCodeChanged { get; set; } + // ── Inviter (دعوت‌کننده) ── + [Parameter] public string? InviterMobile { get; set; } + [Parameter] public EventCallback InviterMobileChanged { get; set; } + // ── Verify actions ── [Parameter] public EventCallback OnChangePhone { get; set; } [Parameter] public EventCallback OnResendOtp { get; set; } diff --git a/src/FrontOffice.Main/Utilities/RouteConstants.cs b/src/FrontOffice.Main/Utilities/RouteConstants.cs index 7000f3f..cc1dddd 100644 --- a/src/FrontOffice.Main/Utilities/RouteConstants.cs +++ b/src/FrontOffice.Main/Utilities/RouteConstants.cs @@ -21,6 +21,7 @@ public static class RouteConstants public const string Settings = "/profile/settings"; public const string ChangePassword = "/profile/change-password"; public const string Tree = "/profile/tree"; + public const string Invitees = "/profile/invitees"; public const string Wallet = "/profile/wallet"; public const string MagicWallet = "/profile/magic-wallet"; public const string ChargeDiscountWallet = "/profile/charge-discount-wallet"; From c815f8d358a1a819ad06ba39f07fdd10d2383f72 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Sun, 20 Sep 2026 23:35:11 +0330 Subject: [PATCH 04/10] refactor(project): update Protobuf package management and add conditional ProjectReference - Removed the direct PackageReference for Foursat.CMSMicroservice.Protobuf and added a conditional ProjectReference to the CMSMicroservice.Protobuf project for local development. - This change allows for direct communication with the CMS when the project is available locally, while still maintaining the NuGet package reference for CI/Docker environments. These updates improve the flexibility of the project setup for different development scenarios. --- src/FrontOffice.Main/FrontOffice.Main.csproj | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/FrontOffice.Main/FrontOffice.Main.csproj b/src/FrontOffice.Main/FrontOffice.Main.csproj index 7ef57ee..812bdb9 100644 --- a/src/FrontOffice.Main/FrontOffice.Main.csproj +++ b/src/FrontOffice.Main/FrontOffice.Main.csproj @@ -10,8 +10,7 @@ - - + @@ -23,9 +22,18 @@ - - - + + + + + + + + + + + + From c71062decf7f54b3774292982d02ab740736598a Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Mon, 21 Sep 2026 00:44:15 +0330 Subject: [PATCH 05/10] refactor(profile): clean up Invitees.razor by removing unused using directive - Removed the unused DateTimeConverterCL using directive from the Invitees.razor file, streamlining the code and improving readability. This change enhances the maintainability of the profile invitees page by eliminating unnecessary dependencies. --- src/FrontOffice.Main/Pages/Profile/Invitees.razor | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/FrontOffice.Main/Pages/Profile/Invitees.razor b/src/FrontOffice.Main/Pages/Profile/Invitees.razor index 601b4b0..68b7142 100644 --- a/src/FrontOffice.Main/Pages/Profile/Invitees.razor +++ b/src/FrontOffice.Main/Pages/Profile/Invitees.razor @@ -1,9 +1,7 @@ -@page "/profile/invitees" @attribute [Authorize] @attribute [Route(RouteConstants.Profile.Invitees)] @using CMSMicroservice.Protobuf.Protos.User @using CMSMicroservice.Protobuf.Protos.City -@using DateTimeConverterCL @inject UserContract.UserContractClient UserClient @inject ISnackbar Snackbar From a108f892133b57e1813b47126246d0f970b7f98e Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Mon, 21 Sep 2026 21:32:15 +0330 Subject: [PATCH 06/10] chore(config): update CreditPortalUrl in appsettings files and clean up .gitignore - Changed the CreditPortalUrl in appsettings.json, appsettings.Production.json, and appsettings.Staging.json to point to the new user panel URL. - Removed an unnecessary blank line from the .gitignore file to maintain consistency. These updates ensure correct configuration for the TwentyCard integration and improve the project's file management. --- .gitignore | 2 +- src/FrontOffice.Main/appsettings.Production.json | 2 +- src/FrontOffice.Main/appsettings.Staging.json | 2 +- src/FrontOffice.Main/appsettings.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 28a74b2..bf1fd69 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore - + # User-specific files *.rsuser *.suo diff --git a/src/FrontOffice.Main/appsettings.Production.json b/src/FrontOffice.Main/appsettings.Production.json index 3411fe9..9b93861 100644 --- a/src/FrontOffice.Main/appsettings.Production.json +++ b/src/FrontOffice.Main/appsettings.Production.json @@ -2,7 +2,7 @@ "GwUrl": "https://cms.kbs1.ir", "DownloadUrl": "", "TwentyCard": { - "CreditPortalUrl": "https://20card.ir" + "CreditPortalUrl": "https://userpanel.20card.ir/" }, "EncryptionSettings": { "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", diff --git a/src/FrontOffice.Main/appsettings.Staging.json b/src/FrontOffice.Main/appsettings.Staging.json index 038c752..83fc1e5 100644 --- a/src/FrontOffice.Main/appsettings.Staging.json +++ b/src/FrontOffice.Main/appsettings.Staging.json @@ -7,7 +7,7 @@ "GwUrl": "https://cms.se.kbs1.ir", "DownloadUrl": "", "TwentyCard": { - "CreditPortalUrl": "https://20card.ir" + "CreditPortalUrl": "https://userpanel.20card.ir/" }, "EncryptionSettings": { "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", diff --git a/src/FrontOffice.Main/appsettings.json b/src/FrontOffice.Main/appsettings.json index 9ecc7ab..1d16bad 100644 --- a/src/FrontOffice.Main/appsettings.json +++ b/src/FrontOffice.Main/appsettings.json @@ -7,7 +7,7 @@ "GwUrl": "https://cms.se.kbs1.ir", "DownloadUrl": "", "TwentyCard": { - "CreditPortalUrl": "https://20card.ir" + "CreditPortalUrl": "https://userpanel.20card.ir/" }, "EncryptionSettings": { "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", From a4061c041ba8b7a01038b9afd580538936578a53 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Tue, 22 Sep 2026 00:08:02 +0330 Subject: [PATCH 07/10] fix(profile): update invitees description for clarity - Revised the text in the Invitees.razor file to clarify that registered invitees are distinct from the sales organization, improving user understanding of the invitee section. This change enhances the clarity of the information presented to users on the profile invitees page. --- src/FrontOffice.Main/Pages/Profile/Invitees.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FrontOffice.Main/Pages/Profile/Invitees.razor b/src/FrontOffice.Main/Pages/Profile/Invitees.razor index 68b7142..8c7c385 100644 --- a/src/FrontOffice.Main/Pages/Profile/Invitees.razor +++ b/src/FrontOffice.Main/Pages/Profile/Invitees.razor @@ -11,7 +11,7 @@ - افرادی که با شماره موبایل شما به‌عنوان دعوت‌کننده ثبت‌نام کرده‌اند (متفاوت از زیرمجموعه شبکه). + افرادی که با شماره موبایل شما به‌عنوان دعوت‌کننده ثبت‌نام کرده‌اند (متفاوت از سازمان فروش). @if (_loading) From ea357e986597bbc83159933e97a155d4f6a3f76f Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Tue, 22 Sep 2026 22:18:43 +0330 Subject: [PATCH 08/10] chore(staging): point registry and K8S to 185.252.31.44 after server migration --- .gitea/workflows/kub-deploy.yml | 10 +++++----- .gitea/workflows/prod-deploy.yml | 10 +++++----- k8s/production/frontoffice-deployment.yaml | 2 +- k8s/staging/frontoffice-deployment.yaml | 2 +- src/FrontOffice.Main/Dockerfile | 4 ++-- src/FrontOffice.Main/NuGet.config | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.gitea/workflows/kub-deploy.yml b/.gitea/workflows/kub-deploy.yml index 7084740..34633a9 100644 --- a/.gitea/workflows/kub-deploy.yml +++ b/.gitea/workflows/kub-deploy.yml @@ -6,15 +6,15 @@ on: - kub-stage env: - REGISTRY: 194.5.195.53:30080 + REGISTRY: 185.252.31.44:30080 IMAGE_NAME: admin/frontoffice - K8S_SERVER: 194.5.195.53 + K8S_SERVER: 185.252.31.44 jobs: build-and-deploy: runs-on: ubuntu-latest container: - image: 194.5.195.53:32082/docker-sshpass:latest + image: 185.252.31.44:32082/docker-sshpass:latest options: --privileged steps: - name: Start Docker daemon @@ -22,7 +22,7 @@ jobs: mkdir -p /etc/docker cat > /etc/docker/daemon.json << 'DAEMON' { - "insecure-registries": ["194.5.195.53:30080", "194.5.195.53:32500", "194.5.195.53:32082"] + "insecure-registries": ["185.252.31.44:30080", "185.252.31.44:32500", "185.252.31.44:32082"] } DAEMON echo "🚀 Starting Docker daemon..." @@ -52,7 +52,7 @@ jobs: - name: Login to Docker registries run: | - echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 194.5.195.53:32082 -u admin --password-stdin + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 185.252.31.44:32082 -u admin --password-stdin echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin - name: Build Docker Image diff --git a/.gitea/workflows/prod-deploy.yml b/.gitea/workflows/prod-deploy.yml index cdfe89b..846a51b 100644 --- a/.gitea/workflows/prod-deploy.yml +++ b/.gitea/workflows/prod-deploy.yml @@ -6,15 +6,15 @@ on: - production env: - REGISTRY: 194.5.195.53:30080 + REGISTRY: 185.252.31.44:30080 IMAGE_NAME: admin/frontoffice - K8S_SERVER: 194.5.195.53 + K8S_SERVER: 45.149.79.127 jobs: build-and-deploy: runs-on: ubuntu-latest container: - image: 194.5.195.53:32082/docker-sshpass:latest + image: 185.252.31.44:32082/docker-sshpass:latest options: --privileged steps: - name: Start Docker daemon @@ -22,7 +22,7 @@ jobs: mkdir -p /etc/docker cat > /etc/docker/daemon.json << 'DAEMON' { - "insecure-registries": ["194.5.195.53:30080", "194.5.195.53:32500", "194.5.195.53:32082"] + "insecure-registries": ["185.252.31.44:30080", "185.252.31.44:32500", "185.252.31.44:32082"] } DAEMON echo "🚀 Starting Docker daemon..." @@ -50,7 +50,7 @@ jobs: - name: Login to Docker registries run: | - echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 194.5.195.53:32082 -u admin --password-stdin + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 185.252.31.44:32082 -u admin --password-stdin echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin - name: Build Docker Image diff --git a/k8s/production/frontoffice-deployment.yaml b/k8s/production/frontoffice-deployment.yaml index 15111ac..a373512 100644 --- a/k8s/production/frontoffice-deployment.yaml +++ b/k8s/production/frontoffice-deployment.yaml @@ -20,7 +20,7 @@ spec: spec: containers: - name: frontoffice - image: 194.5.195.53:30080/admin/frontoffice:prod + image: 185.252.31.44:30080/admin/frontoffice:prod imagePullPolicy: Always ports: - containerPort: 80 diff --git a/k8s/staging/frontoffice-deployment.yaml b/k8s/staging/frontoffice-deployment.yaml index 989e9a2..c5873b2 100644 --- a/k8s/staging/frontoffice-deployment.yaml +++ b/k8s/staging/frontoffice-deployment.yaml @@ -20,7 +20,7 @@ spec: spec: containers: - name: frontoffice - image: 194.5.195.53:30080/admin/frontoffice:latest + image: 185.252.31.44:30080/admin/frontoffice:latest imagePullPolicy: Always ports: - containerPort: 80 diff --git a/src/FrontOffice.Main/Dockerfile b/src/FrontOffice.Main/Dockerfile index b7a1691..c415855 100644 --- a/src/FrontOffice.Main/Dockerfile +++ b/src/FrontOffice.Main/Dockerfile @@ -1,4 +1,4 @@ -FROM 194.5.195.53:32082/dotnet/sdk:9.0 AS build +FROM 185.252.31.44:32082/dotnet/sdk:9.0 AS build WORKDIR /src # Copy NuGet config and project file @@ -16,7 +16,7 @@ WORKDIR "/src/FrontOffice.Main" RUN dotnet publish "FrontOffice.Main.csproj" -c Release -o /app/publish # Runtime stage - aspnet for Blazor Server -FROM 194.5.195.53:32082/dotnet/aspnet:9.0 AS runtime +FROM 185.252.31.44:32082/dotnet/aspnet:9.0 AS runtime WORKDIR /app COPY --from=build /app/publish . diff --git a/src/FrontOffice.Main/NuGet.config b/src/FrontOffice.Main/NuGet.config index c53f59f..706d210 100644 --- a/src/FrontOffice.Main/NuGet.config +++ b/src/FrontOffice.Main/NuGet.config @@ -3,7 +3,7 @@ - + From 955736d345c0efe6f707f4b99e5d8dc025b8b5aa Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Tue, 22 Sep 2026 22:49:41 +0330 Subject: [PATCH 09/10] =?UTF-8?q?fix(copy):=20replace=20=D8=B4=D8=A8=DA=A9?= =?UTF-8?q?=D9=87=20with=20=D8=B3=D8=A7=D8=B2=D9=85=D8=A7=D9=86=20and=20cl?= =?UTF-8?q?arify=20inviter=20wording?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- src/FrontOffice.Main/Pages/Index.razor.cs | 2 +- src/FrontOffice.Main/Pages/RegisterWizard.razor.cs | 6 +++--- src/FrontOffice.Main/Shared/PhoneVerifyForm.razor | 6 +++--- src/FrontOffice.Main/Utilities/Seo/SeoMetadataProvider.cs | 2 +- src/FrontOffice.Main/Utilities/Seo/SeoSettings.cs | 2 +- src/FrontOffice.Main/appsettings.Staging.json | 2 +- src/FrontOffice.Main/appsettings.json | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/FrontOffice.Main/Pages/Index.razor.cs b/src/FrontOffice.Main/Pages/Index.razor.cs index a66bc26..d019edc 100644 --- a/src/FrontOffice.Main/Pages/Index.razor.cs +++ b/src/FrontOffice.Main/Pages/Index.razor.cs @@ -162,7 +162,7 @@ public partial class Index : IDisposable (Icons.Material.Outlined.VerifiedUser, "ثبت‌نام سریع و ساده", "در چند گام کوتاه حساب بسازید و شروع کنید.", 0), (Icons.Material.Outlined.StarBorder, "پاداش‌های شفاف", "قوانین روشن، دسترسی آسان به سوابق و گزارش‌ها.", 100), (Icons.Material.Outlined.Devices, "طراحی واکنش‌گرا", "تجربه‌ای روان در موبایل و دسکتاپ.", 200), - (Icons.Material.Outlined.Groups, "تیم‌سازی هوشمند", "ساختار درختی شبکه و مدیریت تیم‌های فروش.", 300), + (Icons.Material.Outlined.Groups, "تیم‌سازی هوشمند", "ساختار درختی سازمان و مدیریت تیم‌های فروش.", 300), (Icons.Material.Outlined.Insights, "گزارش‌های لحظه‌ای", "داشبورد پویا برای مشاهده عملکرد و کمیسیون.", 400), (Icons.Material.Outlined.Lock, "امنیت بالا", "رمزنگاری اطلاعات و احراز هویت چندمرحله‌ای.", 500), }; diff --git a/src/FrontOffice.Main/Pages/RegisterWizard.razor.cs b/src/FrontOffice.Main/Pages/RegisterWizard.razor.cs index 02891d0..c8c0e7c 100644 --- a/src/FrontOffice.Main/Pages/RegisterWizard.razor.cs +++ b/src/FrontOffice.Main/Pages/RegisterWizard.razor.cs @@ -319,17 +319,17 @@ public partial class RegisterWizard $"

شماره ملی: {_model.NationalCode?.PersianToEnglish()}

" + $"

شماره تماس: {_userAuthInfo.MobileNumber?.PersianToEnglish()}

" + "

کارابازار و کاربر که در این قرارداد جداگانه «طرف» و مجموعاً «طرفین» نامیده می‌شوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا می‌نمایند.

ماده ۱ - موضوع قرارداد

" + - "

موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر ازخدمات، باشگاه مشتریان، مزایا، طرح‌های همکاری، شبکه معرفی، خرید از فروشگاه‌های طرف‌قراردادو هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرم‌ها و شرکت‌هایهمکار در اختیار کاربر قرار می‌گیرد، بدون اینکه جزئیات مدل کسب‌وکار، شیوه تأمین منابع مالی،شبکه همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.

" + + "

موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر ازخدمات، باشگاه مشتریان، مزایا، طرح‌های همکاری، سازمان معرفی، خرید از فروشگاه‌های طرف‌قراردادو هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرم‌ها و شرکت‌هایهمکار در اختیار کاربر قرار می‌گیرد، بدون اینکه جزئیات مدل کسب‌وکار، شیوه تأمین منابع مالی،سازمان همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.

" + "

ماده ۲ - اقرار و آگاهی کاربر

۲-۱. کاربر اقرار می‌نماید که کلیه اطلاعات کلی لازم در خصوص نحوه فعالیت، مزایا، ریسک‌های احتمالی," + "سازوکار کلی استفاده از خدمات، و چارچوب کلی همکاری را از مراجع رسمی معرفی‌شده توسط کارابازاردریافت کرده، سؤالات خود را مطرح نموده و پاسخ مناسب را دریافت نموده است.

۲-۲. کاربر با امضای این قرارداد اقرار می‌نماید که:

  • با اراده آزاد و بدون هرگونه اجبار، اکراه، فریب یا سوءاستفاده از ناآگاهی وارد این همکاری شده است.
  • از احتمال وجود ریسک‌های مالی، اعتباری، قانونی و شبکه‌ای مرتبط با فعالیت خود آگاه بوده و آن را می‌پذیرد.
  • " + - "
  • هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در شبکه معرفی، خرید از فروشگاه‌ها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و به‌عنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمی‌شود.
" + + "
  • هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در سازمان معرفی، خرید از فروشگاه‌ها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و به‌عنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمی‌شود.
  • " + "

    ماده ۳ - سلب مسئولیت کارابازار

    ۳-۱. کاربر صراحتاً می‌پذیرد که کارابازار صرفاً در چارچوب قوانین و مقررات حاکم و مطابق قراردادها و تفاهم‌نامه‌های خود با شرکای تجاری و پلتفرم‌های همکار، خدمات و امکانات مشخصی را در اختیار کاربر قرار می‌دهد و هیچ‌گونه تعهدی نسبت به:

    • تحقق سود یا بازده مالی مشخص،
    • ثبات ارزش هرگونه اعتبار، امتیاز، یا منافع غیرنقدی که ممکن است در قالب طرح‌ها به کاربر تخصیص یابد،
    • " + "
    • عملکرد اشخاص ثالث (از جمله پلتفرم‌ها، فروشگاه‌ها، شرکت‌های بیمه، ارائه‌دهندگان خدمات سلامت و هر شخص حقیقی یا حقوقی همکار)،
    • تصمیمات و اقدامات کاربر در جذب افراد جدید و ایجاد زیرمجموعه،

    نداشته و نخواهد داشت مگر در حدودی که به‌صراحت در قرارداد یا قوانین آمره بر عهده کارابازار گذاشته شده است.

    " + "۳-۲. هرگونه خسارت، دعوی، تهدید، مطالبه، ادعا، شکایت یا پیگیری حقوقی که ناشی از تصمیمات شخصی کاربر،نحوه استفاده وی از تسهیلات و مزایا، جذب دیگران، خرید کالا و خدمات، یا تعاملات او با اشخاص ثالث باشد،مستقیماً متوجه خود کاربر است و کارابازار نسبت به آن هیچ‌گونه مسئولیت مدنی، کیفری، مالی یا قراردادی ندارد," + "مگر در مواردی که طبق قوانین آمره، مسئولیت صریح و غیرقابل‌اسقاط بر عهده کارابازار قرار گرفته باشد.

    ۳-۳. کاربر می‌پذیرد که هیچ‌گونه ادعایی مبنی بر فریب، اغفال، ارائه اطلاعات نادرست یا وعده‌های خارج ازچهارچوب رسمی از سوی کارابازار یا نمایندگان رسمی آن، پس از امضای این قرارداد، از وی مسموع نخواهد بود،مگر آنکه طبق رأی قطعی مرجع قضایی صالح، خلاف آن ثابت شود.

    ماده ۴ - مسئولیت کاربر در قبال تهدید، ادعا و شکایت

    " + "

    ۴-۱. کاربر متعهد است در صورت طرح هرگونه تهدید، ادعا، مطالبه، شکایت یا پیگیری حقوقی از سوی اشخاص ثالث(از جمله افراد جذب‌شده توسط کاربر، زیرمجموعه‌ها، خریداران معرفی‌شده یا سایر اشخاص)، که ناشی از عملکردشخصی کاربر، معرفی‌های وی، شیوه تبلیغ، وعده‌های خارج از چارچوب رسمی کارابازار، یا نقض قوانین و مقرراتباشد، خود رأساً پاسخگو باشد و کارابازار را از هرگونه مسئولیت و هزینه احتمالی در این خصوص مصون بدارد.

    ۴-۲. کاربر می‌پذیرد که:

    • هرگونه تهدید یا ادعای بی‌جا، غیرمنطقی، غیرمستند یا مغایر با مفاد این قرارداد، متوجه شخص کاربر است.
    • " + "
    • در صورت وارد آمدن خسارت مادی یا معنوی به کارابازار ناشی از چنین تهدیدات یا ادعاهایی، کارابازار حق دارد نسبت به مطالبه خسارت از کاربر، طبق قوانین و از طریق مراجع صالح اقدام نماید.
    " + - "

    ماده ۵ - محرمانگی و عدم افشای جزئیات کسب‌وکار

    ۵-۱. کاربر می‌پذیرد که جزئیات فنی، مالی، ساختار شبکه، شیوه توزیع مزایا، قراردادهای داخلی کارابازار باشرکای تجاری و پلتفرم‌های همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آن‌هاتوسط کاربر بدون مجوز کتبی کارابازار، مجاز نمی‌باشد.

    ۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسب‌وکار در این قرارداد را به‌عنوان دلیل بطلان، فسخ یاادعای فریب علیه کارابازار از خود سلب می‌نماید.

    " + + "

    ماده ۵ - محرمانگی و عدم افشای جزئیات کسب‌وکار

    ۵-۱. کاربر می‌پذیرد که جزئیات فنی، مالی، ساختار سازمان، شیوه توزیع مزایا، قراردادهای داخلی کارابازار باشرکای تجاری و پلتفرم‌های همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آن‌هاتوسط کاربر بدون مجوز کتبی کارابازار، مجاز نمی‌باشد.

    ۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسب‌وکار در این قرارداد را به‌عنوان دلیل بطلان، فسخ یاادعای فریب علیه کارابازار از خود سلب می‌نماید.

    " + "

    ماده ۶ - کد تأیید یکبارمصرف (OTP) و شناسه قرارداد

    ۶-۱. به منظور تأیید هویت کاربر و جایگزین کردن امضا در محیط غیرحضوری، برای این قرارداد یک شناسه یکتا(GUID) تولید شده و از طریق سامانه کارابازار، کد تأیید یکبارمصرف (OTP) مرتبط با آن برای کاربر ارسالمی‌گردد.

    " + "

    ۶-۲. کاربر با وارد کردن صحیح کد تأیید (OTP) در سامانه، اقرار می‌نماید که:

    • مالک شماره تماس ثبت‌شده در این قرارداد است یا با اجازه قانونی مالک از آن استفاده می‌کند،
    • از محتوای قرارداد به‌طور کامل آگاه است و آن را بدون ابهام و با رضایت کامل می‌پذیرد،
    • شناسه یکتا و OTP ارسال‌شده، معادل امضای الکترونیکی معتبر وی بر روی این قرارداد است.
    " + "

    ماده ۷ - مدت، اصلاح و حاکمیت قانون

    " + diff --git a/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor b/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor index d6ea5ae..a56cc58 100644 --- a/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor +++ b/src/FrontOffice.Main/Shared/PhoneVerifyForm.razor @@ -38,12 +38,12 @@ + HelperText="جایگاه شما در سازمان — با لینک معرف پر می‌شود" /> + HelperText="کسی که شما را به کارابازار معرفی کرده — متفاوت از معرف سازمان" /> @if (!string.IsNullOrWhiteSpace(ErrorMessage)) { diff --git a/src/FrontOffice.Main/Utilities/Seo/SeoMetadataProvider.cs b/src/FrontOffice.Main/Utilities/Seo/SeoMetadataProvider.cs index 6909b42..c0b73ab 100644 --- a/src/FrontOffice.Main/Utilities/Seo/SeoMetadataProvider.cs +++ b/src/FrontOffice.Main/Utilities/Seo/SeoMetadataProvider.cs @@ -208,6 +208,6 @@ public class SeoMetadataProvider private static string GetHomeCrawlableContent() => "کارابازار سلامت (KBS) — باشگاه مشتریان و فروشگاه محصولات سلامت. " + - "با عضویت در باشگاه مشتریان KBS از پاداش شفاف، کیف پول جادویی، فروشگاه اعتباری و شبکه فروش بهره‌مند شوید. " + + "با عضویت در باشگاه مشتریان KBS از پاداش شفاف، کیف پول جادویی، فروشگاه اعتباری و سازمان فروش بهره‌مند شوید. " + "ثبت‌نام رایگان در kbs2.ir."; } diff --git a/src/FrontOffice.Main/Utilities/Seo/SeoSettings.cs b/src/FrontOffice.Main/Utilities/Seo/SeoSettings.cs index 89d19e9..bf8f2f4 100644 --- a/src/FrontOffice.Main/Utilities/Seo/SeoSettings.cs +++ b/src/FrontOffice.Main/Utilities/Seo/SeoSettings.cs @@ -7,5 +7,5 @@ public class SeoSettings public string SiteUrl { get; set; } = "https://kbs2.ir"; public string SiteName { get; set; } = "کارابازار سلامت"; public string DefaultDescription { get; set; } = - "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و شبکه فروش."; + "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و سازمان فروش."; } diff --git a/src/FrontOffice.Main/appsettings.Staging.json b/src/FrontOffice.Main/appsettings.Staging.json index 83fc1e5..9eeec81 100644 --- a/src/FrontOffice.Main/appsettings.Staging.json +++ b/src/FrontOffice.Main/appsettings.Staging.json @@ -2,7 +2,7 @@ "Seo": { "SiteUrl": "https://kbs1.ir", "SiteName": "کارابازار سلامت", - "DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و شبکه فروش." + "DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و سازمان فروش." }, "GwUrl": "https://cms.se.kbs1.ir", "DownloadUrl": "", diff --git a/src/FrontOffice.Main/appsettings.json b/src/FrontOffice.Main/appsettings.json index 1d16bad..33d9fbb 100644 --- a/src/FrontOffice.Main/appsettings.json +++ b/src/FrontOffice.Main/appsettings.json @@ -2,7 +2,7 @@ "Seo": { "SiteUrl": "http://localhost:5268", "SiteName": "کارابازار سلامت", - "DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و شبکه فروش." + "DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و سازمان فروش." }, "GwUrl": "https://cms.se.kbs1.ir", "DownloadUrl": "", From c2c07c6b89ab02ee97aa0e647fb42341979c1b51 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Thu, 24 Sep 2026 21:26:19 +0330 Subject: [PATCH 10/10] chore(k8s): deploy staging apps to namespace kbs-stage Co-authored-by: Cursor --- .gitea/workflows/kub-deploy.yml | 6 ++--- k8s/staging/frontoffice-deployment.yaml | 34 ++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/.gitea/workflows/kub-deploy.yml b/.gitea/workflows/kub-deploy.yml index 34633a9..7d393c6 100644 --- a/.gitea/workflows/kub-deploy.yml +++ b/.gitea/workflows/kub-deploy.yml @@ -73,10 +73,10 @@ jobs: # Apply manifests and restart 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 && - kubectl rollout restart deployment/frontoffice && - kubectl rollout status deployment/frontoffice --timeout=180s && + kubectl -n kbs-stage rollout restart deployment/frontoffice && + kubectl -n kbs-stage rollout status deployment/frontoffice --timeout=180s && rm -f /tmp/frontoffice-deployment.yaml " echo "✅ Deployed!" diff --git a/k8s/staging/frontoffice-deployment.yaml b/k8s/staging/frontoffice-deployment.yaml index c5873b2..22d2154 100644 --- a/k8s/staging/frontoffice-deployment.yaml +++ b/k8s/staging/frontoffice-deployment.yaml @@ -4,7 +4,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: frontoffice - namespace: default + namespace: kbs-stage labels: app: frontoffice environment: staging @@ -21,7 +21,7 @@ spec: containers: - name: frontoffice image: 185.252.31.44:30080/admin/frontoffice:latest - imagePullPolicy: Always + imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: http @@ -43,7 +43,7 @@ apiVersion: v1 kind: Service metadata: name: frontoffice-svc - namespace: default + namespace: kbs-stage labels: app: frontoffice spec: @@ -54,3 +54,31 @@ spec: targetPort: 80 name: http 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