OnProfNext/OnProfNext.Client/Pages/Bookings/ClassicView.razor
2025-10-17 10:41:53 +02:00

209 lines
7.7 KiB
Plaintext

@using OnProfNext.Client.Services
@using OnProfNext.Shared.Models.DTOs
@inject BookingApiService BookingService
<div class="card shadow-sm border-0 mb-4">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3">
<button class="btn btn-outline-primary" @onclick="PreviousMonth">
<i class="bi bi-chevron-left"></i> Vorheriger Monat
</button>
<h5 class="text-primary m-0">@CurrentMonth.ToString("MMMM yyyy")</h5>
<button class="btn btn-outline-primary" @onclick="NextMonth">
Nächster Monat <i class="bi bi-chevron-right"></i>
</button>
</div>
<div class="monthly-calendar">
<table class="table table-bordered text-center">
<thead class="table-light">
<tr>
<th>Mo</th>
<th>Di</th>
<th>Mi</th>
<th>Do</th>
<th>Fr</th>
<th>Sa</th>
<th>So</th>
</tr>
</thead>
<tbody>
@foreach (var week in GetCalendarWeeks())
{
<tr>
@foreach (var day in week)
{
<td class="@(day.Month == CurrentMonth.Month ? "" : "text-muted") @(IsWeekend(day) ? "weekend" : "")"
@onclick="() => OpenModal(day)">
@day.Day
<br />
<small class="@GetHoursColorClass(day)">@GetHoursForDay(day) h</small>
</td>
}
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
@if (showModal)
{
<div class="modal fade show d-block" tabindex="-1" style="background-color: rgba(0,0,0,0.5);">
<div class="modal-dialog modal-dialog-centered" @onclick:stopPropagation>
<div class="modal-content border-0 shadow">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title">Buchung für @selectedDate.ToString("dd.MM.yyyy")</h5>
<button type="button" class="btn-close btn-close-white" @onclick="CloseModal"></button>
</div>
<div class="modal-body">
<EditForm Model="newBooking" OnValidSubmit="SaveBookingAsync">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="mb-3">
<label class="form-label">Auftrag</label>
<InputSelect class="form-select" @bind-Value="newBooking.OrderId">
<option value="0" disabled>Auswählen...</option>
@foreach (var order in Orders)
{
<option value="@order.Id">@order.Titel (@order.Auftragsnummer)</option>
}
</InputSelect>
</div>
<div class="mb-3">
<label class="form-label">Stunden</label>
<InputNumber class="form-control" @bind-Value="newBooking.Hours" />
</div>
<div class="mb-3">
<label class="form-label">Beschreibung</label>
<InputTextArea class="form-control" @bind-Value="newBooking.Description" />
</div>
<div class="d-flex justify-content-end">
<button type="button" class="btn btn-secondary me-2" @onclick="CloseModal">Abbrechen</button>
<button type="submit" class="btn btn-success">Speichern</button>
</div>
</EditForm>
</div>
</div>
</div>
</div>
}
@code {
[Parameter] public List<BookingDto> Bookings { get; set; } = new();
[Parameter] public List<OrderDto> Orders { get; set; } = new();
[Parameter] public EventCallback OnBookingCreated { get; set; }
[Parameter] public EventCallback<string> OnError { get; set; }
private DateTime CurrentMonth = DateTime.Today;
private bool showModal;
private DateTime selectedDate;
private BookingCreateDto newBooking = new();
private void PreviousMonth()
{
CurrentMonth = CurrentMonth.AddMonths(-1);
}
private void NextMonth()
{
CurrentMonth = CurrentMonth.AddMonths(1);
}
private List<DateTime[]> GetCalendarWeeks()
{
var weeks = new List<DateTime[]>();
var firstDayOfMonth = new DateTime(CurrentMonth.Year, CurrentMonth.Month, 1);
var firstMonday = firstDayOfMonth.AddDays(-(int)firstDayOfMonth.DayOfWeek + (firstDayOfMonth.DayOfWeek == DayOfWeek.Sunday ? 0 : 1));
var currentDay = firstMonday;
for (int weekCount = 0; weekCount < 6; weekCount++)
{
// Prüfe, ob currentDay noch im gültigen DateTime-Bereich liegt
if (currentDay.Year >= DateTime.MaxValue.Year)
break;
var week = new DateTime[7];
for (int i = 0; i < 7; i++)
{
week[i] = currentDay;
// Prüfe, ob das Hinzufügen eines Tages möglich ist
if (currentDay < DateTime.MaxValue.AddDays(-1))
currentDay = currentDay.AddDays(1);
else
break;
}
weeks.Add(week);
// Wenn currentDay nicht mehr incrementiert werden kann, beende die Schleife
if (currentDay >= DateTime.MaxValue.AddDays(-1))
break;
}
return weeks;
}
private bool IsWeekend(DateTime day)
{
return day.DayOfWeek == DayOfWeek.Saturday || day.DayOfWeek == DayOfWeek.Sunday;
}
private decimal GetHoursForDay(DateTime day)
{
return Bookings.Where(b => b.Date.Date == day.Date).Sum(b => b.Hours);
}
private string GetHoursColorClass(DateTime day)
{
var hours = GetHoursForDay(day);
if (hours >= 8)
return "text-success";
else if (hours > 6 && hours < 8)
return "text-warning";
else
return "text-danger";
}
private void OpenModal(DateTime date)
{
selectedDate = date;
newBooking = new() { Date = date, MandantId = 1 };
showModal = true;
}
private void CloseModal() => showModal = false;
private async Task SaveBookingAsync()
{
var (success, error) = await BookingService.CreateBookingAsync(newBooking);
if (success)
{
await OnBookingCreated.InvokeAsync();
CloseModal();
}
else
{
await OnError.InvokeAsync(error ?? "Fehler beim Speichern der Buchung.");
}
}
}
<style>
.monthly-calendar td {
cursor: pointer;
padding: 10px;
vertical-align: top;
height: 80px;
}
.monthly-calendar td:hover {
background-color: #f8f9fa;
}
.monthly-calendar td.weekend {
background-color: #f8f9fa;
}
</style>