Historia ogladania i uklad panelu osobno dla kazdego konta
Deploy Polska Lokalnie / deploy (push) Successful in 11s

Oba klucze byly globalne dla przegladarki, wiec na wspolnym komputerze
jedno konto widzialo, czego szukalo drugie, i nadpisywalo mu uklad
kafelkow. Teraz oba siedza pod accountProfile:<id>:*.

Zapis do historii czeka na zakonczenie wczytywania konta - wczesniej
oferta otwarta zaraz po wejsciu trafiala do historii "goscia".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-23 11:43:44 +02:00
parent d6b6e3edd9
commit 45a32d7ef0
+48 -27
View File
@@ -224,16 +224,18 @@ type RecentlyViewedItem = {
photo: string | null; photo: string | null;
}; };
const RECENTLY_VIEWED_KEY = 'polskalokalnie-recently-viewed'; // Historia ogladania jest osobna dla kazdego konta - na wspolnym komputerze jedna osoba
// nie moze zobaczyc, czego szukala druga.
const RECENTLY_VIEWED_SUFFIX = 'recently-viewed';
// Ile ostatnio otwartych ofert pokazuje panel "Ostatnio przeglądane". // Ile ostatnio otwartych ofert pokazuje panel "Ostatnio przeglądane".
const RECENTLY_VIEWED_PANEL_LIMIT = 5; const RECENTLY_VIEWED_PANEL_LIMIT = 5;
function readRecentlyViewed(): RecentlyViewedItem[] { function readRecentlyViewed(user: AuthUser | null): RecentlyViewedItem[] {
if (typeof window === 'undefined') { if (typeof window === 'undefined') {
return []; return [];
} }
try { try {
const raw = window.localStorage.getItem(RECENTLY_VIEWED_KEY); const raw = window.localStorage.getItem(accountStorageKey(RECENTLY_VIEWED_SUFFIX, user));
const parsed = raw ? JSON.parse(raw) : []; const parsed = raw ? JSON.parse(raw) : [];
return Array.isArray(parsed) ? parsed : []; return Array.isArray(parsed) ? parsed : [];
} catch { } catch {
@@ -241,14 +243,14 @@ function readRecentlyViewed(): RecentlyViewedItem[] {
} }
} }
function pushRecentlyViewed(item: RecentlyViewedItem): void { function pushRecentlyViewed(item: RecentlyViewedItem, user: AuthUser | null): void {
if (typeof window === 'undefined') { if (typeof window === 'undefined') {
return; return;
} }
try { try {
const list = readRecentlyViewed().filter((entry) => entry.id !== item.id); const list = readRecentlyViewed(user).filter((entry) => entry.id !== item.id);
list.unshift(item); list.unshift(item);
window.localStorage.setItem(RECENTLY_VIEWED_KEY, JSON.stringify(list.slice(0, 12))); window.localStorage.setItem(accountStorageKey(RECENTLY_VIEWED_SUFFIX, user), JSON.stringify(list.slice(0, 12)));
} catch { } catch {
/* brak dostepu do localStorage - pomijamy */ /* brak dostepu do localStorage - pomijamy */
} }
@@ -6653,18 +6655,19 @@ function AccountDashboardPage({
order: number; order: number;
}; };
const dashboardWidgetsStorageKey = 'polskalokalnie-dashboard-widgets'; // Uklad kafelkow to personalizacja konta - na wspolnym komputerze kazde konto ma swoj.
const dashboardWidgetsStorageKey = accountStorageKey('dashboard-widgets', user);
// Realne dane panelu: ostatnio oglądane oferty (localStorage) i alerty cenowe użytkownika // Realne dane panelu: ostatnio oglądane oferty (localStorage) i alerty cenowe użytkownika
// (to samo źródło co strona /konto/alerty-cenowe). // (to samo źródło co strona /konto/alerty-cenowe).
const [recentlyViewed, setRecentlyViewed] = useState<RecentlyViewedItem[]>(() => readRecentlyViewed()); const [recentlyViewed, setRecentlyViewed] = useState<RecentlyViewedItem[]>(() => readRecentlyViewed(user));
const [cityAlerts, setCityAlerts] = useState<CityPriceAlertSubscription[]>( const [cityAlerts, setCityAlerts] = useState<CityPriceAlertSubscription[]>(
() => readUserJsonStorage<CityPriceAlertSubscription[]>(user, CITY_PRICE_ALERTS_STORAGE_SUFFIX, []), () => readUserJsonStorage<CityPriceAlertSubscription[]>(user, CITY_PRICE_ALERTS_STORAGE_SUFFIX, []),
); );
// Po zmianie konta wczytujemy dane właściwego użytkownika. // Po zmianie konta wczytujemy dane właściwego użytkownika.
useEffect(() => { useEffect(() => {
setRecentlyViewed(readRecentlyViewed()); setRecentlyViewed(readRecentlyViewed(user));
setCityAlerts(readUserJsonStorage<CityPriceAlertSubscription[]>(user, CITY_PRICE_ALERTS_STORAGE_SUFFIX, [])); setCityAlerts(readUserJsonStorage<CityPriceAlertSubscription[]>(user, CITY_PRICE_ALERTS_STORAGE_SUFFIX, []));
}, [user]); }, [user]);
@@ -6707,9 +6710,9 @@ function AccountDashboardPage({
const [isWidgetEditorOpen, setIsWidgetEditorOpen] = useState(false); const [isWidgetEditorOpen, setIsWidgetEditorOpen] = useState(false);
const [draggedWidgetId, setDraggedWidgetId] = useState<DashboardWidgetId | null>(null); const [draggedWidgetId, setDraggedWidgetId] = useState<DashboardWidgetId | null>(null);
const [dragOverWidgetId, setDragOverWidgetId] = useState<DashboardWidgetId | null>(null); const [dragOverWidgetId, setDragOverWidgetId] = useState<DashboardWidgetId | null>(null);
const [dashboardWidgets, setDashboardWidgets] = useState<DashboardWidgetConfig[]>(() => { const readDashboardWidgets = (storageKey: string): DashboardWidgetConfig[] => {
try { try {
const raw = window.localStorage.getItem(dashboardWidgetsStorageKey); const raw = window.localStorage.getItem(storageKey);
if (!raw) { if (!raw) {
return defaultDashboardWidgets; return defaultDashboardWidgets;
} }
@@ -6732,11 +6735,21 @@ function AccountDashboardPage({
} catch { } catch {
return defaultDashboardWidgets; return defaultDashboardWidgets;
} }
}); };
const [dashboardWidgets, setDashboardWidgets] = useState<DashboardWidgetConfig[]>(
() => readDashboardWidgets(dashboardWidgetsStorageKey),
);
// Po zmianie konta wczytujemy uklad wlasciwego uzytkownika, zeby nie zapisac mu cudzego.
useEffect(() => {
setDashboardWidgets(readDashboardWidgets(dashboardWidgetsStorageKey));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dashboardWidgetsStorageKey]);
useEffect(() => { useEffect(() => {
window.localStorage.setItem(dashboardWidgetsStorageKey, JSON.stringify(dashboardWidgets)); window.localStorage.setItem(dashboardWidgetsStorageKey, JSON.stringify(dashboardWidgets));
}, [dashboardWidgets]); }, [dashboardWidgets, dashboardWidgetsStorageKey]);
const sortedWidgets = [...dashboardWidgets].sort((left, right) => left.order - right.order); const sortedWidgets = [...dashboardWidgets].sort((left, right) => left.order - right.order);
@@ -13116,8 +13129,9 @@ function CardSlider({ ariaLabel, children, autoScroll = false }: { ariaLabel: st
function HomePage({ filters, onOpenMap }: { filters: FilterState; onOpenMap: (city: string, mode?: 'buy' | 'rent') => void }) { function HomePage({ filters, onOpenMap }: { filters: FilterState; onOpenMap: (city: string, mode?: 'buy' | 'rent') => void }) {
const navigate = useNavigate(); const navigate = useNavigate();
const { formatPrice, formatPricePerArea, formatArea, showRecentlyViewedOnHome } = useDisplay(); const { formatPrice, formatPricePerArea, formatArea, showRecentlyViewedOnHome } = useDisplay();
const { user } = useAuth();
const [searchMode, setSearchMode] = useState<'buy' | 'rent'>('buy'); const [searchMode, setSearchMode] = useState<'buy' | 'rent'>('buy');
const [recentlyViewed] = useState<RecentlyViewedItem[]>(() => readRecentlyViewed()); const [recentlyViewed] = useState<RecentlyViewedItem[]>(() => readRecentlyViewed(user));
const { items: liveSaleListings, loading: liveSaleLoading } = useLiveListings('SALE'); const { items: liveSaleListings, loading: liveSaleLoading } = useLiveListings('SALE');
// Liczba ogloszen na zywo per miasto do sekcji "Przegladaj miasta". Bierzemy wszystkie zatwierdzone // Liczba ogloszen na zywo per miasto do sekcji "Przegladaj miasta". Bierzemy wszystkie zatwierdzone
@@ -21474,7 +21488,7 @@ function PriceHistoryPage({ user }: { user: AuthUser | null }) {
() => readUserJsonStorage<PriceHistoryMarket[]>(user, PRICE_HISTORY_MARKETS_SUFFIX, []), () => readUserJsonStorage<PriceHistoryMarket[]>(user, PRICE_HISTORY_MARKETS_SUFFIX, []),
); );
// Ostatnio otwarte oferte (sprzedaz i wynajem) - wspolny rejestr zasilany przy wejsciu na oferte. // Ostatnio otwarte oferte (sprzedaz i wynajem) - wspolny rejestr zasilany przy wejsciu na oferte.
const recentListings = useMemo(() => readRecentlyViewed().slice(0, RECENTLY_VIEWED_PANEL_LIMIT), []); const recentListings = useMemo(() => readRecentlyViewed(user).slice(0, RECENTLY_VIEWED_PANEL_LIMIT), [user]);
const skipNextFetch = useRef(false); const skipNextFetch = useRef(false);
const locationQuery = locationInput.trim(); const locationQuery = locationInput.trim();
const localSuggestions = locationQuery.length >= 2 ? historyLocalSuggestions(locationQuery) : HISTORY_POPULAR_MARKETS.map((label, index) => { const localSuggestions = locationQuery.length >= 2 ? historyLocalSuggestions(locationQuery) : HISTORY_POPULAR_MARKETS.map((label, index) => {
@@ -26961,9 +26975,27 @@ function ListingDetailPage({
onToggleListingAlert: (listing: ApiListingDetail) => void; onToggleListingAlert: (listing: ApiListingDetail) => void;
}) { }) {
const navigate = useNavigate(); const navigate = useNavigate();
const { user } = useAuth(); const { user, loading: authLoading } = useAuth();
const { formatPrice, formatPricePerArea, formatArea, areaSuffix } = useDisplay(); const { formatPrice, formatPricePerArea, formatArea, areaSuffix } = useDisplay();
const [listing, setListing] = useState<ApiListingDetail | null>(null); const [listing, setListing] = useState<ApiListingDetail | null>(null);
// Historia ogladania jest per konto, wiec zapisujemy ja dopiero, gdy wiadomo, kto oglada -
// inaczej oferta obejrzana zaraz po wejsciu trafilaby do historii "goscia".
useEffect(() => {
if (!listing || authLoading) {
return;
}
pushRecentlyViewed({
id: listing.id,
title: listing.title,
city: listing.city,
district: listing.district,
price: listing.price,
offerType: listing.offerType,
area: listing.area,
rooms: listing.rooms,
photo: listing.photos[0] ?? null,
}, user);
}, [listing, authLoading, user]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [activePhoto, setActivePhoto] = useState(0); const [activePhoto, setActivePhoto] = useState(0);
@@ -27031,17 +27063,6 @@ function ListingDetailPage({
if (!cancelled) { if (!cancelled) {
setListing(data); setListing(data);
setLoading(false); setLoading(false);
pushRecentlyViewed({
id: data.id,
title: data.title,
city: data.city,
district: data.district,
price: data.price,
offerType: data.offerType,
area: data.area,
rooms: data.rooms,
photo: data.photos[0] ?? null,
});
} }
}) })
.catch((err) => { .catch((err) => {