159 lines
5.9 KiB
C#
159 lines
5.9 KiB
C#
using System.Diagnostics;
|
|
using FrymasterBadgeApp.Services;
|
|
using Microsoft.Maui.Storage;
|
|
|
|
namespace FrymasterBadgeApp;
|
|
|
|
public partial class AppShell : Shell
|
|
{
|
|
private readonly SqlService _db;
|
|
private readonly PrinterService _printerService;
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private bool _isInitialized = false;
|
|
|
|
/// <summary>
|
|
/// AppShell is a class that contains the initialization code for the app. It is responsible for
|
|
/// loading all companies in the background and then switching to the main thread to
|
|
/// update the UI.
|
|
/// </summary>
|
|
public AppShell(SqlService db, PrinterService printerService, IServiceProvider serviceProvider)
|
|
{
|
|
InitializeComponent();
|
|
_db = db;
|
|
_printerService = printerService;
|
|
_serviceProvider = serviceProvider;
|
|
|
|
// Register pages that are NOT part of the TabBar permanently
|
|
Routing.RegisterRoute(nameof(SettingsPage), typeof(SettingsPage));
|
|
Routing.RegisterRoute(nameof(CompanyPage), typeof(CompanyPage));
|
|
Routing.RegisterRoute(nameof(EmployeePage), typeof(EmployeePage));
|
|
}
|
|
|
|
protected override async void OnAppearing()
|
|
{
|
|
base.OnAppearing();
|
|
|
|
// Using a small delay or ensuring initialization happens once
|
|
if (!_isInitialized)
|
|
{
|
|
_isInitialized = true;
|
|
await LoadCompaniesAsync();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads all companies in the background and then switches to the main thread to update the UI.
|
|
/// </summary>
|
|
private async Task LoadCompaniesAsync()
|
|
{
|
|
try
|
|
{
|
|
// 1. Fetch data in background
|
|
AppLogger.Debug("AppShell: Fetching companies");
|
|
var companies = await Task.Run(() => _db.Query("SELECT * FROM dbo.Companies", null));
|
|
|
|
// 2. Switch to Main Thread for UI changes
|
|
await MainThread.InvokeOnMainThreadAsync(async () =>
|
|
{
|
|
// Clear the "Loading" item
|
|
MainTabBar.Items.Clear();
|
|
|
|
if (companies == null || !companies.Any())
|
|
{
|
|
MainTabBar.Items.Add(
|
|
new ShellContent
|
|
{
|
|
Title = "Setup",
|
|
Route = "InitialSetup",
|
|
ContentTemplate = new DataTemplate(() =>
|
|
_serviceProvider.GetRequiredService<CompanyPage>()
|
|
),
|
|
}
|
|
);
|
|
}
|
|
else
|
|
{
|
|
foreach (var company in companies)
|
|
{
|
|
var companyId = company.GetValueOrDefault("ID")?.ToString() ?? "0";
|
|
MainTabBar.Items.Add(
|
|
new ShellContent
|
|
{
|
|
Title = company.GetValueOrDefault("Name")?.ToString() ?? "Unknown",
|
|
Route = $"EmployeePage_{companyId}",
|
|
ContentTemplate = new DataTemplate(() =>
|
|
new EmployeePage(_db, _printerService, company)
|
|
),
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
// 3. Navigate away from the Loading page to the first real tab
|
|
if (MainTabBar.Items.Count > 0)
|
|
{
|
|
var targetRoute = MainTabBar.Items[0].Route;
|
|
// The "///" is critical—it tells Shell to rebuild the navigation stack
|
|
await Shell.Current.GoToAsync($"///{targetRoute}");
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppLogger.Error("AppShell: Error loading companies", ex);
|
|
// Fallback: If DB fails, at least show the Company page
|
|
await Shell.Current.GoToAsync($"///InitialSetup");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Navigates to CompanyPage as a sub-page (pushed onto the stack).
|
|
public async void OnManageCompaniesClicked(object sender, EventArgs e)
|
|
{
|
|
// Navigates to CompanyPage as a sub-page (pushed onto the stack)
|
|
await Shell.Current.GoToAsync(nameof(CompanyPage));
|
|
}
|
|
|
|
private async void OnSettingsClicked(object sender, EventArgs e) =>
|
|
await Shell.Current.GoToAsync(nameof(SettingsPage));
|
|
|
|
/// <summary>
|
|
/// Open a simple action sheet to choose theme globally
|
|
/// </summary>
|
|
/// <param name="sender">The object that triggered the event</param>
|
|
/// <param name="e">The event arguments</param>
|
|
private async void OnThemeClicked(object sender, EventArgs e)
|
|
{
|
|
// Open a simple action sheet to choose theme globally
|
|
string action = await Shell.Current.DisplayActionSheet("Select Theme", "Cancel", null, "System", "Light", "Dark");
|
|
if (action == "Cancel" || string.IsNullOrEmpty(action))
|
|
return;
|
|
|
|
switch (action)
|
|
{
|
|
case "Light":
|
|
Application.Current.UserAppTheme = AppTheme.Light;
|
|
Preferences.Default.Set("AppTheme", "Light");
|
|
break;
|
|
case "Dark":
|
|
Application.Current.UserAppTheme = AppTheme.Dark;
|
|
Preferences.Default.Set("AppTheme", "Dark");
|
|
break;
|
|
default:
|
|
Application.Current.UserAppTheme = AppTheme.Unspecified;
|
|
Preferences.Default.Set("AppTheme", "System");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void OnExitClicked(object sender, EventArgs e) => Application.Current?.Quit();
|
|
|
|
/// <summary>
|
|
/// Open a simple action sheet to show the app's about page
|
|
/// </summary>
|
|
/// <param name="sender">The object that triggered the event</param>
|
|
/// <param name="e">The event arguments</param>
|
|
private async void OnAboutClicked(object sender, EventArgs e) =>
|
|
await DisplayAlert("About", "Frymaster Badge App v1.0", "OK");
|
|
}
|