Sprawdzone lokalizacje w Historii cen zapisane na koncie
Deploy Polska Lokalnie / deploy (push) Successful in 12s
Deploy Polska Lokalnie / deploy (push) Successful in 12s
Lista ostatnio sprawdzonych lokalizacji zyla w localStorage, wiec ginela przy zmianie urzadzenia. Teraz jest polem ustawien konta (user_settings.price_history_markets), a wpisy z przegladarki przenosimy raz przy pierwszym wejsciu. To historia przegladania, nie alerty - nic z niej nie wysyla powiadomien. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+51
-7
@@ -444,7 +444,27 @@ function toSavedSearchPayload(search: SavedSearchRecord | SavedSearchDraft) {
|
||||
};
|
||||
}
|
||||
// Lokalizacje, ktorych cene za m2 sprawdzil uzytkownik - najnowsza pierwsza, przechowywane per konto.
|
||||
// Klucz zostaje tylko po to, zeby raz przeniesc na konto lokalizacje zapisane w przegladarce
|
||||
// przed przeniesieniem tej listy na serwer.
|
||||
const PRICE_HISTORY_MARKETS_SUFFIX = 'price-history-markets';
|
||||
|
||||
function parsePriceHistoryMarkets(raw: string | null): PriceHistoryMarket[] {
|
||||
if (!raw) {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed) ? parsed.filter((item) => item && typeof item.key === 'string') : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** Lista lokalizacji z Historii cen jest ustawieniem konta - zapisujemy ja przy kazdej zmianie. */
|
||||
function savePriceHistoryMarkets(markets: PriceHistoryMarket[]): void {
|
||||
apiFetch<unknown>('/me/settings', { method: 'PUT', body: JSON.stringify({ priceHistoryMarkets: JSON.stringify(markets) }) })
|
||||
.catch(() => { /* brak sieci - lista wroci do stanu z konta przy nastepnym wejsciu */ });
|
||||
}
|
||||
const PRICE_HISTORY_MARKETS_LIMIT = 5;
|
||||
const PRICE_ALERT_EVENTS_LIMIT = 40;
|
||||
const SAVED_SEARCHES_LIMIT = 60;
|
||||
@@ -21484,9 +21504,33 @@ function PriceHistoryPage({ user }: { user: AuthUser | null }) {
|
||||
const [suggestLoading, setSuggestLoading] = useState(false);
|
||||
const [hoveredHistoryIndex, setHoveredHistoryIndex] = useState<number | null>(null);
|
||||
// Historia sprawdzonych lokalizacji tego konta - najnowsza na poczatku, maksymalnie 5 pozycji.
|
||||
const [recentMarkets, setRecentMarkets] = useState<PriceHistoryMarket[]>(
|
||||
() => readUserJsonStorage<PriceHistoryMarket[]>(user, PRICE_HISTORY_MARKETS_SUFFIX, []),
|
||||
);
|
||||
// Lista siedzi w ustawieniach konta (/api/me/settings), wiec porownanie wyglada tak samo
|
||||
// na kazdym urzadzeniu. Wpisy z przegladarki przenosimy raz, przy pierwszym wejsciu.
|
||||
const [recentMarkets, setRecentMarkets] = useState<PriceHistoryMarket[]>([]);
|
||||
useEffect(() => {
|
||||
if (!user) {
|
||||
setRecentMarkets([]);
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
const local = readUserJsonStorage<PriceHistoryMarket[]>(user, PRICE_HISTORY_MARKETS_SUFFIX, []);
|
||||
apiFetch<{ priceHistoryMarkets: string | null }>('/me/settings')
|
||||
.then((settings) => {
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
const fromAccount = parsePriceHistoryMarkets(settings.priceHistoryMarkets);
|
||||
if (fromAccount.length === 0 && local.length > 0) {
|
||||
setRecentMarkets(local);
|
||||
savePriceHistoryMarkets(local);
|
||||
} else {
|
||||
setRecentMarkets(fromAccount);
|
||||
}
|
||||
writeUserJsonStorage<PriceHistoryMarket[]>(user, PRICE_HISTORY_MARKETS_SUFFIX, []);
|
||||
})
|
||||
.catch(() => { if (!cancelled) { setRecentMarkets(local); } });
|
||||
return () => { cancelled = true; };
|
||||
}, [user]);
|
||||
// Ostatnio otwarte oferte (sprzedaz i wynajem) - wspolny rejestr zasilany przy wejsciu na oferte.
|
||||
const recentListings = useMemo(() => readRecentlyViewed(user).slice(0, RECENTLY_VIEWED_PANEL_LIMIT), [user]);
|
||||
const skipNextFetch = useRef(false);
|
||||
@@ -21719,7 +21763,7 @@ function PriceHistoryPage({ user }: { user: AuthUser | null }) {
|
||||
// Nowa lokalizacja wchodzi na poczatek listy, najstarsza wypada po przekroczeniu limitu.
|
||||
setRecentMarkets((current) => {
|
||||
const next = [market, ...current.filter((item) => item.key !== market.key)].slice(0, PRICE_HISTORY_MARKETS_LIMIT);
|
||||
writeUserJsonStorage(user, PRICE_HISTORY_MARKETS_SUFFIX, next);
|
||||
savePriceHistoryMarkets(next);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
@@ -21729,18 +21773,18 @@ function PriceHistoryPage({ user }: { user: AuthUser | null }) {
|
||||
};
|
||||
|
||||
// Usuwanie pojedynczej lokalizacji z porownania i czyszczenie calej listy - zapis leci od razu
|
||||
// do pamieci konta, zeby stan zgadzal sie po odswiezeniu strony.
|
||||
// na konto, zeby stan zgadzal sie po odswiezeniu i na innym urzadzeniu.
|
||||
const removeComparison = (marketKey: string) => {
|
||||
setRecentMarkets((current) => {
|
||||
const next = current.filter((item) => item.key !== marketKey);
|
||||
writeUserJsonStorage(user, PRICE_HISTORY_MARKETS_SUFFIX, next);
|
||||
savePriceHistoryMarkets(next);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
const clearComparisons = () => {
|
||||
setRecentMarkets([]);
|
||||
writeUserJsonStorage(user, PRICE_HISTORY_MARKETS_SUFFIX, []);
|
||||
savePriceHistoryMarkets([]);
|
||||
};
|
||||
|
||||
// Wejscie z adresu z parametrami (np. "Zobacz historie cen" przy alercie lokalizacji)
|
||||
|
||||
@@ -37,6 +37,8 @@ export type UserSettings = {
|
||||
notifyPriceAlerts: boolean;
|
||||
notifyMessages: boolean;
|
||||
notifyProductNews: boolean;
|
||||
// Lokalizacje sprawdzone w Historii cen (JSON) - historia przegladania, bez powiadomien.
|
||||
priceHistoryMarkets: string | null;
|
||||
searchLocations: string | null;
|
||||
searchPropertyType: string | null;
|
||||
searchBudgetMax: number | null;
|
||||
|
||||
@@ -597,3 +597,25 @@ test.describe('Ulubione', () => {
|
||||
await expect(page.locator('main')).not.toContainText(title.trim().slice(0, 20));
|
||||
});
|
||||
});
|
||||
|
||||
// Lista sprawdzonych lokalizacji w Historii cen jest ustawieniem konta, nie pamiecia przegladarki.
|
||||
test.describe('Historia cen', () => {
|
||||
test('sprawdzone lokalizacje przezywaja wyczyszczenie pamieci przegladarki', async ({ page }) => {
|
||||
await login(page);
|
||||
await goto(page, ROUTES.priceHistory);
|
||||
await page.locator('.history-location-display').click();
|
||||
await page.locator('.history-location-pop input').fill('Kraków');
|
||||
await page.locator('.history-location-pop button', { hasText: 'Kraków' }).first().click();
|
||||
await expect(page.locator('main')).toContainText('Kraków');
|
||||
|
||||
await page.evaluate(() => {
|
||||
const token = window.localStorage.getItem('polskalokalnie-auth-token');
|
||||
window.localStorage.clear();
|
||||
if (token) {
|
||||
window.localStorage.setItem('polskalokalnie-auth-token', token);
|
||||
}
|
||||
});
|
||||
await goto(page, ROUTES.priceHistory);
|
||||
await expect(page.locator('main')).toContainText('Kraków');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user