column visibility fixed in this

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-15 10:44:22 +00:00
parent 7fb2a9309e
commit 06e5f252a4
2 changed files with 44 additions and 211 deletions

View File

@@ -1,171 +1,53 @@
/**
* Column Visibility Store (Zustand)
* Manages column visibility settings per page with localStorage persistence
* Uses the same pattern as siteStore and sectorStore
* Stores preferences per user for multi-user support
* Column preferences expire after 30 days
* Simple localStorage-based column visibility per page per user
*/
import { create } from 'zustand';
import { persist, createJSONStorage, StateStorage } from 'zustand/middleware';
interface ColumnPreference {
columns: string[];
timestamp: number;
}
interface ColumnVisibilityState {
// Map of page pathname to column preference with timestamp
pageColumns: Record<string, ColumnPreference>;
// Hydration flag to know when persist has loaded
_hasHydrated: boolean;
setHasHydrated: (state: boolean) => void;
// Actions
setPageColumns: (pathname: string, columnKeys: string[]) => void;
getPageColumns: (pathname: string) => string[];
toggleColumn: (pathname: string, columnKey: string) => void;
resetPageColumns: (pathname: string) => void;
getVisibleColumns: (pathname: string) => string[];
setVisibleColumns: (pathname: string, columns: string[]) => void;
}
// Helper function to get user ID directly from localStorage (synchronous, no race conditions)
// CRITICAL: We must read directly from localStorage, not from useAuthStore.getState().user
// because the auth store might not be hydrated yet when this storage is accessed
const getUserIdFromStorage = (): string => {
// Get user ID from auth storage
const getUserId = (): string => {
try {
const authData = localStorage.getItem('auth-storage');
if (authData) {
const parsed = JSON.parse(authData);
const userId = parsed?.state?.user?.id;
if (userId) {
return String(userId);
}
return String(parsed?.state?.user?.id || 'anonymous');
}
} catch (error) {
// Silent fail - will use anonymous
} catch (e) {
// ignore
}
return 'anonymous';
};
// Custom storage that uses user-specific keys
// IMPORTANT: The persist middleware passes the 'name' param, but we need to append user ID
// CRITICAL FIX: Get user ID directly from localStorage synchronously to avoid race conditions
const userSpecificStorage: StateStorage = {
getItem: (name: string) => {
const userId = getUserIdFromStorage();
const key = `${name}-user-${userId}`;
const value = localStorage.getItem(key);
if (typeof window !== 'undefined' && window.location.pathname.includes('/writer/')) {
console.log('🔍 STORAGE GET:', { key, hasValue: !!value, valuePreview: value?.substring(0, 50) });
}
return value;
},
setItem: (name: string, value: string) => {
const userId = getUserIdFromStorage();
const key = `${name}-user-${userId}`;
if (typeof window !== 'undefined' && window.location.pathname.includes('/writer/')) {
console.log('💾 STORAGE SET:', { key, valuePreview: value?.substring(0, 50) });
}
localStorage.setItem(key, value);
},
removeItem: (name: string) => {
const userId = getUserIdFromStorage();
const key = `${name}-user-${userId}`;
localStorage.removeItem(key);
},
// Build storage key
const getStorageKey = (pathname: string): string => {
return `columns-${getUserId()}-${pathname}`;
};
// 30 days in milliseconds
const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
export const useColumnVisibilityStore = create<ColumnVisibilityState>()(
persist<ColumnVisibilityState>(
(set, get) => ({
pageColumns: {},
_hasHydrated: false,
setHasHydrated: (state: boolean) => {
set({ _hasHydrated: state });
},
setPageColumns: (pathname: string, columnKeys: string[]) => {
if (pathname.includes('/writer/')) {
console.log('📝 setPageColumns:', { pathname, columns: columnKeys, timestamp: new Date().toISOString() });
}
set((state) => ({
pageColumns: {
...state.pageColumns,
[pathname]: {
columns: columnKeys,
timestamp: Date.now(),
},
},
}));
},
getPageColumns: (pathname: string) => {
const preference = get().pageColumns[pathname];
if (pathname.includes('/writer/')) {
console.log('📖 getPageColumns:', { pathname, hasPreference: !!preference, columns: preference?.columns });
}
if (!preference) return [];
// Check if preference has expired (older than 30 days)
const now = Date.now();
if (now - preference.timestamp > THIRTY_DAYS_MS) {
// Remove expired preference
set((state) => {
const newPageColumns = { ...state.pageColumns };
delete newPageColumns[pathname];
return { pageColumns: newPageColumns };
});
return [];
}
return preference.columns;
},
toggleColumn: (pathname: string, columnKey: string) => {
set((state) => {
const preference = state.pageColumns[pathname];
const currentColumns = preference?.columns || [];
const newColumns = currentColumns.includes(columnKey)
? currentColumns.filter((key) => key !== columnKey)
: [...currentColumns, columnKey];
return {
pageColumns: {
...state.pageColumns,
[pathname]: {
columns: newColumns,
timestamp: Date.now(),
},
},
};
});
},
resetPageColumns: (pathname: string) => {
set((state) => {
const newPageColumns = { ...state.pageColumns };
delete newPageColumns[pathname];
return { pageColumns: newPageColumns };
});
},
}),
{
name: 'igny8-column-visibility',
storage: createJSONStorage(() => userSpecificStorage),
partialize: (state) => ({
pageColumns: state.pageColumns,
}),
onRehydrateStorage: () => (state) => {
if (state && typeof window !== 'undefined' && window.location.pathname.includes('/writer/')) {
console.log('💧 REHYDRATED:', { pageColumns: state.pageColumns });
}
state?.setHasHydrated(true);
},
export const useColumnVisibilityStore = create<ColumnVisibilityState>((set, get) => ({
getVisibleColumns: (pathname: string) => {
try {
const key = getStorageKey(pathname);
const stored = localStorage.getItem(key);
if (stored) {
return JSON.parse(stored);
}
} catch (e) {
// ignore
}
)
);
return [];
},
setVisibleColumns: (pathname: string, columns: string[]) => {
try {
const key = getStorageKey(pathname);
localStorage.setItem(key, JSON.stringify(columns));
} catch (e) {
// ignore
}
},
}));