Using angular-mat in toolbar

This commit is contained in:
Artur 2024-11-27 20:54:25 +01:00
parent 8312bfb121
commit 34ed2b4bd0
10 changed files with 2673 additions and 591 deletions

View File

@ -28,6 +28,7 @@
}
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.css"
],
@ -106,6 +107,7 @@
}
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css"
],
"scripts": []

3044
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,12 @@
"private": true,
"dependencies": {
"@angular/animations": "^18.2.0",
"@angular/cdk": "^17.0.0",
"@angular/common": "^18.2.0",
"@angular/compiler": "^18.2.0",
"@angular/core": "^18.2.0",
"@angular/forms": "^18.2.0",
"@angular/material": "^17.0.0",
"@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0",
@ -28,9 +30,10 @@
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.2.4",
"@angular/cli": "^18.2.4",
"@angular/cli": "^19.0.0",
"@angular/compiler-cli": "^18.2.0",
"@angular/localize": "^18.2.4",
"@schematics/angular": "^19.0.0",
"@types/jasmine": "~5.1.0",
"angular-eslint": "18.4.0",
"eslint": "^9.13.0",

View File

@ -0,0 +1,40 @@
.mat-toolbar {
display: flex;
align-items: center;
justify-content: space-between; /* Równe rozmieszczenie elementów */
padding: 0 16px; /* Marginesy wewnętrzne */
}
.col-left {
display: flex;
align-items: center;
justify-content: flex-start; /* Wyrównanie flagi do lewej */
}
.flag {
height: 25px; /* Powiększenie flagi */
width: auto;
margin-right: 16px; /* Odstęp od sąsiednich elementów */
border: none; /* Brak ramki */
}
.toolbar-item {
font-size: 22px; /* Większy rozmiar tekstu */
font-weight: 500;
text-transform: none; /* Bez uppercase */
color: white; /* Kolor tekstu */
}
button.mat-icon-button {
padding: 0; /* Brak dodatkowych marginesów */
}
.mat-toolbar-row {
display: flex;
width: 100%;
}
.col {
text-align: center; /* Wyśrodkowanie tekstu w kolumnach */
flex: 1; /* Równe rozciąganie kolumn */
}

View File

@ -1,30 +1,31 @@
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="me-auto col-auto">
<a class="navbar-brand ms-2">
<a
class="navbar-brand ms-2"
role="button"
tabindex="0"
(click)="switchLanguage( translate.currentLang === 'pl' ? 'en' : 'pl' )"
(keydown)="handleKeyDown($event)">
<img
loading="lazy"
class="border border-dark"
height="25"
src= "/flag-icons-main/flags/4x3/{{ translate.currentLang === 'pl' ? 'us' : 'pl' }}.svg"
alt="Switch language"
>
</a>
<mat-toolbar color="primary" class="sticky-top mat-toolbar">
<mat-toolbar-row>
<div class="col-left">
<button mat-icon-button class="flag-button" (click)="switchLanguage(translate.currentLang === 'pl' ? 'en' : 'pl')">
<img loading="lazy" class="flag"
src="/flag-icons-main/flags/4x3/{{ translate.currentLang === 'pl' ? 'us' : 'pl' }}.svg"
alt="Switch language">
</button>
</div>
<div class="col">
<button mat-button class="toolbar-item" [routerLink]="'/about-me'">{{ 'topBar.aboutMe' | translate }}</button>
</div>
<div class="col">
<button mat-button class="toolbar-item" [routerLink]="'/asset-calculator'">{{ 'topBar.depreciationCalculator' | translate }}</button>
</div>
<div class="col">
<button mat-button class="toolbar-item" [routerLink]="'/quotes'">{{ 'topBar.courses' | translate }}</button>
</div>
<div class="col">
<button mat-button class="toolbar-item" [routerLink]="'/friendly-pages'">{{ 'topBar.friendlyPages' | translate }}</button>
</div>
</mat-toolbar-row>
</mat-toolbar>
<router-outlet></router-outlet>
</a>
</div>
<div class="container d-flex justify-content-between align-items-center">
<!-- Navbar links -->
<a class="navbar-brand" [routerLink]="'/about-me'">{{ 'topBar.aboutMe' | translate }}</a>
<a class="navbar-brand" [routerLink]="'/asset-calculator'">{{ 'topBar.depreciationCalculator' | translate }}</a>
<a class="navbar-brand" [routerLink]="'/quotes'">{{ 'topBar.courses' | translate }}</a>
<a class="navbar-brand" [routerLink]="'/friendly-pages'">{{ 'topBar.friendlyPages' | translate }}</a>
</div>
</nav>
<router-outlet />

View File

@ -2,11 +2,14 @@ import { Component, HostListener, OnDestroy } from '@angular/core';
import { RouterOutlet, RouterModule } from '@angular/router';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, TranslateModule, RouterModule],
imports: [RouterOutlet, TranslateModule, RouterModule, MatToolbarModule, MatButtonModule, MatIconModule, MatMenuModule],
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'], // Fixed typo
})

View File

@ -7,6 +7,7 @@ import { HttpClient, provideHttpClient} from '@angular/common/http';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
const httpLoaderFactory: (http: HttpClient) => TranslateHttpLoader = (http: HttpClient) =>
new TranslateHttpLoader(http, './i18n/', '.json');
@ -24,7 +25,7 @@ export const appConfig: ApplicationConfig = {
useFactory: httpLoaderFactory,
deps: [ HttpClient ],
},
})])
})]), provideAnimationsAsync()
],
};

View File

@ -3,7 +3,7 @@ import { DecimalPipe} from '@angular/common';
import { Asset, AssetPlanPosition, TypeDepreciation, YearMonth, AssetLifeChange, AssetDepreciationMethod } from '../assets/asset';
import { AssetService } from '../assets/service/asset.service';
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { FormsModule } from '@angular/forms';
import { FormsModule } from '@angular/forms';
interface FormValues {
initialValueAsset:number;
@ -17,20 +17,24 @@ class AssetLifeChangeWrapper{
when = signal<string> ( YearMonth.todayTxt());
initial = signal<number>( 0 );
constructor( assetLifeChange : AssetLifeChange ){
this.set(assetLifeChange);
}
get(): AssetLifeChange {
const ym = this.when();
const when = YearMonth.from( ym );
return new AssetLifeChange( when, this.initial() , 0, 0 );
}
constructor( assetLifeChange : AssetLifeChange ){
this.when.set( YearMonth.toTxt( assetLifeChange.when ) );
this.initial.set( assetLifeChange.initial );
set(assetLifeChange: AssetLifeChange) {
this.when.set(YearMonth.toTxt(assetLifeChange.when));
this.initial.set(assetLifeChange.initial);
}
}
const NAME_IN_STORAGE = 'assetForCalculator';
@Component({
selector: 'app-asset-calculator',
standalone: true,
@ -70,6 +74,24 @@ export class AssetCalculatorComponent {
effect( () => this.reCalculate( ) )
}
private storage = {
load: (key: string) => {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch {
console.error(`Failed to load ${key} from localStorage`);
return null;
}
},
save: (key: string, data: any) => {
try {
localStorage.setItem(key, JSON.stringify(data));
} catch {
console.error(`Failed to save ${key} to localStorage`);
}
}
};
ngOnInit(): void{
this.restoreState();
@ -84,28 +106,12 @@ export class AssetCalculatorComponent {
}
private restoreState() {
const savedAsset = localStorage.getItem(NAME_IN_STORAGE);
if( savedAsset ) {
try {
const parsedAsset : Asset = JSON.parse(savedAsset);
this.assetToControls( parsedAsset );
} catch (error) {
console.error('Failed to parse saved asset:', error);
localStorage.removeItem(NAME_IN_STORAGE);
}
}
const savedAsset = this.storage.load(NAME_IN_STORAGE);
if (savedAsset) this.assetToControls(savedAsset);
}
private saveState(asset:Asset) {
// Zapisywanie danych przed zniszczeniem komponentu
try {
// Serialize the asset to a JSON string
localStorage.setItem(NAME_IN_STORAGE, JSON.stringify(asset) );
} catch (error) {
console.error('Failed to save asset:', error);
}
private saveState(asset: Asset) {
this.storage.save(NAME_IN_STORAGE, asset);
}
@ -115,24 +121,22 @@ export class AssetCalculatorComponent {
}
}
private updateBatch(asset: Asset) {
const life0 = asset.life[0];
const method0 = asset.depreciationMethods[0];
this.initialValueAsset.set(life0.initial);
const ymText =YearMonth.toTxt( life0.when );
this.startDepreciation.set(ymText);
this.rate.set(method0.rate);
this.typeDepreciation.set(method0.type);
this.factor.set(method0.rate);
private updateBatch(asset: Asset) {
const [firstLife, ...restLives] = asset.life;
const method0 = asset.depreciationMethods[0];
this.initialValueAsset.set(firstLife.initial);
this.startDepreciation.set(YearMonth.toTxt(firstLife.when));
this.rate.set(method0.rate);
this.typeDepreciation.set(method0.type);
this.factor.set(method0.factor);
const lifeChanges = restLives.map((lifeChange) =>
new AssetLifeChangeWrapper(lifeChange)
);
this.lifeChangesSignal.set(lifeChanges);
}
console.log( asset.life );
for( let i = 1; i < asset.life.length ; i++ ){
const assetLifeChange = asset.life[i];
const lifeChangeWrapper = this.addLifeChange2(assetLifeChange);
lifeChangeWrapper.initial.set( assetLifeChange.initial );
lifeChangeWrapper.when.set(YearMonth.toTxt( assetLifeChange.when ));
};
}
private controlsToAsset(): Asset {

View File

@ -6,8 +6,10 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<body class="mat-typography">
<app-root></app-root>
</body>
</html>

View File

@ -16,3 +16,15 @@ main {
padding: 20px; /* Odstęp wewnętrzny */
background-color: #f8f9fa; /* Tło formularza */
}
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
.spacer {
flex: 1 1 auto;
}
mat-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
}