diff --git a/frontend/angular.json b/frontend/angular.json index de6be2a..bb140e7 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -29,9 +29,7 @@ "input": "public" } ], - "styles": [ - "src/styles.scss" - ] + "styles": ["src/styles.scss"] }, "configurations": { "production": { @@ -47,7 +45,8 @@ "maximumError": "8kB" } ], - "outputHashing": "all" + "outputHashing": "all", + "serviceWorker": "ngsw-config.json" }, "development": { "optimization": false, diff --git a/frontend/ngsw-config.json b/frontend/ngsw-config.json new file mode 100644 index 0000000..2160127 --- /dev/null +++ b/frontend/ngsw-config.json @@ -0,0 +1,28 @@ +{ + "$schema": "./node_modules/@angular/service-worker/config/schema.json", + "index": "/index.html", + "assetGroups": [ + { + "name": "app", + "installMode": "prefetch", + "resources": { + "files": [ + "/favicon.ico", + "/index.csr.html", + "/index.html", + "/manifest.webmanifest", + "/*.css", + "/*.js" + ] + } + }, + { + "name": "assets", + "installMode": "lazy", + "updateMode": "prefetch", + "resources": { + "files": ["/**/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"] + } + } + ] +} diff --git a/frontend/package.json b/frontend/package.json index 05bfcd5..5344ef4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,7 @@ "@angular/forms": "^21.2.0", "@angular/platform-browser": "^21.2.0", "@angular/router": "^21.2.0", + "@angular/service-worker": "^21.2.0", "rxjs": "~7.8.0", "tslib": "^2.3.0" }, @@ -28,4 +29,4 @@ "typescript": "~5.9.2", "vitest": "^4.0.8" } -} \ No newline at end of file +} diff --git a/frontend/public/icons/icon-128x128.png b/frontend/public/icons/icon-128x128.png new file mode 100644 index 0000000..5a9a2cc Binary files /dev/null and b/frontend/public/icons/icon-128x128.png differ diff --git a/frontend/public/icons/icon-144x144.png b/frontend/public/icons/icon-144x144.png new file mode 100644 index 0000000..11702cd Binary files /dev/null and b/frontend/public/icons/icon-144x144.png differ diff --git a/frontend/public/icons/icon-152x152.png b/frontend/public/icons/icon-152x152.png new file mode 100644 index 0000000..ff4e06b Binary files /dev/null and b/frontend/public/icons/icon-152x152.png differ diff --git a/frontend/public/icons/icon-192x192.png b/frontend/public/icons/icon-192x192.png new file mode 100644 index 0000000..afd36a4 Binary files /dev/null and b/frontend/public/icons/icon-192x192.png differ diff --git a/frontend/public/icons/icon-384x384.png b/frontend/public/icons/icon-384x384.png new file mode 100644 index 0000000..613ac79 Binary files /dev/null and b/frontend/public/icons/icon-384x384.png differ diff --git a/frontend/public/icons/icon-512x512.png b/frontend/public/icons/icon-512x512.png new file mode 100644 index 0000000..7574990 Binary files /dev/null and b/frontend/public/icons/icon-512x512.png differ diff --git a/frontend/public/icons/icon-72x72.png b/frontend/public/icons/icon-72x72.png new file mode 100644 index 0000000..033724e Binary files /dev/null and b/frontend/public/icons/icon-72x72.png differ diff --git a/frontend/public/icons/icon-96x96.png b/frontend/public/icons/icon-96x96.png new file mode 100644 index 0000000..3090dc2 Binary files /dev/null and b/frontend/public/icons/icon-96x96.png differ diff --git a/frontend/public/manifest.webmanifest b/frontend/public/manifest.webmanifest new file mode 100644 index 0000000..198d9dd --- /dev/null +++ b/frontend/public/manifest.webmanifest @@ -0,0 +1,57 @@ +{ + "name": "frontend", + "short_name": "frontend", + "display": "standalone", + "scope": "./", + "start_url": "./", + "icons": [ + { + "src": "icons/icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "icons/icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "icons/icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable any" + } + ] +} diff --git a/frontend/src/app/app.config.ts b/frontend/src/app/app.config.ts index cb1270e..655d9ae 100644 --- a/frontend/src/app/app.config.ts +++ b/frontend/src/app/app.config.ts @@ -1,11 +1,16 @@ -import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { ApplicationConfig, provideBrowserGlobalErrorListeners, isDevMode } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; +import { provideServiceWorker } from '@angular/service-worker'; export const appConfig: ApplicationConfig = { providers: [ provideBrowserGlobalErrorListeners(), - provideRouter(routes) - ] + provideRouter(routes), + provideServiceWorker('ngsw-worker.js', { + enabled: !isDevMode(), + registrationStrategy: 'registerWhenStable:30000', + }), + ], }; diff --git a/frontend/src/app/app.html b/frontend/src/app/app.html index a1c4296..003ae49 100644 --- a/frontend/src/app/app.html +++ b/frontend/src/app/app.html @@ -1,344 +1,5 @@ - - - - - - - - - - - -
-
-
- -

Hello, {{ title() }}

-

Congratulations! Your app is running. 🎉

-
- -
-
- @for (item of [ - { title: 'Explore the Docs', link: 'https://angular.dev' }, - { title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' }, - { title: 'Prompt and best practices for AI', link: 'https://angular.dev/ai/develop-with-ai'}, - { title: 'CLI Docs', link: 'https://angular.dev/tools/cli' }, - { title: 'Angular Language Service', link: 'https://angular.dev/tools/language-service' }, - { title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' }, - ]; track item.title) { - - {{ item.title }} - - - - - } -
- -
-
+
+

Travel Planner

+

Reisen planen, gemeinsam entscheiden.

+
- - - - - - - - - - - diff --git a/frontend/src/app/app.spec.ts b/frontend/src/app/app.spec.ts index f13c264..1821efb 100644 --- a/frontend/src/app/app.spec.ts +++ b/frontend/src/app/app.spec.ts @@ -14,10 +14,10 @@ describe('App', () => { expect(app).toBeTruthy(); }); - it('should render title', async () => { + it('renders the Travel Planner shell', async () => { const fixture = TestBed.createComponent(App); await fixture.whenStable(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain('Hello, frontend'); + expect(fixture.nativeElement.textContent).toContain('Travel Planner'); + expect(fixture.nativeElement.textContent).toContain('Reisen planen, gemeinsam entscheiden.'); }); }); diff --git a/frontend/src/app/app.ts b/frontend/src/app/app.ts index d560a9f..372b06c 100644 --- a/frontend/src/app/app.ts +++ b/frontend/src/app/app.ts @@ -1,12 +1,10 @@ -import { Component, signal } from '@angular/core'; +import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', imports: [RouterOutlet], templateUrl: './app.html', - styleUrl: './app.scss' + styleUrl: './app.scss', }) -export class App { - protected readonly title = signal('frontend'); -} +export class App {} diff --git a/frontend/src/index.html b/frontend/src/index.html index 3af61ec..14ad3c7 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -1,13 +1,15 @@ - - - Frontend - - - - - - - + + + Frontend + + + + + + + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac150a3..607bd49 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -116,6 +116,9 @@ importers: '@angular/router': specifier: ^21.2.0 version: 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(rxjs@7.8.2) + '@angular/service-worker': + specifier: ^21.2.0 + version: 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2) rxjs: specifier: ~7.8.0 version: 7.8.2 @@ -125,7 +128,7 @@ importers: devDependencies: '@angular/build': specifier: ^21.2.6 - version: 21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0))) + version: 21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@angular/service-worker@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0))) '@angular/cli': specifier: ^21.2.6 version: 21.2.21(@types/node@24.13.3)(chokidar@5.0.0) @@ -374,6 +377,14 @@ packages: '@angular/platform-browser': 21.2.20 rxjs: ^6.5.3 || ^7.4.0 + '@angular/service-worker@21.2.20': + resolution: {integrity: sha512-4ruMK6QbGfSnmzm7lbF+UueOx0VmedvYL/Zbu76ZfsnzIxjraBUxb5KexhVji0xXvFv3DNzahcLuc57/gGOPZA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@angular/core': 21.2.20 + rxjs: ^6.5.3 || ^7.4.0 + '@asamuzakjp/css-color@5.1.11': resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -5003,7 +5014,7 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular/build@21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)))': + '@angular/build@21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@angular/service-worker@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)))': dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.2102.21(chokidar@5.0.0) @@ -5039,6 +5050,7 @@ snapshots: optionalDependencies: '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2) '@angular/platform-browser': 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)) + '@angular/service-worker': 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2) lmdb: 3.5.1 postcss: 8.5.26 vitest: 4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)) @@ -5139,6 +5151,12 @@ snapshots: rxjs: 7.8.2 tslib: 2.8.1 + '@angular/service-worker@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2)': + dependencies: + '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2) + rxjs: 7.8.2 + tslib: 2.8.1 + '@asamuzakjp/css-color@5.1.11': dependencies: '@asamuzakjp/generational-cache': 1.0.1