diff --git a/src/app/components/back-button/back-button.component.ts b/src/app/components/back-button/back-button.component.ts index 7803a7a..0b3be16 100644 --- a/src/app/components/back-button/back-button.component.ts +++ b/src/app/components/back-button/back-button.component.ts @@ -1,7 +1,7 @@ import { Component, ChangeDetectionStrategy, inject } from '@angular/core'; import { Location } from '@angular/common'; -import { environment } from '../../../environments/environment'; import { TranslateService } from '../../i18n/translate.service'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; @Component({ selector: 'app-back-button', @@ -62,9 +62,13 @@ import { TranslateService } from '../../i18n/translate.service'; changeDetection: ChangeDetectionStrategy.OnPush }) export class BackButtonComponent { - isnovo = environment.theme === 'novo'; + private readonly uiRuntime = inject(UiRuntimeFacade); i18n = inject(TranslateService); + get isnovo(): boolean { + return this.uiRuntime.isNovo(); + } + constructor(private location: Location) {} goBack(): void { diff --git a/src/app/components/footer/footer.component.ts b/src/app/components/footer/footer.component.ts index 76f421a..0778b8e 100644 --- a/src/app/components/footer/footer.component.ts +++ b/src/app/components/footer/footer.component.ts @@ -1,9 +1,9 @@ import { Component, ChangeDetectionStrategy } from '@angular/core'; import { RouterLink } from '@angular/router'; -import { environment } from '../../../environments/environment'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; import { LogoComponent } from '../logo/logo.component'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; @Component({ selector: 'app-footer', @@ -13,9 +13,23 @@ import { LogoComponent } from '../logo/logo.component'; changeDetection: ChangeDetectionStrategy.OnPush }) export class FooterComponent { + constructor(private readonly uiRuntime: UiRuntimeFacade) {} + currentYear = new Date().getFullYear(); - brandName = environment.brandName; - contactEmail = environment.contactEmail; - isnovo = environment.theme === 'novo'; - islavero = environment.theme === 'lavero'; + + get brandName(): string { + return this.uiRuntime.brandName(); + } + + get contactEmail(): string { + return this.uiRuntime.contactEmail(); + } + + get isnovo(): boolean { + return this.uiRuntime.isNovo(); + } + + get islavero(): boolean { + return this.uiRuntime.isLavero(); + } } diff --git a/src/app/components/header/header.component.ts b/src/app/components/header/header.component.ts index 2f4d528..6b6e6e7 100644 --- a/src/app/components/header/header.component.ts +++ b/src/app/components/header/header.component.ts @@ -2,12 +2,12 @@ import { Component, ChangeDetectionStrategy, Renderer2, inject, DOCUMENT } from import { Router, RouterLink, RouterLinkActive } from '@angular/router'; import { CartService } from '../../services/cart.service'; import { LanguageService } from '../../services/language.service'; -import { environment } from '../../../environments/environment'; import { LogoComponent } from '../logo/logo.component'; import { LanguageSelectorComponent } from '../language-selector/language-selector.component'; import { RegionSelectorComponent } from '../region-selector/region-selector.component'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; @Component({ selector: 'app-header', @@ -20,19 +20,29 @@ export class HeaderComponent { cartItemCount; cartTotal; menuOpen = false; - brandName = environment.brandFullName; - logo = environment.logo; - isnovo = environment.theme === 'novo'; private renderer = inject(Renderer2); private document = inject(DOCUMENT); private langService = inject(LanguageService); + private uiRuntime = inject(UiRuntimeFacade); constructor(private cartService: CartService, private router: Router) { this.cartItemCount = this.cartService.itemCount; this.cartTotal = this.cartService.totalPrice; } + get brandName(): string { + return this.uiRuntime.brandFullName(); + } + + get logo(): string { + return this.uiRuntime.logoUrl(); + } + + get isnovo(): boolean { + return this.uiRuntime.isNovo(); + } + get homeUrl(): string { return `/${this.langService.currentLanguage()}`; } diff --git a/src/app/components/items-carousel/items-carousel.component.ts b/src/app/components/items-carousel/items-carousel.component.ts index dda963c..4fd47a6 100644 --- a/src/app/components/items-carousel/items-carousel.component.ts +++ b/src/app/components/items-carousel/items-carousel.component.ts @@ -6,11 +6,11 @@ import { ButtonModule } from 'primeng/button'; import { TagModule } from 'primeng/tag'; import { ApiService, CartService } from '../../services'; import { Item } from '../../models'; -import { environment } from '../../../environments/environment'; import { getDiscountedPrice, getMainImage, getBadgeClass, getTranslatedField } from '../../utils/item.utils'; import { LanguageService } from '../../services/language.service'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; @Component({ selector: 'app-items-carousel', @@ -22,7 +22,7 @@ import { TranslatePipe } from '../../i18n/translate.pipe'; export class ItemsCarouselComponent implements OnInit { products = signal([]); loading = signal(true); - isnovo = environment.theme === 'novo'; + private readonly uiRuntime = inject(UiRuntimeFacade); responsiveOptions: { breakpoint: string; numVisible: number; numScroll: number }[] | undefined; @@ -102,6 +102,7 @@ export class ItemsCarouselComponent implements OnInit { readonly getBadgeClass = getBadgeClass; private langService = inject(LanguageService); + get isnovo(): boolean { return this.uiRuntime.isNovo(); } itemName(product: Item): string { return getTranslatedField(product, 'name', this.langService.currentLanguage()); } addToCart(event: Event, item: Item): void { diff --git a/src/app/components/logo/logo.component.ts b/src/app/components/logo/logo.component.ts index e2e6ee6..9b40034 100644 --- a/src/app/components/logo/logo.component.ts +++ b/src/app/components/logo/logo.component.ts @@ -1,5 +1,5 @@ import { Component, ChangeDetectionStrategy } from '@angular/core'; -import { environment } from '../../../environments/environment'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; @Component({ selector: 'app-logo', @@ -17,6 +17,13 @@ import { environment } from '../../../environments/environment'; changeDetection: ChangeDetectionStrategy.OnPush }) export class LogoComponent { - brandName = environment.brandName; - logoPath = (environment as any).logo ?? `/assets/images/${environment.theme}-logo.svg`; + constructor(private readonly uiRuntime: UiRuntimeFacade) {} + + get brandName(): string { + return this.uiRuntime.brandName(); + } + + get logoPath(): string { + return this.uiRuntime.logoUrl(); + } } diff --git a/src/app/facades/runtime/ui-runtime.facade.ts b/src/app/facades/runtime/ui-runtime.facade.ts new file mode 100644 index 0000000..a974fda --- /dev/null +++ b/src/app/facades/runtime/ui-runtime.facade.ts @@ -0,0 +1,65 @@ +import { Injectable, signal } from '@angular/core'; +import { take } from 'rxjs/operators'; +import { ConfigService } from '../../core/config/config.service'; +import { environment } from '../../../environments/environment'; + +interface UiRuntimeState { + brandName: string; + brandFullName: string; + logoUrl: string; + contactEmail: string; + themeId: string; +} + +@Injectable({ providedIn: 'root' }) +export class UiRuntimeFacade { + private readonly state = signal({ + brandName: environment.brandName, + brandFullName: environment.brandFullName, + logoUrl: environment.logo, + contactEmail: environment.contactEmail, + themeId: environment.theme + }); + + constructor(private readonly configService: ConfigService) { + this.configService.loadBootstrap().pipe(take(1)).subscribe({ + next: (bootstrap) => { + this.state.set({ + brandName: bootstrap.branding.brandName, + brandFullName: bootstrap.branding.brandName, + logoUrl: bootstrap.branding.logoUrl, + contactEmail: bootstrap.branding.supportEmail ?? environment.contactEmail, + themeId: bootstrap.theme.themeId + }); + } + }); + } + + brandName(): string { + return this.state().brandName; + } + + brandFullName(): string { + return this.state().brandFullName; + } + + logoUrl(): string { + return this.state().logoUrl; + } + + contactEmail(): string { + return this.state().contactEmail; + } + + themeId(): string { + return this.state().themeId; + } + + isNovo(): boolean { + return this.themeId().includes('novo'); + } + + isLavero(): boolean { + return this.themeId().includes('lavero'); + } +} \ No newline at end of file diff --git a/src/app/pages/cart/cart.component.ts b/src/app/pages/cart/cart.component.ts index 2c6c939..d823716 100644 --- a/src/app/pages/cart/cart.component.ts +++ b/src/app/pages/cart/cart.component.ts @@ -10,12 +10,12 @@ import { catchError, exhaustMap, take, timeout } from 'rxjs/operators'; import { DeliverySelectorComponent } from '../../components/delivery-selector/delivery-selector.component'; import { EmptyCartIconComponent } from '../../components/empty-cart-icon/empty-cart-icon.component'; import { TelegramLoginComponent } from '../../components/telegram-login/telegram-login.component'; -import { environment } from '../../../environments/environment'; import { getDiscountedPrice, getMainImage, trackByItemId, getBadgeClass, getTranslatedField } from '../../utils/item.utils'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; import { TranslateService } from '../../i18n/translate.service'; import { PAYMENT_POLL_INTERVAL_MS, PAYMENT_MAX_CHECKS, PAYMENT_TIMEOUT_CLOSE_MS, LINK_COPIED_DURATION_MS } from '../../config/constants'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; type PaymentMethod = 'qr' | 'card'; @@ -35,10 +35,14 @@ export class CartComponent implements OnDestroy { hasDeliveryPrice; allRequiredDeliveriesSelected; termsAccepted = false; - isnovo = environment.theme === 'novo'; + private readonly uiRuntime = inject(UiRuntimeFacade); private i18n = inject(TranslateService); private authService = inject(AuthService); + + get isnovo(): boolean { + return this.uiRuntime.isNovo(); + } isAuthenticated = this.authService.isAuthenticated; diff --git a/src/app/pages/home/home.component.ts b/src/app/pages/home/home.component.ts index f1a1e0d..9ee66ce 100644 --- a/src/app/pages/home/home.component.ts +++ b/src/app/pages/home/home.component.ts @@ -2,11 +2,11 @@ import { Router, RouterLink } from '@angular/router'; import { ApiService, LanguageService } from '../../services'; import { Category } from '../../models'; -import { environment } from '../../../environments/environment'; import { getTranslatedCategoryName } from '../../utils/item.utils'; import { ItemsCarouselComponent } from '../../components/items-carousel/items-carousel.component'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; @Component({ selector: 'app-home', @@ -16,8 +16,13 @@ import { TranslatePipe } from '../../i18n/translate.pipe'; changeDetection: ChangeDetectionStrategy.OnPush }) export class HomeComponent implements OnInit, OnDestroy { - brandName = environment.brandFullName; - isnovo = environment.theme === 'novo'; + constructor( + private apiService: ApiService, + private router: Router, + private langService: LanguageService, + private readonly uiRuntime: UiRuntimeFacade + ) {} + categories = signal([]); wideCategories = signal>(new Set()); loading = signal(true); @@ -53,7 +58,13 @@ export class HomeComponent implements OnInit, OnDestroy { return cache; }); - constructor(private apiService: ApiService, private router: Router, private langService: LanguageService) {} + get brandName(): string { + return this.uiRuntime.brandFullName(); + } + + get isnovo(): boolean { + return this.uiRuntime.isNovo(); + } ngOnInit(): void { this.loadCategories(); diff --git a/src/app/pages/item-detail/item-detail.component.ts b/src/app/pages/item-detail/item-detail.component.ts index 6cc9146..de00028 100644 --- a/src/app/pages/item-detail/item-detail.component.ts +++ b/src/app/pages/item-detail/item-detail.component.ts @@ -7,12 +7,12 @@ import { AuthService } from '../../services/auth.service'; import { Item, ItemDetail, DescriptionField, DeliveryOption } from '../../models'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { Subscription } from 'rxjs'; -import { environment } from '../../../environments/environment'; import { SecurityContext } from '@angular/core'; import { getStockStatus, getBadgeClass, getTranslatedField } from '../../utils/item.utils'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; import { TranslateService } from '../../i18n/translate.service'; +import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade'; @Component({ selector: 'app-item-detail', @@ -26,7 +26,11 @@ export class ItemDetailComponent implements OnInit, OnDestroy { selectedPhotoIndex = signal(0); loading = signal(true); error = signal(null); - isnovo = environment.theme === 'novo'; + private readonly uiRuntime = inject(UiRuntimeFacade); + + get isnovo(): boolean { + return this.uiRuntime.isNovo(); + } // Variant selection selectedColour = signal(null);