Iman_AMS/asm_app/src/hooks/useWorkflow.ts

205 lines
5.7 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
import workflowService, {
type WorkflowTransition,
type WorkflowInfo,
getWorkflowStateStyle,
getActionButtonStyle,
getActionIcon
} from '../services/workflowService';
interface UseWorkflowOptions {
doctype: string;
docname: string | null;
workflowState?: string;
enabled?: boolean;
docData?: Record<string, any>; // Added: Document data for condition evaluation
}
interface UseWorkflowReturn {
// State
transitions: WorkflowTransition[];
workflowInfo: WorkflowInfo | null;
userRoles: string[];
currentUser: string;
isSystemManager: boolean;
loading: boolean;
actionLoading: boolean;
error: string | null;
canEdit: boolean;
// Actions
applyAction: (action: string, nextState?: string) => Promise<boolean>;
refreshTransitions: () => Promise<void>;
// Helpers
getStateStyle: (state: string) => { bg: string; text: string; border: string };
getButtonStyle: (action: string) => string;
getIcon: (action: string) => string;
}
export const useWorkflow = ({
doctype,
docname,
workflowState,
enabled = true,
docData, // Added: Document data for condition evaluation
}: UseWorkflowOptions): UseWorkflowReturn => {
const [transitions, setTransitions] = useState<WorkflowTransition[]>([]);
const [workflowInfo, setWorkflowInfo] = useState<WorkflowInfo | null>(null);
const [userRoles, setUserRoles] = useState<string[]>([]);
const [currentUser, setCurrentUser] = useState<string>('');
const [isSystemManagerUser, setIsSystemManagerUser] = useState(false);
const [loading, setLoading] = useState(false);
const [actionLoading, setActionLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [canEdit, setCanEdit] = useState(true);
// Fetch workflow info on mount
useEffect(() => {
if (!enabled) return;
const fetchWorkflowInfo = async () => {
try {
const info = await workflowService.getWorkflowInfo(doctype);
setWorkflowInfo(info);
} catch (err) {
console.error('Error fetching workflow info:', err);
}
};
fetchWorkflowInfo();
}, [doctype, enabled]);
// Fetch user roles, current user, and check System Manager
useEffect(() => {
if (!enabled) return;
const fetchUserInfo = async () => {
try {
const [roles, user, isSysManager] = await Promise.all([
workflowService.getCurrentUserRoles(),
workflowService.getCurrentUser(),
workflowService.isSystemManager(),
]);
setUserRoles(roles);
setCurrentUser(user);
setIsSystemManagerUser(isSysManager);
// System Manager can always edit
if (isSysManager) {
setCanEdit(true);
}
} catch (err) {
console.error('Error fetching user info:', err);
}
};
fetchUserInfo();
}, [enabled]);
// Fetch available transitions when docname, workflowState, or docData changes
const refreshTransitions = useCallback(async () => {
if (!docname || !enabled) {
setTransitions([]);
return;
}
setLoading(true);
setError(null);
try {
// Pass document data for condition evaluation
const availableTransitions = await workflowService.getWorkflowTransitions(
doctype,
docname,
workflowState,
docData // Pass document data
);
console.log('[useWorkflow] Available transitions:', availableTransitions);
setTransitions(availableTransitions);
// Check if user can edit (System Manager always can)
if (workflowState) {
const canUserEdit = await workflowService.canUserEditDocument(doctype, docname, workflowState);
setCanEdit(canUserEdit);
}
} catch (err) {
console.error('Error fetching transitions:', err);
setError('Failed to load workflow actions');
setTransitions([]);
} finally {
setLoading(false);
}
}, [doctype, docname, workflowState, enabled, docData]);
useEffect(() => {
refreshTransitions();
}, [refreshTransitions]);
// Apply workflow action
const applyAction = useCallback(async (action: string, nextState?: string): Promise<boolean> => {
if (!docname) {
setError('Document not saved yet');
return false;
}
setActionLoading(true);
setError(null);
try {
// Pass nextState for System Manager force update if needed
await workflowService.applyWorkflowAction(doctype, docname, action, nextState);
// Refresh transitions after action
await refreshTransitions();
return true;
} catch (err: any) {
console.error('Error applying workflow action:', err);
// Extract error message
let errorMessage = 'Failed to apply action';
if (err.message) {
errorMessage = err.message;
} else if (err._server_messages) {
try {
const serverMessages = JSON.parse(err._server_messages);
errorMessage = serverMessages.map((m: string) => {
try {
return JSON.parse(m).message;
} catch {
return m;
}
}).join('\n');
} catch {
errorMessage = err._server_messages;
}
}
setError(errorMessage);
return false;
} finally {
setActionLoading(false);
}
}, [doctype, docname, refreshTransitions]);
return {
transitions,
workflowInfo,
userRoles,
currentUser,
isSystemManager: isSystemManagerUser,
loading,
actionLoading,
error,
canEdit,
applyAction,
refreshTransitions,
getStateStyle: getWorkflowStateStyle,
getButtonStyle: getActionButtonStyle,
getIcon: getActionIcon,
};
};
export default useWorkflow;