fix: persist selected household across refresh
This commit is contained in:
parent
af0d95432f
commit
12b514262e
@ -2,6 +2,8 @@ import { createContext, useCallback, useContext, useEffect, useState } from 'rea
|
||||
import { createHousehold as createHouseholdApi, getUserHouseholds } from '../api/households';
|
||||
import { AuthContext } from './AuthContext';
|
||||
|
||||
const ACTIVE_HOUSEHOLD_STORAGE_KEY = 'activeHouseholdId';
|
||||
|
||||
export const HouseholdContext = createContext({
|
||||
households: [],
|
||||
activeHousehold: null,
|
||||
@ -23,7 +25,7 @@ export const HouseholdProvider = ({ children }) => {
|
||||
|
||||
const clearActiveHousehold = useCallback(() => {
|
||||
setActiveHouseholdState(null);
|
||||
localStorage.removeItem('activeHouseholdId');
|
||||
localStorage.removeItem(ACTIVE_HOUSEHOLD_STORAGE_KEY);
|
||||
}, []);
|
||||
|
||||
const loadHouseholds = useCallback(async () => {
|
||||
@ -32,10 +34,8 @@ export const HouseholdProvider = ({ children }) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
console.log('[HouseholdContext] Loading households...');
|
||||
const response = await getUserHouseholds();
|
||||
const nextHouseholds = Array.isArray(response.data) ? response.data : [];
|
||||
console.log('[HouseholdContext] Loaded households:', nextHouseholds);
|
||||
setHouseholds(nextHouseholds);
|
||||
|
||||
if (nextHouseholds.length === 0) {
|
||||
@ -69,33 +69,30 @@ export const HouseholdProvider = ({ children }) => {
|
||||
// Load active household from localStorage on mount
|
||||
useEffect(() => {
|
||||
if (households.length === 0) {
|
||||
clearActiveHousehold();
|
||||
setActiveHouseholdState(null);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[HouseholdContext] Setting active household from:', households);
|
||||
const savedHouseholdId = localStorage.getItem('activeHouseholdId');
|
||||
const savedHouseholdId = localStorage.getItem(ACTIVE_HOUSEHOLD_STORAGE_KEY);
|
||||
if (savedHouseholdId) {
|
||||
const household = households.find(h => h.id === parseInt(savedHouseholdId, 10));
|
||||
const household = households.find((candidate) => String(candidate.id) === savedHouseholdId);
|
||||
if (household) {
|
||||
console.log('[HouseholdContext] Found saved household:', household);
|
||||
setActiveHouseholdState(household);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No saved household or not found, use first one
|
||||
console.log('[HouseholdContext] Using first household:', households[0]);
|
||||
setActiveHouseholdState(households[0]);
|
||||
localStorage.setItem('activeHouseholdId', households[0].id);
|
||||
}, [clearActiveHousehold, households]);
|
||||
localStorage.setItem(ACTIVE_HOUSEHOLD_STORAGE_KEY, String(households[0].id));
|
||||
}, [households]);
|
||||
|
||||
const setActiveHousehold = (household) => {
|
||||
setActiveHouseholdState(household);
|
||||
if (household) {
|
||||
localStorage.setItem('activeHouseholdId', household.id);
|
||||
localStorage.setItem(ACTIVE_HOUSEHOLD_STORAGE_KEY, String(household.id));
|
||||
} else {
|
||||
localStorage.removeItem('activeHouseholdId');
|
||||
localStorage.removeItem(ACTIVE_HOUSEHOLD_STORAGE_KEY);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
103
frontend/tests/household-selection-persistence.spec.ts
Normal file
103
frontend/tests/household-selection-persistence.spec.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
function seedAuthStorage(page: import("@playwright/test").Page) {
|
||||
return page.addInitScript(() => {
|
||||
localStorage.setItem("token", "test-token");
|
||||
localStorage.setItem("userId", "1");
|
||||
localStorage.setItem("role", "admin");
|
||||
localStorage.setItem("username", "persistent-user");
|
||||
});
|
||||
}
|
||||
|
||||
async function mockConfig(page: import("@playwright/test").Page) {
|
||||
await page.route("**/config", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
maxFileSizeMB: 20,
|
||||
maxImageDimension: 800,
|
||||
imageQuality: 85,
|
||||
}),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
test("selected household stays active after refreshing on settings and home pages", async ({ page }) => {
|
||||
await seedAuthStorage(page);
|
||||
await mockConfig(page);
|
||||
|
||||
const households = [
|
||||
{ id: 1, name: "Alpha Home", role: "owner" },
|
||||
{ id: 2, name: "Bravo Home", role: "admin" },
|
||||
];
|
||||
|
||||
const storesByHousehold = {
|
||||
1: [{ id: 101, name: "Costco", is_default: true }],
|
||||
2: [{ id: 201, name: "Trader Joe's", is_default: true }],
|
||||
};
|
||||
|
||||
await page.route("**/households", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify(households),
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/stores/household/*", async (route) => {
|
||||
const householdId = Number(route.request().url().split("/").pop());
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify(
|
||||
storesByHousehold[householdId as keyof typeof storesByHousehold] ?? []
|
||||
),
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/households/*/stores/*/list/recent", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([]),
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/households/*/stores/*/list", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ items: [] }),
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/households/*/members", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([{ id: 1, username: "persistent-user", role: "owner" }]),
|
||||
});
|
||||
});
|
||||
|
||||
await page.goto("/");
|
||||
|
||||
await expect(page.getByRole("button", { name: "Alpha Home" })).toBeVisible();
|
||||
|
||||
await page.getByRole("button", { name: "Alpha Home" }).click();
|
||||
await page.getByRole("button", { name: "Bravo Home" }).click();
|
||||
|
||||
await expect(page.getByRole("button", { name: "Bravo Home" })).toBeVisible();
|
||||
await expect.poll(() => page.evaluate(() => localStorage.getItem("activeHouseholdId"))).toBe("2");
|
||||
|
||||
await page.goto("/settings");
|
||||
await expect(page.getByRole("button", { name: "Bravo Home" })).toBeVisible();
|
||||
|
||||
await page.reload();
|
||||
await expect(page.getByRole("button", { name: "Bravo Home" })).toBeVisible();
|
||||
await expect.poll(() => page.evaluate(() => localStorage.getItem("activeHouseholdId"))).toBe("2");
|
||||
|
||||
await page.goto("/");
|
||||
await expect(page.getByRole("button", { name: "Bravo Home" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Trader Joe's" })).toBeVisible();
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user