diff --git a/CHANGELOG.md b/CHANGELOG.md index d7676efee..e8a33af2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +- Extracted the page tabs to a reusable component + ### Fixed - Resolved an issue with the cash balance calculation of an account for `SELL` activities to ensure fees are correctly subtracted diff --git a/apps/client/src/app/pages/about/about-page.component.ts b/apps/client/src/app/pages/about/about-page.component.ts index b23377f3c..fb632a586 100644 --- a/apps/client/src/app/pages/about/about-page.component.ts +++ b/apps/client/src/app/pages/about/about-page.component.ts @@ -1,20 +1,15 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { publicRoutes } from '@ghostfolio/common/routes/routes'; +import { + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; import { DataService } from '@ghostfolio/ui/services'; -import { - ChangeDetectorRef, - Component, - CUSTOM_ELEMENTS_SCHEMA, - DestroyRef, - OnInit -} from '@angular/core'; +import { ChangeDetectorRef, Component, DestroyRef } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { documentTextOutline, @@ -24,18 +19,15 @@ import { shieldCheckmarkOutline, sparklesOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [IonIcon, MatTabsModule, RouterModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [GfPageTabsComponent], selector: 'gf-about-page', styleUrls: ['./about-page.scss'], templateUrl: './about-page.html' }) -export class AboutPageComponent implements OnInit { - public deviceType: string; +export class AboutPageComponent { public hasPermissionForSubscription: boolean; public tabs: TabConfiguration[] = []; public user: User; @@ -44,7 +36,6 @@ export class AboutPageComponent implements OnInit { private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, private destroyRef: DestroyRef, - private deviceDetectorService: DeviceDetectorService, private userService: UserService ) { const { globalPermissions } = this.dataService.fetchInfo(); @@ -112,8 +103,4 @@ export class AboutPageComponent implements OnInit { sparklesOutline }); } - - public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - } } diff --git a/apps/client/src/app/pages/about/about-page.html b/apps/client/src/app/pages/about/about-page.html index bd1338774..5d1bdce9b 100644 --- a/apps/client/src/app/pages/about/about-page.html +++ b/apps/client/src/app/pages/about/about-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/app/pages/admin/admin-page.component.ts b/apps/client/src/app/pages/admin/admin-page.component.ts index 8ec094915..6b653efb0 100644 --- a/apps/client/src/app/pages/admin/admin-page.component.ts +++ b/apps/client/src/app/pages/admin/admin-page.component.ts @@ -1,10 +1,10 @@ -import { TabConfiguration } from '@ghostfolio/common/interfaces'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; +import { + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; import { Component, OnInit } from '@angular/core'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { flashOutline, @@ -13,20 +13,18 @@ import { serverOutline, settingsOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [IonIcon, MatTabsModule, RouterModule], + imports: [GfPageTabsComponent], selector: 'gf-admin-page', styleUrls: ['./admin-page.scss'], templateUrl: './admin-page.html' }) export class AdminPageComponent implements OnInit { - public deviceType: string; public tabs: TabConfiguration[] = []; - public constructor(private deviceDetectorService: DeviceDetectorService) { + public constructor() { addIcons({ flashOutline, peopleOutline, @@ -37,8 +35,6 @@ export class AdminPageComponent implements OnInit { } public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - this.tabs = [ { iconName: 'reader-outline', diff --git a/apps/client/src/app/pages/admin/admin-page.html b/apps/client/src/app/pages/admin/admin-page.html index a5c5ed7e9..5d1bdce9b 100644 --- a/apps/client/src/app/pages/admin/admin-page.html +++ b/apps/client/src/app/pages/admin/admin-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/app/pages/faq/faq-page.component.ts b/apps/client/src/app/pages/faq/faq-page.component.ts index 8ae074bee..6dabdb5e2 100644 --- a/apps/client/src/app/pages/faq/faq-page.component.ts +++ b/apps/client/src/app/pages/faq/faq-page.component.ts @@ -1,33 +1,27 @@ -import { TabConfiguration } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { publicRoutes } from '@ghostfolio/common/routes/routes'; +import { + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; import { DataService } from '@ghostfolio/ui/services'; -import { CUSTOM_ELEMENTS_SCHEMA, Component, OnInit } from '@angular/core'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; +import { Component } from '@angular/core'; import { addIcons } from 'ionicons'; import { cloudyOutline, readerOutline, serverOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [IonIcon, MatTabsModule, RouterModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [GfPageTabsComponent], selector: 'gf-faq-page', styleUrls: ['./faq-page.scss'], templateUrl: './faq-page.html' }) -export class GfFaqPageComponent implements OnInit { - public deviceType: string; +export class GfFaqPageComponent { public hasPermissionForSubscription: boolean; public tabs: TabConfiguration[] = []; - public constructor( - private dataService: DataService, - private deviceDetectorService: DeviceDetectorService - ) { + public constructor(private dataService: DataService) { const { globalPermissions } = this.dataService.fetchInfo(); this.hasPermissionForSubscription = hasPermission( @@ -56,8 +50,4 @@ export class GfFaqPageComponent implements OnInit { addIcons({ cloudyOutline, readerOutline, serverOutline }); } - - public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - } } diff --git a/apps/client/src/app/pages/faq/faq-page.html b/apps/client/src/app/pages/faq/faq-page.html index bd1338774..5d1bdce9b 100644 --- a/apps/client/src/app/pages/faq/faq-page.html +++ b/apps/client/src/app/pages/faq/faq-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/app/pages/home/home-page.component.ts b/apps/client/src/app/pages/home/home-page.component.ts index 958428331..453a79a52 100644 --- a/apps/client/src/app/pages/home/home-page.component.ts +++ b/apps/client/src/app/pages/home/home-page.component.ts @@ -1,20 +1,20 @@ import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; +import { + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; import { ChangeDetectorRef, Component, - CUSTOM_ELEMENTS_SCHEMA, DestroyRef, OnInit } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { albumsOutline, @@ -23,18 +23,15 @@ import { newspaperOutline, readerOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [IonIcon, MatTabsModule, RouterModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [GfPageTabsComponent], selector: 'gf-home-page', styleUrls: ['./home-page.scss'], templateUrl: './home-page.html' }) export class GfHomePageComponent implements OnInit { - public deviceType: string; public hasImpersonationId: boolean; public tabs: TabConfiguration[] = []; public user: User; @@ -42,7 +39,6 @@ export class GfHomePageComponent implements OnInit { public constructor( private changeDetectorRef: ChangeDetectorRef, private destroyRef: DestroyRef, - private deviceDetectorService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private userService: UserService ) { @@ -104,8 +100,6 @@ export class GfHomePageComponent implements OnInit { } public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - this.impersonationStorageService .onChangeHasImpersonation() .pipe(takeUntilDestroyed(this.destroyRef)) diff --git a/apps/client/src/app/pages/home/home-page.html b/apps/client/src/app/pages/home/home-page.html index bd1338774..5d1bdce9b 100644 --- a/apps/client/src/app/pages/home/home-page.html +++ b/apps/client/src/app/pages/home/home-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts index dca39c4a6..00fb3242b 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts +++ b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts @@ -1,16 +1,13 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { User } from '@ghostfolio/common/interfaces'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; - import { - ChangeDetectorRef, - Component, - DestroyRef, - OnInit -} from '@angular/core'; + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; + +import { ChangeDetectorRef, Component, DestroyRef } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; import { addIcons } from 'ionicons'; import { analyticsOutline, @@ -19,24 +16,21 @@ import { scanOutline, swapVerticalOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [MatTabsModule, RouterModule], + imports: [GfPageTabsComponent], selector: 'gf-portfolio-page', styleUrls: ['./portfolio-page.scss'], templateUrl: './portfolio-page.html' }) -export class PortfolioPageComponent implements OnInit { - public deviceType: string; +export class PortfolioPageComponent { public tabs: TabConfiguration[] = []; public user: User; public constructor( private changeDetectorRef: ChangeDetectorRef, private destroyRef: DestroyRef, - private deviceDetectorService: DeviceDetectorService, private userService: UserService ) { this.userService.stateChanged @@ -86,8 +80,4 @@ export class PortfolioPageComponent implements OnInit { swapVerticalOutline }); } - - public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - } } diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.html b/apps/client/src/app/pages/portfolio/portfolio-page.html index bd1338774..5d1bdce9b 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.html +++ b/apps/client/src/app/pages/portfolio/portfolio-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/app/pages/resources/resources-page.component.ts b/apps/client/src/app/pages/resources/resources-page.component.ts index 016f92fa8..faba06f28 100644 --- a/apps/client/src/app/pages/resources/resources-page.component.ts +++ b/apps/client/src/app/pages/resources/resources-page.component.ts @@ -1,10 +1,10 @@ -import { TabConfiguration } from '@ghostfolio/common/interfaces'; import { publicRoutes } from '@ghostfolio/common/routes/routes'; +import { + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; -import { Component, OnInit } from '@angular/core'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; +import { Component } from '@angular/core'; import { addIcons } from 'ionicons'; import { bookOutline, @@ -12,17 +12,15 @@ import { newspaperOutline, readerOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [IonIcon, MatTabsModule, RouterModule], + imports: [GfPageTabsComponent], selector: 'gf-resources-page', styleUrls: ['./resources-page.scss'], templateUrl: './resources-page.html' }) -export class ResourcesPageComponent implements OnInit { - public deviceType: string; +export class ResourcesPageComponent { public tabs: TabConfiguration[] = [ { iconName: 'reader-outline', @@ -46,11 +44,7 @@ export class ResourcesPageComponent implements OnInit { } ]; - public constructor(private deviceDetectorService: DeviceDetectorService) { + public constructor() { addIcons({ bookOutline, libraryOutline, newspaperOutline, readerOutline }); } - - public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - } } diff --git a/apps/client/src/app/pages/resources/resources-page.html b/apps/client/src/app/pages/resources/resources-page.html index bd1338774..5d1bdce9b 100644 --- a/apps/client/src/app/pages/resources/resources-page.html +++ b/apps/client/src/app/pages/resources/resources-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/app/pages/user-account/user-account-page.component.ts b/apps/client/src/app/pages/user-account/user-account-page.component.ts index 7d5af5423..71b93b2e4 100644 --- a/apps/client/src/app/pages/user-account/user-account-page.component.ts +++ b/apps/client/src/app/pages/user-account/user-account-page.component.ts @@ -1,39 +1,30 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { User } from '@ghostfolio/common/interfaces'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; - import { - ChangeDetectorRef, - Component, - CUSTOM_ELEMENTS_SCHEMA, - DestroyRef, - OnInit -} from '@angular/core'; + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; + +import { ChangeDetectorRef, Component, DestroyRef } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { diamondOutline, keyOutline, settingsOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [IonIcon, MatTabsModule, RouterModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [GfPageTabsComponent], selector: 'gf-user-account-page', styleUrls: ['./user-account-page.scss'], templateUrl: './user-account-page.html' }) -export class GfUserAccountPageComponent implements OnInit { - public deviceType: string; +export class GfUserAccountPageComponent { public tabs: TabConfiguration[] = []; public user: User; public constructor( private changeDetectorRef: ChangeDetectorRef, private destroyRef: DestroyRef, - private deviceDetectorService: DeviceDetectorService, private userService: UserService ) { this.userService.stateChanged @@ -68,8 +59,4 @@ export class GfUserAccountPageComponent implements OnInit { addIcons({ diamondOutline, keyOutline, settingsOutline }); } - - public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - } } diff --git a/apps/client/src/app/pages/user-account/user-account-page.html b/apps/client/src/app/pages/user-account/user-account-page.html index bd1338774..5d1bdce9b 100644 --- a/apps/client/src/app/pages/user-account/user-account-page.html +++ b/apps/client/src/app/pages/user-account/user-account-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/app/pages/zen/zen-page.component.ts b/apps/client/src/app/pages/zen/zen-page.component.ts index b3c14b4e0..df3684fd2 100644 --- a/apps/client/src/app/pages/zen/zen-page.component.ts +++ b/apps/client/src/app/pages/zen/zen-page.component.ts @@ -1,37 +1,30 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { User } from '@ghostfolio/common/interfaces'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; - import { - ChangeDetectorRef, - Component, - DestroyRef, - OnInit -} from '@angular/core'; + GfPageTabsComponent, + TabConfiguration +} from '@ghostfolio/ui/page-tabs'; + +import { ChangeDetectorRef, Component, DestroyRef } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { MatTabsModule } from '@angular/material/tabs'; -import { RouterModule } from '@angular/router'; -import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { albumsOutline, analyticsOutline } from 'ionicons/icons'; -import { DeviceDetectorService } from 'ngx-device-detector'; @Component({ host: { class: 'page has-tabs' }, - imports: [IonIcon, MatTabsModule, RouterModule], + imports: [GfPageTabsComponent], selector: 'gf-zen-page', styleUrls: ['./zen-page.scss'], templateUrl: './zen-page.html' }) -export class GfZenPageComponent implements OnInit { - public deviceType: string; +export class GfZenPageComponent { public tabs: TabConfiguration[] = []; public user: User; public constructor( private changeDetectorRef: ChangeDetectorRef, private destroyRef: DestroyRef, - private deviceDetectorService: DeviceDetectorService, private userService: UserService ) { this.userService.stateChanged @@ -58,8 +51,4 @@ export class GfZenPageComponent implements OnInit { addIcons({ albumsOutline, analyticsOutline }); } - - public ngOnInit() { - this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; - } } diff --git a/apps/client/src/app/pages/zen/zen-page.html b/apps/client/src/app/pages/zen/zen-page.html index bd1338774..5d1bdce9b 100644 --- a/apps/client/src/app/pages/zen/zen-page.html +++ b/apps/client/src/app/pages/zen/zen-page.html @@ -1,30 +1 @@ - - - - - + diff --git a/apps/client/src/styles.scss b/apps/client/src/styles.scss index 4138d9d9b..83fd69c91 100644 --- a/apps/client/src/styles.scss +++ b/apps/client/src/styles.scss @@ -265,16 +265,6 @@ body { } } - .page { - &.has-tabs { - @media (min-width: 576px) { - .mat-mdc-tab-header { - background-color: rgba(var(--palette-foreground-base-dark), 0.02); - } - } - } - } - .svgMap-tooltip { background: var(--dark-background); @@ -489,7 +479,6 @@ ngx-skeleton-loader { .page { display: flex; - flex-direction: column; overflow-y: auto; padding-bottom: env(safe-area-inset-bottom); padding-bottom: constant(safe-area-inset-bottom); @@ -506,44 +495,6 @@ ngx-skeleton-loader { padding: 2rem 0; } } - - &.has-tabs { - height: calc(100svh - var(--mat-toolbar-standard-height)); - - .fab-container { - @media (max-width: 575.98px) { - bottom: 5rem; - } - } - - .mat-mdc-tab-nav-panel { - padding: 2rem 0; - } - - @include mat.tabs-overrides( - ( - divider-height: 0 - ) - ); - - @media (min-width: 576px) { - flex-direction: row-reverse; - - .mat-mdc-tab-header { - background-color: rgba(var(--palette-foreground-base), 0.02); - padding: 2rem 0; - width: 14rem; - - .mat-mdc-tab-links { - flex-direction: column; - - .mat-mdc-tab-link { - justify-content: flex-start; - } - } - } - } - } } .svgMap-tooltip { diff --git a/apps/client/src/styles/theme.scss b/apps/client/src/styles/theme.scss index 3cec572cc..f8a194651 100644 --- a/apps/client/src/styles/theme.scss +++ b/apps/client/src/styles/theme.scss @@ -293,24 +293,6 @@ $gf-typography: ( container-shape: 4px ) ); - - .page.has-tabs { - @include mat.tabs-overrides( - ( - container-height: 3rem - ) - ); - } - } - - @media (min-width: 576px) { - .page.has-tabs { - @include mat.tabs-overrides( - ( - container-height: 2rem - ) - ); - } } @include mat.badge-overrides( @@ -436,15 +418,6 @@ $gf-typography: ( ) ); } - - .page.has-tabs { - @include mat.tabs-overrides( - ( - active-indicator-height: 0, - label-text-tracking: normal - ) - ); - } } :root { diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index 89874da60..536fc0feb 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -91,7 +91,6 @@ import type { SubscriptionOffer } from './subscription-offer.interface'; import type { SymbolItem } from './symbol-item.interface'; import type { SymbolMetrics } from './symbol-metrics.interface'; import type { SystemMessage } from './system-message.interface'; -import type { TabConfiguration } from './tab-configuration.interface'; import type { ToggleOption } from './toggle-option.interface'; import type { UserItem } from './user-item.interface'; import type { UserSettings } from './user-settings.interface'; @@ -186,7 +185,6 @@ export { SymbolItem, SymbolMetrics, SystemMessage, - TabConfiguration, ToggleOption, User, UserItem, diff --git a/libs/ui/src/lib/page-tabs/index.ts b/libs/ui/src/lib/page-tabs/index.ts new file mode 100644 index 000000000..a7b3468fd --- /dev/null +++ b/libs/ui/src/lib/page-tabs/index.ts @@ -0,0 +1,2 @@ +export * from './interfaces/interfaces'; +export * from './page-tabs.component'; diff --git a/libs/common/src/lib/interfaces/tab-configuration.interface.ts b/libs/ui/src/lib/page-tabs/interfaces/interfaces.ts similarity index 100% rename from libs/common/src/lib/interfaces/tab-configuration.interface.ts rename to libs/ui/src/lib/page-tabs/interfaces/interfaces.ts diff --git a/libs/ui/src/lib/page-tabs/page-tabs.component.html b/libs/ui/src/lib/page-tabs/page-tabs.component.html new file mode 100644 index 000000000..fa9af9b11 --- /dev/null +++ b/libs/ui/src/lib/page-tabs/page-tabs.component.html @@ -0,0 +1,30 @@ + + + + + diff --git a/libs/ui/src/lib/page-tabs/page-tabs.component.scss b/libs/ui/src/lib/page-tabs/page-tabs.component.scss new file mode 100644 index 000000000..bed3596bb --- /dev/null +++ b/libs/ui/src/lib/page-tabs/page-tabs.component.scss @@ -0,0 +1,70 @@ +@use '@angular/material' as mat; + +:host { + display: flex; + flex-direction: column; + height: calc(100svh - var(--mat-toolbar-standard-height)); + width: 100%; + + @include mat.tabs-overrides( + ( + active-indicator-height: 0, + divider-height: 0, + label-text-tracking: normal + ) + ); + + .fab-container { + @media (max-width: 575.98px) { + bottom: 5rem; + } + } + + ::ng-deep { + .mat-mdc-tab-nav-panel { + padding: 2rem 0; + } + } + + @media (max-width: 575.98px) { + @include mat.tabs-overrides( + ( + container-height: 3rem + ) + ); + } + + @media (min-width: 576px) { + flex-direction: row-reverse; + + @include mat.tabs-overrides( + ( + container-height: 2rem + ) + ); + + ::ng-deep { + .mat-mdc-tab-header { + background-color: rgba(var(--palette-foreground-base), 0.02); + padding: 2rem 0; + width: 14rem; + + .mat-mdc-tab-links { + flex-direction: column; + + .mat-mdc-tab-link { + justify-content: flex-start; + } + } + } + } + } +} + +:host-context(.theme-dark) { + @media (min-width: 576px) { + .mat-mdc-tab-header { + background-color: rgba(var(--palette-foreground-base-dark), 0.02); + } + } +} diff --git a/libs/ui/src/lib/page-tabs/page-tabs.component.ts b/libs/ui/src/lib/page-tabs/page-tabs.component.ts new file mode 100644 index 000000000..61c2caf05 --- /dev/null +++ b/libs/ui/src/lib/page-tabs/page-tabs.component.ts @@ -0,0 +1,30 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + input +} from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { DeviceDetectorService } from 'ngx-device-detector'; + +import { TabConfiguration } from './interfaces/interfaces'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [IonIcon, MatTabsModule, RouterModule], + selector: 'gf-page-tabs', + styleUrls: ['./page-tabs.component.scss'], + templateUrl: './page-tabs.component.html' +}) +export class GfPageTabsComponent { + public deviceType: string; + public readonly tabs = input.required(); + + private readonly deviceService = inject(DeviceDetectorService); + + public constructor() { + this.deviceType = this.deviceService.getDeviceInfo().deviceType; + } +}