diff --git a/.gitignore b/.gitignore index 686d413..0e5c9aa 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,7 @@ nunit-*.xml node_modules/ dist/ dist-ssr/ +API/wwwroot/ .vite/ .npm/ .pnpm-store/ diff --git a/API/API.csproj b/API/API.csproj index 6e13ddb..a3a34b6 100644 --- a/API/API.csproj +++ b/API/API.csproj @@ -6,8 +6,4 @@ enable - - - - diff --git a/API/Controllers/HealthController.cs b/API/Controllers/HealthController.cs new file mode 100644 index 0000000..007bb6d --- /dev/null +++ b/API/Controllers/HealthController.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Mvc; + +namespace API.Controllers; + +[ApiController] +[Route("api/health")] +public class HealthController : ControllerBase +{ + [HttpGet] + public IActionResult Get() + { + return Ok(); + } +} diff --git a/API/Controllers/WeatherForecastController.cs b/API/Controllers/WeatherForecastController.cs deleted file mode 100644 index a6e5178..0000000 --- a/API/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace API.Controllers -{ - [ApiController] - [Route("[controller]")] - public class WeatherForecastController : ControllerBase - { - private static readonly string[] Summaries = - [ - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - ]; - - [HttpGet(Name = "GetWeatherForecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } - } -} diff --git a/API/Program.cs b/API/Program.cs index 666a9c5..c6e5257 100644 --- a/API/Program.cs +++ b/API/Program.cs @@ -1,23 +1,31 @@ var builder = WebApplication.CreateBuilder(args); -// Add services to the container. - builder.Services.AddControllers(); -// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi -builder.Services.AddOpenApi(); var app = builder.Build(); +var webRootPath = app.Environment.WebRootPath ?? Path.Combine(app.Environment.ContentRootPath, "wwwroot"); +var indexFilePath = Path.Combine(webRootPath, "index.html"); -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.MapOpenApi(); -} - -app.UseHttpsRedirection(); - -app.UseAuthorization(); +app.UseDefaultFiles(); +app.UseStaticFiles(); app.MapControllers(); +app.MapFallback(async context => +{ + if (context.Request.Path.StartsWithSegments("/api")) + { + context.Response.StatusCode = StatusCodes.Status404NotFound; + return; + } + + if (!File.Exists(indexFilePath)) + { + context.Response.StatusCode = StatusCodes.Status404NotFound; + return; + } + + context.Response.ContentType = "text/html; charset=utf-8"; + await context.Response.SendFileAsync(indexFilePath); +}); app.Run(); diff --git a/API/WeatherForecast.cs b/API/WeatherForecast.cs deleted file mode 100644 index 10c41a8..0000000 --- a/API/WeatherForecast.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace API -{ - public class WeatherForecast - { - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } - } -} diff --git a/GUI/vite.config.ts b/GUI/vite.config.ts index 4217010..56fc17d 100644 --- a/GUI/vite.config.ts +++ b/GUI/vite.config.ts @@ -10,6 +10,10 @@ export default defineConfig({ vue(), vueDevTools(), ], + build: { + outDir: fileURLToPath(new URL('../API/wwwroot', import.meta.url)), + emptyOutDir: true, + }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) diff --git a/codexInfo.md b/codexInfo.md index f8fbc9c..91d3444 100644 --- a/codexInfo.md +++ b/codexInfo.md @@ -87,6 +87,8 @@ Ich baue alleine neben meiner Ausbildung eine einfache self-hosted Web-App für - Sidebar-Sichtbarkeit unterstützt `Visibility.Route` mit optionalem `visibilityRoute` in `GUI/src/plugins/routesLayout.ts`. - Mobile-Touch-Optimierung ist für alle aktuellen öffentlichen Oberflächen aktiv (Shell, Home, Login, Impressum, 404), inklusive Safe-Area-Unterstützung. - Desktop-Ansicht bleibt unverändert, da alle neuen Anpassungen ausschließlich in mobilen Breakpoints (`<= 960px`, Feinschliff `<= 600px`) umgesetzt sind. +- Backend-API ist auf ein Minimal-Setup reduziert und stellt aktuell den Test-Endpunkt `GET /api/health` bereit. +- Frontend-Build (`npm run build` im `GUI`-Projekt) schreibt direkt nach `API/wwwroot`; das Backend liefert die SPA und statische Assets aus. ## Änderungen durch Codex - Grundlegender UI-Neuaufbau der App-Shell (`GUI/src/Layout.vue`) inklusive Navigation, Footer und Seitenkontext. @@ -102,3 +104,8 @@ Ich baue alleine neben meiner Ausbildung eine einfache self-hosted Web-App für - Mobile-spezifische Detailoptimierungen in `Home.vue`, `Login.vue`, `Impressum.vue` und `404NotFound.vue` ergänzt (Actions, Card-/Form-Spacing, CTA-Stacking), ohne Desktop-Basislayout zu verändern. - `GUI/style.md` um einen verbindlichen Abschnitt „Umsetzungsstandard Responsivität“ ergänzt (Breakpoints, Touch-Zielgrößen, Safe-Area, globale Pattern-Nutzung, QA-Checkliste), damit Folgeaufgaben denselben Stil beibehalten. - Topbar-Kontext in `GUI/src/Layout.vue` für schmalere Breiten beruhigt: auf Mobile wird der Seitenkontext komplett ausgeblendet, auf mittleren Breiten bleibt nur der Seitentitel (ohne Unterzeile), damit das Header-Layout sauber und nicht gequetscht wirkt. +- Backend-Template-Code bereinigt: `WeatherForecastController` und `WeatherForecast` entfernt, OpenAPI-Templatepaket aus `API/API.csproj` entfernt. +- Neuen Test-Controller `API/Controllers/HealthController.cs` angelegt (`GET /api/health`), der `200 OK` zurückgibt. +- `GUI/vite.config.ts` Build-Ausgabe auf `API/wwwroot` umgestellt (`outDir`) und Bereinigung des Zielordners beim Build aktiviert (`emptyOutDir: true`). +- `API/Program.cs` erweitert, damit statische Dateien aus `wwwroot` inkl. SPA-Fallback (`index.html`) ausgeliefert werden. +- SPA-Fallback im Backend aufgeteilt: Frontend-Routen liefern `index.html`, unbekannte `/api/*`-Routen bleiben korrekt `404` statt auf die SPA zu fallen.