mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 10:23:27 +00:00
- Import wizard: added step indicator (numbered circles), widened to max-w-5xl - Admin sidebar: added Marketing → Campaigns nav link - Clear campaign leads: Ctrl+Shift+C shortcut with campaign picker modal (test-only) - Test CSV data for all 3 campaigns - Defect fixing plan + CSV import spec docs - Session memory update Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
81 lines
2.6 KiB
TypeScript
81 lines
2.6 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react';
|
|
|
|
export type MaintAction = {
|
|
endpoint: string;
|
|
label: string;
|
|
description: string;
|
|
};
|
|
|
|
const MAINT_ACTIONS: Record<string, MaintAction> = {
|
|
forceReady: {
|
|
endpoint: 'force-ready',
|
|
label: 'Force Ready',
|
|
description: 'Logout and re-login the agent to force Ready state on Ozonetel.',
|
|
},
|
|
unlockAgent: {
|
|
endpoint: 'unlock-agent',
|
|
label: 'Unlock Agent',
|
|
description: 'Release the Redis session lock so the agent can log in again.',
|
|
},
|
|
backfill: {
|
|
endpoint: 'backfill-missed-calls',
|
|
label: 'Backfill Missed Calls',
|
|
description: 'Match existing missed calls with lead records by phone number.',
|
|
},
|
|
fixTimestamps: {
|
|
endpoint: 'fix-timestamps',
|
|
label: 'Fix Timestamps',
|
|
description: 'Correct call timestamps that were stored with IST double-offset.',
|
|
},
|
|
clearCampaignLeads: {
|
|
endpoint: '__client__clear-campaign-leads',
|
|
label: 'Clear Campaign Leads',
|
|
description: 'Delete all imported leads from a selected campaign. For testing only.',
|
|
},
|
|
};
|
|
|
|
export const useMaintShortcuts = () => {
|
|
const [activeAction, setActiveAction] = useState<MaintAction | null>(null);
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
const openAction = useCallback((action: MaintAction) => {
|
|
setActiveAction(action);
|
|
setIsOpen(true);
|
|
}, []);
|
|
|
|
const close = useCallback(() => {
|
|
setIsOpen(false);
|
|
setActiveAction(null);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const handler = (e: KeyboardEvent) => {
|
|
if (e.ctrlKey && e.shiftKey && e.key === 'R') {
|
|
e.preventDefault();
|
|
openAction(MAINT_ACTIONS.forceReady);
|
|
}
|
|
if (e.ctrlKey && e.shiftKey && e.key === 'U') {
|
|
e.preventDefault();
|
|
openAction(MAINT_ACTIONS.unlockAgent);
|
|
}
|
|
if (e.ctrlKey && e.shiftKey && e.key === 'B') {
|
|
e.preventDefault();
|
|
openAction(MAINT_ACTIONS.backfill);
|
|
}
|
|
if (e.ctrlKey && e.shiftKey && e.key === 'T') {
|
|
e.preventDefault();
|
|
openAction(MAINT_ACTIONS.fixTimestamps);
|
|
}
|
|
if (e.ctrlKey && e.shiftKey && e.key === 'C') {
|
|
e.preventDefault();
|
|
openAction(MAINT_ACTIONS.clearCampaignLeads);
|
|
}
|
|
};
|
|
|
|
window.addEventListener('keydown', handler);
|
|
return () => window.removeEventListener('keydown', handler);
|
|
}, [openAction]);
|
|
|
|
return { isOpen, activeAction, close };
|
|
};
|