/** * PolicyExplorerV2Client * * Client component wrapper for Policy Explorer V2. * Manages state, fetches data via Server Actions, and orchestrates all subcomponents. * * This component: * - Uses useURLState for pagination, sorting, filtering * - Uses useTablePreferences for localStorage persistence * - Uses usePolicyTable for TanStack Table integration * - Fetches data via getPolicySettingsV2 Server Action * - Renders PolicyTableToolbar, PolicyTableV2, PolicyTablePagination */ 'use client'; import { useEffect, useState, useCallback } from 'react'; import { useURLState } from '@/lib/hooks/useURLState'; import { useTablePreferences } from '@/lib/hooks/useTablePreferences'; import { usePolicyTable } from '@/lib/hooks/usePolicyTable'; import { PolicyTableV2 } from '@/components/policy-explorer/PolicyTableV2'; import { PolicyTableToolbar } from '@/components/policy-explorer/PolicyTableToolbar'; import { PolicyTablePagination } from '@/components/policy-explorer/PolicyTablePagination'; import { policyTableColumns } from '@/components/policy-explorer/PolicyTableColumns'; import { getPolicySettingsV2 } from '@/lib/actions/policySettings'; import type { PolicySettingRow, PaginationMeta } from '@/lib/types/policy-table'; export function PolicyExplorerV2Client() { const [data, setData] = useState([]); const [meta, setMeta] = useState(); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // URL state management const urlState = useURLState(); // localStorage preferences const { preferences, isLoaded: preferencesLoaded, updateColumnVisibility, updateColumnSizing, updateDensity, updateDefaultPageSize, } = useTablePreferences(); // Fetch data via Server Action const fetchData = useCallback(async () => { setIsLoading(true); setError(null); try { const result = await getPolicySettingsV2({ page: urlState.page, pageSize: urlState.pageSize as 10 | 25 | 50 | 100, sortBy: urlState.sortBy as 'settingName' | 'policyName' | 'policyType' | 'lastSyncedAt' | undefined, sortDir: urlState.sortDir, policyTypes: urlState.policyTypes.length > 0 ? urlState.policyTypes : undefined, searchQuery: urlState.searchQuery || undefined, }); if (result.success) { setData(result.data || []); setMeta(result.meta); } else { setError(result.error || 'Failed to fetch data'); } } catch (err) { console.error('Fetch error:', err); setError('An unexpected error occurred'); } finally { setIsLoading(false); } }, [urlState.page, urlState.pageSize, urlState.sortBy, urlState.sortDir, urlState.policyTypes, urlState.searchQuery]); // Fetch data when URL state changes useEffect(() => { fetchData(); }, [fetchData]); // TanStack Table integration const { table, selectedRows, selectedCount, totalCount, hasSelection } = usePolicyTable({ data, columns: policyTableColumns, pagination: { pageIndex: urlState.page, pageSize: urlState.pageSize as 10 | 25 | 50 | 100, }, onPaginationChange: (updater) => { const newPagination = typeof updater === 'function' ? updater({ pageIndex: urlState.page, pageSize: urlState.pageSize as 10 | 25 | 50 | 100 }) : updater; urlState.updatePage(newPagination.pageIndex); if (newPagination.pageSize !== urlState.pageSize) { urlState.updatePageSize(newPagination.pageSize); } }, sorting: urlState.sortBy ? [{ id: urlState.sortBy, desc: urlState.sortDir === 'desc' }] : [], onSortingChange: (updater) => { const newSorting = typeof updater === 'function' ? updater(urlState.sortBy ? [{ id: urlState.sortBy, desc: urlState.sortDir === 'desc' }] : []) : updater; if (newSorting.length > 0) { urlState.updateSorting(newSorting[0].id, newSorting[0].desc ? 'desc' : 'asc'); } }, columnVisibility: preferencesLoaded ? preferences.columnVisibility : {}, onColumnVisibilityChange: (updater) => { const newVisibility = typeof updater === 'function' ? updater(preferences.columnVisibility) : updater; updateColumnVisibility(newVisibility); }, columnSizing: preferencesLoaded ? preferences.columnSizing : {}, onColumnSizingChange: (updater) => { const newSizing = typeof updater === 'function' ? updater(preferences.columnSizing) : updater; updateColumnSizing(newSizing); }, meta, enableRowSelection: true, }); // Handle density change const handleDensityChange = useCallback((density: 'compact' | 'comfortable') => { updateDensity(density); }, [updateDensity]); if (error) { return (

Error loading policy settings

{error}

); } return (
{/* Toolbar */} {/* Table */} {/* Pagination */} {meta && ( )}
); }