widgets and other fixes

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-11 15:24:52 +00:00
parent 747770ac58
commit e9369df151
16 changed files with 761 additions and 277 deletions

View File

@@ -26,6 +26,7 @@ import { useToast } from '../../components/ui/toast/ToastContainer';
import { GroupIcon, PlusIcon, DownloadIcon, ListIcon, BoltIcon } from '../../icons';
import { createClustersPageConfig } from '../../config/pages/clusters.config';
import { useSectorStore } from '../../store/sectorStore';
import { useSiteStore } from '../../store/siteStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
import { getDifficultyLabelFromNumber, getDifficultyRange } from '../../utils/difficulty';
import PageHeader from '../../components/common/PageHeader';
@@ -33,6 +34,7 @@ import StandardThreeWidgetFooter from '../../components/dashboard/StandardThreeW
export default function Clusters() {
const toast = useToast();
const { activeSite } = useSiteStore();
const { activeSector } = useSectorStore();
const { pageSize } = usePageSizeStore();
@@ -84,39 +86,40 @@ export default function Clusters() {
const progressModal = useProgressModal();
const hasReloadedRef = useRef(false);
// Load total metrics for footer widget (not affected by pagination)
// Load total metrics for footer widget (site-wide totals, no sector filter)
const loadTotalMetrics = useCallback(async () => {
try {
// Fetch summary metrics in parallel with status counts
const [summaryRes, mappedRes, newRes, imagesRes] = await Promise.all([
fetchClustersSummary(activeSector?.id),
// Batch all API calls in parallel for better performance
const [allRes, mappedRes, newRes, imagesRes] = await Promise.all([
// Fetch all clusters (site-wide)
fetchClusters({
page_size: 1,
...(activeSector?.id && { sector_id: activeSector.id }),
site_id: activeSite?.id,
}),
// Fetch clusters with ideas (status='mapped')
fetchClusters({
page_size: 1,
site_id: activeSite?.id,
status: 'mapped',
}),
// Fetch clusters without ideas (status='new')
fetchClusters({
page_size: 1,
...(activeSector?.id && { sector_id: activeSector.id }),
site_id: activeSite?.id,
status: 'new',
}),
// Fetch images count
fetchImages({ page_size: 1 }),
]);
// Set summary metrics
setTotalVolume(summaryRes.total_volume || 0);
setTotalKeywords(summaryRes.total_keywords || 0);
// Set status counts
setTotalCount(allRes.count || 0);
setTotalWithIdeas(mappedRes.count || 0);
setTotalReady(newRes.count || 0);
// Set images count
setTotalImagesCount(imagesRes.count || 0);
} catch (error) {
console.error('Error loading total metrics:', error);
}
}, [activeSector]);
}, [activeSite]);
// Load total metrics when sector changes
useEffect(() => {

View File

@@ -28,12 +28,14 @@ import { BoltIcon, PlusIcon, DownloadIcon, ListIcon, GroupIcon, ArrowRightIcon }
import { LightBulbIcon } from '@heroicons/react/24/outline';
import { createIdeasPageConfig } from '../../config/pages/ideas.config';
import { useSectorStore } from '../../store/sectorStore';
import { useSiteStore } from '../../store/siteStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
import PageHeader from '../../components/common/PageHeader';
import StandardThreeWidgetFooter from '../../components/dashboard/StandardThreeWidgetFooter';
export default function Ideas() {
const toast = useToast();
const { activeSite } = useSiteStore();
const { activeSector } = useSectorStore();
const { pageSize } = usePageSizeStore();
@@ -96,37 +98,46 @@ export default function Ideas() {
loadClusters();
}, []);
// Load total metrics for footer widget (not affected by pagination)
// Load total metrics for footer widget (site-wide totals, no sector filter)
const loadTotalMetrics = useCallback(async () => {
try {
// Get ideas with status='queued' or 'completed' (those in tasks/writer)
const queuedRes = await fetchContentIdeas({
page_size: 1,
...(activeSector?.id && { sector_id: activeSector.id }),
status: 'queued',
});
const completedRes = await fetchContentIdeas({
page_size: 1,
...(activeSector?.id && { sector_id: activeSector.id }),
status: 'completed',
});
// Batch all API calls in parallel for better performance
const [allRes, queuedRes, completedRes, newRes, imagesRes] = await Promise.all([
// Get all ideas (site-wide)
fetchContentIdeas({
page_size: 1,
site_id: activeSite?.id,
}),
// Get ideas with status='queued'
fetchContentIdeas({
page_size: 1,
site_id: activeSite?.id,
status: 'queued',
}),
// Get ideas with status='completed'
fetchContentIdeas({
page_size: 1,
site_id: activeSite?.id,
status: 'completed',
}),
// Get ideas with status='new' (those ready to become tasks)
fetchContentIdeas({
page_size: 1,
site_id: activeSite?.id,
status: 'new',
}),
// Get actual total images count
fetchImages({ page_size: 1 }),
]);
setTotalCount(allRes.count || 0);
setTotalInTasks((queuedRes.count || 0) + (completedRes.count || 0));
// Get ideas with status='new' (those ready to become tasks)
const newRes = await fetchContentIdeas({
page_size: 1,
...(activeSector?.id && { sector_id: activeSector.id }),
status: 'new',
});
setTotalPending(newRes.count || 0);
// Get actual total images count
const imagesRes = await fetchImages({ page_size: 1 });
setTotalImagesCount(imagesRes.count || 0);
} catch (error) {
console.error('Error loading total metrics:', error);
}
}, [activeSector]);
}, [activeSite]);
// Load total metrics when sector changes
useEffect(() => {

View File

@@ -115,42 +115,47 @@ export default function Keywords() {
loadClusters();
}, []);
// Load total metrics for footer widget (not affected by pagination)
// Load total metrics for footer widget (site-wide totals, no sector filter)
const loadTotalMetrics = useCallback(async () => {
if (!activeSite) return;
try {
// Get all keywords (total count) - this is already in totalCount from main load
// Get keywords with status='mapped' (those that have been mapped to a cluster)
const mappedRes = await fetchKeywords({
page_size: 1,
site_id: activeSite.id,
...(activeSector?.id && { sector_id: activeSector.id }),
status: 'mapped',
});
// Batch all API calls in parallel for better performance
const [allRes, mappedRes, newRes, imagesRes] = await Promise.all([
// Get total keywords count (site-wide)
fetchKeywords({
page_size: 1,
site_id: activeSite.id,
}),
// Get keywords with status='mapped' (site-wide)
fetchKeywords({
page_size: 1,
site_id: activeSite.id,
status: 'mapped',
}),
// Get keywords with status='new' (site-wide)
fetchKeywords({
page_size: 1,
site_id: activeSite.id,
status: 'new',
}),
// Get actual total images count
fetchImages({ page_size: 1 }),
]);
setTotalCount(allRes.count || 0);
setTotalClustered(mappedRes.count || 0);
// Get keywords with status='new' (those that are ready to cluster but haven't been yet)
const newRes = await fetchKeywords({
page_size: 1,
site_id: activeSite.id,
...(activeSector?.id && { sector_id: activeSector.id }),
status: 'new',
});
setTotalUnmapped(newRes.count || 0);
setTotalImagesCount(imagesRes.count || 0);
// Get total volume across all keywords (we need to fetch all or rely on backend aggregation)
// For now, we'll just calculate from current data or set to 0
// TODO: Backend should provide total volume as an aggregated metric
setTotalVolume(0);
// Get actual total images count
const imagesRes = await fetchImages({ page_size: 1 });
setTotalImagesCount(imagesRes.count || 0);
} catch (error) {
console.error('Error loading total metrics:', error);
}
}, [activeSite, activeSector]);
}, [activeSite]);
// Load total metrics when site/sector changes
useEffect(() => {