diff --git a/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml.cs b/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml.cs index 5f13325..c1e6c8e 100644 --- a/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml.cs +++ b/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml.cs @@ -28,7 +28,7 @@ public partial class ProfileButton : UserControl } catch (Exception e) { - Console.WriteLine(e); + //Console.WriteLine(e); } ProfileNameLabel.Content = string.IsNullOrEmpty(critter.Name) ? "New Critter" : critter.Name ; diff --git a/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml new file mode 100644 index 0000000..a4e5fb0 --- /dev/null +++ b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml.cs b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml.cs new file mode 100644 index 0000000..836ec3c --- /dev/null +++ b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using Avalonia.Threading; +using CritterFolio.DataModels; +using CritterFolio.Services; + +namespace CritterFolio.Pages; + +public partial class CritterPage : Page +{ + private Critter? _critter; + + public CritterPage() + { + InitializeComponent(); + } + + public void Init(Critter critter) + { + _critter = critter; + + UpdateInfo(); + } + + public override void Refresh() + { + base.Refresh(); + CreateHeaderButtons(); + GenderOption.ItemsSource = Enum.GetNames(typeof(Gender)); + + LoadComboItemsAsync(); + } + + private async void LoadComboItemsAsync() + { + try + { + var allCritters = await DatabaseService.GetAllCritters(); + var allCritterIds = allCritters.Select(c => c.Id).ToList(); + + await Dispatcher.UIThread.InvokeAsync(() => + { + FatherPicker.ItemsSource = allCritterIds; + MotherPicker.ItemsSource = allCritterIds; + + UpdateInfo(); + }); + } + catch (Exception ex) + { + Logger.LogToFile($"Error loading critters: {ex}"); + } + } + + private void UpdateInfo() + { + Sys.Navigation?.SetTitle(_critter.Name); + + NameBox.Text = _critter.Name; + GenderOption.SelectedItem = Enum.GetName(typeof(Gender), _critter.Gender); + BirthdayPicker.SelectedDate = _critter.DateOfBirth; + MotherPicker.SelectedItem = _critter.FatherId; + FatherPicker.SelectedItem = _critter.FatherId; + } + + private void CreateHeaderButtons() + { + var saveBttn = new Button() + { + Classes = { "headerBttn" }, + Content = "\ue248" + }; + + saveBttn.Click += SaveButtonClicked; + Sys.Navigation?.AddHeaderButton(saveBttn); + + var delBttn = new Button() + { + Classes = { "headerBttn" }, + Content = "\ue4a6" + }; + delBttn.Foreground = new SolidColorBrush(Colors.DarkRed); + delBttn.Click += DeleteButtonClicked; + Sys.Navigation?.AddHeaderButton(delBttn); + } + + private async void DeleteButtonClicked(object? sender, RoutedEventArgs args) + { + + try + { + var result = await DialogHelper.ShowConfirmationDialog("Are you sure you want to delete this critter?"); + if (!result) return; + await DatabaseService.DeleteCritter(_critter); + Sys.Navigation?.PopPage(); + } + catch (Exception e) + { + Logger.LogToFile(e.ToString()); + await DialogHelper.ShowMessage($"Error: {e.Message}"); + } + + } + + private async void SaveButtonClicked(object? sender, RoutedEventArgs args) + { + if (_critter is null) return; + try + { + var result = await DialogHelper.ShowConfirmationDialog("Are you sure you want to save this critter?"); + if (!result) return; + + var validationResult = await TryValidateAndSave(); + if (!validationResult.isValid) + { + await DialogHelper.ShowMessage($"Validation error:\n{validationResult.errors}"); + return; + } + + await DatabaseService.UpdateCritter(_critter); + UpdateInfo(); + + await DialogHelper.ShowMessage($"Critter '{_critter.Name}' saved!"); + } + catch (Exception e) + { + Logger.LogToFile(e.ToString()); + await DialogHelper.ShowMessage($"Error: {e.Message}"); + } + } + + private async Task<(bool isValid, string errors)> TryValidateAndSave() + { + var errString = ""; + + if (_critter is null) return (false, "Critter is null somehow. Please report this to the developer"); + + _critter.Name = NameBox.Text!; + + // Gender validation + if (Enum.TryParse(GenderOption.SelectedItem?.ToString(), true, out var gender)) + { + _critter.Gender = gender; + } + else + { + errString += "Invalid gender somehow. Please report this to the developer\n"; + } + + // Birthday validation + if (BirthdayPicker.SelectedDate is not null) + { + _critter.DateOfBirth = BirthdayPicker.SelectedDate.Value.DateTime; + } + else + { + errString += "Birthday is null somehow. Please report this to the developer\n"; + } + + // Father ID validation + if (FatherPicker.SelectedItem is int fatherId) + { + _critter.FatherId = fatherId; + } + else + { + errString += "FatherId is null or invalid somehow. Please report this to the developer\n"; + } + + // Mother ID validation + if (MotherPicker.SelectedItem is int motherId) + { + _critter.MotherId = motherId; + } + else + { + errString += "MotherId is null or invalid somehow. Please report this to the developer\n"; + } + + return errString != "" ? (false, errString) : (true, errString); + } + +} \ No newline at end of file diff --git a/critterfolio/CritterFolio/CritterFolio/Pages/HomePage.axaml.cs b/critterfolio/CritterFolio/CritterFolio/Pages/HomePage.axaml.cs index 1f5a918..4c0f8a6 100644 --- a/critterfolio/CritterFolio/CritterFolio/Pages/HomePage.axaml.cs +++ b/critterfolio/CritterFolio/CritterFolio/Pages/HomePage.axaml.cs @@ -66,31 +66,23 @@ public partial class HomePage : Page } } - private async void AddProfileButton(Critter critter) + private void AddProfileButton(Critter critter) { var newProfButton = new ProfileButton(); newProfButton.Init(critter); CritterStack.Children.Add(newProfButton); - - - newProfButton.Clicked += async (sender, args) => + newProfButton.Clicked += (sender, args) => { - await ProfileButtonClicked(critter); + ProfileButtonClicked(critter); }; } - private async Task ProfileButtonClicked(Critter critter) + private void ProfileButtonClicked(Critter critter) { - try - { - await DialogHelper.ShowMessage($"{critter.Name} was clicked"); - } - catch (Exception e) - { - Console.WriteLine(e); - Logger.LogToFile(e.ToString()); - } + var critterPage = new CritterPage(); + critterPage.Init(critter); + Sys.Navigation?.PushPage(critterPage); } private async void AddButtonClicked(object? sender, RoutedEventArgs e) diff --git a/critterfolio/CritterFolio/CritterFolio/Services/DatabaseService.cs b/critterfolio/CritterFolio/CritterFolio/Services/DatabaseService.cs index b54970d..0c7d9d5 100644 --- a/critterfolio/CritterFolio/CritterFolio/Services/DatabaseService.cs +++ b/critterfolio/CritterFolio/CritterFolio/Services/DatabaseService.cs @@ -72,5 +72,11 @@ public static class DatabaseService return result ?? []; } + public static async Task GetCritter(int id) + { + await Init(); + return _db?.GetAsync(id).Result; + } + #endregion } \ No newline at end of file diff --git a/critterfolio/CritterFolio/CritterFolio/Services/DialogHelper.cs b/critterfolio/CritterFolio/CritterFolio/Services/DialogHelper.cs index c42ee43..e323978 100644 --- a/critterfolio/CritterFolio/CritterFolio/Services/DialogHelper.cs +++ b/critterfolio/CritterFolio/CritterFolio/Services/DialogHelper.cs @@ -21,4 +21,15 @@ public static class DialogHelper Console.WriteLine(e); } } + + public static async Task ShowConfirmationDialog(string message) + { + TwofoldDialog dialog = new() + { + Message = message, + PositiveText = "Yes", + NegativeText = "Cancel" + }; + return (await dialog.ShowAsync()).GetValueOrDefault(); + } } \ No newline at end of file diff --git a/critterfolio/CritterFolio/CritterFolio/Views/MainWindow.axaml b/critterfolio/CritterFolio/CritterFolio/Views/MainWindow.axaml index fe744e3..63b11a8 100644 --- a/critterfolio/CritterFolio/CritterFolio/Views/MainWindow.axaml +++ b/critterfolio/CritterFolio/CritterFolio/Views/MainWindow.axaml @@ -9,7 +9,5 @@ x:Class="CritterFolio.Views.MainWindow" Icon="/Assets/icon.ico" Title="CritterFolio"> - - - +