303 lines
9.9 KiB
C#
303 lines
9.9 KiB
C#
using System.Diagnostics;
|
|
using FrymasterBadgeApp.Services;
|
|
using Microsoft.Data.SqlClient;
|
|
using Microsoft.Maui.Storage;
|
|
|
|
namespace FrymasterBadgeApp;
|
|
|
|
public partial class CompanyPage : ContentPage
|
|
{
|
|
private readonly SqlService _db;
|
|
private Dictionary<string, object>? _selectedCompany;
|
|
private string _tempLogoPath = "";
|
|
private const string LogoPathKey = "LogoBasePath";
|
|
|
|
/// <summary>
|
|
/// Constructor for CompanyPage.
|
|
/// of type ContentPage.
|
|
/// the main page for viewing and editing company information.
|
|
/// <param name="db">The SQLService object used to access the database.</param>
|
|
public CompanyPage(SqlService db)
|
|
{
|
|
InitializeComponent();
|
|
_db = db;
|
|
|
|
Shell.SetBackButtonBehavior(
|
|
this,
|
|
new BackButtonBehavior
|
|
{
|
|
TextOverride = "Back",
|
|
Command = new Command(async () => await Shell.Current.GoToAsync("..")),
|
|
}
|
|
);
|
|
|
|
LoadCompanies();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the path to the directory used to store company logos.
|
|
/// </summary>
|
|
/// <returns>The path to the directory used to store company logos.</returns>
|
|
private string GetLogoDirectory() =>
|
|
Preferences.Default.Get(LogoPathKey, @"C:\FrymasterData\logos");
|
|
|
|
/// <summary>
|
|
/// Loads the list of companies from the database.
|
|
/// the results are ordered by company name (ascending).
|
|
/// and displays the companies are stored in the CompanyList.
|
|
/// </summary>
|
|
private void LoadCompanies()
|
|
{
|
|
try
|
|
{
|
|
var companies = _db.Query("SELECT * FROM Companies ORDER BY Name ASC", null);
|
|
CompanyList.ItemsSource = companies;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppLogger.Error("Failed to load companies", ex);
|
|
DisplayAlert("Error", "Failed to load companies.", "OK");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the selection in the companies list changes.
|
|
/// the selection is used to update the company name, address, city, state, zip code, and delete button visibility.
|
|
/// </summary>
|
|
private void OnCompanySelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
{
|
|
var selected = e.CurrentSelection.FirstOrDefault() as Dictionary<string, object>;
|
|
if (selected == null)
|
|
{
|
|
ClearFields();
|
|
return;
|
|
}
|
|
|
|
_selectedCompany = selected;
|
|
|
|
MainThread.BeginInvokeOnMainThread(async () =>
|
|
{
|
|
CompName.Text = GetValue(selected, "Name");
|
|
CompAddress.Text = GetValue(selected, "Address");
|
|
CompCity.Text = GetValue(selected, "City");
|
|
CompState.Text = GetValue(selected, "State");
|
|
CompZip.Text = GetValue(selected, "Zip");
|
|
DeleteBtn.IsVisible = true;
|
|
|
|
LogoPreview.Source = null;
|
|
_tempLogoPath = "";
|
|
|
|
// Get stored filename only
|
|
string storedFileName = GetValue(selected, "logo");
|
|
if (!string.IsNullOrWhiteSpace(storedFileName))
|
|
{
|
|
string logoDir = GetLogoDirectory();
|
|
string fullPath = Path.Combine(logoDir, storedFileName);
|
|
|
|
if (File.Exists(fullPath))
|
|
{
|
|
_tempLogoPath = fullPath;
|
|
LogoPreview.Source = ImageSource.FromFile(fullPath);
|
|
AppLogger.Info($"Logo loaded for company: {fullPath}");
|
|
}
|
|
else
|
|
{
|
|
AppLogger.Warning($"Logo file missing: {fullPath}");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the value of the given key from the dictionary, trimmed of whitespace.
|
|
/// If the key does not exist, an empty string is returned.
|
|
/// </summary>
|
|
/// <param name="dict">The dictionary to search.</param>
|
|
/// <param name="key">The key to search for.</param>
|
|
/// <returns>The value of the given key, trimmed of whitespace, or an empty string if the key does not exist.</returns>
|
|
private string GetValue(Dictionary<string, object> dict, string key)
|
|
{
|
|
var actualKey = dict.Keys.FirstOrDefault(k =>
|
|
k.Equals(key, StringComparison.OrdinalIgnoreCase)
|
|
);
|
|
return actualKey != null ? dict[actualKey]?.ToString()?.Trim() ?? "" : "";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the user selects a logo image from the file picker.
|
|
/// </summary>
|
|
/// <param name="sender">The object that triggered the event</param>
|
|
/// <param name="e">The event data which contains information about the event</param>
|
|
private async void OnSelectLogoClicked(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
var result = await FilePicker.Default.PickAsync(
|
|
new PickOptions
|
|
{
|
|
PickerTitle = "Select Company Logo",
|
|
FileTypes = FilePickerFileType.Images,
|
|
}
|
|
);
|
|
|
|
if (result != null)
|
|
{
|
|
_tempLogoPath = result.FullPath;
|
|
LogoPreview.Source = ImageSource.FromFile(_tempLogoPath);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await DisplayAlert("Error", $"Failed to select logo: {ex.Message}", "OK");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Save the selected company to the database.
|
|
/// </summary>
|
|
/// <param name="sender">The object that invoked this method.</param>
|
|
/// <param name="e">The event data for this method.</param>
|
|
private async void OnSaveClicked(object sender, EventArgs e)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(CompName.Text))
|
|
{
|
|
await DisplayAlert("Error", "Company Name is required", "OK");
|
|
return;
|
|
}
|
|
|
|
string logoDir = GetLogoDirectory();
|
|
if (!Directory.Exists(logoDir))
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(logoDir);
|
|
}
|
|
catch
|
|
{
|
|
await DisplayAlert("Error", "Cannot create logo directory.", "OK");
|
|
return;
|
|
}
|
|
}
|
|
|
|
string logoFileNameToSave = ""; // will be stored in DB
|
|
|
|
if (!string.IsNullOrEmpty(_tempLogoPath))
|
|
{
|
|
try
|
|
{
|
|
string originalFileName = Path.GetFileName(_tempLogoPath);
|
|
string extension = Path.GetExtension(originalFileName);
|
|
string baseName = Path.GetFileNameWithoutExtension(originalFileName);
|
|
|
|
// Avoid overwrites: add timestamp if file already exists
|
|
string destFileName = originalFileName;
|
|
string destPath = Path.Combine(logoDir, destFileName);
|
|
|
|
if (File.Exists(destPath))
|
|
{
|
|
destFileName = $"{baseName}_{DateTime.Now:yyyyMMdd_HHmmss}{extension}";
|
|
destPath = Path.Combine(logoDir, destFileName);
|
|
}
|
|
|
|
File.Copy(_tempLogoPath, destPath, true);
|
|
logoFileNameToSave = destFileName; // only filename saved to DB
|
|
_tempLogoPath = destPath; // update local temp for preview
|
|
|
|
AppLogger.Info($"Logo saved as: {destPath}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppLogger.Error("Failed to copy logo", ex);
|
|
await DisplayAlert("Error", "Failed to save logo file.", "OK");
|
|
return;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
var parameters = new List<SqlParameter>
|
|
{
|
|
new("@n", CompName.Text ?? ""),
|
|
new("@a", CompAddress.Text ?? ""),
|
|
new("@c", CompCity.Text ?? ""),
|
|
new("@s", CompState.Text ?? ""),
|
|
new("@z", CompZip.Text ?? ""),
|
|
new("@l", logoFileNameToSave), // ← only filename
|
|
};
|
|
|
|
if (_selectedCompany == null)
|
|
{
|
|
_db.Execute(
|
|
"INSERT INTO Companies (Name, Address, City, State, Zip, logo) VALUES (@n, @a, @c, @s, @z, @l)",
|
|
parameters.ToArray()
|
|
);
|
|
await DisplayAlert("Success", "Company added.", "OK");
|
|
}
|
|
else
|
|
{
|
|
parameters.Add(new("@id", _selectedCompany["ID"]));
|
|
_db.Execute(
|
|
"UPDATE Companies SET Name=@n, Address=@a, City=@c, State=@s, Zip=@z, logo=@l WHERE ID=@id",
|
|
parameters.ToArray()
|
|
);
|
|
await DisplayAlert("Success", "Company updated.", "OK");
|
|
}
|
|
|
|
LoadCompanies();
|
|
ClearFields();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppLogger.Error("Database save failed", ex);
|
|
await DisplayAlert("Database Error", ex.Message, "OK");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets the UI state after clicking the "Add New" button.
|
|
/// </summary>
|
|
private void OnAddNewClicked(object sender, EventArgs e)
|
|
{
|
|
CompanyList.SelectedItem = null;
|
|
ClearFields();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets the UI state after clicking the "Add New" button or deleting a company.
|
|
/// </summary>
|
|
private void ClearFields()
|
|
{
|
|
_selectedCompany = null;
|
|
_tempLogoPath = "";
|
|
CompName.Text = CompAddress.Text = CompCity.Text = CompState.Text = CompZip.Text = "";
|
|
LogoPreview.Source = null;
|
|
DeleteBtn.IsVisible = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete a company from the database.
|
|
/// </summary>
|
|
private async void OnDeleteClicked(object sender, EventArgs e)
|
|
{
|
|
if (_selectedCompany == null)
|
|
return;
|
|
|
|
if (await DisplayAlert("Confirm", $"Delete {CompName.Text}?", "Yes", "No"))
|
|
{
|
|
try
|
|
{
|
|
_db.Execute(
|
|
"DELETE FROM Companies WHERE ID=@id",
|
|
new SqlParameter[] { new("@id", _selectedCompany["ID"]) }
|
|
);
|
|
LoadCompanies();
|
|
ClearFields();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await DisplayAlert("Error", ex.Message, "OK");
|
|
}
|
|
}
|
|
}
|
|
}
|