import { useState, useEffect } from 'react'; /** * Custom Hook: useConclusionRemark * * Purpose: Manages conclusion remark generation and finalization * * Responsibilities: * - Fetches existing AI-generated conclusion * - Generates new conclusion using AI * - Finalizes conclusion and closes request * - Manages loading and submission states * - Handles navigation after successful closure * * @param request - Current request object * @param requestIdentifier - Request number or UUID * @param isInitiator - Whether current user is the request initiator * @param refreshDetails - Function to refresh request data * @param onBack - Navigation callback * @param setActionStatus - Function to show action status modal * @param setShowActionStatusModal - Function to control action status modal visibility * @returns Object with conclusion state and action handlers */ export function useConclusionRemark( request: any, requestIdentifier: string, isInitiator: boolean, refreshDetails: () => Promise, onBack?: () => void, setActionStatus?: (status: { success: boolean; title: string; message: string }) => void, setShowActionStatusModal?: (show: boolean) => void ) { // State: The conclusion remark text (editable by user) const [conclusionRemark, setConclusionRemark] = useState(''); // State: Indicates if AI is currently generating conclusion const [conclusionLoading, setConclusionLoading] = useState(false); // State: Indicates if conclusion is being submitted to backend const [conclusionSubmitting, setConclusionSubmitting] = useState(false); // State: Tracks if current conclusion was AI-generated (shows badge in UI) const [aiGenerated, setAiGenerated] = useState(false); /** * Function: fetchExistingConclusion * * Purpose: Load existing AI-generated conclusion from backend * * Use Case: When request is approved, final approver generates conclusion. * Initiator needs to review and finalize it before closing request. * * Process: * 1. Dynamically import conclusion API service * 2. Fetch conclusion by request ID * 3. Load into state if exists * 4. Mark as AI-generated if applicable */ const fetchExistingConclusion = async () => { try { // Lazy load: Import conclusion API only when needed const { getConclusion } = await import('@/services/conclusionApi'); // API Call: Fetch existing conclusion const result = await getConclusion(request.requestId || requestIdentifier); if (result && result.aiGeneratedRemark) { // Load: Set the AI-generated or final remark setConclusionRemark(result.finalRemark || result.aiGeneratedRemark); setAiGenerated(!!result.aiGeneratedRemark); } } catch (err) { // No conclusion yet - this is expected for newly approved requests } }; /** * Function: handleGenerateConclusion * * Purpose: Generate a new conclusion remark using AI * * How it works: * 1. Sends request details to AI service * 2. AI analyzes approval history, comments, and request data * 3. Generates professional conclusion summarizing outcome * 4. User can edit the AI suggestion before finalizing * * Process: * 1. Set loading state * 2. Call AI generation API * 3. Load generated text into textarea * 4. Mark as AI-generated (shows badge) * 5. Handle errors silently (user can type manually) */ const handleGenerateConclusion = async () => { try { setConclusionLoading(true); // Lazy load: Import conclusion API const { generateConclusion } = await import('@/services/conclusionApi'); // API Call: Generate AI conclusion based on request data const result = await generateConclusion(request.requestId || requestIdentifier); // Success: Load AI-generated remark setConclusionRemark(result.aiGeneratedRemark); setAiGenerated(true); } catch (err) { // Fail silently: User can write conclusion manually console.error('[useConclusionRemark] AI generation failed:', err); setConclusionRemark(''); setAiGenerated(false); } finally { setConclusionLoading(false); } }; /** * Function: handleFinalizeConclusion * * Purpose: Submit conclusion remark and close the request * * Business Logic: * - Only initiators can finalize approved requests * - Conclusion cannot be empty * - After finalization: * → Request status changes to CLOSED * → All participants are notified * → Request moves to Closed Requests * → Conclusion is permanently saved * * Process: * 1. Validate conclusion is not empty * 2. Submit to backend * 3. Show success modal * 4. Refresh request data (status will be "closed") * 5. Navigate to Closed Requests after 2 seconds * 6. Handle errors with user-friendly messages */ const handleFinalizeConclusion = async () => { // Validation: Ensure conclusion is not empty if (!conclusionRemark.trim()) { setActionStatus?.({ success: false, title: 'Validation Error', message: 'Conclusion remark cannot be empty' }); setShowActionStatusModal?.(true); return; } try { setConclusionSubmitting(true); // Lazy load: Import conclusion API const { finalizeConclusion } = await import('@/services/conclusionApi'); // API Call: Submit conclusion and close request // Backend will: // - Update request status to CLOSED // - Save conclusion remark // - Send notifications to all participants // - Record closure timestamp await finalizeConclusion(request.requestId || requestIdentifier, conclusionRemark); // Success feedback setActionStatus?.({ success: true, title: 'Request Closed with Successful Completion', message: 'The request has been finalized and moved to Closed Requests.' }); setShowActionStatusModal?.(true); // Refresh: Update UI with new "closed" status await refreshDetails(); /** * Navigate: Redirect to Closed Requests after showing success message * Delay allows user to see the success notification */ setTimeout(() => { if (onBack) { // Use callback navigation if provided onBack(); // Then navigate to closed requests setTimeout(() => { window.location.hash = '#/closed-requests'; }, 100); } else { // Direct navigation window.location.hash = '#/closed-requests'; } }, 2000); // 2 second delay } catch (err: any) { // Error feedback with backend message setActionStatus?.({ success: false, title: 'Error', message: err.response?.data?.error || 'Failed to finalize conclusion' }); setShowActionStatusModal?.(true); } finally { setConclusionSubmitting(false); } }; /** * Effect: Auto-fetch existing conclusion when request becomes approved * * Trigger: When request status changes to "approved" and user is initiator * Purpose: Load any conclusion generated by final approver */ useEffect(() => { if (request?.status === 'approved' && isInitiator && !conclusionRemark) { fetchExistingConclusion(); } }, [request?.status, isInitiator]); return { conclusionRemark, setConclusionRemark, conclusionLoading, conclusionSubmitting, aiGenerated, handleGenerateConclusion, handleFinalizeConclusion }; }