diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..4db92b0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,91 @@ +# Claude Code Guidelines + +## Project Overview + +This is the frontend of the Playground project, built with Angular 21 and Angular Material. It includes features like a light/dark theme toggle and multi-language support via ngx-translate. The application is a static Single Page Application (SPA) served by NGINX. + +**Key Technologies:** +* **Frontend Framework:** Angular 21 +* **UI Components & Theming:** Angular Material +* **Internationalization:** ngx-translate +* **Server:** NGINX (for serving the SPA) +* **Containerization:** Docker +* **CI/CD:** GitHub Actions + +## Building and Running + +### Local Development + +1. **Install dependencies:** + ```bash + npm install + ``` +2. **Start development server:** + ```bash + ng serve --open + ``` + The app will run at `http://localhost:4200`. + +### Building for Production + +To build the project for production, which creates the optimized static files: +```bash +ng build +``` + +## Language +- All code must be written in **English** — including variable names, function names, comments, and commit messages. + +## Clean Code +- Write simple, clear, and readable code. +- Avoid deeply nested or chained calls. Break complex expressions into named intermediate variables or separate steps. +- Code should be understandable by junior developers without additional explanation. + +## Braces +- Always use curly braces `{}` for branches and loops — even for single-line bodies. + + ```ts + // ✅ correct + if (isValid) { + doSomething(); + } + + // ❌ avoid + if (isValid) doSomething(); + ``` + +## Functions +- Extract reusable or logically distinct logic into separate, well-named functions. +- A function should do one thing and do it well. +- Prefer short functions that are easy to test and understand. + +## Comments +- Only add comments when they explain the **why** or the **idea** behind the code — not the **what**. +- Do not comment on things that are already obvious from the code itself. + + ```ts + // ✅ useful comment — explains intent + // Retry once to handle transient network errors + const result = await fetchWithRetry(url); + + // ❌ useless comment — just restates the code + // Call fetchWithRetry with url + const result = await fetchWithRetry(url); + ``` + +## Development Conventions + +* **Language:** TypeScript +* **Framework:** Angular +* **Styling:** SCSS (based on `styles.scss` and component-specific `.scss` files). +* **Linting:** ESLint is configured (see `eslint.config.js` and `package.json` scripts). +* **Internationalization:** Uses `ngx-translate` with `en.json` and `de.json` asset files. + +## Project Structure (Key Areas) + +* `src/app/`: Contains the main application logic, components, services, and routing. +* `src/app/pages/`: Specific pages of the application (e.g., about, algorithms, imprint, projects). +* `src/assets/`: Static assets including images, internationalization files (`i18n`), and logos. +* `Dockerfile`: Defines the Docker image for the application. +* `nginx.conf`: NGINX configuration for serving the SPA. +* `.gitea/workflows/`: Contains CI/CD workflows (e.g., `build-Frontend-a.yml`). diff --git a/src/app/shared/components/render-canvas/babylon-canvas.component.ts b/src/app/shared/components/render-canvas/babylon-canvas.component.ts index 8c04da1..f14940c 100644 --- a/src/app/shared/components/render-canvas/babylon-canvas.component.ts +++ b/src/app/shared/components/render-canvas/babylon-canvas.component.ts @@ -1,4 +1,6 @@ import {AfterViewInit, Component, ElementRef, EventEmitter, inject, Input, NgZone, OnDestroy, Output, ViewChild} from '@angular/core'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {TranslateService} from '@ngx-translate/core'; import {ArcRotateCamera, Camera, MeshBuilder, Scene, ShaderLanguage, ShaderMaterial, Vector2, Vector3, WebGPUEngine} from '@babylonjs/core'; export interface RenderConfig { @@ -26,6 +28,8 @@ export interface SceneEventData { }) export class BabylonCanvas implements AfterViewInit, OnDestroy { readonly ngZone = inject(NgZone); + private readonly snackBar = inject(MatSnackBar); + private readonly translate = inject(TranslateService); @ViewChild('renderCanvas', { static: true }) canvasRef!: ElementRef; @@ -72,9 +76,11 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy { engine: this.engine }); this.addRenderLoop(canvas); + }) .catch(() => { - alert("WebGPU could not be started. Please check your browser if it supports WebGPU."); + const message = this.translate.instant('WEBGPU.NOT_SUPPORTED'); + this.snackBar.open(message, 'OK', { duration: 8000, horizontalPosition: "center", verticalPosition: "top" }); this.engine = null!; }); } diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 4ccc18c..c6771f5 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -500,6 +500,9 @@ "DISCLAIMER_4": "Der XPBD-Kompromiss: XPBD umgeht dieses komplexe Matrix-Problem völlig, indem es als lokaler Löser arbeitet. Es kombiniert die unbedingte Stabilität eines impliziten Lösers mit der enormen Geschwindigkeit, Parallelisierbarkeit und dynamischen Anpassungsfähigkeit eines expliziten Systems." } }, + "WEBGPU": { + "NOT_SUPPORTED": "WebGPU konnte nicht gestartet werden. Bitte prüfe, ob dein Browser WebGPU unterstützt." + }, "ALGORITHM": { "TITLE": "Algorithmen", "PATHFINDING": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index aab76fb..b4e4bd0 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -499,6 +499,9 @@ "DISCLAIMER_4": "The XPBD Compromise: XPBD completely bypasses this complex matrix problem by acting as a local solver. It combines the absolute stability of an implicit solver with the enormous speed, parallelizability, and dynamic adaptability of an explicit system." } }, + "WEBGPU": { + "NOT_SUPPORTED": "WebGPU could not be started. Please check if your browser supports WebGPU." + }, "ALGORITHM": { "TITLE": "Algorithms", "PATHFINDING": {