diff --git a/frontend/src/components/Layout/Sidebar.tsx b/frontend/src/components/Layout/Sidebar.tsx index 2aa81d9..4570dda 100644 --- a/frontend/src/components/Layout/Sidebar.tsx +++ b/frontend/src/components/Layout/Sidebar.tsx @@ -1,7 +1,7 @@ import { Link, useLocation, useParams } from 'react-router-dom'; import { useAuthStore } from '../../lib/auth'; import { useMyMemberships } from '../../hooks/useClients'; -import { useJobs, useBriefs } from '../../hooks/useJob'; +import { useJobs, useBriefs, useMyQCQueueCount } from '../../hooks/useJob'; interface SidebarItem { label: string; @@ -25,10 +25,7 @@ export function Sidebar({ onMobileClose }: SidebarProps) { const isPMOrAdmin = ['project_manager', 'admin'].includes(user?.role || ''); const isAdminOrProduction = ['production', 'admin'].includes(user?.role || ''); - const { data: qcData } = useJobs( - { status: 'pending_qc', size: 1 }, - { enabled: isQCRole } - ); + const myQCCount = useMyQCQueueCount(isQCRole); const { data: finalData } = useJobs( { status: 'pending_final_review', size: 1 }, { enabled: isPMOrAdmin } @@ -40,7 +37,7 @@ export function Sidebar({ onMobileClose }: SidebarProps) { const { data: allBriefs = [] } = useBriefs(); - const qcBadge = isQCRole ? (qcData?.total || 0) : 0; + const qcBadge = isQCRole ? myQCCount : 0; const finalBadge = isPMOrAdmin ? (finalData?.total || 0) : 0; const failuresBadge = isAdminOrProduction ? (failuresData?.total || 0) : 0; const briefsBadge = allBriefs.filter(b => b.status === 'submitted').length; diff --git a/frontend/src/hooks/useJob.ts b/frontend/src/hooks/useJob.ts index d0af875..4641d02 100644 --- a/frontend/src/hooks/useJob.ts +++ b/frontend/src/hooks/useJob.ts @@ -1,4 +1,4 @@ -import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { useQuery, useMutation, useQueryClient, useQueries } from '@tanstack/react-query'; import { apiClient } from '../lib/api'; import type { Job, @@ -441,4 +441,27 @@ export function useUploadFinalVtt() { queryClient.invalidateQueries({ queryKey: ['jobs'] }); }, }); +} + +/** Returns the total count of QC tasks personally assigned to the current user (linguist + reviewer combined). */ +export function useMyQCQueueCount(enabled = true) { + const results = useQueries({ + queries: [ + { + queryKey: ['linguist-queue', 'linguist', 'all'], + queryFn: () => apiClient.getMyLanguageQCQueue('linguist'), + enabled, + staleTime: 30_000, + refetchInterval: 30_000, + }, + { + queryKey: ['linguist-queue', 'reviewer', 'all'], + queryFn: () => apiClient.getMyLanguageQCQueue('reviewer'), + enabled, + staleTime: 30_000, + refetchInterval: 30_000, + }, + ], + }); + return (results[0].data?.total ?? 0) + (results[1].data?.total ?? 0); } \ No newline at end of file diff --git a/frontend/src/routes/jobs/LinguistQueue.tsx b/frontend/src/routes/jobs/LinguistQueue.tsx index 978ce4f..a507f98 100644 --- a/frontend/src/routes/jobs/LinguistQueue.tsx +++ b/frontend/src/routes/jobs/LinguistQueue.tsx @@ -94,7 +94,7 @@ export function LinguistQueue({ defaultRole }: LinguistQueueProps = {}) { const [activeTab, setActiveTab] = useState('all'); const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc'); - const { data, isLoading, refetch } = useQuery({ + const { data, isLoading, isFetching, refetch } = useQuery({ queryKey: ['linguist-queue', activeRole, activeTab], queryFn: () => apiClient.getMyLanguageQCQueue( activeRole, @@ -125,9 +125,16 @@ export function LinguistQueue({ defaultRole }: LinguistQueueProps = {}) {