diff --git a/angular.json b/angular.json
index 7790e20..028588d 100644
--- a/angular.json
+++ b/angular.json
@@ -116,6 +116,10 @@
}
],
"fileReplacements": [
+ {
+ "replace": "src/assets/images/brandingAssets.ts",
+ "with": "src/tenants/tis/brandingAssets.ts"
+ },
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.tis.ts"
@@ -132,6 +136,50 @@
"outputHashing": "all",
"outputPath": "dist/tis",
"serviceWorker": "ngsw-config.json"
+ },
+ "tis-development": {
+ "assets": [
+ {
+ "glob": "**/*",
+ "input": "public-tis"
+ }
+ ],
+ "budgets": [
+ {
+ "maximumError": "2.5MB",
+ "maximumWarning": "1.5MB",
+ "type": "initial"
+ },
+ {
+ "maximumError": "6kB",
+ "maximumWarning": "3kB",
+ "type": "anyComponentStyle"
+ }
+ ],
+ "extractLicenses": false,
+ "fileReplacements": [
+ {
+ "replace": "src/assets/images/brandingAssets.ts",
+ "with": "src/tenants/tis/brandingAssets.ts"
+ },
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.tis.ts"
+ },
+ {
+ "replace": "src/app.routes.ts",
+ "with": "src/tenants/tis/app.routes.ts"
+ },
+ {
+ "replace": "src/app/branding/branding.config.ts",
+ "with": "src/tenants/tis/branding.config.ts"
+ }
+ ],
+ "optimization": false,
+ "outputHashing": "all",
+ "outputPath": "dist/tis",
+ "serviceWorker": "ngsw-config.json",
+ "sourceMap": true
}
},
"defaultConfiguration": "production",
@@ -179,7 +227,7 @@
"buildTarget": "pos.client:build:staging"
},
"tis": {
- "buildTarget": "pos.client:build:tis"
+ "buildTarget": "pos.client:build:tis-development"
}
},
"defaultConfiguration": "development",
diff --git a/ngsw-config.json b/ngsw-config.json
index 074fee2..9e4c54b 100644
--- a/ngsw-config.json
+++ b/ngsw-config.json
@@ -2,7 +2,7 @@
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
"appData": {
"appVersion": "0.0.0",
- "buildDate": "2026-05-10T09:04:30.388Z"
+ "buildDate": "2026-05-11T09:56:45.724Z"
},
"assetGroups": [
{
diff --git a/package.json b/package.json
index c9501fa..39adfe5 100644
--- a/package.json
+++ b/package.json
@@ -71,10 +71,10 @@
"build:tis": "ng build --configuration tis",
"ng": "ng",
"prebuild": "node scripts/update-ngsw-appdata.js",
- "prebuild:tis": "node scripts/tis/prepare-tis-logo.js && node scripts/tis/update-tis-ngsw-appdata.js",
+ "prebuild:tis": "node scripts/tis/update-tis-ngsw-appdata.js",
"prestart": "node aspnetcore-https",
"start": "run-script-os",
- "start:tis": "ng serve --configuration tis",
+ "start:tis": " ng serve --configuration tis",
"test": "ng test",
"watch": "ng build --watch --configuration development"
},
diff --git a/src/app.routes.ts b/src/app.routes.ts
index 38c1f0b..c32f4f2 100644
--- a/src/app.routes.ts
+++ b/src/app.routes.ts
@@ -1 +1,26 @@
-export { appRoutes } from './tenants/default/app.routes';
+import { CONSUMER_ROUTES } from '@/domains/consumer/routes';
+import { PARTNER_ROUTES } from '@/domains/partner/routes';
+import { POS_ROUTES } from '@/domains/pos/routes';
+import { PROVIDER_ROUTES } from '@/domains/provider/routes';
+import { SUPER_ADMIN_ROUTES } from '@/domains/superAdmin/routes';
+import { Notfound } from '@/pages/notfound/notfound.component';
+import { Routes } from '@angular/router';
+
+export const appRoutes: Routes = [
+ {
+ path: '',
+ loadComponent: () => import('@/layout/default/app.layout.component').then((m) => m.AppLayout),
+ children: [SUPER_ADMIN_ROUTES, CONSUMER_ROUTES, PROVIDER_ROUTES, PARTNER_ROUTES],
+ },
+ {
+ ...POS_ROUTES,
+ path: 'pos',
+ },
+
+ {
+ path: 'auth',
+ loadComponent: () => import('@/modules/auth/pages/auth.component').then((m) => m.AuthComponent),
+ },
+ { path: 'notfound', component: Notfound },
+ { path: '**', redirectTo: '/notfound' },
+];
diff --git a/src/app/domains/pos/components/splash.component.html b/src/app/domains/pos/components/splash.component.html
new file mode 100644
index 0000000..eee44a3
--- /dev/null
+++ b/src/app/domains/pos/components/splash.component.html
@@ -0,0 +1,4 @@
+
+
![]()
+
در حال بارگذاری ...
+
diff --git a/src/app/domains/pos/components/splash.component.ts b/src/app/domains/pos/components/splash.component.ts
new file mode 100644
index 0000000..4905a2b
--- /dev/null
+++ b/src/app/domains/pos/components/splash.component.ts
@@ -0,0 +1,33 @@
+import { Component, EventEmitter, inject, Output } from '@angular/core';
+import { finalize, forkJoin } from 'rxjs';
+import images from 'src/assets/images';
+import { PosInfoStore, PosProfileStore } from '../store';
+import { DeviceInfoStore } from '../store/device.store';
+
+@Component({
+ selector: 'pos-splash',
+ templateUrl: 'splash.component.html',
+})
+export class PosSplashComponent {
+ @Output() onComplete = new EventEmitter();
+
+ private readonly posProfileStore = inject(PosProfileStore);
+ private readonly posInfoStore = inject(PosInfoStore);
+ private readonly deviceInfoStore = inject(DeviceInfoStore);
+
+ logo = images.logo;
+
+ async ngOnInit() {
+ const data = await this.deviceInfoStore.getData();
+ const profileObs = await this.posProfileStore.getData();
+ const infoObs = await this.posInfoStore.getData();
+
+ forkJoin([profileObs, infoObs])
+ .pipe(
+ finalize(() => {
+ this.onComplete.emit();
+ }),
+ )
+ .subscribe(([profileResult, infoResult]) => {});
+ }
+}
diff --git a/src/app/domains/pos/layouts/layout.component.html b/src/app/domains/pos/layouts/layout.component.html
index 9dc8be4..909538a 100644
--- a/src/app/domains/pos/layouts/layout.component.html
+++ b/src/app/domains/pos/layouts/layout.component.html
@@ -1,101 +1,37 @@
-
-
-
-
-
- @if (posInfo()) {
-
-
-
![Logo]()
-
- {{ posInfo()?.partner?.name }}
-
- }
-
-
-
-
-
-
-
- @if (pullDistance() >= 0) {
+@if (showSplash()) {
+
+} @else {
+ @defer (when !showSplash()) {
- }
- @if (loading()) {
-
- } @else {
-
-
-
-
-
-
-
- -->
- @if (error()) {
- @switch (error()?.status) {
- @case (412) {
-
- }
- @default {
-
-
-
-
-
عدم دسترسی
-
متاسفانه امکان دسترسی برای کاربر شما فراهم نیست
-
-
-
-
+ }
+ @if (isAuth()) {
+
+ } @else {
+ @defer (when !isAuth()) {
+
}
}
- } @else {
-
-
- }
-
+
}
-
+}
diff --git a/src/app/domains/pos/layouts/layout.component.ts b/src/app/domains/pos/layouts/layout.component.ts
index 0067bcc..5b48242 100644
--- a/src/app/domains/pos/layouts/layout.component.ts
+++ b/src/app/domains/pos/layouts/layout.component.ts
@@ -1,143 +1,25 @@
-import { AuthService } from '@/core';
-import { LayoutService } from '@/layout/service/layout.service';
-import { PageLoadingComponent } from '@/shared/components/page-loading.component';
import { CommonModule } from '@angular/common';
-import {
- AfterViewInit,
- Component,
- TemplateRef,
- ViewChild,
- computed,
- inject,
- signal,
-} from '@angular/core';
-import { RouterLinkWithHref, RouterOutlet } from '@angular/router';
-import { MenuItem } from 'primeng/api';
-import { Button, ButtonDirective } from 'primeng/button';
-import { Card } from 'primeng/card';
-import { Menu } from 'primeng/menu';
-import { finalize } from 'rxjs';
-import images from 'src/assets/images';
-import { PosInfoStore, PosProfileStore } from '../store';
-import { DeviceInfoStore } from '../store/device.store';
-import { PosChooseCardsComponent } from './choose-pos.component';
-import { PosMainMenuSidebarComponent } from './mainMenuSidebar/main-menu-sidebar.component';
+import { Component, computed, signal } from '@angular/core';
+import { RouterOutlet } from '@angular/router';
+import { PosSplashComponent } from '../components/splash.component';
+import { PosPagesLayoutComponent } from './pagesLayout/layout.component';
@Component({
selector: 'pos-layout',
- templateUrl: './layout.component.html',
- imports: [
- PageLoadingComponent,
- RouterOutlet,
- ButtonDirective,
- Card,
- PosChooseCardsComponent,
- Button,
- PosMainMenuSidebarComponent,
- Menu,
- CommonModule,
- RouterLinkWithHref,
- ],
+ templateUrl: 'layout.component.html',
+ imports: [PosSplashComponent, PosPagesLayoutComponent, RouterOutlet, CommonModule],
})
-export class PosLayoutComponent implements AfterViewInit {
- constructor() {}
+export class PosLayoutComponent {
+ showSplash = signal(true);
+ isAuth = computed(() => window.location.pathname === '/auth');
- // private readonly nativeBridgeService = inject(NativeBridgeService);
- // private readonly toastService = inject(ToastService);
-
- @ViewChild('topbarStart', { static: true }) topbarStart!: TemplateRef;
- @ViewChild('topbarCenter', { static: true }) topbarCenter!: TemplateRef;
- @ViewChild('topbarEnd', { static: true }) topbarEnd!: TemplateRef;
-
- private readonly posProfileStore = inject(PosProfileStore);
- private readonly posInfoStore = inject(PosInfoStore);
- private readonly deviceInfoStore = inject(DeviceInfoStore);
- private readonly authService = inject(AuthService);
- private readonly layoutService = inject(LayoutService);
-
- mainMenuVisible = signal(false);
-
- readonly posProfileLoading = computed(() => this.posProfileStore.loading());
- readonly posProfile = computed(() => this.posProfileStore.entity());
- readonly posProfileError = computed(() => this.posProfileStore.error());
-
- readonly posInfoLoading = computed(() => this.posInfoStore.loading());
- readonly posInfo = computed(() => this.posInfoStore.entity());
- readonly posInfoError = computed(() => this.posInfoStore.error());
-
- readonly loading = computed(() => this.posProfileLoading());
- readonly error = computed(() => this.posProfileError());
-
- readonly deviceInfo = computed(() => this.deviceInfoStore.entity());
-
- logout = () => {
- this.authService.logout();
- };
-
- profileMenuItems: MenuItem[] = [
- {
- label: 'راهنمای سامانه',
- icon: 'pi pi-question-circle',
- disabled: true,
- },
- {
- label: 'خروج',
- icon: 'pi pi-sign-out',
- command: this.logout,
- },
- ];
-
- placeholderLogo = images.placeholders.logo;
-
- now = new Date();
private touchStartY = 0;
private pulling = false;
pullDistance = signal(0);
readonly pullThreshold = 80;
- homeRouteLink = '/pos';
-
- async getData() {
- await this.layoutService.changeFullPageLoading(true);
- await this.deviceInfoStore.getData();
- await this.posProfileStore.getData().subscribe({
- next: () => {
- this.posInfoStore
- .getData()
- .pipe(
- finalize(() => {
- this.layoutService.changeFullPageLoading(false);
- }),
- )
- .subscribe();
- },
- });
- }
-
- toggleMenu() {
- this.mainMenuVisible.update((v) => !v);
- }
-
- onChoosePos() {
- this.getData();
- }
-
- ngOnInit() {
- this.layoutService.changeIsFullPage(true);
- this.getData();
- }
-
- ngAfterViewInit() {
- this.layoutService.setTopbarStartSlot(this.topbarStart);
- this.layoutService.setTopbarCenterSlot(this.topbarCenter);
- this.layoutService.setTopbarEndSlot(this.topbarEnd);
- }
-
- ngOnDestroy() {
- this.layoutService.changeIsFullPage(false);
- this.layoutService.setTopbarStartSlot(null);
- this.layoutService.setTopbarCenterSlot(null);
- this.layoutService.setTopbarEndSlot(null);
+ onSplashCompleted() {
+ this.showSplash.set(false);
}
onTouchStart(event: TouchEvent) {
@@ -165,8 +47,7 @@ export class PosLayoutComponent implements AfterViewInit {
this.pulling = false;
this.pullDistance.set(0);
if (shouldRefresh) {
- this.layoutService.changeIsFullPage(true);
- this.getData();
+ this.showSplash.set(true);
}
}
}
diff --git a/src/app/domains/pos/layouts/choose-pos.component.html b/src/app/domains/pos/layouts/pagesLayout/choose-pos.component.html
similarity index 100%
rename from src/app/domains/pos/layouts/choose-pos.component.html
rename to src/app/domains/pos/layouts/pagesLayout/choose-pos.component.html
diff --git a/src/app/domains/pos/layouts/choose-pos.component.ts b/src/app/domains/pos/layouts/pagesLayout/choose-pos.component.ts
similarity index 92%
rename from src/app/domains/pos/layouts/choose-pos.component.ts
rename to src/app/domains/pos/layouts/pagesLayout/choose-pos.component.ts
index 2b525b3..27e958a 100644
--- a/src/app/domains/pos/layouts/choose-pos.component.ts
+++ b/src/app/domains/pos/layouts/pagesLayout/choose-pos.component.ts
@@ -8,8 +8,8 @@ import { Card } from 'primeng/card';
import { Message } from 'primeng/message';
import { catchError, finalize } from 'rxjs';
import { COOKIE_KEYS } from 'src/assets/constants';
-import { IPosAccessibleResponse } from '../models/pos.io';
-import { PosService } from '../modules/landing/services/main.service';
+import { IPosAccessibleResponse } from '../../models/pos.io';
+import { PosService } from '../../modules/landing/services/main.service';
@Component({
selector: 'pos-choose-cards',
diff --git a/src/app/domains/pos/layouts/pagesLayout/layout.component.html b/src/app/domains/pos/layouts/pagesLayout/layout.component.html
new file mode 100644
index 0000000..758ab48
--- /dev/null
+++ b/src/app/domains/pos/layouts/pagesLayout/layout.component.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+ @if (posInfo()) {
+
+
+
![Logo]()
+
+ {{ posInfo()?.partner?.name }}
+
+ }
+
+
+
+
+
+
+@if (loading()) {
+
+} @else {
+
+
+ @if (error()) {
+ @switch (error()?.status) {
+ @case (412) {
+
+ }
+ @default {
+
+
+
+
+
عدم دسترسی
+
متاسفانه امکان دسترسی برای کاربر شما فراهم نیست
+
+
+
+
+ }
+ }
+ } @else {
+
+
+ }
+
+}
diff --git a/src/app/domains/pos/layouts/pagesLayout/layout.component.ts b/src/app/domains/pos/layouts/pagesLayout/layout.component.ts
new file mode 100644
index 0000000..17e61bb
--- /dev/null
+++ b/src/app/domains/pos/layouts/pagesLayout/layout.component.ts
@@ -0,0 +1,131 @@
+import { AuthService } from '@/core';
+import { LayoutService } from '@/layout/service/layout.service';
+import { PageLoadingComponent } from '@/shared/components/page-loading.component';
+import { CommonModule } from '@angular/common';
+import {
+ AfterViewInit,
+ Component,
+ TemplateRef,
+ ViewChild,
+ computed,
+ inject,
+ signal,
+} from '@angular/core';
+import { RouterLinkWithHref, RouterOutlet } from '@angular/router';
+import { MenuItem } from 'primeng/api';
+import { Button, ButtonDirective } from 'primeng/button';
+import { Card } from 'primeng/card';
+import { Menu } from 'primeng/menu';
+import images from 'src/assets/images';
+import { PosInfoStore, PosProfileStore } from '../../store';
+import { DeviceInfoStore } from '../../store/device.store';
+import { PosMainMenuSidebarComponent } from '../mainMenuSidebar/main-menu-sidebar.component';
+import { PosChooseCardsComponent } from './choose-pos.component';
+
+@Component({
+ selector: 'pos-pages-layout',
+ templateUrl: './layout.component.html',
+ imports: [
+ PageLoadingComponent,
+ ButtonDirective,
+ Card,
+ PosChooseCardsComponent,
+ Button,
+ PosMainMenuSidebarComponent,
+ Menu,
+ CommonModule,
+ RouterLinkWithHref,
+ RouterOutlet,
+ ],
+})
+export class PosPagesLayoutComponent implements AfterViewInit {
+ constructor() {}
+
+ // private readonly nativeBridgeService = inject(NativeBridgeService);
+ // private readonly toastService = inject(ToastService);
+
+ @ViewChild('topbarStart', { static: true }) topbarStart!: TemplateRef;
+ @ViewChild('topbarCenter', { static: true }) topbarCenter!: TemplateRef;
+ @ViewChild('topbarEnd', { static: true }) topbarEnd!: TemplateRef;
+
+ private readonly posProfileStore = inject(PosProfileStore);
+ private readonly posInfoStore = inject(PosInfoStore);
+ private readonly deviceInfoStore = inject(DeviceInfoStore);
+ private readonly authService = inject(AuthService);
+ private readonly layoutService = inject(LayoutService);
+
+ mainMenuVisible = signal(false);
+
+ readonly posProfileLoading = computed(() => this.posProfileStore.loading());
+ readonly posProfile = computed(() => this.posProfileStore.entity());
+ readonly posProfileError = computed(() => this.posProfileStore.error());
+
+ readonly posInfoLoading = computed(() => this.posInfoStore.loading());
+ readonly posInfo = computed(() => this.posInfoStore.entity());
+ readonly posInfoError = computed(() => this.posInfoStore.error());
+
+ readonly loading = computed(() => this.posProfileLoading());
+ readonly error = computed(() => this.posProfileError());
+
+ readonly deviceInfo = computed(() => this.deviceInfoStore.entity());
+
+ logout = () => {
+ this.authService.logout();
+ };
+
+ profileMenuItems: MenuItem[] = [
+ {
+ label: 'راهنمای سامانه',
+ icon: 'pi pi-question-circle',
+ disabled: true,
+ },
+ {
+ label: 'خروج',
+ icon: 'pi pi-sign-out',
+ command: this.logout,
+ },
+ ];
+
+ placeholderLogo = images.placeholders.logo;
+
+ now = new Date();
+
+ homeRouteLink = '/pos';
+
+ async getData() {
+ // await this.layoutService.changeFullPageLoading(true);
+ // await this.posProfileStore.getData().subscribe({
+ // next: () => {
+ // this.posInfoStore
+ // .getData()
+ // .pipe(
+ // finalize(() => {
+ // this.layoutService.changeFullPageLoading(false);
+ // }),
+ // )
+ // .subscribe();
+ // },
+ // });
+ }
+
+ toggleMenu() {
+ this.mainMenuVisible.update((v) => !v);
+ }
+
+ onChoosePos() {
+ this.getData();
+ }
+
+ ngAfterViewInit() {
+ this.layoutService.setTopbarStartSlot(this.topbarStart);
+ this.layoutService.setTopbarCenterSlot(this.topbarCenter);
+ this.layoutService.setTopbarEndSlot(this.topbarEnd);
+ }
+
+ ngOnDestroy() {
+ this.layoutService.changeIsFullPage(false);
+ this.layoutService.setTopbarStartSlot(null);
+ this.layoutService.setTopbarCenterSlot(null);
+ this.layoutService.setTopbarEndSlot(null);
+ }
+}
diff --git a/src/app/domains/pos/models/device.io.ts b/src/app/domains/pos/models/device.io.ts
index ee03ce5..a2c43ac 100644
--- a/src/app/domains/pos/models/device.io.ts
+++ b/src/app/domains/pos/models/device.io.ts
@@ -1,5 +1,5 @@
export interface IDeviceProfileRawResponse {
- androidId: string;
+ deviceId: string;
deviceName: string;
}
diff --git a/src/app/domains/pos/modules/landing/components/goods.component.html b/src/app/domains/pos/modules/landing/components/goods.component.html
index 39d9086..7faa050 100644
--- a/src/app/domains/pos/modules/landing/components/goods.component.html
+++ b/src/app/domains/pos/modules/landing/components/goods.component.html
@@ -1,5 +1,5 @@