From 86feec930b6a882100384bb4da54dea2972d7ef5 Mon Sep 17 00:00:00 2001 From: OlgunR Date: Mon, 30 Mar 2026 15:16:33 +0200 Subject: [PATCH] Add Clock page with live DB time and TimeApiClient service Introduced a new Clock page that displays and updates the current database server time every second by calling a backend API. Added the TimeApiClient service to handle API requests for the server time. Registered TimeApiClient in Program.cs and updated the navigation menu to include a link to the new Clock page. Includes error handling and custom UI styling for the clock display. --- .../Components/Layout/NavMenu.razor | 6 ++ .../Components/Pages/Clock.razor | 100 ++++++++++++++++++ DbFirst.BlazorWebApp/Program.cs | 5 + .../Services/TimeApiClient.cs | 27 +++++ 4 files changed, 138 insertions(+) create mode 100644 DbFirst.BlazorWebApp/Components/Pages/Clock.razor create mode 100644 DbFirst.BlazorWebApp/Services/TimeApiClient.cs diff --git a/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor b/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor index 68901b3..a4c739c 100644 --- a/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor +++ b/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor @@ -31,6 +31,12 @@ MassData + + diff --git a/DbFirst.BlazorWebApp/Components/Pages/Clock.razor b/DbFirst.BlazorWebApp/Components/Pages/Clock.razor new file mode 100644 index 0000000..fe35b78 --- /dev/null +++ b/DbFirst.BlazorWebApp/Components/Pages/Clock.razor @@ -0,0 +1,100 @@ +@rendermode InteractiveServer +@page "/clock" +@inject TimeApiClient TimeApi +@implements IAsyncDisposable + +Clock + +

DB Server Clock

+ +
+
+ @if (_dbTime.HasValue) + { + @_dbTime.Value.ToString("HH:mm:ss") + @_dbTime.Value.ToString("dd.MM.yyyy") + } + else if (_error != null) + { + --:--:-- + @_error + } + else + { + ... + } +
+
+ + + +@code { + private DateTime? _dbTime; + private string? _error; + private Timer? _timer; + + protected override async Task OnInitializedAsync() + { + await TickAsync(); + _timer = new Timer(async _ => + { + await TickAsync(); + await InvokeAsync(StateHasChanged); + }, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + } + + private async Task TickAsync() + { + try + { + _dbTime = await TimeApi.InsertAndGetLastAsync(); + _error = null; + } + catch (Exception ex) + { + _error = ex.Message; + } + } + + public async ValueTask DisposeAsync() + { + if (_timer != null) + await _timer.DisposeAsync(); + } +} diff --git a/DbFirst.BlazorWebApp/Program.cs b/DbFirst.BlazorWebApp/Program.cs index e06db92..ed58f10 100644 --- a/DbFirst.BlazorWebApp/Program.cs +++ b/DbFirst.BlazorWebApp/Program.cs @@ -31,6 +31,10 @@ if (!string.IsNullOrWhiteSpace(apiBaseUrl)) { client.BaseAddress = new Uri(apiBaseUrl); }); + builder.Services.AddHttpClient(client => + { + client.BaseAddress = new Uri(apiBaseUrl); + }); } else { @@ -38,6 +42,7 @@ else builder.Services.AddHttpClient(); builder.Services.AddHttpClient(); builder.Services.AddHttpClient(); + builder.Services.AddHttpClient(); } var app = builder.Build(); diff --git a/DbFirst.BlazorWebApp/Services/TimeApiClient.cs b/DbFirst.BlazorWebApp/Services/TimeApiClient.cs new file mode 100644 index 0000000..b2f0b74 --- /dev/null +++ b/DbFirst.BlazorWebApp/Services/TimeApiClient.cs @@ -0,0 +1,27 @@ +using System.Net.Http.Json; + +namespace DbFirst.BlazorWebApp.Services; + +public class TimeApiClient +{ + private readonly HttpClient _httpClient; + private const string Endpoint = "api/time"; + + public TimeApiClient(HttpClient httpClient) + { + _httpClient = httpClient; + } + + public async Task InsertAndGetLastAsync() + { + var response = await _httpClient.PostAsync(Endpoint, null); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + return result?.Now; + } + + private sealed class TimeResponse + { + public DateTime? Now { get; set; } + } +}