Bilder hinzufügen

This commit is contained in:
MarcWieland 2025-11-18 10:49:35 +01:00
parent fda4543775
commit 92e92142ce
4 changed files with 99 additions and 46 deletions

View File

@ -19,23 +19,20 @@
<DataAnnotationsValidator />
<ValidationSummary />
<!-- === BESTEHENDE FELDER (unverändert) === -->
<div class="row g-3">
<div class="col-md-6">
<label class="form-label fw-semibold">Bezeichnung</label>
<InputText class="form-control form-control-lg" @bind-Value="filter.Bezeichnung" placeholder="z. B. Filter Nordhalle" />
<InputText class="form-control form-control-lg" @bind-Value="filter.Bezeichnung" />
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">Typ</label>
<InputText class="form-control form-control-lg" @bind-Value="filter.Typ" placeholder="z. B. Aktivkohle" />
<InputText class="form-control form-control-lg" @bind-Value="filter.Typ" />
</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" />
<InputText class="form-control form-control-lg" @bind-Value="filter.Seriennummer" />
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">Zustand</label>
<InputSelect class="form-select form-select-lg" @bind-Value="filter.Zustand">
@ -45,72 +42,75 @@
<option>Defekt</option>
</InputSelect>
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">Einbaudatum</label>
<InputDate class="form-control form-control-lg" @bind-Value="filter.Einbaudatum" />
</div>
<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>
<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" />
<InputText class="form-control form-control-lg" @bind-Value="filter.QRCode" />
</div>
</div>
<div class="d-grid mt-4">
<!-- === NEU: FOTO-BEREICH === -->
<div class="mt-5">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="mb-0 text-primary">
<i class="bi bi-camera me-2"></i> Fotos (@filter.Photos.Count)
</h5>
<button type="button" class="btn btn-outline-primary rounded-pill" @onclick="TakePhoto">
<i class="bi bi-camera-fill me-1"></i> Foto aufnehmen
</button>
</div>
@if (filter.Photos.Any())
{
<div class="row g-3">
@foreach (var photo in filter.Photos)
{
<div class="col-6 col-md-4 col-lg-3">
<div class="position-relative">
<img src="@photo" class="img-fluid rounded shadow-sm" style="height:180px; object-fit:cover; width:100%;" />
<button type="button" class="btn btn-danger btn-sm position-absolute top-0 end-0 m-2 rounded-circle"
@onclick="() => RemovePhoto(photo)">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
}
</div>
}
else
{
<div class="alert alert-light text-center py-4">
<i class="bi bi-image fs-1 text-muted"></i>
<p class="mt-2 text-muted">Noch keine Fotos tippe auf "Foto aufnehmen"</p>
</div>
}
</div>
<div class="d-grid mt-5">
<button type="submit" class="btn btn-primary btn-lg rounded-pill shadow-sm">
<i class="bi bi-save me-2"></i> Speichern
</button>
</div>
</EditForm>
@if (showToast)
{
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div class="toast align-items-center text-bg-success border-0 show fade-in-toast">
<div class="d-flex">
<div class="toast-body">
✅ Filterdaten erfolgreich gespeichert!
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
@code {
private FilterModel filter = new();
private bool showToast;
private async Task SaveForm()
{
bool success = await FilterService.SaveFilterAsync(filter);
if (success)
{
await JS.InvokeVoidAsync("showToast", "✅ Offline gespeichert wird synchronisiert!", "success");
NavManager.NavigateTo($"/stations/{filter.CustomerId}/filters/{filter.StationId}");
}
else
{
await JS.InvokeVoidAsync("showToast", "Fehler", "error");
}
}
private FilterModel filter = new() { Photos = new List<string>() };
protected override async Task OnInitializedAsync()
{
var uri = NavManager.ToAbsoluteUri(NavManager.Uri);
var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
// Standardwerte setzen
if (int.TryParse(query.Get("customerId"), out int customerId))
filter.CustomerId = customerId;
@ -123,11 +123,44 @@
if (existing != null)
{
filter = existing;
StateHasChanged();
// Sicherstellen, dass Photos existieren
filter.Photos ??= new List<string>();
}
}
}
private async Task TakePhoto()
{
try
{
var photoBase64 = await JS.InvokeAsync<string>("takePhoto");
if (!string.IsNullOrEmpty(photoBase64))
{
filter.Photos.Add(photoBase64);
StateHasChanged();
await JS.InvokeVoidAsync("showToast", "Foto hinzugefügt!", "success");
}
}
catch (Exception ex)
{
await JS.InvokeVoidAsync("showToast", "Kamera-Fehler", "error");
Console.WriteLine(ex);
}
}
private void RemovePhoto(string photo)
{
filter.Photos.Remove(photo);
StateHasChanged();
}
}
private async Task SaveForm()
{
bool success = await FilterService.SaveFilterAsync(filter);
if (success)
{
await JS.InvokeVoidAsync("showToast", "Filter + Fotos gespeichert!", "success");
NavManager.NavigateTo($"/stations/{filter.CustomerId}/filters/{filter.StationId}");
}
}
}

View File

@ -47,6 +47,7 @@
<script src="https://unpkg.com/dexie@3.2.4/dist/dexie.min.js"></script>
<script src="js/filterdb.js"></script>
<script src="js/onlineStatus.js"></script>
<script src="js/camera.js"></script>
<script src="_framework/blazor.webassembly.js"></script>
<script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>

View File

@ -0,0 +1,17 @@
window.takePhoto = async () => {
const video = document.createElement('video');
const canvas = document.createElement('canvas');
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } });
video.srcObject = stream;
video.play();
return new Promise((resolve) => {
video.onloadedmetadata = () => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
stream.getTracks().forEach(t => t.stop());
resolve(canvas.toDataURL('image/jpeg', 0.8));
};
});
};

View File

@ -19,5 +19,7 @@ namespace FilterCair.Shared.Models
public DateTime? LetzteWartung { get; set; }
public string Zustand { get; set; } = string.Empty;
public string QRCode { get; set; } = string.Empty;
//Bilder
public List<string> Photos { get; set; } = new();
}
}