Neuste Version
This commit is contained in:
parent
c4ad142e4f
commit
0bf240ccda
@ -40,7 +40,7 @@
|
||||
<th>Ansprechpartner</th>
|
||||
<th>Telefon</th>
|
||||
<th>Email</th>
|
||||
<th style="width:120px;"></th>
|
||||
<th style="width:160px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -53,6 +53,10 @@
|
||||
<td>@c.Telefon</td>
|
||||
<td>@c.Email</td>
|
||||
<td class="text-end">
|
||||
<button class="btn btn-outline-primary btn-sm rounded-pill me-1"
|
||||
@onclick="() => ShowEditModal(c)">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-danger btn-sm rounded-pill"
|
||||
@onclick="() => DeleteCustomer(c)">
|
||||
<i class="bi bi-trash"></i>
|
||||
@ -72,7 +76,10 @@
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow-lg rounded-4">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title"><i class="bi bi-person-plus me-2"></i> Neuer Kunde</h5>
|
||||
<h5 class="modal-title">
|
||||
<i class="bi @(isEditMode ? "bi-pencil" : "bi-person-plus") me-2"></i>
|
||||
@(isEditMode ? "Kunde bearbeiten" : "Neuer Kunde")
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" @onclick="CloseModal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@ -103,7 +110,9 @@
|
||||
|
||||
<div class="text-end">
|
||||
<button type="button" class="btn btn-outline-secondary me-2 rounded-pill" @onclick="CloseModal">Abbrechen</button>
|
||||
<button type="submit" class="btn btn-success rounded-pill">Speichern</button>
|
||||
<button type="submit" class="btn btn-success rounded-pill">
|
||||
@(isEditMode ? "Aktualisieren" : "Speichern")
|
||||
</button>
|
||||
</div>
|
||||
</EditForm>
|
||||
</div>
|
||||
@ -117,6 +126,7 @@
|
||||
private List<CustomerModel> customers = new();
|
||||
private CustomerModel newCustomer = new();
|
||||
private bool showModal = false;
|
||||
private bool isEditMode = false;
|
||||
private bool isLoading = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
@ -134,6 +144,22 @@
|
||||
private void ShowCreateModal()
|
||||
{
|
||||
newCustomer = new CustomerModel();
|
||||
isEditMode = false;
|
||||
showModal = true;
|
||||
}
|
||||
|
||||
private void ShowEditModal(CustomerModel c)
|
||||
{
|
||||
newCustomer = new CustomerModel
|
||||
{
|
||||
Id = c.Id,
|
||||
Name = c.Name,
|
||||
Standort = c.Standort,
|
||||
Ansprechpartner = c.Ansprechpartner,
|
||||
Telefon = c.Telefon,
|
||||
Email = c.Email
|
||||
};
|
||||
isEditMode = true;
|
||||
showModal = true;
|
||||
}
|
||||
|
||||
@ -144,16 +170,22 @@
|
||||
|
||||
private async Task SaveCustomer()
|
||||
{
|
||||
var success = await CustomerService.AddCustomerAsync(newCustomer);
|
||||
bool success;
|
||||
|
||||
if (isEditMode)
|
||||
success = await CustomerService.UpdateCustomerAsync(newCustomer);
|
||||
else
|
||||
success = await CustomerService.AddCustomerAsync(newCustomer);
|
||||
|
||||
if (success)
|
||||
{
|
||||
await LoadCustomers();
|
||||
await JS.InvokeVoidAsync("alert", "✅ Kunde erfolgreich angelegt!");
|
||||
CloseModal();
|
||||
await JS.InvokeVoidAsync("showToast", "✅ Erfolgreich gespeichert!");
|
||||
}
|
||||
else
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "❌ Fehler beim Speichern.");
|
||||
await JS.InvokeVoidAsync("showToast", "❌ Fehler beim Speichern.", "error");
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,11 +198,11 @@
|
||||
if (success)
|
||||
{
|
||||
customers.Remove(customer);
|
||||
await JS.InvokeVoidAsync("alert", "🗑️ Kunde gelöscht.");
|
||||
await JS.InvokeVoidAsync("showToast", "🗑️ Kunde gelöscht");
|
||||
}
|
||||
else
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "❌ Fehler beim Löschen.");
|
||||
await JS.InvokeVoidAsync("showToast", "❌ Fehler beim Löschen.", "error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,9 +76,12 @@
|
||||
customers = await CustomerService.GetCustomersAsync();
|
||||
}
|
||||
|
||||
private async Task SelectCustomer(CustomerModel c)
|
||||
{
|
||||
await State.SetCustomerAsync(c.Name);
|
||||
Nav.NavigateTo("/qrscanner");
|
||||
}
|
||||
private async Task SelectCustomer(CustomerModel c)
|
||||
{
|
||||
|
||||
await State.SetCustomerAsync(c.Name);
|
||||
|
||||
Nav.NavigateTo($"/stations/{c.Id}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
@page "/filterform"
|
||||
@inject IJSRuntime JS
|
||||
@inject NavigationManager NavManager
|
||||
@using FilterCair.Shared.Models
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@inject FilterCair.Client.Services.API.FilterService FilterService
|
||||
|
||||
<PageTitle>Filterdaten erfassen</PageTitle>
|
||||
|
||||
@ -18,20 +20,20 @@
|
||||
<ValidationSummary />
|
||||
|
||||
<div class="row g-3">
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Filter-ID</label>
|
||||
<InputText class="form-control form-control-lg" @bind-Value="filter.FilterId" placeholder="z. B. FC-A-234" />
|
||||
<label class="form-label fw-semibold">Bezeichnung</label>
|
||||
<InputText class="form-control form-control-lg" @bind-Value="filter.Bezeichnung" placeholder="z. B. Filter Nordhalle" />
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Halle</label>
|
||||
<InputSelect class="form-select form-select-lg" @bind-Value="filter.Halle">
|
||||
<option value="">– bitte wählen –</option>
|
||||
@foreach (var h in halls)
|
||||
{
|
||||
<option value="@h">@h</option>
|
||||
}
|
||||
</InputSelect>
|
||||
<label class="form-label fw-semibold">Typ</label>
|
||||
<InputText class="form-control form-control-lg" @bind-Value="filter.Typ" placeholder="z. B. Aktivkohle" />
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Seriennummer</label>
|
||||
<InputText class="form-control form-control-lg" @bind-Value="filter.Seriennummer" placeholder="z. B. SN-2024-0012" />
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
@ -45,34 +47,20 @@
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Luftdruck (Pa)</label>
|
||||
<InputNumber class="form-control form-control-lg" @bind-Value="filter.Luftdruck" />
|
||||
<label class="form-label fw-semibold">Einbaudatum</label>
|
||||
<InputDate class="form-control form-control-lg" @bind-Value="filter.Einbaudatum" />
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label fw-semibold">Bemerkung</label>
|
||||
<InputTextArea class="form-control form-control-lg" rows="3" @bind-Value="filter.Bemerkung" />
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Letzte Wartung</label>
|
||||
<InputDate class="form-control form-control-lg" @bind-Value="filter.LetzteWartung" />
|
||||
</div>
|
||||
|
||||
<!-- 📸 Fotos hinzufügen -->
|
||||
<div class="col-12">
|
||||
<label class="form-label fw-semibold">Fotos anhängen</label>
|
||||
<InputFile OnChange="OnFilesSelected" multiple class="form-control" />
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">QR-Code</label>
|
||||
<InputText class="form-control form-control-lg" @bind-Value="filter.QRCode" placeholder="z. B. FC-Q12345" />
|
||||
</div>
|
||||
|
||||
@if (imagePreviews.Count > 0)
|
||||
{
|
||||
<div class="col-12 mt-3">
|
||||
<div class="d-flex flex-wrap gap-3 justify-content-center">
|
||||
@foreach (var img in imagePreviews)
|
||||
{
|
||||
<div class="image-preview border rounded shadow-sm">
|
||||
<img src="@img" alt="Foto" class="img-thumbnail" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="d-grid mt-4">
|
||||
@ -100,48 +88,72 @@
|
||||
|
||||
@code {
|
||||
private FilterModel filter = new();
|
||||
private List<string> halls = new() { "Halle A", "Halle B", "Halle C" };
|
||||
private bool showToast;
|
||||
private List<string> imagePreviews = new();
|
||||
|
||||
private async Task OnFilesSelected(InputFileChangeEventArgs e)
|
||||
{
|
||||
imagePreviews.Clear();
|
||||
|
||||
foreach (var file in e.GetMultipleFiles(3)) // max. 3 Bilder
|
||||
{
|
||||
using var stream = file.OpenReadStream(maxAllowedSize: 5_000_000); // 5 MB max
|
||||
using var ms = new MemoryStream();
|
||||
await stream.CopyToAsync(ms);
|
||||
var base64 = Convert.ToBase64String(ms.ToArray());
|
||||
imagePreviews.Add($"data:{file.ContentType};base64,{base64}");
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task SaveForm()
|
||||
{
|
||||
Console.WriteLine($"Gespeichert: {System.Text.Json.JsonSerializer.Serialize(filter)}");
|
||||
await JS.InvokeVoidAsync("console.log", "Filter gespeichert:", filter);
|
||||
bool success;
|
||||
|
||||
showToast = true;
|
||||
StateHasChanged();
|
||||
if (filter.Id > 0)
|
||||
{
|
||||
// Update vorhandenen Filter
|
||||
success = await FilterService.UpdateFilterAsync(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Neuer Filter
|
||||
success = await FilterService.AddFilterAsync(filter);
|
||||
}
|
||||
|
||||
await Task.Delay(3000);
|
||||
showToast = false;
|
||||
StateHasChanged();
|
||||
if (success)
|
||||
{
|
||||
showToast = true;
|
||||
StateHasChanged();
|
||||
|
||||
await Task.Delay(3000);
|
||||
showToast = false;
|
||||
StateHasChanged();
|
||||
|
||||
await JS.InvokeVoidAsync("showToast", "✅ Filter erfolgreich gespeichert!");
|
||||
}
|
||||
else
|
||||
{
|
||||
await JS.InvokeVoidAsync("showToast", "❌ Fehler beim Speichern.", "error");
|
||||
}
|
||||
}
|
||||
|
||||
[Inject] NavigationManager? NavManager { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
var qrParam = NavManager?.ToAbsoluteUri(NavManager.Uri).Query;
|
||||
if (!string.IsNullOrEmpty(qrParam))
|
||||
var uri = NavManager.ToAbsoluteUri(NavManager.Uri);
|
||||
var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
|
||||
var stationIdStr = query.Get("stationId");
|
||||
if (int.TryParse(stationIdStr, out int stationId))
|
||||
{
|
||||
var parts = System.Web.HttpUtility.ParseQueryString(qrParam);
|
||||
filter.FilterId = parts.Get("id");
|
||||
filter.StationId = stationId;
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var uri = NavManager.ToAbsoluteUri(NavManager.Uri);
|
||||
var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
|
||||
|
||||
// StationId setzen
|
||||
if (int.TryParse(query.Get("stationId"), out int stationId))
|
||||
{
|
||||
filter.StationId = stationId;
|
||||
}
|
||||
|
||||
// Falls FilterId vorhanden → bestehenden Filter laden
|
||||
if (int.TryParse(query.Get("filterId"), out int filterId))
|
||||
{
|
||||
var existing = await FilterService.GetFilterByIdAsync(filterId);
|
||||
if (existing != null)
|
||||
filter = existing;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
87
FilterCair.Client/Pages/Filters.razor
Normal file
87
FilterCair.Client/Pages/Filters.razor
Normal file
@ -0,0 +1,87 @@
|
||||
@page "/stations/{customerId:int}/filters/{stationId:int}"
|
||||
@using FilterCair.Shared.Models
|
||||
@inject FilterCair.Client.Services.API.FilterService FilterService
|
||||
@inject NavigationManager Nav
|
||||
|
||||
<PageTitle>Filterübersicht</PageTitle>
|
||||
|
||||
<div class="container py-4 fade-in">
|
||||
<h4 class="text-primary text-center mb-4">
|
||||
<i class="bi bi-funnel me-2"></i> Filterübersicht
|
||||
</h4>
|
||||
|
||||
@if (isLoading)
|
||||
{
|
||||
<div class="text-center text-muted py-5">
|
||||
<div class="spinner-border text-primary" role="status"></div>
|
||||
<p class="mt-3">Lade Filter...</p>
|
||||
</div>
|
||||
}
|
||||
else if (filters.Count == 0)
|
||||
{
|
||||
<div class="alert alert-info text-center">
|
||||
Keine Filter für diese Station vorhanden.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row g-3 justify-content-center">
|
||||
@foreach (var f in filters)
|
||||
{
|
||||
<div class="col-12 col-md-6 col-lg-4">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="fw-semibold text-primary">
|
||||
<i class="bi bi-funnel me-1"></i> @f.Bezeichnung
|
||||
</h5>
|
||||
<p class="text-muted small mb-1">
|
||||
<strong>Typ:</strong> @f.Typ
|
||||
</p>
|
||||
<p class="text-muted small mb-1">
|
||||
<strong>Seriennr.:</strong> @f.Seriennummer
|
||||
</p>
|
||||
<p class="text-muted small mb-1">
|
||||
<strong>Zustand:</strong> @f.Zustand
|
||||
</p>
|
||||
<p class="text-muted small mb-0">
|
||||
<strong>Letzte Wartung:</strong>
|
||||
@(f.LetzteWartung?.ToString("dd.MM.yyyy") ?? "–")
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-footer bg-light text-end">
|
||||
<button class="btn btn-outline-primary btn-sm rounded-pill"
|
||||
@onclick="() => OpenFilterForm(f)">
|
||||
<i class="bi bi-pencil"></i> Bearbeiten
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public int customerId { get; set; }
|
||||
[Parameter] public int stationId { get; set; }
|
||||
|
||||
private List<FilterModel> filters = new();
|
||||
private bool isLoading = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadFilters();
|
||||
}
|
||||
|
||||
private async Task LoadFilters()
|
||||
{
|
||||
isLoading = true;
|
||||
filters = await FilterService.GetFiltersByStationAsync(stationId);
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
private void OpenFilterForm(FilterModel filter)
|
||||
{
|
||||
Nav.NavigateTo($"/filterform?filterId={filter.Id}&stationId={stationId}&customerId={customerId}");
|
||||
}
|
||||
}
|
||||
126
FilterCair.Client/Pages/Stations.razor
Normal file
126
FilterCair.Client/Pages/Stations.razor
Normal file
@ -0,0 +1,126 @@
|
||||
@page "/stations/{customerId:int}"
|
||||
@using FilterCair.Shared.Models
|
||||
@inject FilterCair.Client.Services.API.StationService StationService
|
||||
@inject FilterCair.Client.Services.API.FilterService FilterService
|
||||
@inject NavigationManager Nav
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<PageTitle>Stationen</PageTitle>
|
||||
|
||||
<div class="container py-4">
|
||||
<h4 class="text-primary text-center mb-4">
|
||||
<i class="bi bi-geo-alt me-2"></i> Stationen der Fabrik
|
||||
</h4>
|
||||
|
||||
<!-- QR Scanner -->
|
||||
<div class="text-center mb-4">
|
||||
<video id="video" autoplay playsinline class="border rounded shadow-sm"
|
||||
style="width:100%;max-width:420px;"></video>
|
||||
|
||||
@if (!string.IsNullOrEmpty(scanResult))
|
||||
{
|
||||
<div class="alert alert-success mt-3">
|
||||
<strong>QR erkannt:</strong> @scanResult
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="mt-3">
|
||||
<button class="btn btn-secondary me-2" @onclick="StartScan">🔄 Neu starten</button>
|
||||
<button class="btn btn-outline-danger" @onclick="StopScan">⏹ Stop</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<!-- Stationsliste -->
|
||||
@if (isLoading)
|
||||
{
|
||||
<div class="text-center text-muted py-5">
|
||||
<div class="spinner-border text-primary" role="status"></div>
|
||||
<p class="mt-3">Lade Stationen...</p>
|
||||
</div>
|
||||
}
|
||||
else if (stations.Count == 0)
|
||||
{
|
||||
<div class="alert alert-info text-center">
|
||||
Keine Stationen gefunden.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row g-3 justify-content-center">
|
||||
@foreach (var s in stations)
|
||||
{
|
||||
<div class="col-12 col-md-6 col-lg-4">
|
||||
<div class="card shadow-sm border-0 station-card h-100"
|
||||
@onclick="() => SelectStation(s)">
|
||||
<div class="card-body">
|
||||
<h5 class="fw-semibold text-primary mb-2">
|
||||
<i class="bi bi-building me-1"></i> @s.Name
|
||||
</h5>
|
||||
<p class="text-muted small mb-1">
|
||||
<i class="bi bi-geo me-1"></i> @s.Standort
|
||||
</p>
|
||||
<p class="text-muted small mb-0">@s.Beschreibung</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public int customerId { get; set; }
|
||||
|
||||
private List<StationModel> stations = new();
|
||||
private string? scanResult;
|
||||
private bool isLoading = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadStations();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await JS.InvokeVoidAsync("QRScanner.init", DotNetObjectReference.Create(this));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadStations()
|
||||
{
|
||||
try
|
||||
{
|
||||
isLoading = true;
|
||||
stations = await StationService.GetStationsByCustomerAsync(customerId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Laden der Stationen: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectStation(StationModel s)
|
||||
{
|
||||
Nav.NavigateTo($"/stations/{customerId}/filters/{s.Id}");
|
||||
}
|
||||
|
||||
private async Task StartScan() => await JS.InvokeVoidAsync("QRScanner.start");
|
||||
private async Task StopScan() => await JS.InvokeVoidAsync("QRScanner.stop");
|
||||
|
||||
[JSInvokable]
|
||||
public void OnQrDetected(string code)
|
||||
{
|
||||
scanResult = code;
|
||||
// TODO: später Filter anhand QR-Code öffnen
|
||||
// Nav.NavigateTo($"/stations/{customerId}/filterdetail/{code}");
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
using FilterCair.Client;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
|
||||
using FilterCair.Client.Services;
|
||||
using FilterCair.Client.Services.API;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
builder.RootComponents.Add<App>("#app");
|
||||
@ -26,6 +27,8 @@ builder.Services.AddMsalAuthentication(options =>
|
||||
builder.Services.AddScoped<AppState>();
|
||||
|
||||
//API Services
|
||||
builder.Services.AddScoped<FilterCair.Client.Services.API.CustomerService>();
|
||||
builder.Services.AddScoped<CustomerService>();
|
||||
builder.Services.AddScoped<StationService>();
|
||||
builder.Services.AddScoped<FilterService>();
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
|
||||
@ -57,5 +57,19 @@ namespace FilterCair.Client.Services.API
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateCustomerAsync(CustomerModel customer)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _http.PutAsJsonAsync($"{BaseUrl}/{customer.Id}", customer);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Aktualisieren: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
FilterCair.Client/Services/API/FilterService.cs
Normal file
96
FilterCair.Client/Services/API/FilterService.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System.Net.Http.Json;
|
||||
using FilterCair.Shared.Models;
|
||||
|
||||
namespace FilterCair.Client.Services.API
|
||||
{
|
||||
public class FilterService
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly IConfiguration _config;
|
||||
private string BaseUrl => _config["Api:BaseUrl"] + "/api/Filter";
|
||||
|
||||
public FilterService(HttpClient http, IConfiguration config)
|
||||
{
|
||||
_http = http;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
// Alle Filter einer Station laden
|
||||
public async Task<List<FilterModel>> GetFiltersByStationAsync(int stationId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filters = await _http.GetFromJsonAsync<List<FilterModel>>($"{BaseUrl}/byStation/{stationId}");
|
||||
return filters ?? new();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Laden der Filter: {ex.Message}");
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
||||
// Filter anlegen
|
||||
public async Task<bool> AddFilterAsync(FilterModel filter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _http.PostAsJsonAsync(BaseUrl, filter);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Erstellen: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter per QR-Code abrufen
|
||||
public async Task<FilterModel?> GetFilterByQRCodeAsync(string qrCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _http.GetFromJsonAsync<FilterModel>($"{BaseUrl}/byQr/{qrCode}");
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Laden per QR-Code: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Einzelnen Filter per ID laden
|
||||
public async Task<FilterModel?> GetFilterByIdAsync(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _http.GetFromJsonAsync<FilterModel>($"{BaseUrl}/{id}");
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Laden des Filters: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter aktualisieren
|
||||
public async Task<bool> UpdateFilterAsync(FilterModel filter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _http.PutAsJsonAsync($"{BaseUrl}/{filter.Id}", filter);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Aktualisieren: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
48
FilterCair.Client/Services/API/StationService.cs
Normal file
48
FilterCair.Client/Services/API/StationService.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System.Net.Http.Json;
|
||||
using FilterCair.Shared.Models;
|
||||
|
||||
namespace FilterCair.Client.Services.API
|
||||
{
|
||||
public class StationService
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly IConfiguration _config;
|
||||
private string BaseUrl => _config["Api:BaseUrl"] + "/api/Station";
|
||||
|
||||
public StationService(HttpClient http, IConfiguration config)
|
||||
{
|
||||
_http = http;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
// 🔹 Alle Stationen eines Kunden laden
|
||||
public async Task<List<StationModel>> GetStationsByCustomerAsync(int customerId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var stations = await _http.GetFromJsonAsync<List<StationModel>>($"{BaseUrl}/byCustomer/{customerId}");
|
||||
return stations ?? new();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Laden der Stationen: {ex.Message}");
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 Neue Station anlegen
|
||||
public async Task<bool> AddStationAsync(StationModel station)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _http.PostAsJsonAsync(BaseUrl, station);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Fehler beim Erstellen: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,6 +43,7 @@
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/jsQR.js"></script>
|
||||
<script src="js/filtercair.js"></script>
|
||||
<script src="js/toastcontainer.js"></script>
|
||||
|
||||
<script src="_framework/blazor.webassembly.js"></script>
|
||||
<script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>
|
||||
|
||||
30
FilterCair.Client/wwwroot/js/toastcontainer.js
Normal file
30
FilterCair.Client/wwwroot/js/toastcontainer.js
Normal file
@ -0,0 +1,30 @@
|
||||
window.showToast = (message, type = "success") => {
|
||||
const container = document.querySelector(".toast-container") || createToastContainer();
|
||||
const toastEl = document.createElement("div");
|
||||
|
||||
toastEl.className = `toast align-items-center text-white border-0 mb-2 bg-${type === "error" ? "danger" :
|
||||
type === "warning" ? "warning" :
|
||||
type === "info" ? "info" : "success"
|
||||
}`;
|
||||
|
||||
toastEl.role = "alert";
|
||||
toastEl.innerHTML = `
|
||||
<div class="d-flex">
|
||||
<div class="toast-body fw-semibold">${message}</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.appendChild(toastEl);
|
||||
const toast = new bootstrap.Toast(toastEl, { delay: 3000 });
|
||||
toast.show();
|
||||
|
||||
toastEl.addEventListener("hidden.bs.toast", () => toastEl.remove());
|
||||
};
|
||||
|
||||
function createToastContainer() {
|
||||
const container = document.createElement("div");
|
||||
container.className = "toast-container position-fixed bottom-0 end-0 p-3";
|
||||
document.body.appendChild(container);
|
||||
return container;
|
||||
}
|
||||
@ -19,7 +19,7 @@ builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("AllowClient", policy =>
|
||||
{
|
||||
policy.WithOrigins("https://filtercair-client-efava4bfgvamhkfu.westeurope-01.azurewebsites.net", "https://localhost:5001")
|
||||
policy.WithOrigins("https://filtercair-client-efava4bfgvamhkfu.westeurope-01.azurewebsites.net", "https://localhost:5186", "http://localhost:5186")
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod();
|
||||
});
|
||||
|
||||
@ -9,14 +9,14 @@ namespace FilterCair.Shared.Models
|
||||
{
|
||||
public class FilterModel
|
||||
{
|
||||
[Required]
|
||||
public string? FilterId { get; set; }
|
||||
|
||||
[Required]
|
||||
public string? Halle { get; set; }
|
||||
|
||||
public string? Zustand { get; set; }
|
||||
public double? Luftdruck { get; set; }
|
||||
public string? Bemerkung { get; set; }
|
||||
public int Id { get; set; }
|
||||
public int StationId { get; set; }
|
||||
public string Bezeichnung { get; set; } = string.Empty;
|
||||
public string Typ { get; set; } = string.Empty;
|
||||
public string Seriennummer { get; set; } = string.Empty;
|
||||
public DateTime? Einbaudatum { get; set; }
|
||||
public DateTime? LetzteWartung { get; set; }
|
||||
public string Zustand { get; set; } = string.Empty;
|
||||
public string QRCode { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user