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.
This commit is contained in:
@@ -31,6 +31,12 @@
|
||||
<span class="bi bi-table-nav-menu" aria-hidden="true"></span> MassData
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="clock">
|
||||
<span class="bi bi-clock-nav-menu" aria-hidden="true"></span> Clock
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
100
DbFirst.BlazorWebApp/Components/Pages/Clock.razor
Normal file
100
DbFirst.BlazorWebApp/Components/Pages/Clock.razor
Normal file
@@ -0,0 +1,100 @@
|
||||
@rendermode InteractiveServer
|
||||
@page "/clock"
|
||||
@inject TimeApiClient TimeApi
|
||||
@implements IAsyncDisposable
|
||||
|
||||
<PageTitle>Clock</PageTitle>
|
||||
|
||||
<h3>DB Server Clock</h3>
|
||||
|
||||
<div class="clock-wrapper">
|
||||
<div class="clock-display @(_error != null ? "clock-error" : "")">
|
||||
@if (_dbTime.HasValue)
|
||||
{
|
||||
<span class="clock-time">@_dbTime.Value.ToString("HH:mm:ss")</span>
|
||||
<span class="clock-date">@_dbTime.Value.ToString("dd.MM.yyyy")</span>
|
||||
}
|
||||
else if (_error != null)
|
||||
{
|
||||
<span class="clock-time">--:--:--</span>
|
||||
<span class="clock-date text-danger">@_error</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="clock-time">...</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.clock-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
.clock-display {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: var(--bs-body-bg, #1e1e2e);
|
||||
border: 2px solid var(--bs-border-color, #444);
|
||||
border-radius: 1rem;
|
||||
padding: 2rem 4rem;
|
||||
box-shadow: 0 4px 24px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.clock-time {
|
||||
font-size: 5rem;
|
||||
font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--bs-primary, #0d6efd);
|
||||
}
|
||||
|
||||
.clock-date {
|
||||
font-size: 1.4rem;
|
||||
margin-top: 0.5rem;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.clock-error .clock-time {
|
||||
color: var(--bs-danger, #dc3545);
|
||||
}
|
||||
</style>
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user