From 4449b4ad0e1ac9f990049ed0dae26d8373bed3e1 Mon Sep 17 00:00:00 2001 From: DaPi Date: Sat, 15 Feb 2025 22:59:06 +0100 Subject: [PATCH] 1.0.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bessere Trennung manueller / automatischer Login Umstellung auf Sekunden wegen aktualisierter Hauptanwendung Umstellung auf Toasts bei Informationsmeldungen Abstände und Sichtbarkeiten vereinheitlicht Upgrade auf .NET9 --- Jugenddienst Stunden/AppShell.xaml | 2 +- Jugenddienst Stunden/AppShell.xaml.cs | 1 - .../Converter/SecondsTimeConverter.cs | 29 ++++++++++ .../Jugenddienst Stunden.csproj | 12 ++-- Jugenddienst Stunden/MauiProgram.cs | 15 ++--- Jugenddienst Stunden/Models/BaseFunc.cs | 12 +++- Jugenddienst Stunden/Models/HoursBase.cs | 4 +- Jugenddienst Stunden/Types/Hours.cs | 22 +++---- Jugenddienst Stunden/Types/NominalDay.cs | 2 +- Jugenddienst Stunden/Types/NominalWeek.cs | 2 +- .../ViewModels/StundeViewModel.cs | 57 ++++++++++++------ .../ViewModels/StundenViewModel.cs | 39 +++++++++---- Jugenddienst Stunden/Views/LoginPage.xaml | 4 -- Jugenddienst Stunden/Views/LoginPage.xaml.cs | 33 +++++++++-- Jugenddienst Stunden/Views/StundePage.xaml | 52 +++++++++++------ Jugenddienst Stunden/Views/StundePage.xaml.cs | 58 +++++++++++++------ Jugenddienst Stunden/Views/StundenPage.xaml | 29 ++++++---- .../Views/StundenPage.xaml.cs | 16 ++++- 18 files changed, 268 insertions(+), 121 deletions(-) create mode 100644 Jugenddienst Stunden/Converter/SecondsTimeConverter.cs diff --git a/Jugenddienst Stunden/AppShell.xaml b/Jugenddienst Stunden/AppShell.xaml index 666f0e9..bc39da4 100644 --- a/Jugenddienst Stunden/AppShell.xaml +++ b/Jugenddienst Stunden/AppShell.xaml @@ -10,7 +10,7 @@ + Icon="{OnPlatform 'icon_watch.png', iOS='icon_watch_ios.png', MacCatalyst='icon_watch_ios.png'}" Route="StundenPage" /> + - + true - - - - + + + + + diff --git a/Jugenddienst Stunden/MauiProgram.cs b/Jugenddienst Stunden/MauiProgram.cs index f8db9f9..98e83e0 100644 --- a/Jugenddienst Stunden/MauiProgram.cs +++ b/Jugenddienst Stunden/MauiProgram.cs @@ -1,4 +1,5 @@ -using Jugenddienst_Stunden.Models; +using CommunityToolkit.Maui; +using Jugenddienst_Stunden.Models; using Microsoft.Extensions.Logging; using ZXing.Net.Maui.Controls; @@ -13,6 +14,8 @@ public static class MauiProgram { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp() + // Initialize the .NET MAUI Community Toolkit by adding the below line of code + .UseMauiCommunityToolkit() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); @@ -22,19 +25,11 @@ public static class MauiProgram { #if DEBUG if (GlobalVar.ApiKey == null) { - //Preferences.Default.Set("apiKey - //Preferences.Default.Set("apiKey", "M3xneWlWNG85TmNIcmo1NnpxWkxVYS9JMDBFRlV8aHR0cDovL2hvdXJzLmRhdW5pLm1pbmUubnU6ODEvYXBwYXBp"); - //Preferences.Default.Set("name", "Testserver: Lea"); - //Preferences.Default.Set("surname", "Mair"); - //Preferences.Default.Set("EmployeeId", 3); - //Preferences.Default.Set("apiUrl", "http://hours.dauni.mine.nu:81/appapi"); - //HoursBase HoursBase = new HoursBase(); - //HoursBase.tokendata = new TokenData("MTQxfHNkdFptQkNZTXlPT3ZyMHNBZDl0UnVxNExMRXxodHRwOi8vaG91cnMuZGF1bmkubWluZS5udTo4MS9hcHBhcGk="); GlobalVar.ApiKey = Preferences.Default.Get("apiKey", "MTQxfHNkdFptQkNZTXlPT3ZyMHNBZDl0UnVxNExMRXxodHRwOi8vaG91cnMuZGF1bmkubWluZS5udTo4MS9hcHBhcGk="); GlobalVar.Name = Preferences.Default.Get("name", "Testserver: Isabell"); GlobalVar.Surname = Preferences.Default.Get("surname", "Biasi"); GlobalVar.EmployeeId = Preferences.Default.Get("EmployeeId", 141); - GlobalVar.ApiUrl = Preferences.Default.Get("apiUrl", "http://hours.dauni.mine.nu:81/appapi"); + GlobalVar.ApiUrl = Preferences.Default.Get("apiUrl", "https://hours.dauni.mine.nu/appapi"); } builder.Logging.AddDebug(); #endif diff --git a/Jugenddienst Stunden/Models/BaseFunc.cs b/Jugenddienst Stunden/Models/BaseFunc.cs index 1ea4bf7..2f87bfa 100644 --- a/Jugenddienst Stunden/Models/BaseFunc.cs +++ b/Jugenddienst Stunden/Models/BaseFunc.cs @@ -29,9 +29,9 @@ internal static class BaseFunc { using (HttpResponseMessage HttpResponseMessage = await client.GetAsync(url).ConfigureAwait(false)) { var byteArray = await HttpResponseMessage.Content.ReadAsByteArrayAsync(); string responseData = Encoding.UTF8.GetString(byteArray); - using (HttpContent HttpContent = HttpResponseMessage.Content) { - //responseData = await HttpContent.ReadAsStringAsync(); - } + //using (HttpContent HttpContent = HttpResponseMessage.Content) { + // //responseData = await HttpContent.ReadAsStringAsync(); + //} if (HttpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK) { return responseData; } else { @@ -98,6 +98,9 @@ internal static class BaseFunc { return null; } + /// + /// Notiz laden + /// internal static Note Load(string filename) { filename = System.IO.Path.Combine(FileSystem.AppDataDirectory, filename); @@ -169,6 +172,9 @@ internal static class BaseFunc { } + /// + /// Stundeneintrag löschen + /// internal static async Task DeleteItemAsync(string url, string token) { using (HttpClient client = new HttpClient() { Timeout = TimeSpan.FromSeconds(15) }) { diff --git a/Jugenddienst Stunden/Models/HoursBase.cs b/Jugenddienst Stunden/Models/HoursBase.cs index 9f8aacc..b6c515b 100644 --- a/Jugenddienst Stunden/Models/HoursBase.cs +++ b/Jugenddienst Stunden/Models/HoursBase.cs @@ -6,7 +6,7 @@ namespace Jugenddienst_Stunden.Models; internal static class HoursBase { /// - /// what can be: "settings", "hours", date="YYYY-MM-DD", id= + /// Laden ... what can be: "settings", "hours", date="YYYY-MM-DD", id= /// /// Entire response internal static async Task LoadBase(string what) { @@ -16,7 +16,7 @@ internal static class HoursBase { } /// - /// Einstellungen + /// Einstellungen laden /// /// Settings only internal static async Task LoadSettings() { diff --git a/Jugenddienst Stunden/Types/Hours.cs b/Jugenddienst Stunden/Types/Hours.cs index 2b79c03..e79afe5 100644 --- a/Jugenddienst Stunden/Types/Hours.cs +++ b/Jugenddienst Stunden/Types/Hours.cs @@ -5,8 +5,8 @@ using System.Collections.ObjectModel; namespace Jugenddienst_Stunden.Types; internal class Hours : ObservableObject { - public string? Zeit; - public string? Nominal; + public int? Zeit; + public int? Nominal; //public Dictionary nominal_day_api; public List? Nominal_day_api; //public Dictionary nominal_week_api; @@ -21,16 +21,16 @@ internal class Hours : ObservableObject { public List zeit_total_daily_api; public List? daytime; //public List wochensumme; - public string overtime_month; - public string overtime; + public int overtime_month; + public int overtime; //public List overtime_day; - public string zeitausgleich; - public string zeitausgleich_month; - public string holiday; - public string krankheit; - public string weiterbildung; - public string bereitschaft; - public string bereitschaft_month; + public int zeitausgleich; + public int zeitausgleich_month; + public int holiday; + public int krankheit; + public int weiterbildung; + public int bereitschaft; + public int bereitschaft_month; //public Operator operator_api; public DateTime Today; public DateTime Date; diff --git a/Jugenddienst Stunden/Types/NominalDay.cs b/Jugenddienst Stunden/Types/NominalDay.cs index 34590b1..4d69374 100644 --- a/Jugenddienst Stunden/Types/NominalDay.cs +++ b/Jugenddienst Stunden/Types/NominalDay.cs @@ -2,6 +2,6 @@ internal class NominalDay { public int day_number; public int month_number; - public decimal hours; + public int hours; public DateOnly date; } diff --git a/Jugenddienst Stunden/Types/NominalWeek.cs b/Jugenddienst Stunden/Types/NominalWeek.cs index db2747b..12cc07f 100644 --- a/Jugenddienst Stunden/Types/NominalWeek.cs +++ b/Jugenddienst Stunden/Types/NominalWeek.cs @@ -2,5 +2,5 @@ internal class NominalWeek { public int Week_number; - public decimal Hours; + public int Hours; } diff --git a/Jugenddienst Stunden/ViewModels/StundeViewModel.cs b/Jugenddienst Stunden/ViewModels/StundeViewModel.cs index 8ab10ce..82fd06b 100644 --- a/Jugenddienst Stunden/ViewModels/StundeViewModel.cs +++ b/Jugenddienst Stunden/ViewModels/StundeViewModel.cs @@ -22,6 +22,8 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable { public event EventHandler AlertEvent; public event EventHandler InfoEvent; public event Func> ConfirmEvent; + //public event Func> ConfirmEvent; + //public event EventHandler ConfirmEvent; /// /// 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")}"); + } } } } + /// + /// Löschen ohne Bestätigung + /// private async Task Delete() { await HoursBase.DeleteEntry(DayTime); await Shell.Current.GoToAsync($"..?date={DayTime.Day.ToString("yyyy-MM-dd")}"); } + /// + /// Löschen mit Bestätigung + /// 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 /// async void IQueryAttributable.ApplyQueryAttributes(IDictionary 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(); OptionsProjekt = dat.settings.Projekte ?? new List(); OptionsFreistellung = dat.settings.Freistellungen ?? new List(); @@ -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)); } diff --git a/Jugenddienst Stunden/ViewModels/StundenViewModel.cs b/Jugenddienst Stunden/ViewModels/StundenViewModel.cs index d9fd05a..9ce41c8 100644 --- a/Jugenddienst Stunden/ViewModels/StundenViewModel.cs +++ b/Jugenddienst Stunden/ViewModels/StundenViewModel.cs @@ -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; /// 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 AlertEvent; public event EventHandler InfoEvent; + + /// + /// Beschriftung Button Monatsübersicht + /// + [ObservableProperty] + private string loadOverview; + //private HoursBase HoursBase = new HoursBase(); internal Settings Settings = new Settings(); @@ -45,7 +52,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable, /// [ObservableProperty] private List dayTimes = new List(); - + 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, /// /// Monatsübersicht: Sollstunden /// - public string? Nominal { + public int? Nominal { get => Hours.Nominal; } /// /// Monatsübersicht: Differenz zwischen Soll und geleisteten Stunden /// - public string? Overtime { + public int? Overtime { get => Hours.overtime; } /// /// Monatsübersicht: Restüberstunden insgesamt /// - public string OvertimeMonth { + public int OvertimeMonth { get => Hours.overtime_month; } /// /// Monatsübersicht: Resturlaub /// - public string Holiday { + public int Holiday { get => Hours.holiday; } @@ -138,12 +145,15 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable, private bool doContinue = true; + /// /// CTOR /// public StundenViewModel() { _hour = new Hours(); + LoadOverview = "Lade Summen für " + DateToday.ToString("MMMM"); + LoadDataCommand = new AsyncRelayCommand(LoadData); NewEntryCommand = new AsyncRelayCommand(NewEntryAsync); SelectEntryCommand = new AsyncRelayCommand(SelectEntryAsync); @@ -183,7 +193,7 @@ internal partial class StundenViewModel : ObservableObject, IQueryAttributable, /// 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, /// 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 query) { if (query.ContainsKey("date")) { await LoadDay(Convert.ToDateTime(query["date"])); } } - + /// + /// Seite aktualisieren + /// 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) { diff --git a/Jugenddienst Stunden/Views/LoginPage.xaml b/Jugenddienst Stunden/Views/LoginPage.xaml index 950f0a7..1b4f5eb 100644 --- a/Jugenddienst Stunden/Views/LoginPage.xaml +++ b/Jugenddienst Stunden/Views/LoginPage.xaml @@ -52,13 +52,9 @@