From 8aa3f232541b76ea4bba8d87157cf884d6cce423 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Mon, 9 Feb 2026 13:34:08 -0600 Subject: [PATCH 1/9] fix: fix boxes in user list view --- .../LocationUserAdminView.razor | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor index c5ae9ff..5f33e92 100644 --- a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor +++ b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor @@ -75,25 +75,27 @@ @user.Role - @if (user.Role == "Manager") - { - + } + else + { + + } + + - } - else - { - - } - - + } From c3dc71eed83bbb51172031139d4bb8683dd7ee4f Mon Sep 17 00:00:00 2001 From: rrrockey Date: Mon, 9 Feb 2026 14:49:38 -0600 Subject: [PATCH 2/9] fix: update location settings to add Manager to location --- .../Components/Layout/NavMenu.razor | 10 ++----- .../LocationUserAdminView.razor | 28 +++++++++++++------ .../Components/Pages/Users/UserList.razor | 3 +- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/CulinaryCommandApp/Components/Layout/NavMenu.razor b/CulinaryCommandApp/Components/Layout/NavMenu.razor index fc56718..5ef9038 100644 --- a/CulinaryCommandApp/Components/Layout/NavMenu.razor +++ b/CulinaryCommandApp/Components/Layout/NavMenu.razor @@ -40,18 +40,14 @@ *@ - + @if (Auth.UserRole == "Employee") + { - - + } @if (Auth.UserRole == "Admin") { diff --git a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor index 5f33e92..aa71e77 100644 --- a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor +++ b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationUserAdminView.razor @@ -75,7 +75,7 @@ @user.Role -
+
@if (user.Role == "Manager") { } - - + @if (!(user.Role == "Admin" && user.Id == Auth.CurrentUser?.Id)) { + @* Admins shouldn't be able to remove themselves *@ + + }
@@ -177,7 +179,17 @@ if (!int.TryParse(selectedUserId, out var userId)) return; - await LocationService.AddUserToLocationAsync(LocationId, userId); + var UserToAdd = AvailableUsers.FirstOrDefault(u => u.Id == userId); + + if (UserToAdd != null) { + // add to general user mapping + await LocationService.AddUserToLocationAsync(LocationId, userId); + + // add to manager list if user is manager + if (UserToAdd.Role == "Manager") { + await LocationService.AddManagerToLocationAsync(LocationId, userId); + } + } await ReloadUsers(); HideAddExistingForm(); diff --git a/CulinaryCommandApp/Components/Pages/Users/UserList.razor b/CulinaryCommandApp/Components/Pages/Users/UserList.razor index 556c31d..dc66da7 100644 --- a/CulinaryCommandApp/Components/Pages/Users/UserList.razor +++ b/CulinaryCommandApp/Components/Pages/Users/UserList.razor @@ -57,7 +57,8 @@ else } // Now safe to load data - _users = await Users.GetAllUsersAsync(); + @* _users = await Users.GetAllUsersAsync(); *@ + _users = await Users.GetUsersByCompanyAsync(Auth.CurrentUser?.CompanyId ?? 0); StateHasChanged(); } From 21e749336ed2c0f78375b0d74ab266c4689773b9 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Mon, 9 Feb 2026 18:39:53 -0600 Subject: [PATCH 3/9] fix: fix generic tasks not showing to users --- .../Components/Pages/Assignments/MyTasks.razor | 5 +++-- CulinaryCommandApp/Components/Pages/EmployeeView.razor | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor b/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor index b74a754..1a4543a 100644 --- a/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor +++ b/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor @@ -34,7 +34,7 @@ else {

Welcome, @username

-
Location: @SelectedLocationName
+
Location: @SelectedLocationName (@LocationState.CurrentLocation?.Id)
Here's what needs your attention today.
@if (prepTasks is null || prepTasks.Count == 0) @@ -104,10 +104,11 @@ else allTasks = await TaskService.GetForUserAsync(Auth.UserId.Value, selectedLocationId); prepTasks = allTasks - .Where(t => t.Kind == WorkTaskKind.PrepFromRecipe) + @* .Where(t => t.Kind == WorkTaskKind.PrepFromRecipe) *@ .Where(t => !string.Equals(t.Status, "Completed", StringComparison.OrdinalIgnoreCase)) .OrderBy(t => t.DueDate) .ToList(); + } finally { diff --git a/CulinaryCommandApp/Components/Pages/EmployeeView.razor b/CulinaryCommandApp/Components/Pages/EmployeeView.razor index 0f988e2..9a5c8fa 100644 --- a/CulinaryCommandApp/Components/Pages/EmployeeView.razor +++ b/CulinaryCommandApp/Components/Pages/EmployeeView.razor @@ -5,7 +5,7 @@
  • View your active tasks and prep items
  • -
  • Check your assigned location: @LocationState.CurrentLocation
  • +
  • Check your assigned location: @(LocationState.CurrentLocation?.Name ?? "Not assigned")
  • Submit updates to your manager
From 4927aed35ad7c8e7b0302041d76edd98a38b4197 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Mon, 9 Feb 2026 19:03:48 -0600 Subject: [PATCH 4/9] fix: fix location not updating for employee dashboard --- .../Pages/Assignments/MyTasks.razor | 2 +- .../Components/Pages/EmployeeView.razor | 23 +++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor b/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor index 1a4543a..152b9f2 100644 --- a/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor +++ b/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor @@ -34,7 +34,7 @@ else {

Welcome, @username

-
Location: @SelectedLocationName (@LocationState.CurrentLocation?.Id)
+
Location: @SelectedLocationName
Here's what needs your attention today.
@if (prepTasks is null || prepTasks.Count == 0) diff --git a/CulinaryCommandApp/Components/Pages/EmployeeView.razor b/CulinaryCommandApp/Components/Pages/EmployeeView.razor index 9a5c8fa..b066f23 100644 --- a/CulinaryCommandApp/Components/Pages/EmployeeView.razor +++ b/CulinaryCommandApp/Components/Pages/EmployeeView.razor @@ -1,7 +1,8 @@ @rendermode InteractiveServer +@implements IDisposable

Employee Dashboard

-

Welcome, @Auth.CurrentUser.Name!

+

Welcome, @(Auth.CurrentUser?.Name ?? "User")!

  • View your active tasks and prep items
  • @@ -12,6 +13,24 @@ @code { [Inject] private CulinaryCommand.Services.AuthService Auth { get; set; } = default!; - [Inject] private CulinaryCommand.Services.LocationState LocationState { get; set; } = default!; + [Inject] private CulinaryCommand.Services.LocationState LocationState { get; set; } = default!; + private async void HandleLocationStateChanged() + { + await InvokeAsync(async () => + { + StateHasChanged(); + }); + } + + protected override void OnInitialized() + { + // Subscribe to the change event + LocationState.OnChange += HandleLocationStateChanged; + } + + public void Dispose() + { + LocationState.OnChange -= HandleLocationStateChanged; + } } From fff7edf66a1d969aebe0812e0c48a6aafde17e98 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Mon, 9 Feb 2026 19:39:22 -0600 Subject: [PATCH 5/9] fix: update user edit to only show locations within company --- .../Components/Custom/UserLocationTagPicker.razor | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CulinaryCommandApp/Components/Custom/UserLocationTagPicker.razor b/CulinaryCommandApp/Components/Custom/UserLocationTagPicker.razor index ed240c3..aaefd25 100644 --- a/CulinaryCommandApp/Components/Custom/UserLocationTagPicker.razor +++ b/CulinaryCommandApp/Components/Custom/UserLocationTagPicker.razor @@ -1,5 +1,6 @@ @using CulinaryCommand.Data.Entities @inject ILocationService LocationService +@inject AuthService Auth @rendermode InteractiveServer
    @@ -52,7 +53,7 @@ protected override async Task OnInitializedAsync() { - AllLocations = await LocationService.GetAllLocationsAsync(); + AllLocations = await LocationService.GetLocationsByCompanyAsync(Auth.CurrentUser?.CompanyId); RefreshLists(); } From 468ca6c601d74818bb942d096255b9cf7bb25201 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Tue, 10 Feb 2026 09:37:43 -0600 Subject: [PATCH 6/9] fix: fix location picker not updating location in the admin user page + restructure nav bar --- .../Components/Layout/NavMenu.razor | 53 ++++--------------- .../Components/Pages/AdminView.razor | 2 +- .../Components/Pages/ManagerView.razor | 2 +- .../Components/Pages/Users/Edit.razor | 1 + .../Components/Pages/Users/UserForm.razor | 9 +++- 5 files changed, 21 insertions(+), 46 deletions(-) diff --git a/CulinaryCommandApp/Components/Layout/NavMenu.razor b/CulinaryCommandApp/Components/Layout/NavMenu.razor index 5ef9038..49be8e9 100644 --- a/CulinaryCommandApp/Components/Layout/NavMenu.razor +++ b/CulinaryCommandApp/Components/Layout/NavMenu.razor @@ -27,19 +27,6 @@
    - @* *@ - - - @* *@ - @if (Auth.UserRole == "Employee") { } - - @if (Auth.UserRole == "Admin") - { - - + else { @* admin or manager *@ - - - } - else if (Auth.UserRole == "Manager") - { + + + } + @if (Auth.UserRole == "Admin") + { } diff --git a/CulinaryCommandApp/Components/Pages/AdminView.razor b/CulinaryCommandApp/Components/Pages/AdminView.razor index d40d810..307be3f 100644 --- a/CulinaryCommandApp/Components/Pages/AdminView.razor +++ b/CulinaryCommandApp/Components/Pages/AdminView.razor @@ -16,7 +16,7 @@ + Link="/inventory-management" />
diff --git a/CulinaryCommandApp/Components/Pages/ManagerView.razor b/CulinaryCommandApp/Components/Pages/ManagerView.razor index ee7c476..b9f6768 100644 --- a/CulinaryCommandApp/Components/Pages/ManagerView.razor +++ b/CulinaryCommandApp/Components/Pages/ManagerView.razor @@ -34,7 +34,7 @@ + Link="/inventory-management" />
diff --git a/CulinaryCommandApp/Components/Pages/Users/Edit.razor b/CulinaryCommandApp/Components/Pages/Users/Edit.razor index 089e12f..6ea6a24 100644 --- a/CulinaryCommandApp/Components/Pages/Users/Edit.razor +++ b/CulinaryCommandApp/Components/Pages/Users/Edit.razor @@ -39,6 +39,7 @@ else { await UserService.UpdateUserAsync(u); await UserService.AssignLocationsAsync(u.Id, u.UserLocations.Select(x => x.LocationId).ToList()); + Nav.NavigateTo("/users"); } } diff --git a/CulinaryCommandApp/Components/Pages/Users/UserForm.razor b/CulinaryCommandApp/Components/Pages/Users/UserForm.razor index 4e339e9..1f2ff0f 100644 --- a/CulinaryCommandApp/Components/Pages/Users/UserForm.razor +++ b/CulinaryCommandApp/Components/Pages/Users/UserForm.razor @@ -58,7 +58,14 @@ async Task Save() { - await OnValidSubmit.InvokeAsync(Model); + // force the sync from the list of IDs into the model's collection + Model.UserLocations = AssignedLocationIds.Select(id => new UserLocation + { + UserId = Model.Id, + LocationId = id + }).ToList(); + + await OnValidSubmit.InvokeAsync(Model); } void Cancel() => Nav.NavigateTo("/users"); From b84e96b739fb35ccf3768e248639e5dd90af60b0 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Tue, 10 Feb 2026 12:34:43 -0600 Subject: [PATCH 7/9] fix: update UserService to update manager status within /users page --- CulinaryCommandApp/Services/UserService.cs | 42 +++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/CulinaryCommandApp/Services/UserService.cs b/CulinaryCommandApp/Services/UserService.cs index a39dc5e..8ccfcec 100644 --- a/CulinaryCommandApp/Services/UserService.cs +++ b/CulinaryCommandApp/Services/UserService.cs @@ -86,7 +86,10 @@ public async Task> GetUsersByCompanyAsync(int companyId) public async Task UpdateUserAsync(User user) { - var existing = await _context.Users.FindAsync(user.Id); + var existing = await _context.Users + .Include(u => u.UserLocations) + .Include(u => u.ManagerLocations) + .FirstOrDefaultAsync(u => u.Id == user.Id); if (existing == null) return; existing.Name = user.Name; @@ -95,6 +98,43 @@ public async Task UpdateUserAsync(User user) existing.Phone = user.Phone; existing.UpdatedAt = DateTime.UtcNow; + // get the list of IDs from the incoming model + var newUserLocationIds = user.UserLocations.Select(ul => ul.LocationId).ToList(); + + // sync user-locations (general access) + var toRemoveUL = existing.UserLocations.Where(ul => !newUserLocationIds.Contains(ul.LocationId)).ToList(); + foreach (var ul in toRemoveUL) existing.UserLocations.Remove(ul); + + foreach (var locId in newUserLocationIds) + { + if (!existing.UserLocations.Any(ul => ul.LocationId == locId)) + { + existing.UserLocations.Add(new UserLocation { UserId = user.Id, LocationId = locId }); + } + } + + // sync manager-locations (manager access) + if (string.Equals(existing.Role, "Manager", StringComparison.OrdinalIgnoreCase)) + { + // remove manager records for locations no longer assigned + var toRemoveML = existing.ManagerLocations.Where(ml => !newUserLocationIds.Contains(ml.LocationId)).ToList(); + foreach (var ml in toRemoveML) existing.ManagerLocations.Remove(ml); + + // add manager records for new locations + foreach (var locId in newUserLocationIds) + { + if (!existing.ManagerLocations.Any(ml => ml.LocationId == locId)) + { + existing.ManagerLocations.Add(new ManagerLocation { UserId = user.Id, LocationId = locId }); + } + } + } + else + { + // if role was changed from Manager to something else, wipe manager entries + existing.ManagerLocations.Clear(); + } + await _context.SaveChangesAsync(); } From de648220a1ed6773c70e4ea5cd6dbef063d772e5 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Wed, 11 Feb 2026 10:29:15 -0600 Subject: [PATCH 8/9] fix: get locationState (mostly) working by fixing AI dashboard freezing app --- .../Pages/Assignments/MyTasks.razor | 1 + .../Components/Pages/Dashboard.razor | 32 +++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor b/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor index 152b9f2..31604c8 100644 --- a/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor +++ b/CulinaryCommandApp/Components/Pages/Assignments/MyTasks.razor @@ -79,6 +79,7 @@ else selectedLocationId = LocationState.CurrentLocation?.Id; + LocationState.OnChange -= HandleLocationStateChanged; LocationState.OnChange += HandleLocationStateChanged; await LoadTasksAsync(); diff --git a/CulinaryCommandApp/Components/Pages/Dashboard.razor b/CulinaryCommandApp/Components/Pages/Dashboard.razor index 9ec92df..c2b1390 100644 --- a/CulinaryCommandApp/Components/Pages/Dashboard.razor +++ b/CulinaryCommandApp/Components/Pages/Dashboard.razor @@ -149,12 +149,12 @@ else protected override async Task OnAfterRenderAsync(bool firstRender) { - + if (!firstRender) return; await Auth.EnsureHydratedAsync(); // safe here (interactive) _ready = true; StateHasChanged(); - if (!_aiLoadedOnce) + if (!_aiLoadedOnce && Auth.IsSignedIn) { _aiLoadedOnce = true; _aiLoading = true; @@ -162,25 +162,29 @@ else // Get analysis: - var csvPath = Path.Combine(Env.ContentRootPath, "AIDashboard", "Services", "Reporting", "test_data.csv"); - _aiAnalysis = await ReportingService.AnalyzeCsvAsync(csvPath); - - // Try to deserialize the returned JSON into the DTO so we can render structured cards UI. - if (!string.IsNullOrWhiteSpace(_aiAnalysis)) + try { - try + var csvPath = Path.Combine(Env.ContentRootPath, "AIDashboard", "Services", "Reporting", "test_data.csv"); + _aiAnalysis = await ReportingService.AnalyzeCsvAsync(csvPath); + + // Try to deserialize the returned JSON into the DTO so we can render structured cards UI. + if (!string.IsNullOrWhiteSpace(_aiAnalysis)) { var options = new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true }; _aiAnalysisObj = System.Text.Json.JsonSerializer.Deserialize(_aiAnalysis, options); } - catch - { - _aiAnalysisObj = null; - } } + catch(Exception e) + { + Console.WriteLine($"AI Analysis failed: {e.Message}"); + _aiAnalysisObj = null; + _aiAnalysis = null; - _aiLoading = false; - StateHasChanged(); + } + finally { + _aiLoading = false; + StateHasChanged(); + } } } From 5260281dc4ba856436d35aeafe01dec50c5d6556 Mon Sep 17 00:00:00 2001 From: rrrockey Date: Wed, 11 Feb 2026 13:52:54 -0600 Subject: [PATCH 9/9] fix: show all locations employees work at in settings --- .../Components/Layout/MainLayout.razor | 3 +++ .../LocationEmployeeView.razor | 20 ++++++++++++++++--- .../LocationSettings/SettingsLocations.razor | 8 ++++---- CulinaryCommandApp/Services/LocationState.cs | 20 +++++++++++++++++-- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/CulinaryCommandApp/Components/Layout/MainLayout.razor b/CulinaryCommandApp/Components/Layout/MainLayout.razor index 1c00367..d507af9 100644 --- a/CulinaryCommandApp/Components/Layout/MainLayout.razor +++ b/CulinaryCommandApp/Components/Layout/MainLayout.razor @@ -3,6 +3,7 @@ @using CulinaryCommand.Services @inject CulinaryCommand.Services.AuthService Auth @inject NavigationManager Nav +@inject LocationState LocationState @using System.Threading.Tasks @rendermode InteractiveServer @@ -30,6 +31,8 @@ if (!firstRender || _hydrated) return; + await LocationState.HydrateAsync(); + var path = Nav.Uri.ToLowerInvariant(); if (!path.Contains("/signin") && !path.Contains("/signup") && !path.Contains("/adminsignup")) { diff --git a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationEmployeeView.razor b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationEmployeeView.razor index 76ebd4a..9538df1 100644 --- a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationEmployeeView.razor +++ b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/LocationEmployeeView.razor @@ -1,6 +1,20 @@ @using CulinaryCommand.Data.Entities @inject AuthService Auth -
+ +@foreach (var loc in Locations) +{ +
+
+
+
@loc.Name
+

@loc.Address

+ @loc.City, @loc.State @loc.ZipCode +
+
+
+} + +@*

@Auth.Company

@@ -15,8 +29,8 @@

@Location.City, @Location.State @Location.ZipCode

} -
+
*@ @code { - [Parameter] public Location? Location { get; set; } + [Parameter] public List Locations { get; set; } = new List(); } \ No newline at end of file diff --git a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/SettingsLocations.razor b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/SettingsLocations.razor index d5d5df9..176253e 100644 --- a/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/SettingsLocations.razor +++ b/CulinaryCommandApp/Components/Pages/UserSettings/LocationSettings/SettingsLocations.razor @@ -26,9 +26,9 @@ Locations="locations" OnEdit="Update" /> } - else + else // Auth.UserRole == "Employee" { - + } }
@@ -70,8 +70,8 @@ } else { - employeeLocation = (await LocationService.GetLocationsByEmployeeAsync(Auth.UserId!.Value)) - .FirstOrDefault(); + locations = await LocationService.GetLocationsByEmployeeAsync(Auth.UserId!.Value); + } } diff --git a/CulinaryCommandApp/Services/LocationState.cs b/CulinaryCommandApp/Services/LocationState.cs index b6221f1..d3e3ede 100644 --- a/CulinaryCommandApp/Services/LocationState.cs +++ b/CulinaryCommandApp/Services/LocationState.cs @@ -15,7 +15,6 @@ namespace CulinaryCommand.Services public class LocationState { private readonly IJSRuntime _js; - public List ManagedLocations { get; private set; } = new(); public Location? CurrentLocation { get; private set; } @@ -26,6 +25,22 @@ public LocationState(IJSRuntime js) _js = js; } + private void NotifyStateChanged() => OnChange?.Invoke(); + + public async Task HydrateAsync() + { + if (CurrentLocation != null) return; // Already have it + + var savedId = await _js.InvokeAsync("localStorage.getItem", "cc_selected_location_id"); + + if (!string.IsNullOrEmpty(savedId) && int.TryParse(savedId, out int id)) + { + // Assuming you've loaded your ManagedLocations list already + CurrentLocation = ManagedLocations.FirstOrDefault(l => l.Id == id); + NotifyStateChanged(); + } + } + public async Task SetLocationsAsync(List locations) { ManagedLocations = locations ?? new List(); @@ -51,7 +66,8 @@ public async Task SetCurrentLocationAsync(Location loc) // Persist to localStorage await _js.InvokeVoidAsync("localStorage.setItem", "cc_activeLocationId", loc.Id); - OnChange?.Invoke(); + // OnChange?.Invoke(); + NotifyStateChanged(); } }