Bessere Trennung manueller / automatischer Login
Umstellung auf Sekunden wegen aktualisierter Hauptanwendung
Umstellung auf Toasts bei Informationsmeldungen
Abstände und Sichtbarkeiten vereinheitlicht
Upgrade auf .NET9
This commit is contained in:
2025-02-15 22:59:06 +01:00
parent 65d5dc94df
commit 4449b4ad0e
18 changed files with 268 additions and 121 deletions

View File

@@ -22,6 +22,8 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
public event EventHandler<string> AlertEvent;
public event EventHandler<string> InfoEvent;
public event Func<string, string, Task<bool>> ConfirmEvent;
//public event Func<string, string, string?, string?, Task<bool>> ConfirmEvent;
//public event EventHandler<ConfirmEventArgs> ConfirmEvent;
/// <summary>
/// Gemeinden für die Auswahlliste
@@ -73,6 +75,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
public ICommand DeleteConfirmCommand { get; private set; }
//public ICommand LoadDataCommand { get; private set; }
public StundeViewModel() {
SaveCommand = new AsyncRelayCommand(Save);
//DeleteCommand = new AsyncRelayCommand(Delete);
@@ -95,7 +98,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
GemeindeAktivSet = Settings.GemeindeAktivSet;
ProjektAktivSet = Settings.ProjektAktivSet;
} catch (Exception e) {
AlertEvent?.Invoke(this, e.Message);
}
@@ -103,26 +106,40 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
async Task Save() {
bool exceptionOccurred = false;
try {
await HoursBase.SaveEntry(DayTime);
} catch (Exception e) {
AlertEvent?.Invoke(this, e.Message);
exceptionOccurred = true;
bool proceed = true;
if (DayTime.TimeSpanVon == DayTime.TimeSpanBis && DayTime.FreistellungAktiv.Name == null) {
proceed = false;
AlertEvent?.Invoke(this, "Uhrzeiten sollten unterschiedlich sein");
}
if (!exceptionOccurred) {
if (DayTime.Id != null) {
await Shell.Current.GoToAsync($"..?saved={DayTime.Id}");
} else {
await Shell.Current.GoToAsync($"..?date={DayTime.Day.ToString("yyyy-MM-dd")}");
if (proceed) {
try {
await HoursBase.SaveEntry(DayTime);
} catch (Exception e) {
AlertEvent?.Invoke(this, e.Message);
exceptionOccurred = true;
}
if (!exceptionOccurred) {
if (DayTime.Id != null) {
await Shell.Current.GoToAsync($"..?saved={DayTime.Id}");
} else {
await Shell.Current.GoToAsync($"..?date={DayTime.Day.ToString("yyyy-MM-dd")}");
}
}
}
}
/// <summary>
/// Löschen ohne Bestätigung
/// </summary>
private async Task Delete() {
await HoursBase.DeleteEntry(DayTime);
await Shell.Current.GoToAsync($"..?date={DayTime.Day.ToString("yyyy-MM-dd")}");
}
/// <summary>
/// Löschen mit Bestätigung
/// </summary>
private async Task DeleteConfirm() {
if (ConfirmEvent != null) {
bool answer = await ConfirmEvent.Invoke("Achtung", "Löschen kann nicht ungeschehen gemacht werden. Fortfahren?");
@@ -140,7 +157,8 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
/// Anwenden der Query-Parameter
/// </summary>
async void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query) {
//load beinhaltet die ID: Eintrag bearbeiten
//date beinhaltet einen Tag: Neuen Eintrag erstellen
if (query.ContainsKey("load")) {
//DateTime heute = DateTime.Now;
@@ -154,7 +172,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
DayTime = dat.daytime;
DayTime.TimeSpanVon = dat.daytime.Begin.ToTimeSpan();
DayTime.TimeSpanBis = dat.daytime.End.ToTimeSpan();
OptionsGemeinde = dat.settings.Gemeinden ?? new List<Gemeinde>();
OptionsProjekt = dat.settings.Projekte ?? new List<Projekt>();
OptionsFreistellung = dat.settings.Freistellungen ?? new List<Freistellung>();
@@ -162,7 +180,12 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
DayTime.GemeindeAktiv = OptionsGemeinde.FirstOrDefault(Gemeinde => Gemeinde.Id == DayTime.Gemeinde) ?? new Gemeinde();
DayTime.ProjektAktiv = OptionsProjekt.FirstOrDefault(Projekt => Projekt.Id == DayTime.Projekt) ?? new Projekt();
DayTime.FreistellungAktiv = OptionsFreistellung.FirstOrDefault(Freistellung => Freistellung.Id == DayTime.Free) ?? new Freistellung();
//OnPropertyChanged(nameof(DayTime));
//Evtl. noch die anderen Zeiten des gleichen Tages holen
BaseResponse dat1 = await HoursBase.LoadBase("date=" + DayTime.Day.ToString("yyyy-MM-dd"));
DayTimes = dat1.daytimes;
OnPropertyChanged(nameof(DayTime));
OnPropertyChanged(nameof(DayTimes));
} catch (Exception e) {
AlertEvent?.Invoke(this, e.Message);
@@ -171,7 +194,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
}
if (System.String.IsNullOrEmpty(DayTime.Description)) {
AlertEvent?.Invoke(this, "Eintrag hat keinen Beschreibungstext");
InfoEvent?.Invoke(this, "Eintrag hat keinen Beschreibungstext");
}
SubTitle = DayTime.Day.ToString("dddd, d. MMMM yyyy");
OnPropertyChanged(nameof(SubTitle));
@@ -197,7 +220,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
GemeindeAktivSet = dat.settings.GemeindeAktivSet;
ProjektAktivSet = dat.settings.ProjektAktivSet;
} catch (Exception) {
//Ein Tag ohne Einträge gibt eine Fehlermeldung,
//die soll aber ignoriert werden, weil beim Neueintrag ist das ja Wurscht
@@ -213,7 +236,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
SubTitle = _date.ToString("dddd, d. MMMM yyyy");
FreistellungEnabled = true;
OnPropertyChanged(nameof(SubTitle));
//OnPropertyChanged(nameof(DayTime));
}

View File

@@ -5,6 +5,8 @@ using Jugenddienst_Stunden.Types;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using CommunityToolkit.Maui.Alerts;
using CommunityToolkit.Maui.Core;
namespace Jugenddienst_Stunden.ViewModels;
@@ -13,8 +15,6 @@ namespace Jugenddienst_Stunden.ViewModels;
/// </summary>
internal partial class StundenViewModel : ObservableObject, IQueryAttributable, INotifyPropertyChanged {
public string LoadOverview => "Lade Summen für " + DateTime.Today.ToString("MMMM");
public ICommand NewEntryCommand { get; }
public ICommand SelectEntryCommand { get; }
public ICommand LoadDataCommand { get; private set; }
@@ -25,6 +25,13 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
public event EventHandler<string> AlertEvent;
public event EventHandler<string> InfoEvent;
/// <summary>
/// Beschriftung Button Monatsübersicht
/// </summary>
[ObservableProperty]
private string loadOverview;
//private HoursBase HoursBase = new HoursBase();
internal Settings Settings = new Settings();
@@ -45,7 +52,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
/// </summary>
[ObservableProperty]
private List<DayTime> dayTimes = new List<DayTime>();
public string Title { get; set; } = GlobalVar.Name + " " + GlobalVar.Surname;
private Hours _hour;
@@ -76,7 +83,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
set {
if (dateToday != value) {
dateToday = value;
//GetDay = value;
LoadOverview = "Lade Summen für " + dateToday.ToString("MMMM");
//OnPropertyChanged();
Task.Run(() => LoadDay(value));
}
@@ -93,28 +100,28 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
/// <summary>
/// Monatsübersicht: Sollstunden
/// </summary>
public string? Nominal {
public int? Nominal {
get => Hours.Nominal;
}
/// <summary>
/// Monatsübersicht: Differenz zwischen Soll und geleisteten Stunden
/// </summary>
public string? Overtime {
public int? Overtime {
get => Hours.overtime;
}
/// <summary>
/// Monatsübersicht: Restüberstunden insgesamt
/// </summary>
public string OvertimeMonth {
public int OvertimeMonth {
get => Hours.overtime_month;
}
/// <summary>
/// Monatsübersicht: Resturlaub
/// </summary>
public string Holiday {
public int Holiday {
get => Hours.holiday;
}
@@ -138,12 +145,15 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
private bool doContinue = true;
/// <summary>
/// CTOR
/// </summary>
public StundenViewModel() {
_hour = new Hours();
LoadOverview = "Lade Summen für " + DateToday.ToString("MMMM");
LoadDataCommand = new AsyncRelayCommand(LoadData);
NewEntryCommand = new AsyncRelayCommand(NewEntryAsync);
SelectEntryCommand = new AsyncRelayCommand<DayTime>(SelectEntryAsync);
@@ -183,7 +193,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
/// </summary>
private async Task LoadData() {
try {
BaseResponse dat = await HoursBase.LoadBase("hours");
BaseResponse dat = await HoursBase.LoadBase("hours&month=" + DateToday.ToString("MM"));
_hour = dat.hour;
//_hour = await HoursBase.LoadData();
RefreshProperties();
@@ -198,6 +208,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
/// </summary>
public async Task LoadDay(DateTime date) {
DayTotal = new TimeOnly(0);
Sollstunden = new TimeOnly(0);
try {
//_dayTimes = await HoursBase.LoadDay(date);
BaseResponse dat = await HoursBase.LoadBase("date=" + date.ToString("yyyy-MM-dd"));
@@ -206,6 +217,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
Settings = dat.settings;
GemeindeAktivSet = Settings.GemeindeAktivSet;
ProjektAktivSet = Settings.ProjektAktivSet;
OnPropertyChanged(nameof(GemeindeAktivSet));
OnPropertyChanged(nameof(ProjektAktivSet));
@@ -241,23 +253,25 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
} finally {
OnPropertyChanged(nameof(DayTotal));
OnPropertyChanged(nameof(Sollstunden));
OnPropertyChanged(nameof(DateToday));
OnPropertyChanged(nameof(LoadOverview));
//OnPropertyChanged(nameof(DayTimes));
}
}
async void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query) {
if (query.ContainsKey("date")) {
await LoadDay(Convert.ToDateTime(query["date"]));
}
}
/// <summary>
/// Seite aktualisieren
/// </summary>
private async Task RefreshItemsAsync() {
IsRefreshing = true;
// Fügen Sie hier die Logik zum Aktualisieren der Daten hinzu
//await Task.Delay(2000); // Simuliert eine Datenaktualisierung
await LoadDay(DateToday);
@@ -277,6 +291,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable,
OnPropertyChanged(nameof(Title));
OnPropertyChanged(nameof(MinimumDate));
OnPropertyChanged(nameof(MaximumDate));
OnPropertyChanged(nameof(LoadOverview));
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) {