Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Backend/VanDaemon.Core/Entities/SystemConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class SystemConfiguration
public string VanModel { get; set; } = "Mercedes Sprinter LWB";
public string VanDiagramPath { get; set; } = "/diagrams/sprinter-lwb.svg";
public ToolbarPosition ToolbarPosition { get; set; } = ToolbarPosition.Left;
public string Theme { get; set; } = "Light";
public AlertSettings AlertSettings { get; set; } = new();
public Dictionary<string, object> PluginConfigurations { get; set; } = new();
public DateTime LastUpdated { get; set; }
Expand Down
70 changes: 54 additions & 16 deletions src/Frontend/VanDaemon.Web/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,35 @@
<PageTitle>Dashboard - VanDaemon</PageTitle>

<style>
.dashboard-page {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
position: relative;
background: var(--mud-palette-background);
}

.edit-toggle {
position: absolute;
top: 16px;
right: 16px;
z-index: 20;
}

.diagram-area {
flex: 1;
position: relative;
width: 100%;
overflow: hidden;
}

.van-diagram-container {
position: relative;
width: 100%;
height: 100%;
}

.van-diagram-background {
position: absolute;
top: 0;
Expand All @@ -31,32 +60,42 @@
.overlay-content {
pointer-events: auto;
}

.status-footer {
padding: 12px 16px;
border-top: 1px solid var(--mud-palette-divider);
background: var(--mud-palette-surface);
display: flex;
align-items: center;
justify-content: space-between;
min-height: 56px;
}
</style>

<MudPaper Elevation="2" Class="pa-4" Style="min-height: calc(100vh - 150px); display: flex; flex-direction: column; position: relative;">
<div style="position: absolute; top: 10px; right: 10px; z-index: 20;">
<div class="dashboard-page">
<div class="edit-toggle">
<MudToggleIconButton @bind-Toggled="@isEditMode"
Icon="@Icons.Material.Filled.Lock"
ToggledIcon="@Icons.Material.Filled.Edit"
Title="Toggle Edit Mode"
ToggledTitle="Exit Edit Mode" />
ToggledTitle="Exit Edit Mode"
Size="Size.Large"
Color="Color.Primary" />
</div>

<!-- Van Diagram Container -->
<div style="flex: 1; position: relative; width: 100%; min-height: 500px;"
<div class="diagram-area"
@onmousemove="OnMouseMove"
@onmouseup="OnMouseUp">
<div class="van-diagram-container"
@ref="diagramContainer"
style="position: relative; width: 100%; height: 100%;">
<div class="van-diagram-container" @ref="diagramContainer">
@if (!string.IsNullOrEmpty(backgroundImage))
{
<img src="@backgroundImage" alt="Van Diagram" class="van-diagram-background" />
}
else
{
<div style="text-align: center; padding: 50px; background: #f5f5f5; border-radius: 8px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1;">
<MudIcon Icon="@Icons.Material.Filled.DirectionsCar" Size="Size.Large" Style="font-size: 120px; color: #ccc;" />
<div style="text-align: center; padding: 50px; background: var(--mud-palette-background-grey); border-radius: 8px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1;">
<MudIcon Icon="@Icons.Material.Filled.DirectionsCar" Size="Size.Large" Style="font-size: 120px; opacity: 0.3;" />
<MudText Typo="Typo.h6" Class="mt-4">No background image configured</MudText>
<MudText Typo="Typo.body2">Go to Settings to upload a van diagram</MudText>
</div>
Expand All @@ -74,7 +113,7 @@
@if (overlay.Type == OverlayType.Tank)
{
<MudTooltip Text="@overlay.Name">
<div class="overlay-content" style="text-align: center; background: rgba(255, 255, 255, 0.9); padding: 8px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<div class="overlay-content" style="text-align: center; background: var(--mud-palette-surface); padding: 8px; border-radius: 8px; box-shadow: var(--mud-elevation-4);">
<MudIcon Icon="@overlay.Icon" Size="Size.Large" Color="@GetOverlayColor(overlay)" />
<MudText Typo="Typo.caption" Style="display: block; font-weight: bold;">@overlay.Value.ToString("F1")%</MudText>
</div>
Expand All @@ -83,7 +122,7 @@
else if (overlay.Type == OverlayType.Control)
{
<MudTooltip Text="@overlay.Name">
<div style="background: rgba(255, 255, 255, 0.9); padding: 4px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<div style="background: var(--mud-palette-surface); padding: 4px; border-radius: 8px; box-shadow: var(--mud-elevation-4);">
<MudSwitch Value="@overlay.IsOn"
Color="Color.Primary"
Disabled="@isEditMode"
Expand All @@ -97,17 +136,16 @@
</div>

<!-- Connection Status Footer -->
<MudDivider Class="my-3" />
<div style="display: flex; align-items: center; justify-content: space-between;">
<div class="status-footer">
<div>
<MudChip Size="Size.Small" Color="@(Telemetry.IsConnected ? Color.Success : Color.Warning)"
<MudChip Size="Size.Medium" Color="@(Telemetry.IsConnected ? Color.Success : Color.Warning)"
Icon="@(Telemetry.IsConnected ? Icons.Material.Filled.CheckCircle : Icons.Material.Filled.CloudOff)">
@(Telemetry.IsConnected ? "Connected" : "Connecting...")
</MudChip>
</div>
<MudText Typo="Typo.caption">Last update: @lastUpdateTime</MudText>
<MudText Typo="Typo.body2">Last update: @lastUpdateTime</MudText>
</div>
</MudPaper>
</div>

@code {
private List<TankDto>? tanks;
Expand Down Expand Up @@ -172,7 +210,7 @@
Snackbar.Add($"{name} turned {(Convert.ToBoolean(state) ? "ON" : "OFF")}", Severity.Info);
}

private async Task LoadSettings()

Check warning on line 213 in src/Frontend/VanDaemon.Web/Pages/Index.razor

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 213 in src/Frontend/VanDaemon.Web/Pages/Index.razor

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
try
{
Expand Down
10 changes: 10 additions & 0 deletions src/Frontend/VanDaemon.Web/Pages/Settings.razor
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ else
<MudSelectItem Value="@("Bottom")">Bottom Bar (Tablet/Desktop)</MudSelectItem>
</MudSelect>

<MudSelect @bind-Value="configuration.Theme"
Label="Theme"
Variant="Variant.Outlined"
Class="mb-3"
HelperText="Choose between light and dark mode">
<MudSelectItem Value="@("Light")">Light Mode</MudSelectItem>
<MudSelectItem Value="@("Dark")">Dark Mode</MudSelectItem>
</MudSelect>

<MudText Typo="Typo.subtitle2" Class="mt-4 mb-2">Upload Custom Van Diagram</MudText>
<MudFileUpload T="IBrowserFile"
FilesChanged="OnFileSelected"
Expand Down Expand Up @@ -296,6 +305,7 @@ else
public string VanModel { get; set; } = string.Empty;
public string VanDiagramPath { get; set; } = string.Empty;
public string ToolbarPosition { get; set; } = "Left";
public string Theme { get; set; } = "Light";
public AlertSettingsDto AlertSettings { get; set; } = new();
public DateTime LastUpdated { get; set; }
}
Expand Down
77 changes: 55 additions & 22 deletions src/Frontend/VanDaemon.Web/Shared/MainLayout.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@inherits LayoutComponentBase
@inject HttpClient Http
@inject IJSRuntime JSRuntime
@implements IAsyncDisposable

<style>
Expand Down Expand Up @@ -34,54 +35,58 @@
box-shadow: var(--mud-elevation-2);
display: flex;
flex-direction: column;
justify-content: space-evenly;
}

.toolbar-left .nav-area,
.toolbar-right .nav-area {
width: 280px;
padding: 16px;
width: 120px;
padding: 24px 8px;
}

.toolbar-bottom .nav-area {
width: 100%;
flex-direction: row;
justify-content: space-around;
padding: 12px 16px;
padding: 16px;
height: auto;
}

.main-area {
grid-area: main;
overflow: auto;
padding: 16px;
padding: 0;
height: 100%;
}

.nav-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
padding: 16px;
justify-content: center;
gap: 8px;
padding: 20px 12px;
margin: 4px 0;
border-radius: 8px;
border-radius: 12px;
cursor: pointer;
transition: background-color 0.2s;
transition: background-color 0.2s, transform 0.1s;
text-decoration: none;
color: inherit;
min-height: 56px;
min-height: 90px;
}

.toolbar-bottom .nav-item {
flex-direction: column;
padding: 12px 8px;
margin: 0;
gap: 4px;
min-width: 80px;
text-align: center;
min-height: 72px;
padding: 16px 12px;
margin: 0 4px;
gap: 8px;
min-width: 90px;
min-height: 80px;
}

.nav-item:hover {
background-color: var(--mud-palette-action-default-hover);
transform: translateY(-2px);
}

.nav-item.active {
Expand All @@ -90,14 +95,22 @@
}

.nav-item-icon {
font-size: 28px;
width: 28px;
height: 28px;
font-size: 40px !important;
width: 40px;
height: 40px;
}

.nav-item-text {
font-size: 16px;
font-size: 13px;
font-weight: 500;
text-align: center;
line-height: 1.2;
}

.toolbar-bottom .nav-item-icon {
font-size: 36px !important;
width: 36px;
height: 36px;
}

.toolbar-bottom .nav-item-text {
Expand Down Expand Up @@ -240,17 +253,18 @@ else
private bool isLoading = true;
private string toolbarPosition = "toolbar-left";
private string currentPath = "/";
private string currentTheme = "Light";

protected override async Task OnInitializedAsync()
{
currentPath = new Uri(NavigationManager.Uri).AbsolutePath;
NavigationManager.LocationChanged += OnLocationChanged;

await LoadToolbarPosition();
await LoadSettings();
isLoading = false;
}

private async Task LoadToolbarPosition()
private async Task LoadSettings()
{
try
{
Expand All @@ -264,12 +278,30 @@ else
"Bottom" => "toolbar-bottom",
_ => "toolbar-left"
};

currentTheme = config.Theme ?? "Light";
await ApplyTheme(currentTheme);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error loading toolbar position: {ex.Message}");
Console.WriteLine($"Error loading settings: {ex.Message}");
toolbarPosition = "toolbar-left";
currentTheme = "Light";
}
}

private async Task ApplyTheme(string theme)
{
try
{
var isDark = theme == "Dark";
await JSRuntime.InvokeVoidAsync("eval",
$"document.documentElement.setAttribute('data-theme', '{(isDark ? "dark" : "light")}')");
}
catch (Exception ex)
{
Console.WriteLine($"Error applying theme: {ex.Message}");
}
}

Expand Down Expand Up @@ -305,6 +337,7 @@ else
public string VanModel { get; set; } = string.Empty;
public string VanDiagramPath { get; set; } = string.Empty;
public string ToolbarPosition { get; set; } = "Left";
public string Theme { get; set; } = "Light";
public AlertSettingsDto AlertSettings { get; set; } = new();
public DateTime LastUpdated { get; set; }
}
Expand Down
Loading