arch(sprint1): move UI env reads behind runtime facade
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
|
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { TranslateService } from '../../i18n/translate.service';
|
import { TranslateService } from '../../i18n/translate.service';
|
||||||
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-back-button',
|
selector: 'app-back-button',
|
||||||
@@ -62,9 +62,13 @@ import { TranslateService } from '../../i18n/translate.service';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class BackButtonComponent {
|
export class BackButtonComponent {
|
||||||
isnovo = environment.theme === 'novo';
|
private readonly uiRuntime = inject(UiRuntimeFacade);
|
||||||
i18n = inject(TranslateService);
|
i18n = inject(TranslateService);
|
||||||
|
|
||||||
|
get isnovo(): boolean {
|
||||||
|
return this.uiRuntime.isNovo();
|
||||||
|
}
|
||||||
|
|
||||||
constructor(private location: Location) {}
|
constructor(private location: Location) {}
|
||||||
|
|
||||||
goBack(): void {
|
goBack(): void {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||||
import { LogoComponent } from '../logo/logo.component';
|
import { LogoComponent } from '../logo/logo.component';
|
||||||
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-footer',
|
selector: 'app-footer',
|
||||||
@@ -13,9 +13,23 @@ import { LogoComponent } from '../logo/logo.component';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class FooterComponent {
|
export class FooterComponent {
|
||||||
|
constructor(private readonly uiRuntime: UiRuntimeFacade) {}
|
||||||
|
|
||||||
currentYear = new Date().getFullYear();
|
currentYear = new Date().getFullYear();
|
||||||
brandName = environment.brandName;
|
|
||||||
contactEmail = environment.contactEmail;
|
get brandName(): string {
|
||||||
isnovo = environment.theme === 'novo';
|
return this.uiRuntime.brandName();
|
||||||
islavero = environment.theme === 'lavero';
|
}
|
||||||
|
|
||||||
|
get contactEmail(): string {
|
||||||
|
return this.uiRuntime.contactEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
get isnovo(): boolean {
|
||||||
|
return this.uiRuntime.isNovo();
|
||||||
|
}
|
||||||
|
|
||||||
|
get islavero(): boolean {
|
||||||
|
return this.uiRuntime.isLavero();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import { Component, ChangeDetectionStrategy, Renderer2, inject, DOCUMENT } from
|
|||||||
import { Router, RouterLink, RouterLinkActive } from '@angular/router';
|
import { Router, RouterLink, RouterLinkActive } from '@angular/router';
|
||||||
import { CartService } from '../../services/cart.service';
|
import { CartService } from '../../services/cart.service';
|
||||||
import { LanguageService } from '../../services/language.service';
|
import { LanguageService } from '../../services/language.service';
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { LogoComponent } from '../logo/logo.component';
|
import { LogoComponent } from '../logo/logo.component';
|
||||||
import { LanguageSelectorComponent } from '../language-selector/language-selector.component';
|
import { LanguageSelectorComponent } from '../language-selector/language-selector.component';
|
||||||
import { RegionSelectorComponent } from '../region-selector/region-selector.component';
|
import { RegionSelectorComponent } from '../region-selector/region-selector.component';
|
||||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||||
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
@@ -20,19 +20,29 @@ export class HeaderComponent {
|
|||||||
cartItemCount;
|
cartItemCount;
|
||||||
cartTotal;
|
cartTotal;
|
||||||
menuOpen = false;
|
menuOpen = false;
|
||||||
brandName = environment.brandFullName;
|
|
||||||
logo = environment.logo;
|
|
||||||
isnovo = environment.theme === 'novo';
|
|
||||||
|
|
||||||
private renderer = inject(Renderer2);
|
private renderer = inject(Renderer2);
|
||||||
private document = inject(DOCUMENT);
|
private document = inject(DOCUMENT);
|
||||||
private langService = inject(LanguageService);
|
private langService = inject(LanguageService);
|
||||||
|
private uiRuntime = inject(UiRuntimeFacade);
|
||||||
|
|
||||||
constructor(private cartService: CartService, private router: Router) {
|
constructor(private cartService: CartService, private router: Router) {
|
||||||
this.cartItemCount = this.cartService.itemCount;
|
this.cartItemCount = this.cartService.itemCount;
|
||||||
this.cartTotal = this.cartService.totalPrice;
|
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 {
|
get homeUrl(): string {
|
||||||
return `/${this.langService.currentLanguage()}`;
|
return `/${this.langService.currentLanguage()}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import { ButtonModule } from 'primeng/button';
|
|||||||
import { TagModule } from 'primeng/tag';
|
import { TagModule } from 'primeng/tag';
|
||||||
import { ApiService, CartService } from '../../services';
|
import { ApiService, CartService } from '../../services';
|
||||||
import { Item } from '../../models';
|
import { Item } from '../../models';
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { getDiscountedPrice, getMainImage, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
import { getDiscountedPrice, getMainImage, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
||||||
import { LanguageService } from '../../services/language.service';
|
import { LanguageService } from '../../services/language.service';
|
||||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||||
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-items-carousel',
|
selector: 'app-items-carousel',
|
||||||
@@ -22,7 +22,7 @@ import { TranslatePipe } from '../../i18n/translate.pipe';
|
|||||||
export class ItemsCarouselComponent implements OnInit {
|
export class ItemsCarouselComponent implements OnInit {
|
||||||
products = signal<Item[]>([]);
|
products = signal<Item[]>([]);
|
||||||
loading = signal(true);
|
loading = signal(true);
|
||||||
isnovo = environment.theme === 'novo';
|
private readonly uiRuntime = inject(UiRuntimeFacade);
|
||||||
|
|
||||||
responsiveOptions: { breakpoint: string; numVisible: number; numScroll: number }[] | undefined;
|
responsiveOptions: { breakpoint: string; numVisible: number; numScroll: number }[] | undefined;
|
||||||
|
|
||||||
@@ -102,6 +102,7 @@ export class ItemsCarouselComponent implements OnInit {
|
|||||||
readonly getBadgeClass = getBadgeClass;
|
readonly getBadgeClass = getBadgeClass;
|
||||||
|
|
||||||
private langService = inject(LanguageService);
|
private langService = inject(LanguageService);
|
||||||
|
get isnovo(): boolean { return this.uiRuntime.isNovo(); }
|
||||||
itemName(product: Item): string { return getTranslatedField(product, 'name', this.langService.currentLanguage()); }
|
itemName(product: Item): string { return getTranslatedField(product, 'name', this.langService.currentLanguage()); }
|
||||||
|
|
||||||
addToCart(event: Event, item: Item): void {
|
addToCart(event: Event, item: Item): void {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { environment } from '../../../environments/environment';
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-logo',
|
selector: 'app-logo',
|
||||||
@@ -17,6 +17,13 @@ import { environment } from '../../../environments/environment';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class LogoComponent {
|
export class LogoComponent {
|
||||||
brandName = environment.brandName;
|
constructor(private readonly uiRuntime: UiRuntimeFacade) {}
|
||||||
logoPath = (environment as any).logo ?? `/assets/images/${environment.theme}-logo.svg`;
|
|
||||||
|
get brandName(): string {
|
||||||
|
return this.uiRuntime.brandName();
|
||||||
|
}
|
||||||
|
|
||||||
|
get logoPath(): string {
|
||||||
|
return this.uiRuntime.logoUrl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
src/app/facades/runtime/ui-runtime.facade.ts
Normal file
65
src/app/facades/runtime/ui-runtime.facade.ts
Normal file
@@ -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<UiRuntimeState>({
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,12 +10,12 @@ import { catchError, exhaustMap, take, timeout } from 'rxjs/operators';
|
|||||||
import { DeliverySelectorComponent } from '../../components/delivery-selector/delivery-selector.component';
|
import { DeliverySelectorComponent } from '../../components/delivery-selector/delivery-selector.component';
|
||||||
import { EmptyCartIconComponent } from '../../components/empty-cart-icon/empty-cart-icon.component';
|
import { EmptyCartIconComponent } from '../../components/empty-cart-icon/empty-cart-icon.component';
|
||||||
import { TelegramLoginComponent } from '../../components/telegram-login/telegram-login.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 { getDiscountedPrice, getMainImage, trackByItemId, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
||||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||||
import { TranslateService } from '../../i18n/translate.service';
|
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 { 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';
|
type PaymentMethod = 'qr' | 'card';
|
||||||
|
|
||||||
@@ -35,11 +35,15 @@ export class CartComponent implements OnDestroy {
|
|||||||
hasDeliveryPrice;
|
hasDeliveryPrice;
|
||||||
allRequiredDeliveriesSelected;
|
allRequiredDeliveriesSelected;
|
||||||
termsAccepted = false;
|
termsAccepted = false;
|
||||||
isnovo = environment.theme === 'novo';
|
private readonly uiRuntime = inject(UiRuntimeFacade);
|
||||||
|
|
||||||
private i18n = inject(TranslateService);
|
private i18n = inject(TranslateService);
|
||||||
private authService = inject(AuthService);
|
private authService = inject(AuthService);
|
||||||
|
|
||||||
|
get isnovo(): boolean {
|
||||||
|
return this.uiRuntime.isNovo();
|
||||||
|
}
|
||||||
|
|
||||||
isAuthenticated = this.authService.isAuthenticated;
|
isAuthenticated = this.authService.isAuthenticated;
|
||||||
|
|
||||||
// Swipe state
|
// Swipe state
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
import { Router, RouterLink } from '@angular/router';
|
import { Router, RouterLink } from '@angular/router';
|
||||||
import { ApiService, LanguageService } from '../../services';
|
import { ApiService, LanguageService } from '../../services';
|
||||||
import { Category } from '../../models';
|
import { Category } from '../../models';
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { getTranslatedCategoryName } from '../../utils/item.utils';
|
import { getTranslatedCategoryName } from '../../utils/item.utils';
|
||||||
import { ItemsCarouselComponent } from '../../components/items-carousel/items-carousel.component';
|
import { ItemsCarouselComponent } from '../../components/items-carousel/items-carousel.component';
|
||||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||||
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
@@ -16,8 +16,13 @@ import { TranslatePipe } from '../../i18n/translate.pipe';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class HomeComponent implements OnInit, OnDestroy {
|
export class HomeComponent implements OnInit, OnDestroy {
|
||||||
brandName = environment.brandFullName;
|
constructor(
|
||||||
isnovo = environment.theme === 'novo';
|
private apiService: ApiService,
|
||||||
|
private router: Router,
|
||||||
|
private langService: LanguageService,
|
||||||
|
private readonly uiRuntime: UiRuntimeFacade
|
||||||
|
) {}
|
||||||
|
|
||||||
categories = signal<Category[]>([]);
|
categories = signal<Category[]>([]);
|
||||||
wideCategories = signal<Set<number>>(new Set());
|
wideCategories = signal<Set<number>>(new Set());
|
||||||
loading = signal(true);
|
loading = signal(true);
|
||||||
@@ -53,7 +58,13 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
return cache;
|
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 {
|
ngOnInit(): void {
|
||||||
this.loadCategories();
|
this.loadCategories();
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import { AuthService } from '../../services/auth.service';
|
|||||||
import { Item, ItemDetail, DescriptionField, DeliveryOption } from '../../models';
|
import { Item, ItemDetail, DescriptionField, DeliveryOption } from '../../models';
|
||||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { SecurityContext } from '@angular/core';
|
import { SecurityContext } from '@angular/core';
|
||||||
import { getStockStatus, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
import { getStockStatus, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
||||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||||
import { TranslateService } from '../../i18n/translate.service';
|
import { TranslateService } from '../../i18n/translate.service';
|
||||||
|
import { UiRuntimeFacade } from '../../facades/runtime/ui-runtime.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-item-detail',
|
selector: 'app-item-detail',
|
||||||
@@ -26,7 +26,11 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
|||||||
selectedPhotoIndex = signal(0);
|
selectedPhotoIndex = signal(0);
|
||||||
loading = signal(true);
|
loading = signal(true);
|
||||||
error = signal<string | null>(null);
|
error = signal<string | null>(null);
|
||||||
isnovo = environment.theme === 'novo';
|
private readonly uiRuntime = inject(UiRuntimeFacade);
|
||||||
|
|
||||||
|
get isnovo(): boolean {
|
||||||
|
return this.uiRuntime.isNovo();
|
||||||
|
}
|
||||||
|
|
||||||
// Variant selection
|
// Variant selection
|
||||||
selectedColour = signal<string | null>(null);
|
selectedColour = signal<string | null>(null);
|
||||||
|
|||||||
Reference in New Issue
Block a user