mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
feat: add worklist with missed calls, follow-ups, and leads sections
This commit is contained in:
115
src/hooks/use-worklist.ts
Normal file
115
src/hooks/use-worklist.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
import { apiClient } from '@/lib/api-client';
|
||||
|
||||
type MissedCall = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
callDirection: string | null;
|
||||
callStatus: string | null;
|
||||
callerNumber: { number: string; callingCode: string }[] | null;
|
||||
agentName: string | null;
|
||||
startedAt: string | null;
|
||||
endedAt: string | null;
|
||||
durationSeconds: number | null;
|
||||
disposition: string | null;
|
||||
callNotes: string | null;
|
||||
leadId: string | null;
|
||||
};
|
||||
|
||||
type WorklistFollowUp = {
|
||||
id: string;
|
||||
createdAt: string | null;
|
||||
followUpType: string | null;
|
||||
followUpStatus: string | null;
|
||||
scheduledAt: string | null;
|
||||
completedAt: string | null;
|
||||
priority: string | null;
|
||||
assignedAgent: string | null;
|
||||
patientId: string | null;
|
||||
callId: string | null;
|
||||
};
|
||||
|
||||
type WorklistLead = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
contactName: { firstName: string; lastName: string } | null;
|
||||
contactPhone: { number: string; callingCode: string }[] | null;
|
||||
contactEmail: { address: string }[] | null;
|
||||
leadSource: string | null;
|
||||
leadStatus: string | null;
|
||||
interestedService: string | null;
|
||||
assignedAgent: string | null;
|
||||
campaignId: string | null;
|
||||
adId: string | null;
|
||||
contactAttempts: number | null;
|
||||
spamScore: number | null;
|
||||
isSpam: boolean | null;
|
||||
aiSummary: string | null;
|
||||
aiSuggestedAction: string | null;
|
||||
};
|
||||
|
||||
type WorklistData = {
|
||||
missedCalls: MissedCall[];
|
||||
followUps: WorklistFollowUp[];
|
||||
marketingLeads: WorklistLead[];
|
||||
totalPending: number;
|
||||
};
|
||||
|
||||
type UseWorklistResult = WorklistData & {
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refresh: () => void;
|
||||
};
|
||||
|
||||
const EMPTY_WORKLIST: WorklistData = {
|
||||
missedCalls: [],
|
||||
followUps: [],
|
||||
marketingLeads: [],
|
||||
totalPending: 0,
|
||||
};
|
||||
|
||||
export const useWorklist = (): UseWorklistResult => {
|
||||
const [data, setData] = useState<WorklistData>(EMPTY_WORKLIST);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchWorklist = useCallback(async () => {
|
||||
try {
|
||||
const token = apiClient.getStoredToken();
|
||||
if (!token) {
|
||||
setError('Not authenticated');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const apiUrl = import.meta.env.VITE_API_URL ?? 'http://localhost:4100';
|
||||
const response = await fetch(`${apiUrl}/api/worklist`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const json = await response.json();
|
||||
setData(json);
|
||||
setError(null);
|
||||
} else {
|
||||
setError(`Worklist API returned ${response.status}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Worklist fetch failed:', err);
|
||||
setError('Sidecar not reachable');
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchWorklist();
|
||||
|
||||
// Refresh every 30 seconds
|
||||
const interval = setInterval(fetchWorklist, 30000);
|
||||
return () => clearInterval(interval);
|
||||
}, [fetchWorklist]);
|
||||
|
||||
return { ...data, loading, error, refresh: fetchWorklist };
|
||||
};
|
||||
Reference in New Issue
Block a user