From a4f9962c385b89e335c865402a897321bf11b548 Mon Sep 17 00:00:00 2001 From: laxmanhalaki Date: Thu, 11 Dec 2025 20:22:46 +0530 Subject: [PATCH] after altering the tables rechecked the all steps working as expected --- src/hooks/useRequestDetails.ts | 22 ++ src/pages/RequestDetail/RequestDetail.tsx | 60 ++++ .../components/QuickActionsSidebar.tsx | 38 ++- .../claim-cards/ActivityInformationCard.tsx | 4 +- .../claim-cards/ProcessDetailsCard.tsx | 64 +++- .../claim-cards/ProposalDetailsCard.tsx | 32 +- .../tabs/ClaimManagementOverviewTab.tsx | 58 ++-- .../tabs/DealerClaimWorkflowTab.tsx | 26 +- .../RequestDetail/components/tabs/IOTab.tsx | 288 +++++++++--------- src/utils/claimDataMapper.ts | 96 ++++-- 10 files changed, 453 insertions(+), 235 deletions(-) diff --git a/src/hooks/useRequestDetails.ts b/src/hooks/useRequestDetails.ts index 95ef983..460200d 100644 --- a/src/hooks/useRequestDetails.ts +++ b/src/hooks/useRequestDetails.ts @@ -264,6 +264,19 @@ export function useRequestDetails( proposalDetails = claimData.proposalDetails || claimData.proposal_details; completionDetails = claimData.completionDetails || claimData.completion_details; internalOrder = claimData.internalOrder || claimData.internal_order || null; + // New normalized tables + const budgetTracking = claimData.budgetTracking || claimData.budget_tracking || null; + const invoice = claimData.invoice || null; + const creditNote = claimData.creditNote || claimData.credit_note || null; + const completionExpenses = claimData.completionExpenses || claimData.completion_expenses || null; + + // Store new fields in claimDetails for backward compatibility and easy access + if (claimDetails) { + (claimDetails as any).budgetTracking = budgetTracking; + (claimDetails as any).invoice = invoice; + (claimDetails as any).creditNote = creditNote; + (claimDetails as any).completionExpenses = completionExpenses; + } console.debug('[useRequestDetails] Extracted details:', { claimDetails: claimDetails ? { @@ -278,6 +291,10 @@ export function useRequestDetails( hasProposalDetails: !!proposalDetails, hasCompletionDetails: !!completionDetails, hasInternalOrder: !!internalOrder, + hasBudgetTracking: !!budgetTracking, + hasInvoice: !!invoice, + hasCreditNote: !!creditNote, + hasCompletionExpenses: Array.isArray(completionExpenses) && completionExpenses.length > 0, }); } else { console.warn('[useRequestDetails] No claimData found in response'); @@ -337,6 +354,11 @@ export function useRequestDetails( proposalDetails: proposalDetails || null, completionDetails: completionDetails || null, internalOrder: internalOrder || null, + // New normalized tables (also available via claimDetails for backward compatibility) + budgetTracking: (claimDetails as any)?.budgetTracking || null, + invoice: (claimDetails as any)?.invoice || null, + creditNote: (claimDetails as any)?.creditNote || null, + completionExpenses: (claimDetails as any)?.completionExpenses || null, }; setApiRequest(updatedRequest); diff --git a/src/pages/RequestDetail/RequestDetail.tsx b/src/pages/RequestDetail/RequestDetail.tsx index 7c0e6c3..dbd8aa7 100644 --- a/src/pages/RequestDetail/RequestDetail.tsx +++ b/src/pages/RequestDetail/RequestDetail.tsx @@ -26,6 +26,7 @@ import { ShieldX, RefreshCw, ArrowLeft, + DollarSign, } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; @@ -51,7 +52,9 @@ import { DocumentsTab } from './components/tabs/DocumentsTab'; import { ActivityTab } from './components/tabs/ActivityTab'; import { WorkNotesTab } from './components/tabs/WorkNotesTab'; import { SummaryTab } from './components/tabs/SummaryTab'; +import { IOTab } from './components/tabs/IOTab'; import { isClaimManagementRequest } from '@/utils/claimRequestUtils'; +import { determineUserRole } from '@/utils/claimDataMapper'; import { QuickActionsSidebar } from './components/QuickActionsSidebar'; import { RequestDetailModals } from './components/RequestDetailModals'; import { RequestDetailProps } from './types/requestDetail.types'; @@ -133,6 +136,42 @@ function RequestDetailInner({ requestId: propRequestId, onBack, dynamicRequests accessDenied, } = useRequestDetails(requestIdentifier, dynamicRequests, user); + // Determine if user is initiator (from overview tab initiator info) + const currentUserId = (user as any)?.userId || ''; + const currentUserEmail = (user as any)?.email?.toLowerCase() || ''; + const initiatorUserId = apiRequest?.initiator?.userId; + const initiatorEmail = apiRequest?.initiator?.email?.toLowerCase(); + const isUserInitiator = apiRequest?.initiator && ( + (initiatorUserId && initiatorUserId === currentUserId) || + (initiatorEmail && initiatorEmail === currentUserEmail) + ); + + // Determine if user is department lead (whoever is in step 3 / approval level 3) + const approvalLevels = apiRequest?.approvalLevels || []; + const step3Level = approvalLevels.find((level: any) => + (level.levelNumber || level.level_number) === 3 + ); + const deptLeadUserId = step3Level?.approverId || step3Level?.approver?.userId; + const isDeptLead = deptLeadUserId && deptLeadUserId === currentUserId; + + // Check if IO tab should be visible (for initiator and department lead in claim management requests) + const showIOTab = isClaimManagementRequest(apiRequest) && + (isUserInitiator || isDeptLead); + + // Debug logging for troubleshooting + console.debug('[RequestDetail] IO Tab visibility:', { + isClaimManagement: isClaimManagementRequest(apiRequest), + isUserInitiator, + isDeptLead, + currentUserId, + currentUserEmail, + initiatorUserId, + initiatorEmail, + step3Level: step3Level ? { levelNumber: step3Level.levelNumber || step3Level.level_number, approverId: step3Level.approverId || step3Level.approver?.userId } : null, + deptLeadUserId, + showIOTab, + }); + const { mergedMessages, unreadWorkNotes, @@ -433,6 +472,16 @@ function RequestDetailInner({ requestId: propRequestId, onBack, dynamicRequests Workflow + {showIOTab && ( + + + IO + + )} + {showIOTab && ( + + + + )} + )} diff --git a/src/pages/RequestDetail/components/QuickActionsSidebar.tsx b/src/pages/RequestDetail/components/QuickActionsSidebar.tsx index 03804aa..af10148 100644 --- a/src/pages/RequestDetail/components/QuickActionsSidebar.tsx +++ b/src/pages/RequestDetail/components/QuickActionsSidebar.tsx @@ -2,7 +2,7 @@ * Quick Actions Sidebar Component */ -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; @@ -10,6 +10,9 @@ import { UserPlus, Eye, CheckCircle, XCircle, Share2, Pause, Play, AlertCircle } import { getSharedRecipients, type SharedRecipient } from '@/services/summaryApi'; import { useAuth } from '@/contexts/AuthContext'; import notificationApi, { type Notification } from '@/services/notificationApi'; +import { ProcessDetailsCard } from './claim-cards'; +import { isClaimManagementRequest } from '@/utils/claimRequestUtils'; +import { determineUserRole, getRoleBasedVisibility, mapToClaimManagementRequest } from '@/utils/claimDataMapper'; interface QuickActionsSidebarProps { request: any; @@ -27,6 +30,8 @@ interface QuickActionsSidebarProps { refreshTrigger?: number; // Trigger to refresh shared recipients list pausedByUserId?: string; // User ID of the approver who paused (kept for backwards compatibility) currentUserId?: string; // Current user's ID (kept for backwards compatibility) + apiRequest?: any; + onEditClaimAmount?: () => void; } export function QuickActionsSidebar({ @@ -43,6 +48,10 @@ export function QuickActionsSidebar({ onRetrigger, summaryId, refreshTrigger, + pausedByUserId: pausedByUserIdProp, + currentUserId: currentUserIdProp, + apiRequest, + onEditClaimAmount, }: QuickActionsSidebarProps) { const { user } = useAuth(); const [sharedRecipients, setSharedRecipients] = useState([]); @@ -50,8 +59,8 @@ export function QuickActionsSidebar({ const [hasRetriggerNotification, setHasRetriggerNotification] = useState(false); const isClosed = request?.status === 'closed'; const isPaused = request?.pauseInfo?.isPaused || false; - const pausedByUserId = request?.pauseInfo?.pausedBy?.userId; - const currentUserId = (user as any)?.userId || ''; + const pausedByUserId = pausedByUserIdProp || request?.pauseInfo?.pausedBy?.userId; + const currentUserId = currentUserIdProp || (user as any)?.userId || ''; // Both approver AND initiator can pause (when not already paused and not closed) const canPause = !isPaused && !isClosed && (currentApprovalLevel || isInitiator); @@ -117,6 +126,16 @@ export function QuickActionsSidebar({ fetchSharedRecipients(); }, [isClosed, summaryId, isInitiator, refreshTrigger]); + // Claim details for sidebar (only for claim management requests) + const claimSidebarData = useMemo(() => { + if (!apiRequest || !isClaimManagementRequest(apiRequest)) return null; + const claimRequest = mapToClaimManagementRequest(apiRequest, currentUserId); + if (!claimRequest) return null; + const userRole = determineUserRole(apiRequest, currentUserId); + const visibility = getRoleBasedVisibility(userRole); + return { claimRequest, visibility }; + }, [apiRequest, currentUserId]); + return ( {/* Quick Actions Card - Hide entire card for spectators and closed requests */} @@ -339,6 +358,19 @@ export function QuickActionsSidebar({ )} + + {/* Process details anchored at the bottom of the action sidebar for claim workflows */} + {claimSidebarData && ( + + )} ); } diff --git a/src/pages/RequestDetail/components/claim-cards/ActivityInformationCard.tsx b/src/pages/RequestDetail/components/claim-cards/ActivityInformationCard.tsx index 274f11e..5315c8c 100644 --- a/src/pages/RequestDetail/components/claim-cards/ActivityInformationCard.tsx +++ b/src/pages/RequestDetail/components/claim-cards/ActivityInformationCard.tsx @@ -105,8 +105,8 @@ export function ActivityInformationCard({ activityInfo, className }: ActivityInf