Compare commits

...

58 Commits

Author SHA1 Message Date
masoodafar-web b60d1da4b7 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 9m21s
2026-10-05 01:26:11 +03:30
masoodafar-web 016b259da0 feat(index): add configuration options for landing page sections
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m47s
- Introduced new settings in appsettings files to control the visibility of the steps and features sections on the landing page, allowing for dynamic content presentation.
- Updated Index.razor and Index.razor.cs to utilize these settings, enhancing user experience by enabling or disabling sections based on configuration.
2026-10-04 23:54:42 +03:30
masoodafar-web bb789e443e feat(index): enable conditional rendering for steps and features sections
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m21s
- Added support for conditional rendering of the steps and features sections on the landing page, controlled by the new `StepsEnabled` and `FeaturesEnabled` properties in the Index.razor.cs file.
- This enhancement allows for more dynamic content presentation based on user settings, improving the overall user experience.
2026-10-04 23:34:22 +03:30
masoodafar-web 0c1842cf02 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 11m31s
2026-10-04 23:02:04 +03:30
masoodafar-web 392e038913 chore(k8s): update kub-deploy workflow and frontoffice deployment configuration
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 10m11s
- Modified the kub-deploy.yml to remove cached images using containerd's ctr command, ensuring that both IfNotPresent and Always image pull policies work correctly.
- Updated frontoffice-deployment.yaml to set imagePullPolicy to Always, preventing stale node cache issues with the :latest tag.

These changes improve the deployment process and ensure that the latest images are always used in the staging environment.
2026-10-03 23:53:02 +03:30
masoodafar-web d7f25efce2 fix(index): remove unnecessary fade-in effect from TwentyCard promo section
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 11m13s
- Eliminated the fade-in effect from the MudPaper component in the TwentyCard credit promo section on the landing page, streamlining the visual presentation.

This change enhances the user experience by simplifying the design of the promotional section.
2026-10-03 22:43:53 +03:30
masoodafar-web 5246d8c1ba feat(index): add TwentyCard credit promo section and integrate portal link
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m23s
- Introduced a new promotional section for TwentyCard credit on the landing page, featuring details about the service and a button to access the TwentyCard portal.
- Updated the Index.razor.cs file to retrieve the portal URL from configuration and implemented the logic to open the portal in a new tab.
- Enhanced site.css with styling specific to the TwentyCard promo box.

These changes enhance user engagement by promoting the TwentyCard credit option and providing easy access to its portal.
2026-10-03 22:18:44 +03:30
masoodafar-web f5bfdba124 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 12m51s
2026-09-24 21:49:42 +03:30
masoodafar-web c2c07c6b89 chore(k8s): deploy staging apps to namespace kbs-stage
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 29s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-24 21:26:19 +03:30
masoodafar-web 764742dbe7 chore(infra): point staging registry to 185.252.31.44; keep prod K8S on 45.149.79.127
Build and Deploy to Production / build-and-deploy (push) Failing after 1s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-23 15:17:07 +03:30
masoodafar-web 955736d345 fix(copy): replace شبکه with سازمان and clarify inviter wording
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 16m3s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-22 22:49:41 +03:30
masoodafar-web ea357e9865 chore(staging): point registry and K8S to 185.252.31.44 after server migration 2026-09-22 22:18:43 +03:30
masoodafar-web a4061c041b fix(profile): update invitees description for clarity
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 15m47s
- 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.
2026-09-22 00:08:02 +03:30
masoodafar-web a108f89213 chore(config): update CreditPortalUrl in appsettings files and clean up .gitignore
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 7m20s
- 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.
2026-09-21 21:32:15 +03:30
masoodafar-web c71062decf refactor(profile): clean up Invitees.razor by removing unused using directive
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 5m29s
- 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.
2026-09-21 00:44:15 +03:30
masoodafar-web c815f8d358 refactor(project): update Protobuf package management and add conditional ProjectReference
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 6m22s
- 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.
2026-09-20 23:35:11 +03:30
masoodafar-web 27a3ea76c5 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.
2026-09-20 23:33:18 +03:30
masoodafar-web 690aaa714b Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 4m15s
2026-09-04 07:26:01 +03:30
masoodafar-web 58037f0b49 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 5m9s
2026-08-24 00:10:52 +03:30
masoodafar-web 3d84e726db Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 6m27s
2026-08-09 02:33:27 +03:30
masoodafar-web 9203dc7924 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 6m24s
2026-08-07 14:38:22 +03:30
masoodafar-web 4989cd00e0 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Failing after 16m3s
2026-07-26 00:52:30 +03:30
masoodafar-web bed35935ad Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Failing after 17m17s
2026-07-15 22:02:31 +03:30
masoodafar-web ceaaac3e23 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Failing after 18m42s
2026-07-03 06:04:56 +03:30
masoodafar-web db35814ce3 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-07-03 05:43:14 +03:30
masoodafar-web 7a5a2110c6 feat: add SEO configuration for production environment
Build and Deploy to Production / build-and-deploy (push) Failing after 19m58s
- Introduced SEO settings in appsettings.Production.json, including SiteUrl, SiteName, and DefaultDescription.
- These additions enhance the application's search engine optimization capabilities, improving visibility and user engagement.
2026-07-01 21:48:49 +03:30
masoodafar-web 8dbc64cd86 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-07-01 21:45:43 +03:30
masoodafar-web deadd197e6 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-07-01 21:31:49 +03:30
masoodafar-web 671c8407e5 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-06-30 02:50:03 +03:30
masoodafar-web 1956dcc5f4 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-06-30 02:28:13 +03:30
masoodafar-web d59d829d5f Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Failing after 17m21s
2026-06-26 19:30:51 +03:30
masoodafar-web 3c216feb32 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Failing after 15m3s
2026-06-19 02:38:15 +03:30
masoodafar-web 032b8eb448 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 8m14s
2026-06-08 01:55:28 +03:30
masoodafar-web 088ea8dc7f Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 6m36s
2026-05-29 19:59:19 +03:30
masoodafar-web cd92a2f7b0 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 4m24s
2026-05-14 20:12:20 +03:30
masoodafar-web 0c9eb5f9ef Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 4m25s
2026-05-14 02:07:56 +03:30
masoodafar-web 94fbf49fb9 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 4m51s
2026-05-14 01:56:18 +03:30
masoodafar-web 4330a5eaa5 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 4m16s
2026-05-14 01:12:35 +03:30
masoodafar-web 1e5e6bcf3d Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 5m50s
2026-05-04 00:04:13 +03:30
masoodafar-web d751c06a67 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 4m5s
2026-05-01 00:16:24 +03:30
masoodafar-web 1c5aa0ce15 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 14m28s
- Proto version: 0.0.192
- Remove local nupkg source from NuGet.config (breaks Docker builds)
2026-03-15 03:26:17 +03:30
masoodafar-web caaf28b08e fix: update CMS protobuf package version to 0.0.191 and comment out local package reference
Build and Deploy to Production / build-and-deploy (push) Successful in 6m22s
2026-02-28 05:07:54 +03:30
masoodafar-web 1914f703db Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Failing after 2m40s
2026-02-28 04:47:34 +03:30
masoodafar-web a606cd93cd fix: rename wallet labels — اصلی، اعتباری، پاداش تیمی
Build and Deploy to Production / build-and-deploy (push) Successful in 6m19s
- عادی → اصلی (کیف پول اصلی)
- شبکه → پاداش تیمی
- پورسانت → پاداش تیمی
- موجودی کیف پول → موجودی کیف پول اصلی

Files: Wallet.razor, WalletService.cs, MagicWallet.razor,
       Profile/Index.razor, PaymentCallback.razor
2026-02-23 23:26:52 +03:30
masoodafar-web 8b78235ef5 chore: prevent appsettings.Production.json from merging — keep ours strategy
Build and Deploy to Production / build-and-deploy (push) Successful in 6m27s
2026-02-23 00:03:00 +03:30
masoodafar-web f02d082d7b fix: correct GwUrl in Production config to cms.kbs2.ir
Build and Deploy to Production / build-and-deploy (push) Successful in 6m23s
2026-02-22 22:29:17 +03:30
masoodafar-web a11a3765b8 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-02-22 22:22:43 +03:30
admin 3cf5ad429d Update src/FrontOffice.Main/Shared/Footer.razor
Build and Deploy to Production / build-and-deploy (push) Successful in 6m39s
2026-02-22 10:25:35 +00:00
masoodafar-web 710ddbe261 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 6m2s
2026-02-21 20:38:23 +03:30
masoodafar-web e2ca65ed98 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 6m42s
2026-02-18 01:19:34 +03:30
masoodafar-web ae9b448a64 merge: kub-stage → production (1:1 square images + site pages + landing animation fix)
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-02-18 01:01:44 +03:30
Masoud 1ea928118d fix: update references from تخفیفی to اعتباری across multiple files
Build and Deploy to Production / build-and-deploy (push) Successful in 5m46s
2026-02-17 15:26:09 +03:30
Masoud 8f2d739d1f fix: update references from تخفیفی to اعتباری across multiple files
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
2026-02-17 15:24:13 +03:30
masoodafar-web 8e89d5e064 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 5m43s
2026-02-17 01:59:40 +03:30
masoodafar-web 8bd961ade1 Fix production workflow: use SERVER_PASSWORD, add docker login, use set image for deploy
Build and Deploy to Production / build-and-deploy (push) Successful in 5m39s
2026-02-17 01:24:06 +03:30
masoodafar-web 750d4c6b97 Remove staging workflow files from production branch to prevent cross-deployment 2026-02-17 01:15:59 +03:30
masoodafar-web 276a4c20f2 Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Successful in 1m12s
Features merged:
- Discount store UI improvements (100% auto-discount, VAT breakdown)
- PaymentStatus display on orders (Pending/Success/Failed/Refunded)
- Failed payment UX with re-order link
- Product discount badges show actual percent
- Various UI and bug fixes

Production workflow preserved.
2026-02-17 00:55:52 +03:30
masoodafar-web 98a68074bc chore: Update production workflow to use Nexus registry (no proxy needed)
Build and Deploy to Production / build-and-deploy (push) Failing after 0s
- Changed Dockerfile base images to use 194.5.195.53:32082 (Nexus)
- Updated workflow to use docker-sshpass image from Nexus
- Removed HTTP_PROXY/HTTPS_PROXY dependencies
- Changed deploy method to SSH instead of kubeconfig
- Registry: 194.5.195.53:30080 (Gitea internal)
- K8S Server: 45.149.79.127 (Production)
2026-01-29 22:04:31 +03:30
28 changed files with 400 additions and 97 deletions
-46
View File
@@ -1,46 +0,0 @@
name: Push nuget and docker image Actions Workflow
on:
push:
branches:
- stage-new
jobs:
Deploy:
runs-on: windows
steps:
- name: Checkout
uses: https://git.afrino.co/actions/checkout@v3
- name: Setup dotnet
uses: https://git.afrino.co/actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
- name: Remove Package Source
run: dotnet nuget remove source FourSat
continue-on-error: true
- name: Add Package Source
run: dotnet nuget add source --name FourSat --username systemuser --password sZSA7PTiv3pUSQZ https://git.afrino.co/api/packages/FourSat/nuget/index.json --store-password-in-clear-text
- name: Install dependencies
run: dotnet restore ".\src\FrontOffice.Main\FrontOffice.Main.csproj"
- name: Build
run: dotnet build ".\src\FrontOffice.Main\FrontOffice.Main.csproj" --configuration Release --no-restore
- name: Test
run: dotnet test ".\src\FrontOffice.Main\FrontOffice.Main.csproj" --no-restore --verbosity normal
- name: Recycle Apppool
run: |
& "C:\Windows\System32\inetsrv\appcmd.exe" recycle apppool /apppool.name:kbs1.ir
shell: powershell
- name: Stop Website
run: |
& "C:\Windows\System32\inetsrv\appcmd.exe" stop site /site.name:kbs1.ir
shell: powershell
- name: Publish
run: dotnet publish ".\src\FrontOffice.Main\FrontOffice.Main.csproj" -c Release -o publish
- name: Copy Publish To IIS Directory
run: Get-ChildItem -Path "publish\*" | Copy-Item -Destination "E:\kbs1.ir\kbs1.ir\" -Recurse -Force
- name: Start Website
run: |
& "C:\Windows\System32\inetsrv\appcmd.exe" start site /site.name:kbs1.ir
shell: powershell
+13 -9
View File
@@ -6,15 +6,15 @@ on:
- kub-stage - kub-stage
env: env:
REGISTRY: 194.5.195.53:30080 REGISTRY: 185.252.31.44:30080
IMAGE_NAME: admin/frontoffice IMAGE_NAME: admin/frontoffice
K8S_SERVER: 194.5.195.53 K8S_SERVER: 185.252.31.44
jobs: jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: 194.5.195.53:32082/docker-sshpass:latest image: 185.252.31.44:32082/docker-sshpass:latest
options: --privileged options: --privileged
steps: steps:
- name: Start Docker daemon - name: Start Docker daemon
@@ -22,7 +22,7 @@ jobs:
mkdir -p /etc/docker mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'DAEMON' 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 DAEMON
echo "🚀 Starting Docker daemon..." echo "🚀 Starting Docker daemon..."
@@ -52,7 +52,7 @@ jobs:
- name: Login to Docker registries - name: Login to Docker registries
run: | 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 echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin
- name: Build Docker Image - name: Build Docker Image
@@ -73,10 +73,14 @@ 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 && # Drop cached :latest so IfNotPresent/Always both pick the new digest
kubectl rollout restart deployment/frontoffice && # (crictl is broken on this host — use containerd ctr)
kubectl rollout status deployment/frontoffice --timeout=180s && ctr -n k8s.io images ls -q | grep -E 'frontoffice(:latest|@)' | while read -r ref; do
ctr -n k8s.io images rm \"\$ref\" 2>/dev/null || true
done
kubectl -n kbs-stage rollout restart deployment/frontoffice &&
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!"
+9 -8
View File
@@ -6,15 +6,15 @@ on:
- production - production
env: env:
REGISTRY: 194.5.195.53:30080 REGISTRY: 185.252.31.44:30080
IMAGE_NAME: admin/frontoffice IMAGE_NAME: admin/frontoffice
K8S_SERVER: 194.5.195.53 K8S_SERVER: 45.149.79.127
jobs: jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: 194.5.195.53:32082/docker-sshpass:latest image: 185.252.31.44:32082/docker-sshpass:latest
options: --privileged options: --privileged
steps: steps:
- name: Start Docker daemon - name: Start Docker daemon
@@ -22,7 +22,7 @@ jobs:
mkdir -p /etc/docker mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'DAEMON' 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 DAEMON
echo "🚀 Starting Docker daemon..." echo "🚀 Starting Docker daemon..."
@@ -40,7 +40,7 @@ jobs:
done done
if ! docker info >/dev/null 2>&1; then if ! docker info >/dev/null 2>&1; then
echo "❌ Docker daemon failed to start after 3 minutes" echo "❌ Docker daemon failed to start"
exit 1 exit 1
fi fi
@@ -50,15 +50,16 @@ jobs:
- name: Login to Docker registries - name: Login to Docker registries
run: | 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 echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin
- name: Build Docker Image - name: Build Docker Image
run: | run: |
cd src cd src
DOCKER_BUILDKIT=0 docker build --network host -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \ DOCKER_BUILDKIT=0 docker build --network host -f FrontOffice.Main/Dockerfile \
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod \ -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod \
-f FrontOffice.Main/Dockerfile . .
- name: Push to Registry - name: Push to Registry
run: | run: |
+1 -1
View File
@@ -20,7 +20,7 @@ spec:
spec: spec:
containers: containers:
- name: frontoffice - name: frontoffice
image: 194.5.195.53:30080/admin/frontoffice:prod image: 185.252.31.44:30080/admin/frontoffice:prod
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- containerPort: 80 - containerPort: 80
+32 -3
View File
@@ -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
@@ -20,7 +20,8 @@ spec:
spec: spec:
containers: containers:
- name: frontoffice - name: frontoffice
image: 194.5.195.53:30080/admin/frontoffice:latest image: 185.252.31.44:30080/admin/frontoffice:latest
# Staging uses :latest — Always avoids stale node cache after registry retag
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- containerPort: 80 - containerPort: 80
@@ -43,7 +44,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 +55,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
+2 -2
View File
@@ -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 WORKDIR /src
# Copy NuGet config and project file # 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 RUN dotnet publish "FrontOffice.Main.csproj" -c Release -o /app/publish
# Runtime stage - aspnet for Blazor Server # 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 WORKDIR /app
COPY --from=build /app/publish . COPY --from=build /app/publish .
+12 -4
View File
@@ -10,8 +10,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DateTimeConverterCL" Version="1.0.0" /> <PackageReference Include="DateTimeConverterCL" Version="1.0.0" />
<!-- Local protobuf until 0.0.212 is published to Nexus -->
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.212" />
<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,8 +22,17 @@
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <!-- ============================================================ -->
<!-- <ProjectReference Include="..\..\..\CMS\src\CMSMicroservice.Protobuf\CMSMicroservice.Protobuf.csproj" /> --> <!-- 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> </ItemGroup>
<!-- Local Proto Project Reference for development --> <!-- Local Proto Project Reference for development -->
+1 -1
View File
@@ -3,7 +3,7 @@
<packageSources> <packageSources>
<clear /> <clear />
<!-- Nexus (hosts FourSat packages + proxies nuget.org) --> <!-- Nexus (hosts FourSat packages + proxies nuget.org) -->
<add key="Nexus" value="http://194.5.195.53:32081/repository/nuget-all/index.json" allowInsecureConnections="true" /> <add key="Nexus" value="http://185.252.31.44:32081/repository/nuget-all/index.json" allowInsecureConnections="true" />
</packageSources> </packageSources>
<packageSourceCredentials> <packageSourceCredentials>
<Nexus> <Nexus>
+45 -1
View File
@@ -94,8 +94,47 @@
} }
@* ═══════════════════════════════════════════════ @* ═══════════════════════════════════════════════
2. HOW IT WORKS — 3 numbered steps 1c. TWENTYCARD CREDIT — promo box
═══════════════════════════════════════════════ *@ ═══════════════════════════════════════════════ *@
<section class="py-4" style="background:var(--mud-palette-surface);">
<MudContainer MaxWidth="MaxWidth.Medium">
<MudPaper Elevation="0" Class="landing-twentycard-box rounded-xl pa-4 pa-md-5">
<MudStack Row="true" Spacing="3" AlignItems="AlignItems.Start" Class="flex-wrap">
<MudAvatar Color="Color.Info" Variant="Variant.Filled" Size="Size.Large" Class="rounded-lg" Style="min-width:56px;">
<MudIcon Icon="@Icons.Material.Filled.AccountBalance" />
</MudAvatar>
<MudStack Spacing="2" Style="flex:1; min-width:220px;">
<MudText Typo="Typo.h6">تأمین اعتبار ۲۰کارت</MudText>
<MudText Typo="Typo.body2" Class="mud-text-secondary">
با تأمین اعتبار از طریق ۲۰کارت می‌توانید بدون پرداخت نقدی کامل، هزینه خرید پکیج و محصولات در کارا بازار را پوشش دهید.
فرایند درخواست و تأیید اعتبار در پنل ۲۰کارت انجام می‌شود و پس از آن پرداخت از همان مسیر در دسترس است.
این روش برای کسانی مناسب است که می‌خواهند سریع‌تر وارد مسیر عضویت و خرید شوند.
</MudText>
<MudText Typo="Typo.body2">
بعد از دریافت وام، می‌توانید در کارا بازار از باشگاه مشتریان استفاده کنید و با فروش و دعوت، توسعه سرمایه داشته باشید.
</MudText>
<div class="mt-1">
<MudButton Variant="Variant.Filled"
Color="Color.Info"
Class="rounded-pill"
StartIcon="@Icons.Material.Filled.OpenInNew"
Disabled="@string.IsNullOrWhiteSpace(_twentyCardPortalUrl)"
OnClick="OpenTwentyCardPortal">
ورود به سایت ۲۰کارت
</MudButton>
</div>
</MudStack>
</MudStack>
</MudPaper>
</MudContainer>
</section>
@* ═══════════════════════════════════════════════
2. HOW IT WORKS — 3 numbered steps
(appsettings Landing:ShowStepsSection; default false)
═══════════════════════════════════════════════ *@
@if (_showStepsSection)
{
<section class="section-landing"> <section class="section-landing">
<MudContainer MaxWidth="MaxWidth.Large"> <MudContainer MaxWidth="MaxWidth.Large">
<div class="text-center mb-8 fade-in-up"> <div class="text-center mb-8 fade-in-up">
@@ -121,10 +160,14 @@
</MudGrid> </MudGrid>
</MudContainer> </MudContainer>
</section> </section>
}
@* ═══════════════════════════════════════════════ @* ═══════════════════════════════════════════════
3. FEATURES — 6 cards with icons 3. FEATURES — 6 cards with icons
(appsettings Landing:ShowFeaturesSection; default false)
═══════════════════════════════════════════════ *@ ═══════════════════════════════════════════════ *@
@if (_showFeaturesSection)
{
<section class="section-landing" style="background:var(--mud-palette-background-gray);"> <section class="section-landing" style="background:var(--mud-palette-background-gray);">
<MudContainer MaxWidth="MaxWidth.Large"> <MudContainer MaxWidth="MaxWidth.Large">
<div class="text-center mb-8 fade-in-up"> <div class="text-center mb-8 fade-in-up">
@@ -152,6 +195,7 @@
</MudGrid> </MudGrid>
</MudContainer> </MudContainer>
</section> </section>
}
@* ═══════════════════════════════════════════════ @* ═══════════════════════════════════════════════
4. STATS — Counter cards 4. STATS — Counter cards
+18 -1
View File
@@ -1,5 +1,6 @@
using FrontOffice.Main.Utilities; using FrontOffice.Main.Utilities;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using MudBlazor; using MudBlazor;
@@ -16,8 +17,12 @@ public partial class Index : IDisposable
[Inject] private DiscountCartService DiscountCart { get; set; } = default!; [Inject] private DiscountCartService DiscountCart { get; set; } = default!;
[Inject] private GuestActionGate GuestGate { get; set; } = default!; [Inject] private GuestActionGate GuestGate { get; set; } = default!;
[Inject] private VATService VAT { get; set; } = default!; [Inject] private VATService VAT { get; set; } = default!;
[Inject] private IConfiguration Configuration { get; set; } = default!;
private bool _isAuthenticated; private bool _isAuthenticated;
private string _twentyCardPortalUrl = string.Empty;
private bool _showStepsSection;
private bool _showFeaturesSection;
// ── CMS page data ── // ── CMS page data ──
private PageSettingsDto? _pageData; private PageSettingsDto? _pageData;
@@ -49,6 +54,10 @@ public partial class Index : IDisposable
{ {
MainService.OnChangeHandler += OnStateChanged; MainService.OnChangeHandler += OnStateChanged;
_isAuthenticated = await AuthService.IsAuthenticatedAsync(); _isAuthenticated = await AuthService.IsAuthenticatedAsync();
_twentyCardPortalUrl = Configuration["TwentyCard:CreditPortalUrl"] ?? string.Empty;
// appsettings Landing:* — default false (hidden). Set true to restore sections.
_showStepsSection = Configuration.GetValue("Landing:ShowStepsSection", false);
_showFeaturesSection = Configuration.GetValue("Landing:ShowFeaturesSection", false);
// Load landing page settings from CMS // Load landing page settings from CMS
try try
@@ -162,7 +171,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),
}; };
@@ -298,6 +307,12 @@ public partial class Index : IDisposable
Navigation.NavigateTo(RouteConstants.Registration.Wizard); Navigation.NavigateTo(RouteConstants.Registration.Wizard);
} }
private async Task OpenTwentyCardPortal()
{
if (string.IsNullOrWhiteSpace(_twentyCardPortalUrl)) return;
await JS.InvokeVoidAsync("open", _twentyCardPortalUrl, "_blank");
}
private void NavigateToPost(string slug) private void NavigateToPost(string slug)
{ {
Navigation.NavigateTo($"/blog/{slug}"); Navigation.NavigateTo($"/blog/{slug}");
@@ -334,8 +349,10 @@ public partial class Index : IDisposable
public string? HeroButtonPrimaryText { get; set; } public string? HeroButtonPrimaryText { get; set; }
public string? HeroButtonSecondaryText { get; set; } public string? HeroButtonSecondaryText { get; set; }
public List<TrustBadgeItem>? TrustBadges { get; set; } public List<TrustBadgeItem>? TrustBadges { get; set; }
public bool? StepsEnabled { get; set; }
public string? StepsTitle { get; set; } public string? StepsTitle { get; set; }
public List<StepItem>? Steps { get; set; } public List<StepItem>? Steps { get; set; }
public bool? FeaturesEnabled { get; set; }
public string? FeaturesTitle { get; set; } public string? FeaturesTitle { get; set; }
public List<FeatureItem>? Features { get; set; } public List<FeatureItem>? Features { get; set; }
public string? StatsTitle { get; set; } public string? StatsTitle { get; set; }
@@ -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>
@@ -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();
}
}
@@ -31,7 +31,7 @@
<MudDivider Class="my-4" /> <MudDivider Class="my-4" />
<MudText Typo="Typo.body2" Color="Color.Secondary"> <MudText Typo="Typo.body2" Color="Color.Secondary">
موجودی کیف پول: @FormatPrice(_walletBalance) موجودی کیف پول اصلی: @FormatPrice(_walletBalance)
</MudText> </MudText>
<MudButton Color="Color.Primary" Variant="Variant.Filled" Class="mt-6" <MudButton Color="Color.Primary" Variant="Variant.Filled" Class="mt-6"
@@ -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>کارابازار و کاربر که در این قرارداد جداگانه &laquo;طرف&raquo; و مجموعاً &laquo;طرفین&raquo; نامیده می‌شوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا می‌نمایند.</p></div><div><p class='section-title'>ماده ۱ - موضوع قرارداد</p>" + "<p>کارابازار و کاربر که در این قرارداد جداگانه &laquo;طرف&raquo; و مجموعاً &laquo;طرفین&raquo; نامیده می‌شوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا می‌نمایند.</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>" +
+6 -2
View File
@@ -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;
+3
View File
@@ -45,6 +45,9 @@
Href="https://wa.me/989123456789" Href="https://wa.me/989123456789"
Target="_blank" /> Target="_blank" />
</MudStack> </MudStack>
<MudStack Row="true" Spacing="2" Class="enamad">
<a referrerpolicy='origin' target='_blank' href='https://trustseal.enamad.ir/?id=688255&Code=uoMRGkyUYHAtMxkpBLB0KyPL5Ac66ACX'><img referrerpolicy='origin' src='https://trustseal.enamad.ir/logo.aspx?id=688255&Code=uoMRGkyUYHAtMxkpBLB0KyPL5Ac66ACX' alt='' style='cursor:pointer' code='uoMRGkyUYHAtMxkpBLB0KyPL5Ac66ACX'></a>
</MudStack>
</MudStack> </MudStack>
</MudItem> </MudItem>
@@ -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; }
@@ -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) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و سازمان فروش.";
} }
@@ -1,9 +1,6 @@
{ {
"GwUrl": "https://cms.kbs1.ir", "GwUrl": "https://cms.kbs2.ir",
"DownloadUrl": "", "DownloadUrl": "",
"TwentyCard": {
"CreditPortalUrl": "https://20card.ir"
},
"EncryptionSettings": { "EncryptionSettings": {
"Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
"IV": "1wyF3Tt142MOkCpIyCxh/g==" "IV": "1wyF3Tt142MOkCpIyCxh/g=="
@@ -17,5 +14,10 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"Seo": {
"SiteUrl": "https://kbs2.ir",
"SiteName": "کارابازار سلامت",
"DefaultDescription": "باشگاه مشتریان کارابازار سلامت (KBS) — فروشگاه محصولات سلامت، پاداش شفاف، کیف پول و شبکه فروش."
},
"AllowedHosts": "*" "AllowedHosts": "*"
} }
@@ -2,12 +2,16 @@
"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": { "TwentyCard": {
"CreditPortalUrl": "https://20card.ir" "CreditPortalUrl": "https://userpanel.20card.ir/"
},
"Landing": {
"ShowStepsSection": false,
"ShowFeaturesSection": false
}, },
"EncryptionSettings": { "EncryptionSettings": {
"Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
+6 -2
View File
@@ -2,12 +2,16 @@
"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": { "TwentyCard": {
"CreditPortalUrl": "https://20card.ir" "CreditPortalUrl": "https://userpanel.20card.ir/"
},
"Landing": {
"ShowStepsSection": false,
"ShowFeaturesSection": false
}, },
"EncryptionSettings": { "EncryptionSettings": {
"Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=", "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
@@ -1617,6 +1617,12 @@ html, body {
overflow: hidden; overflow: hidden;
} }
/* ── Landing TwentyCard credit promo ── */
.landing-twentycard-box {
background: var(--ds-info-soft);
border: 1px solid rgba(59, 130, 246, 0.22);
}
/* ── Register Wizard Unified ── */ /* ── Register Wizard Unified ── */
.wizard-section { .wizard-section {
min-height: 80vh; min-height: 80vh;