209 lines
7.7 KiB
Plaintext
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> |