import React, { useState } from 'react'; import { useAuth } from '@/lib/auth-context'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Link } from 'react-router-dom'; import Layout from '@/components/layout/layout'; import { Card, CardContent } from '@/components/ui/card'; import { Package, Loader2, AlertCircle, Home } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, } from '@/components/ui/breadcrumb'; import AssetRequestForm from '@/components/asset-request/AssetRequestForm'; import MyAssetRequests from '@/components/asset-request/MyAssetRequests'; import AcknowledgeDialog from '@/components/asset-request/AcknowledgeDialog'; import ErrorBoundary from '@/components/asset-request/ErrorBoundary'; import { ErrorDisplay } from '@/components/asset-request/ErrorDisplay'; import { AssetRequestFormSkeleton, MyAssetRequestsSkeleton } from '@/components/asset-request/LoadingSkeletons'; import { assetRequestApi } from '@/services/assetRequestApi'; import { AssetRequestCreateRequest } from '@/types/asset-request'; import { notifyRequestSubmitted, notifyError } from '@/utils/assetRequestNotifications'; import { showToast } from '@/components/toast-utils'; const AssetRequestsPage: React.FC = () => { const { userData } = useAuth(); const queryClient = useQueryClient(); const [isSubmitting, setIsSubmitting] = useState(false); const [showAcknowledgeDialog, setShowAcknowledgeDialog] = useState(false); const [selectedRequestId, setSelectedRequestId] = useState(null); // Get employee ID from user data const employeeID = userData?.employeeId || 0; // Fetch employee's asset requests const { data: requests = [], isLoading, error, refetch, } = useQuery({ queryKey: ['assetRequests', 'employee', employeeID], queryFn: () => assetRequestApi.getByEmployeeId(employeeID), enabled: employeeID > 0, staleTime: 30000, // 30 seconds refetchInterval: 60000, // Refresh every minute }); // Create asset request mutation with optimistic updates const createRequestMutation = useMutation({ mutationFn: (data: AssetRequestCreateRequest) => assetRequestApi.create(data), onMutate: async (newRequestData) => { // Cancel any outgoing refetches await queryClient.cancelQueries({ queryKey: ['assetRequests', 'employee', employeeID] }); // Snapshot the previous value const previousRequests = queryClient.getQueryData(['assetRequests', 'employee', employeeID]); // Optimistically update with a temporary request const optimisticRequest = { requestID: Date.now(), // Temporary ID employeeID: newRequestData.employeeID, employeeName: userData ? `${userData.firstName} ${userData.lastName}` : '', requestedAssets: newRequestData.requestedAssets, justification: newRequestData.justification, status: 'pending' as const, submittedDate: new Date().toISOString(), reviewedDate: null, reviewedBy: null, reviewerName: null, adminComments: null, assignedDate: null, assignedBy: null, assignerName: null, }; queryClient.setQueryData( ['assetRequests', 'employee', employeeID], (old: any) => [optimisticRequest, ...(old || [])] ); return { previousRequests }; }, onSuccess: (newRequest) => { // Invalidate and refetch to get the real data queryClient.invalidateQueries({ queryKey: ['assetRequests', 'employee', employeeID] }); queryClient.invalidateQueries({ queryKey: ['assetRequests', 'pending'] }); // Show success notification notifyRequestSubmitted(newRequest); }, onError: (error: Error, _newRequest, context) => { // Rollback optimistic update if (context?.previousRequests) { queryClient.setQueryData( ['assetRequests', 'employee', employeeID], context.previousRequests ); } // Show error notification notifyError('Submit Request', error.message || 'Failed to submit asset request. Please try again.'); }, }); // Acknowledge mutation const acknowledgeMutation = useMutation({ mutationFn: ({ requestId, comments }: { requestId: number; comments: string }) => assetRequestApi.acknowledge(requestId, { acknowledgementComments: comments || undefined, acknowledgedBy: employeeID, }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['assetRequests', 'employee', employeeID] }); showToast('success', 'Asset receipt acknowledged successfully'); }, onError: (error: Error) => { notifyError('Acknowledge Receipt', error.message || 'Failed to acknowledge asset receipt. Please try again.'); }, }); const handleSubmitRequest = async (data: AssetRequestCreateRequest) => { setIsSubmitting(true); try { await createRequestMutation.mutateAsync(data); } finally { setIsSubmitting(false); } }; const handleAcknowledge = (requestId: number) => { setSelectedRequestId(requestId); setShowAcknowledgeDialog(true); }; const handleAcknowledgeConfirm = async (comments: string) => { if (!selectedRequestId) return; await acknowledgeMutation.mutateAsync({ requestId: selectedRequestId, comments }); setSelectedRequestId(null); }; const handleRetry = () => { refetch(); }; // Loading state if (!userData) { return (

Loading user information...

); } // Error state for missing employee ID if (employeeID === 0) { return (

Employee Profile Not Found

Your user account is not linked to an employee profile. Please contact your administrator to set up your employee profile.

); } return ( {/* Breadcrumb Navigation */} Home Asset Management My Asset Requests {/* Page Header */}

Request assets you need and track the status of your requests

{/* Error State */} {error && (
)} {/* Two-Column Layout */}
{/* Left Column: Request Form */}
window.location.reload()}> {isLoading ? ( ) : ( )}
{/* Right Column: My Requests */}
{isLoading ? ( ) : ( )}
{/* Acknowledge Dialog */} {selectedRequestId && ( { setShowAcknowledgeDialog(false); setSelectedRequestId(null); }} onConfirm={handleAcknowledgeConfirm} requestId={selectedRequestId} employeeName={userData?.firstName + ' ' + userData?.lastName || ''} /> )}
); }; export default AssetRequestsPage;