8.0 KiB
Modular Request Flow Architecture - Implementation Summary
Overview
This document summarizes the implementation of a modular, plug-and-play architecture for handling different request flow types (CUSTOM and DEALER_CLAIM) in the application.
What Was Implemented
1. Request Type Detection Utilities (src/utils/requestTypeUtils.ts)
Created centralized utilities for detecting and handling different request types:
isCustomRequest(request)- Checks if a request is a custom requestisDealerClaimRequest(request)- Checks if a request is a dealer claim requestgetRequestFlowType(request)- Returns the flow type ('CUSTOM' | 'DEALER_CLAIM')getRequestDetailRoute(requestId, request?)- Gets the appropriate route for request detailgetCreateRequestRoute(flowType)- Gets the route for creating a new request
2. Global Navigation Utility (src/utils/requestNavigation.ts)
Created a single point of navigation logic for all request-related routes:
navigateToRequest(options)- Main navigation function that handles:- Draft requests (routes to edit)
- Different flow types
- Status-based routing
navigateToCreateRequest(navigate, flowType)- Navigate to create request based on flow typecreateRequestNavigationHandler(navigate)- Factory function for creating navigation handlers
3. Modular Flow Structure (src/flows/)
Created a modular folder structure for different request flows:
src/flows/
├── custom/
│ └── index.ts # Exports Custom flow components
├── dealer-claim/
│ └── index.ts # Exports Dealer Claim flow components
├── shared/
│ └── components/ # Shared components (for future use)
└── index.ts # Flow registry and utilities
Flow Registry (src/flows/index.ts):
FlowRegistry- Maps flow types to their modulesgetFlowModule(flowType)- Gets the flow module for a typegetOverviewTab(flowType)- Gets the appropriate overview tab componentgetWorkflowTab(flowType)- Gets the appropriate workflow tab component
4. Updated RequestDetail Component
Modified src/pages/RequestDetail/RequestDetail.tsx to:
- Use flow type detection instead of hardcoded checks
- Dynamically load appropriate components based on flow type
- Support plug-and-play architecture for different flows
Key Changes:
- Replaced
isClaimManagementRequest()withgetRequestFlowType() - Uses
getOverviewTab()andgetWorkflowTab()to get flow-specific components - Maintains backward compatibility with existing components
5. Updated Navigation Throughout App
Updated all request card click handlers to use the global navigation utility:
Files Updated:
src/App.tsx- MainhandleViewRequestfunctionsrc/pages/ApproverPerformance/components/ApproverPerformanceRequestList.tsxsrc/pages/DetailedReports/DetailedReports.tsx
All navigation now goes through navigateToRequest() for consistency.
How to Use
For Developers
1. Navigating to a Request
import { navigateToRequest } from '@/utils/requestNavigation';
// In a component with navigate function
navigateToRequest({
requestId: 'REQ-123',
requestTitle: 'My Request',
status: 'pending',
request: requestObject, // Optional: helps determine flow type
navigate: navigate,
});
2. Getting Flow-Specific Components
import { getOverviewTab, getWorkflowTab } from '@/flows';
import { getRequestFlowType } from '@/utils/requestTypeUtils';
const flowType = getRequestFlowType(request);
const OverviewTab = getOverviewTab(flowType);
const WorkflowTab = getWorkflowTab(flowType);
// Use in JSX
<OverviewTab {...props} />
<WorkflowTab {...props} />
3. Detecting Request Type
import {
getRequestFlowType,
isCustomRequest,
isDealerClaimRequest
} from '@/utils/requestTypeUtils';
// Check specific type
if (isDealerClaimRequest(request)) {
// Handle dealer claim specific logic
}
// Get flow type
const flowType = getRequestFlowType(request); // 'CUSTOM' | 'DEALER_CLAIM'
Adding a New Flow Type
To add a new flow type (e.g., "VENDOR_PAYMENT"):
Step 1: Update Type Definitions
// src/utils/requestTypeUtils.ts
export type RequestFlowType = 'CUSTOM' | 'DEALER_CLAIM' | 'VENDOR_PAYMENT';
export function isVendorPaymentRequest(request: any): boolean {
// Add detection logic
return request.workflowType === 'VENDOR_PAYMENT';
}
export function getRequestFlowType(request: any): RequestFlowType {
if (isVendorPaymentRequest(request)) return 'VENDOR_PAYMENT';
if (isDealerClaimRequest(request)) return 'DEALER_CLAIM';
return 'CUSTOM';
}
Step 2: Create Flow Folder
src/flows/vendor-payment/
└── index.ts
// src/flows/vendor-payment/index.ts
export { VendorPaymentOverviewTab } from '@/pages/RequestDetail/components/tabs/VendorPaymentOverviewTab';
export { VendorPaymentWorkflowTab } from '@/pages/RequestDetail/components/tabs/VendorPaymentWorkflowTab';
Step 3: Update Flow Registry
// src/flows/index.ts
import * as VendorPaymentFlow from './vendor-payment';
export const FlowRegistry = {
CUSTOM: CustomFlow,
DEALER_CLAIM: DealerClaimFlow,
VENDOR_PAYMENT: VendorPaymentFlow,
} as const;
export function getOverviewTab(flowType: RequestFlowType) {
switch (flowType) {
case 'VENDOR_PAYMENT':
return VendorPaymentFlow.VendorPaymentOverviewTab;
// ... existing cases
}
}
Step 4: Create Components
Create the flow-specific components in src/pages/RequestDetail/components/tabs/:
VendorPaymentOverviewTab.tsxVendorPaymentWorkflowTab.tsx
Benefits
- Modularity: Each flow type is isolated in its own folder
- Maintainability: Changes to one flow don't affect others
- Scalability: Easy to add new flow types
- Consistency: Single navigation utility ensures consistent routing
- Type Safety: TypeScript ensures correct usage
- Reusability: Shared components can be used across flows
Migration Notes
Backward Compatibility
- All existing code continues to work
isClaimManagementRequest()still works (now usesisDealerClaimRequest()internally)- Existing components are preserved and work as before
Breaking Changes
None. This is a non-breaking enhancement.
Testing
To test the new architecture:
-
Test Custom Requests:
- Create a custom request
- Navigate to its detail page
- Verify correct components are loaded
-
Test Dealer Claim Requests:
- Create a dealer claim request
- Navigate to its detail page
- Verify dealer claim-specific components are loaded
-
Test Navigation:
- Click request cards from various pages
- Verify navigation works correctly
- Test draft requests (should route to edit)
Future Enhancements
- Add flow-specific validation rules
- Add flow-specific API endpoints
- Add flow-specific permissions
- Add flow-specific analytics
- Add flow-specific notifications
- Create shared request card component
- Add flow-specific creation wizards
Files Created
src/utils/requestTypeUtils.ts- Request type detection utilitiessrc/utils/requestNavigation.ts- Global navigation utilitysrc/flows/custom/index.ts- Custom flow exportssrc/flows/dealer-claim/index.ts- Dealer claim flow exportssrc/flows/index.ts- Flow registrysrc/flows/shared/components/index.ts- Shared components placeholdersrc/flows/README.md- Flow architecture documentation
Files Modified
src/pages/RequestDetail/RequestDetail.tsx- Uses flow registrysrc/App.tsx- Uses navigation utilitysrc/pages/ApproverPerformance/components/ApproverPerformanceRequestList.tsx- Uses navigation utilitysrc/pages/DetailedReports/DetailedReports.tsx- Uses navigation utility
Conclusion
The modular architecture is now in place and ready for use. The system supports plug-and-play flow types, making it easy to add new request types in the future while maintaining clean separation of concerns.