diff --git a/FilterCair.Client/Layout/AdminLayout.razor b/FilterCair.Client/Layout/AdminLayout.razor new file mode 100644 index 0000000..fa2ffc2 --- /dev/null +++ b/FilterCair.Client/Layout/AdminLayout.razor @@ -0,0 +1,51 @@ +@inherits LayoutComponentBase +@inject NavigationManager Nav + +
+ + + + + +
+ @Body +
+ + +
diff --git a/FilterCair.Client/Layout/MainLayout.razor b/FilterCair.Client/Layout/MainLayout.razor index bc93729..0ad9ff3 100644 --- a/FilterCair.Client/Layout/MainLayout.razor +++ b/FilterCair.Client/Layout/MainLayout.razor @@ -1,6 +1,7 @@ @inherits LayoutComponentBase @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.WebAssembly.Authentication +@inject FilterCair.Client.Services.AppState State
@@ -32,6 +33,11 @@ Filter-Form + @@ -65,6 +71,27 @@
+ + +@code{ + protected override async Task OnInitializedAsync() + { + await State.LoadFromSessionAsync(); + State.OnChange += StateHasChanged; + } + + public void Dispose() + { + State.OnChange -= StateHasChanged; + } +} \ No newline at end of file diff --git a/FilterCair.Client/Pages/Admin/AdminHome.razor b/FilterCair.Client/Pages/Admin/AdminHome.razor new file mode 100644 index 0000000..452b431 --- /dev/null +++ b/FilterCair.Client/Pages/Admin/AdminHome.razor @@ -0,0 +1,34 @@ +@page "/admin" +@layout AdminLayout + +Adminbereich + +
+

+ Willkommen im Adminbereich +

+ +
+
+
+
+ +
Kunden verwalten
+
+
+
+ +
+
+
+ +
Filter verwalten
+
+
+
+
+
+ +@code { + [Inject] NavigationManager Nav { get; set; } = default!; +} diff --git a/FilterCair.Client/Pages/Admin/Customers.razor b/FilterCair.Client/Pages/Admin/Customers.razor new file mode 100644 index 0000000..a9f1ff3 --- /dev/null +++ b/FilterCair.Client/Pages/Admin/Customers.razor @@ -0,0 +1,152 @@ +@page "/admin/customers" +@layout AdminLayout +@using FilterCair.Shared.Models + +Kunden verwalten + +
+
+

+ Kundenverwaltung +

+ +
+ + + @if (customers.Count == 0) + { +
+ Keine Kunden vorhanden. Lege den ersten Kunden an! +
+ } + else + { +
+ + + + + + + + + + + + + @foreach (var c in customers) + { + + + + + + + + + } + +
NameStandortAnsprechpartnerTelefonEmail
@c.Name@c.Standort@c.Ansprechpartner@c.Telefon@c.Email + +
+
+ } + + + @if (showModal) + { + + } +
+ +@code { + private List customers = new(); + private CustomerModel newCustomer = new(); + private bool showModal = false; + + protected override void OnInitialized() + { + // TODO: später über API laden + customers = new() + { + new() { Id = 1, Name = "Freudenberg Weinheim", Standort = "Weinheim", Ansprechpartner = "Marc Wieland", Telefon = "+49 6201 80 1234", Email = "marc.wieland@freudenberg-pm.com" }, + new() { Id = 2, Name = "CleanAir Solutions", Standort = "Mannheim", Ansprechpartner = "Tom Fischer", Telefon = "+49 621 555 123" , Email = "FischersTom@cleanair.de"} + }; + } + + private void ShowCreateModal() + { + newCustomer = new CustomerModel(); + showModal = true; + } + + private void CloseModal() + { + showModal = false; + } + + private void SaveCustomer() + { + newCustomer.Id = customers.Count + 1; + customers.Add(newCustomer); + showModal = false; + } + + private void DeleteCustomer(CustomerModel customer) + { + customers.Remove(customer); + } +} diff --git a/FilterCair.Client/Pages/CustomerList.razor b/FilterCair.Client/Pages/CustomerList.razor new file mode 100644 index 0000000..708efc5 --- /dev/null +++ b/FilterCair.Client/Pages/CustomerList.razor @@ -0,0 +1,84 @@ +@page "/customers" +@using FilterCair.Shared.Models +@inject IJSRuntime JS +@inject NavigationManager Nav +@inject FilterCair.Client.Services.AppState State + +

Kundenübersicht

+ + + +
+

+ Kunden & Fabriken +

+ + +
+ +
+ + +
+ @foreach (var c in FilteredCustomers) + { +
+
+
+
+ @c.Name +
+

+ @c.Standort +

+

+ @c.Ansprechpartner +

+
+
+
+ } +
+ + @if (FilteredCustomers.Count() == 0) + { +
+ + Keine passenden Kunden gefunden. +
+ } +
+ +@code { + private List customers = new(); + private string searchText = ""; + + private IEnumerable FilteredCustomers => + string.IsNullOrWhiteSpace(searchText) + ? customers + : customers.Where(c => + c.Name.Contains(searchText, StringComparison.OrdinalIgnoreCase) || + c.Standort.Contains(searchText, StringComparison.OrdinalIgnoreCase)); + + protected override void OnInitialized() + { + // später aus API laden + customers = new() + { + new() { Id = 1, Name = "Freudenberg Weinheim", Standort = "Weinheim", Ansprechpartner = "Marc Wieland", Telefon = "+49 6201 80 1234" }, + new() { Id = 2, Name = "FilterTech GmbH", Standort = "Kaiserslautern", Ansprechpartner = "Lena Becker", Telefon = "+49 631 987654" }, + new() { Id = 3, Name = "CleanAir Solutions", Standort = "Mannheim", Ansprechpartner = "Tom Fischer", Telefon = "+49 621 555 123" } + }; + } + + private async Task SelectCustomer(CustomerModel c) + { + await State.SetCustomerAsync(c.Name); + Nav.NavigateTo("/qrscanner"); + } + +} \ No newline at end of file diff --git a/FilterCair.Client/Pages/Home.razor b/FilterCair.Client/Pages/Home.razor index 17c8278..adce32e 100644 --- a/FilterCair.Client/Pages/Home.razor +++ b/FilterCair.Client/Pages/Home.razor @@ -48,6 +48,30 @@ + +
+
+
+ +
Meine Aufgaben
+

Übersicht aller offenen Wartungen und Filterprüfungen.

+
+
+
+ +
+
+
+ +
Kundenübersicht
+

Wähle den Kundenstandort aus, um Filterdaten zu erfassen.

+
+
+
+ + + + diff --git a/FilterCair.Client/Pages/Tasks.razor b/FilterCair.Client/Pages/Tasks.razor new file mode 100644 index 0000000..76047c5 --- /dev/null +++ b/FilterCair.Client/Pages/Tasks.razor @@ -0,0 +1,81 @@ +@page "/tasks" +@using FilterCair.Shared.Models + + +
+

+ Meine Aufgaben +

+ +
+ @if (tasks.Count == 0) + { +
+ + Keine Aufgaben vorhanden. +
+ } + else + { + @foreach (var t in tasks) + { +
+
+
+
@t.Title
+

@t.Beschreibung

+ + @t.Status + @t.Prio + + @if (t.FaelligBis.HasValue) + { +
+ + Fällig: @t.FaelligBis.Value.ToShortDateString() +
+ } + +
+ +
+
+
+
+ } + } +
+
+ +@code { + private List tasks = new(); + + protected override void OnInitialized() + { + tasks = new() + { + new() { Id = 1, Title = "Filter prüfen Halle A", Beschreibung = "Sichtprüfung durchführen", ZugewiesenAn = "Marc Wieland", Status = "Offen", Prio = "Normal", FaelligBis = DateTime.Today.AddDays(1) }, + new() { Id = 2, Title = "Wartung Filter B2", Beschreibung = "Druck prüfen & Dokumentation", ZugewiesenAn = "Marc Wieland", Status = "In Arbeit", Prio = "Hoch" }, + new() { Id = 3, Title = "Filter austauschen", Beschreibung = "Alten Filter entfernen & neuen einsetzen", ZugewiesenAn = "Marc Wieland", Status = "Erledigt", Prio = "Normal", FaelligBis = DateTime.Today.AddDays(-2) } + }; + } + + private void ToggleStatus(TaskModel t) + { + t.Status = t.Status switch + { + "Offen" => "In Arbeit", + "In Arbeit" => "Erledigt", + _ => "Offen" + }; + } + + private string GetStatusColor(string status) => status switch + { + "Erledigt" => "success", + "In Arbeit" => "warning", + _ => "secondary" + }; +} \ No newline at end of file diff --git a/FilterCair.Client/Program.cs b/FilterCair.Client/Program.cs index f1afa9f..8916b18 100644 --- a/FilterCair.Client/Program.cs +++ b/FilterCair.Client/Program.cs @@ -2,6 +2,7 @@ using FilterCair.Client; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; +using FilterCair.Client.Services; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add("#app"); @@ -21,4 +22,7 @@ builder.Services.AddMsalAuthentication(options => "api://54b010c7-4a9a-4f2d-bea3-9faba3f12495/API.Access"); }); +//Services +builder.Services.AddScoped(); + await builder.Build().RunAsync(); diff --git a/FilterCair.Client/Services/AppState.cs b/FilterCair.Client/Services/AppState.cs new file mode 100644 index 0000000..b4b44a5 --- /dev/null +++ b/FilterCair.Client/Services/AppState.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading.Tasks; +using Microsoft.JSInterop; + +namespace FilterCair.Client.Services +{ + public class AppState + { + private readonly IJSRuntime _js; + public AppState(IJSRuntime js) + { + _js = js; + } + + public string? SelectedCustomer { get; private set; } + + public bool IsOnline { get; private set; } = true; + public event Action? OnChange; + + private void NotifyStateChanged() => OnChange?.Invoke(); + + public async Task SetCustomerAsync(string customer) + { + SelectedCustomer = customer; + await _js.InvokeVoidAsync("sessionStorage.setItem", "selectedCustomer", customer); + NotifyStateChanged(); + } + + public async Task LoadFromSessionAsync() + { + SelectedCustomer = await _js.InvokeAsync("sessionStorage.getItem", "selectedCustomer"); + NotifyStateChanged(); + } + + public void SetOnlineStatus(bool isOnline) + { + IsOnline = isOnline; + NotifyStateChanged(); + } + + public async Task ClearAsync() + { + SelectedCustomer = null; + await _js.InvokeVoidAsync("sessionStorage.removeItem", "selectedCustomer"); + NotifyStateChanged(); + } + + + + } +} diff --git a/FilterCair.Client/wwwroot/css/app.css b/FilterCair.Client/wwwroot/css/app.css index 68b6258..b2b4a0a 100644 --- a/FilterCair.Client/wwwroot/css/app.css +++ b/FilterCair.Client/wwwroot/css/app.css @@ -220,6 +220,57 @@ code { transition: transform 0.2s ease; } - .image-preview img:hover { - transform: scale(1.05); +.image-preview img:hover { + transform: scale(1.05); +} + + +.task-card { + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.task-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 16px rgba(0, 91, 153, 0.15); +} + + +.customer-card { + border-radius: 1rem; + transition: all 0.25s ease; + cursor: pointer; +} + +.customer-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 18px rgba(0, 91, 153, 0.15); +} + +.customer-card:active { + transform: translateY(1px); +} + + +.admin-tile { + border-radius: 1rem; + transition: all 0.2s ease; + cursor: pointer; +} + +.admin-tile:hover { + transform: translateY(-4px); + box-shadow: 0 8px 20px rgba(0, 91, 153, 0.15); +} + + +.modal-dialog { + max-width: 500px; + margin: 1rem auto; +} + +@media (max-width: 576px) { + .modal-dialog { + max-width: 90%; + margin: 0.5rem auto; } +} diff --git a/FilterCair.Shared/Models/CustomerModel.cs b/FilterCair.Shared/Models/CustomerModel.cs new file mode 100644 index 0000000..4664b8d --- /dev/null +++ b/FilterCair.Shared/Models/CustomerModel.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FilterCair.Shared.Models +{ + public class CustomerModel + { + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public string Standort { get; set; } = string.Empty; + public string Ansprechpartner { get; set; } = string.Empty; + public string Email { get; set; } = string.Empty; + public string Telefon { get; set; } = string.Empty; + } +} diff --git a/FilterCair.Shared/Models/TaskModel.cs b/FilterCair.Shared/Models/TaskModel.cs new file mode 100644 index 0000000..fe86c51 --- /dev/null +++ b/FilterCair.Shared/Models/TaskModel.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FilterCair.Shared.Models +{ + public class TaskModel + { + public int Id { get; set; } + public string Title { get; set; } = string.Empty; + public string Beschreibung { get; set; } = string.Empty; + public string ZugewiesenAn { get; set; } = string.Empty; + public string Status { get; set; } = "Offen"; + public string Prio { get; set; } = "Mittel"; + public DateTime? FaelligBis { get; set; } + + + } +}