fix: saved filters now persistent via API (was local state)
This commit is contained in:
@@ -25,6 +25,7 @@ import { SortPanel, applySorting, emptySortState, type SortState } from '@/compo
|
|||||||
import { GroupPanel, applyGrouping, emptyGroupState, type GroupState, type GroupedContacts } from '@/components/contacts/GroupPanel';
|
import { GroupPanel, applyGrouping, emptyGroupState, type GroupState, type GroupedContacts } from '@/components/contacts/GroupPanel';
|
||||||
import { SaveViewDialog, type SaveViewSelection } from '@/components/contacts/SaveViewDialog';
|
import { SaveViewDialog, type SaveViewSelection } from '@/components/contacts/SaveViewDialog';
|
||||||
import { useSavedViews, useCreateSavedView, useDeleteSavedView } from '@/api/savedViews';
|
import { useSavedViews, useCreateSavedView, useDeleteSavedView } from '@/api/savedViews';
|
||||||
|
import { useSavedFilters as useSavedFiltersApi, useCreateSavedFilter, useDeleteSavedFilter } from '@/api/savedFilters';
|
||||||
import {
|
import {
|
||||||
useUnifiedContacts,
|
useUnifiedContacts,
|
||||||
useUnifiedContact,
|
useUnifiedContact,
|
||||||
@@ -54,7 +55,6 @@ export function ContactsListPage() {
|
|||||||
const [foldersOpen, setFoldersOpen] = useState(true);
|
const [foldersOpen, setFoldersOpen] = useState(true);
|
||||||
const [multiSelectFolders, setMultiSelectFolders] = useState<string[]>([]);
|
const [multiSelectFolders, setMultiSelectFolders] = useState<string[]>([]);
|
||||||
const [activeViewId, setActiveViewId] = useState<string | null>(null);
|
const [activeViewId, setActiveViewId] = useState<string | null>(null);
|
||||||
const [savedFilters, setSavedFilters] = useState<SavedFilter[]>([]);
|
|
||||||
const [saveViewDialogOpen, setSaveViewDialogOpen] = useState(false);
|
const [saveViewDialogOpen, setSaveViewDialogOpen] = useState(false);
|
||||||
const openWindow = useWindowStore((s) => s.openWindow);
|
const openWindow = useWindowStore((s) => s.openWindow);
|
||||||
|
|
||||||
@@ -64,6 +64,17 @@ export function ContactsListPage() {
|
|||||||
const deleteViewMut = useDeleteSavedView();
|
const deleteViewMut = useDeleteSavedView();
|
||||||
const savedViews = apiSavedViews ?? [];
|
const savedViews = apiSavedViews ?? [];
|
||||||
|
|
||||||
|
// Saved filters from API (durable, per-user)
|
||||||
|
const { data: apiSavedFilters } = useSavedFiltersApi('contacts');
|
||||||
|
const createFilterMut = useCreateSavedFilter();
|
||||||
|
const deleteFilterMut = useDeleteSavedFilter();
|
||||||
|
// Map API saved filters to FilterPanel SavedFilter format
|
||||||
|
const savedFilters: SavedFilter[] = (apiSavedFilters ?? []).map((f) => ({
|
||||||
|
id: f.id,
|
||||||
|
name: f.name,
|
||||||
|
filterState: f.filter_criteria as FilterState,
|
||||||
|
}));
|
||||||
|
|
||||||
// Debounce search
|
// Debounce search
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => setDebouncedSearch(search), 300);
|
const timer = setTimeout(() => setDebouncedSearch(search), 300);
|
||||||
@@ -253,11 +264,10 @@ export function ContactsListPage() {
|
|||||||
if (activeViewId === id) setActiveViewId(null);
|
if (activeViewId === id) setActiveViewId(null);
|
||||||
}, [activeViewId, deleteViewMut]);
|
}, [activeViewId, deleteViewMut]);
|
||||||
|
|
||||||
// Save current filter configuration
|
// Save current filter configuration — via API
|
||||||
const handleSaveFilter = useCallback((name: string, filterState: FilterState) => {
|
const handleSaveFilter = useCallback((name: string, filterState: FilterState) => {
|
||||||
const id = `filter-${Date.now()}`;
|
createFilterMut.mutate({ name, entity_type: 'contacts', filter_criteria: filterState as any });
|
||||||
setSavedFilters((prev) => [...prev, { id, name, filterState: { ...filterState, conditions: filterState.conditions.map((c) => ({ ...c })) } }]);
|
}, [createFilterMut]);
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Load a saved filter
|
// Load a saved filter
|
||||||
const handleLoadFilter = useCallback((filterState: FilterState) => {
|
const handleLoadFilter = useCallback((filterState: FilterState) => {
|
||||||
@@ -265,10 +275,10 @@ export function ContactsListPage() {
|
|||||||
setPage(1);
|
setPage(1);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Delete a saved filter
|
// Delete a saved filter — via API
|
||||||
const handleDeleteFilter = useCallback((id: string) => {
|
const handleDeleteFilter = useCallback((id: string) => {
|
||||||
setSavedFilters((prev) => prev.filter((f) => f.id !== id));
|
deleteFilterMut.mutate(id);
|
||||||
}, []);
|
}, [deleteFilterMut]);
|
||||||
|
|
||||||
// Sort options
|
// Sort options
|
||||||
const sortOptions = useMemo(() => [
|
const sortOptions = useMemo(() => [
|
||||||
@@ -415,7 +425,7 @@ export function ContactsListPage() {
|
|||||||
];
|
];
|
||||||
registerItems('contacts', items);
|
registerItems('contacts', items);
|
||||||
return () => unregisterPlugin('contacts');
|
return () => unregisterPlugin('contacts');
|
||||||
}, [handleSearch, handleCreate, handleSelectFilter, handleSaveView, applySavedView, deleteSavedView, handleSaveViewConfirm, handleSaveFilter, handleLoadFilter, handleDeleteFilter, t, registerItems, unregisterPlugin, selectedFilter, viewMode, sortOptions, viewModeOptions, filterState, contactType, sortState, groupState, savedViews, activeViewId, multiSelectFolders, savedFilters, saveViewDialogOpen]);
|
}, [handleSearch, handleCreate, handleSelectFilter, handleSaveView, applySavedView, deleteSavedView, handleSaveViewConfirm, handleSaveFilter, handleLoadFilter, handleDeleteFilter, t, registerItems, unregisterPlugin, selectedFilter, viewMode, sortOptions, viewModeOptions, filterState, contactType, sortState, groupState, savedViews, activeViewId, multiSelectFolders, saveViewDialogOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full" data-testid="contacts-list-page">
|
<div className="flex flex-col h-full" data-testid="contacts-list-page">
|
||||||
|
|||||||
Reference in New Issue
Block a user