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 @@
-
+