can now update basic info on a critter

This commit is contained in:
2026-01-04 23:51:53 -06:00
parent b0cb52c199
commit 4e493c5f06
7 changed files with 249 additions and 19 deletions

View File

@@ -28,7 +28,7 @@ public partial class ProfileButton : UserControl
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e); //Console.WriteLine(e);
} }
ProfileNameLabel.Content = string.IsNullOrEmpty(critter.Name) ? "New Critter" : critter.Name ; ProfileNameLabel.Content = string.IsNullOrEmpty(critter.Name) ? "New Critter" : critter.Name ;

View File

@@ -0,0 +1,33 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="CritterFolio.Pages.CritterPage">
<ScrollViewer HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Spacing="10">
<Label Classes="heading1">Info</Label>
<StackPanel HorizontalAlignment="Stretch">
<Label VerticalAlignment="Center">Name: </Label>
<TextBox x:Name="NameBox" />
</StackPanel>
<StackPanel HorizontalAlignment="Stretch">
<Label VerticalAlignment="Center">Gender: </Label>
<ComboBox x:Name="GenderOption" />
</StackPanel>
<StackPanel HorizontalAlignment="Stretch">
<Label VerticalAlignment="Center">Birthday: </Label>
<DatePicker x:Name="BirthdayPicker" />
</StackPanel>
<StackPanel HorizontalAlignment="Stretch">
<Label VerticalAlignment="Center">Mother: </Label>
<ComboBox x:Name="MotherPicker" />
</StackPanel>
<StackPanel HorizontalAlignment="Stretch">
<Label VerticalAlignment="Center">Father: </Label>
<ComboBox x:Name="FatherPicker" />
</StackPanel>
<!-- <Button x:Name="AddButton" Classes="icon" HorizontalAlignment="Stretch">&#xe3d4;</Button> -->
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@@ -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<Gender>(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);
}
}

View File

@@ -66,31 +66,23 @@ public partial class HomePage : Page
} }
} }
private async void AddProfileButton(Critter critter) private void AddProfileButton(Critter critter)
{ {
var newProfButton = new ProfileButton(); var newProfButton = new ProfileButton();
newProfButton.Init(critter); newProfButton.Init(critter);
CritterStack.Children.Add(newProfButton); CritterStack.Children.Add(newProfButton);
newProfButton.Clicked += (sender, args) =>
newProfButton.Clicked += async (sender, args) =>
{ {
await ProfileButtonClicked(critter); ProfileButtonClicked(critter);
}; };
} }
private async Task ProfileButtonClicked(Critter critter) private void ProfileButtonClicked(Critter critter)
{ {
try var critterPage = new CritterPage();
{ critterPage.Init(critter);
await DialogHelper.ShowMessage($"{critter.Name} was clicked"); Sys.Navigation?.PushPage(critterPage);
}
catch (Exception e)
{
Console.WriteLine(e);
Logger.LogToFile(e.ToString());
}
} }
private async void AddButtonClicked(object? sender, RoutedEventArgs e) private async void AddButtonClicked(object? sender, RoutedEventArgs e)

View File

@@ -72,5 +72,11 @@ public static class DatabaseService
return result ?? []; return result ?? [];
} }
public static async Task<Critter?> GetCritter(int id)
{
await Init();
return _db?.GetAsync<Critter>(id).Result;
}
#endregion #endregion
} }

View File

@@ -21,4 +21,15 @@ public static class DialogHelper
Console.WriteLine(e); Console.WriteLine(e);
} }
} }
public static async Task<bool> ShowConfirmationDialog(string message)
{
TwofoldDialog dialog = new()
{
Message = message,
PositiveText = "Yes",
NegativeText = "Cancel"
};
return (await dialog.ShowAsync()).GetValueOrDefault();
}
} }

View File

@@ -9,7 +9,5 @@
x:Class="CritterFolio.Views.MainWindow" x:Class="CritterFolio.Views.MainWindow"
Icon="/Assets/icon.ico" Icon="/Assets/icon.ico"
Title="CritterFolio"> Title="CritterFolio">
<dialogs:ReactiveDialogHost CloseOnClickAway="True"> <views:MainView />
<views:MainView />
</dialogs:ReactiveDialogHost>
</Window> </Window>