Friendly component and prectise with signal

This commit is contained in:
Artur 2024-11-19 17:32:15 +01:00
parent 8bef46564e
commit d7cd62183d
14 changed files with 888 additions and 730 deletions

1362
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
{
"topBar":{
"aboutMe" : "About me",
"depreciationCalculator" :"Depreciation Calculator",
"courses" : "Courses"
"depreciationCalculator" : "Depreciation Calculator",
"courses" : "Courses",
"friendlyPages" : "Friendly Pages"
},
"asset-calculator": {
"depreciationCalculator" :"Depreciation Calculator",
@ -26,6 +27,17 @@
"digressive" :"digressive",
"depreciationPlan" :"Depreciatin plan"
},
"friendly_pages":{
"bodypainter_eu":
{
"short" : "Shall we paint someone?" ,
"href" : "https://bodypainter.eu?language=en",
"micro" : "Thumbnail of the bodypainter.eu website",
"description" : "Click to go to bodypainter.eu",
"title" : "Let's paint someone? bodypainter.eu",
"alt" : "bodypainter.eu"
}
},
"aboutMe":{
"description": "<p>I am an experienced software engineer with over 20 years of experience in the IT industry.</p>\n<p>I specialize in Java and Angular technologies, as well as in the development and implementation of scalable web applications.</p>\n<p>I am an Oracle Cloud Infrastructure 2024 Generative AI Certified Professional and have prior qualifications in Oracle Cloud and Java programming.</p>\n<p>These skills support my implementation efforts modern cloud-based solutions and creating future-oriented applications.</p>\n<ul><b>Main technologies and tools:</b>\n<li>Programming languages: Java, JavaScript, C++</li> \n<li>Frameworks: Spring Boot, Angular, Thymeleaf</li>\n<li>Databases: Oracle, MSSQL, JavaDB</li>\n<li>Cloud environments: Oracle Cloud Infrastructure, Docker</li>\n<li>Other: HTML, CSS, Bootstrap, SVN, WildFly</li>\n</ul>"
}

View File

@ -2,7 +2,8 @@
"topBar":{
"aboutMe" : "O mnie",
"depreciationCalculator" :"Kalkulator amortyzacyjny",
"courses" : "Kursy"
"courses" : "Kursy",
"friendlyPages" : "Zaprzyjaźnione strony"
},
"asset-calculator": {
"depreciationCalculator" :"Kalkulator amortyzacyjny",
@ -25,6 +26,17 @@
"linear" :"liniowa",
"digressive" :"dygresywna",
"depreciationPlan" :"Plan amortyzacji"
},
"friendly_pages":{
"bodypainter_eu":
{
"short" : "Pomalujemy kogoś ?" ,
"href" : "https://bodypainter.eu",
"micro" : "Miniaturka strony bodypainter.eu",
"description" : "Kliknij aby przejść na bodypainter.eu",
"title" : "Pomalujemy kogoś ? bodypainter.eu",
"alt" : "bodypainter.eu"
}
}
,
"aboutMe":{

View File

@ -1,22 +1,30 @@
<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"
(click)="switchLanguage(translate.currentLang === 'pl' ? 'en' : 'pl')"
alt="Switch language"
>
</a>
</a>
</div>
<div class="container d-flex justify-content-between align-items-center">
<!-- Navbar links -->
<a class="navbar-brand" href="/about-me">{{ 'topBar.aboutMe' | translate }}</a>
<a class="navbar-brand" href="/asset-calculator">{{ 'topBar.depreciationCalculator' | translate }}</a>
<a class="navbar-brand" href="/quotes">{{ 'topBar.courses' | translate }}</a>
<a class="navbar-brand" href="/friendly-pages">{{ 'topBar.friendlyPages' | translate }}</a>
</div>
</nav>
<router-outlet />
`

View File

@ -1,40 +1,61 @@
import { Component } from '@angular/core';
import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
import { Component, OnDestroy } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { TranslateService, TranslateModule} from "@ngx-translate/core";
import { Subscription } from 'rxjs';
@Component({
selector: 'app-root',
standalone: true,
imports: [ RouterOutlet, TranslateModule ],
imports: [ RouterOutlet, TranslateModule, ],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
export class AppComponent implements OnDestroy {
private langChangeSub: Subscription;
constructor( public translate: TranslateService ){
this.translate.addLangs(['pl', 'en']);
// Ustaw domyślny język aplikacji
this.translate.setDefaultLang('pl');
// Pobierz język przeglądarki i obetnij kod regionu // np. 'en' z 'en-US'
const browserLang = navigator.language .slice(0, 2);
// Wyświetl w konsoli dla weryfikacji
console.log('Język przeglądarki krótki:', browserLang);
if( browserLang == 'en' || browserLang =='pl' ){
this.translate.setDefaultLang( browserLang );
}else{
this.translate.setDefaultLang('pl');
}
// Ustaw język pobrany z przeglądarki, jeśli jest obsługiwany
this.translate.use(browserLang.match(/en|pl/) ? browserLang : 'pl');
// this.translate.use(browserLang.match(/en|pl/) ? browserLang : 'pl');
this.langChangeSub = this.translate.onLangChange.subscribe((event) => {
console.log('Język ustawiany:', event.lang);
// localStorage.setItem('lang', selectedLang);
//this.loadAboutDescription();
});
}
ngOnDestroy() {
// Unsubscribing from the event when the component is destroyed to avoid memory leaks
if( this.langChangeSub ) {
console.log('unsubscribe');
this.langChangeSub.unsubscribe();
}
}
// app.component.ts
switchLanguage(language: string) {
this.translate.use(language);
}
handleKeyDown(event: KeyboardEvent): void {
if (event.key === 'Enter' || event.key === ' ') {
this.switchLanguage( this.translate.currentLang === 'pl' ? 'en' : 'pl');
event.preventDefault();
}
}
title = 'Strona';
}

View File

@ -2,15 +2,15 @@ import { Routes } from '@angular/router';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { AssetCalculatorComponent } from './asset-calculator/asset-calculator.component';
import { AboutMeComponent } from './about-me/about-me.component';
import { ChatGPTComponent } from './chat-gpt/chat-gpt.component';
import {JobfinderComponent } from './jobfinder/jobfinder.component';
import { JobfinderComponent } from './jobfinder/jobfinder.component';
import { FixedAssetComponent } from './fixed-asset/fixed-asset.component';
import { FriendlyPagesComponent } from './friendly-pages/friendly-pages.component';
export const routes: Routes = [
{
path: "",
title: "Środki trwałe",
title: "Sygnały",
component:AssetCalculatorComponent
},
{
@ -37,6 +37,13 @@ export const routes: Routes = [
path: "fixed-asset",
title:"Środki trwałe",
component: FixedAssetComponent
},
{
path: "friendly-pages",
title:"Zaprzyjaznione strony",
component: FriendlyPagesComponent
}
]
;

View File

@ -0,0 +1,18 @@
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.thumbnail-container {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.thumbnail-description {
margin-top: 10px; /* Odstęp między obrazem a opisem */
}

View File

@ -0,0 +1,12 @@
<a href="{{'friendly-pages.bodypainter-eu-href' | translate }}">
{{'friendly-pages.bodypainter-eu' | translate }}
</a>
<!-- Template Angular -->
<a [href]="url" target="_blank">
<div class="thumbnail-container">
<img [src]="thumbnailUrl" alt="Miniaturka strony" />
<div class="thumbnail-description">
<p>{{ description }}</p>
</div>
</div>
</a>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FriendlyPagesComponent } from './friendly-pages.component';
describe('FriendlyPagesComponent', () => {
let component: FriendlyPagesComponent;
let fixture: ComponentFixture<FriendlyPagesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FriendlyPagesComponent]
})
.compileComponents();
fixture = TestBed.createComponent(FriendlyPagesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,36 @@
import { Component } from '@angular/core';
import {TranslateModule} from "@ngx-translate/core";
@Component({
selector: 'app-friendly-pages',
standalone: true,
imports: [TranslateModule],
template:`
<div class="container">
<div class="row row-cols-1 row-cols-md-3 g-4">
<div class="col">
<a href="{{ 'friendly_pages.bodypainter_eu.href' | translate }}" target="_blank" class="text-decoration-none">
<div class="card h-100">
<img
src="https://bodypainter.eu/zaklik-public-images/main/about-me.jpg"
class="card-img-top"
alt="{{'friendly_pages.bodypainter_eu.alt'| translate }}"
/>
<div class="card-body">
<div class="card-title text-center h2">{{ 'friendly_pages.bodypainter_eu.title' | translate }}</div>
<p class="card-text text-center">
<I>{{ 'friendly_pages.bodypainter_eu.description' | translate }}</I>
</p>
</div>
</div>
</a>
</div>
<!-- Dodaj więcej kolumn z kartami w podobnym stylu -->
</div>
</div>
`,
styleUrl: './friendly-pages.component.css'
})
export class FriendlyPagesComponent {
}

View File

@ -0,0 +1 @@
<p>signal-counter works!</p>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SignalCounterComponent } from './signal-counter.component';
describe('SignalCounterComponent', () => {
let component: SignalCounterComponent;
let fixture: ComponentFixture<SignalCounterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SignalCounterComponent]
})
.compileComponents();
fixture = TestBed.createComponent(SignalCounterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,29 @@
import { Component, computed, signal } from '@angular/core';
@Component({
selector: 'app-signal-counter',
standalone: true,
imports: [],
template:
`
<h1>Current value of the counter {{counter()}}</h1>
<h3>10x counter: {{derivedCounter()}}</h3>
<button (click)="increment()">Increment</button>
`,
styleUrl: './signal-counter.component.css'
})
export class SignalCounterComponent {
counter = signal( 0 );
derivedCounter = computed(() => {
return this.counter() * 10;
})
increment() {
console.log(`Incrementing counter...`+this.counter())
this.counter.set( this.counter() + 1);
console.log(`Now counter...`+this.counter())
this.counter.update(counter => counter + 1);
console.log(`Updating counter to ...`+this.counter())
}
}