Re_Figma_Code/src/pages/RequestDetail/INTEGRATION_EXAMPLE.tsx

541 lines
14 KiB
TypeScript

/**
* Integration Examples
*
* This file shows how to integrate the new template-driven RequestDetail
* component into your existing application.
*/
import { useEffect, useState } from 'react';
import { Route, Routes, useNavigate, useParams, Link, BrowserRouter, NavigateFunction } from 'react-router-dom';
import { useAuth } from '@/contexts/AuthContext';
import { RequestDetailTemplated } from './RequestDetailTemplated';
import { RequestDetail } from './RequestDetail';
import { registerTemplate, selectTemplate, getTemplate } from './templates';
// Mock components for examples
const Home = () => <div>Home</div>;
const Login = () => <div>Login</div>;
const Dashboard = () => <div>Dashboard</div>;
const ProtectedRoute = () => <div>Protected</div>;
const Modal = ({ children, onClose }: any) => <div>{children}</div>;
const HomePage = () => <div>Home</div>;
const LoginPage = () => <div>Login</div>;
const DashboardPage = () => <div>Dashboard</div>;
const NotFoundPage = () => <div>Not Found</div>;
// Mock hooks
const useRequests = () => [] as any[];
// Mock data
const requests = [] as any[];
const notifications = [] as any[];
/**
* Example 1: Simple Route Integration
*
* Replace your existing route with the new template-driven component
*/
export function SimpleRouteIntegration() {
return (
<Routes>
{/* Old way - still works for backward compatibility */}
<Route
path="/request/:requestId"
element={<RequestDetail />}
/>
{/* New way - template-driven (recommended) */}
<Route
path="/request-v2/:requestId"
element={<RequestDetailTemplated />}
/>
</Routes>
);
}
/**
* Example 2: Gradual Migration Strategy
*
* Run both versions side-by-side during migration
*/
export function GradualMigration() {
return (
<Routes>
{/* Legacy route for existing links */}
<Route
path="/request/:requestId"
element={<RequestDetail />}
/>
{/* New template-driven route */}
<Route
path="/request/v2/:requestId"
element={<RequestDetailTemplated />}
/>
{/* Dealer-specific route */}
<Route
path="/dealer/claim/:requestId"
element={<RequestDetailTemplated template="dealerClaim" />}
/>
{/* Vendor-specific route */}
<Route
path="/vendor/request/:requestId"
element={<RequestDetailTemplated template="vendor" />}
/>
</Routes>
);
}
/**
* Example 3: Conditional Rendering Based on User Role
*/
export function ConditionalRenderingExample() {
return function RequestDetailRoute() {
const { user } = useAuth();
const { requestId } = useParams();
// Use new template system for dealers and vendors
if (user?.role === 'dealer' || user?.role === 'vendor') {
return <RequestDetailTemplated requestId={requestId} />;
}
// Use old component for other users (during migration)
return <RequestDetail requestId={requestId} />;
};
}
/**
* Example 4: Dashboard Integration
*/
export function DashboardIntegration() {
const navigate = useNavigate();
const handleViewRequest = (request: any) => {
// Automatic template selection based on request type
navigate(`/request/${request.requestId}`);
// Or explicit template
if (request.category === 'claim-management') {
navigate(`/dealer/claim/${request.requestId}`);
}
};
return (
<div className="dashboard">
{requests.map(request => (
<div key={request.requestId}>
<h3>{request.title}</h3>
<button onClick={() => handleViewRequest(request)}>
View Details
</button>
</div>
))}
</div>
);
}
/**
* Example 5: Modal Integration
*/
export function ModalIntegration() {
const [selectedRequestId, setSelectedRequestId] = useState<string | null>(null);
return (
<>
<button onClick={() => setSelectedRequestId('REQ-123')}>
View Request
</button>
{selectedRequestId && (
<Modal onClose={() => setSelectedRequestId(null)}>
<RequestDetailTemplated
requestId={selectedRequestId}
onBack={() => setSelectedRequestId(null)}
/>
</Modal>
)}
</>
);
}
/**
* Example 6: App.tsx Integration
*/
export function AppIntegrationExample() {
return (
<BrowserRouter>
<Routes>
{/* Public routes */}
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
{/* Protected routes */}
<Route element={<ProtectedRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
{/* Request Detail Routes */}
<Route
path="/request/:requestId"
element={<RequestDetailTemplated />}
/>
{/* Dealer-specific routes */}
<Route
path="/dealer/claim/:requestId"
element={<RequestDetailTemplated template="dealerClaim" />}
/>
{/* Vendor-specific routes */}
<Route
path="/vendor/request/:requestId"
element={<RequestDetailTemplated template="vendor" />}
/>
</Route>
</Routes>
</BrowserRouter>
);
}
/**
* Example 7: Custom Template Registration at App Startup
*/
export function AppInitialization() {
useEffect(() => {
// Register custom templates at app startup
import('./templates/customTemplates').then(({ customTemplates }) => {
customTemplates.forEach(template => {
registerTemplate(template);
});
});
}, []);
return <App />;
}
/**
* Example 8: Dynamic Template Selection Hook
*/
export function useDynamicTemplate(requestId: string) {
const [template, setTemplate] = useState<string>('standard');
const { user } = useAuth();
useEffect(() => {
// Fetch request details
fetch(`/api/requests/${requestId}`)
.then(res => res.json())
.then(request => {
// Select template based on request data
const templateId = selectTemplate(user, request);
setTemplate(templateId);
});
}, [requestId, user]);
return template;
}
/**
* Example 9: Using with Dynamic Template
*/
export function DynamicTemplateExample() {
const { requestId } = useParams();
const templateId = useDynamicTemplate(requestId || '');
return (
<RequestDetailTemplated
requestId={requestId}
template={templateId}
/>
);
}
/**
* Example 10: Table Row Click Handler
*/
export function TableIntegration() {
const navigate = useNavigate();
const handleRowClick = (request: any) => {
// Navigate to appropriate template based on request type
if (request.category === 'claim-management') {
navigate(`/dealer/claim/${request.requestId}`);
} else if (request.category === 'vendor') {
navigate(`/vendor/request/${request.requestId}`);
} else {
navigate(`/request/${request.requestId}`);
}
};
return (
<table>
<tbody>
{requests.map(request => (
<tr
key={request.requestId}
onClick={() => handleRowClick(request)}
className="cursor-pointer hover:bg-gray-50"
>
<td>{request.requestId}</td>
<td>{request.title}</td>
<td>{request.status}</td>
</tr>
))}
</tbody>
</table>
);
}
/**
* Example 11: Notification Click Handler
*/
export function NotificationIntegration() {
const navigate = useNavigate();
const handleNotificationClick = (notification: any) => {
const { requestId, requestType } = notification;
// Navigate with appropriate template
switch (requestType) {
case 'dealer-claim':
navigate(`/request/${requestId}?template=dealerClaim`);
break;
case 'vendor':
navigate(`/request/${requestId}?template=vendor`);
break;
default:
navigate(`/request/${requestId}`);
}
};
return (
<div className="notifications">
{notifications.map(notification => (
<div
key={notification.id}
onClick={() => handleNotificationClick(notification)}
>
{notification.message}
</div>
))}
</div>
);
}
/**
* Example 12: Search Results Integration
*/
export function SearchResultsIntegration() {
const [searchResults, setSearchResults] = useState([]);
const navigate = useNavigate();
const handleSearchResultClick = (result: any) => {
// Use explicit template if known, otherwise let auto-selection work
if (result.template) {
navigate(`/request/${result.requestId}?template=${result.template}`);
} else {
navigate(`/request/${result.requestId}`);
}
};
return (
<div className="search-results">
{searchResults.map(result => (
<div
key={result.requestId}
onClick={() => handleSearchResultClick(result)}
className="search-result-item"
>
<h4>{result.title}</h4>
<p>{result.description}</p>
<span className="badge">{result.category}</span>
</div>
))}
</div>
);
}
/**
* Complete Integration Example
*
* This shows a complete integration with:
* - Route configuration
* - Protected routes
* - Custom template registration
* - Navigation helpers
*/
// main.tsx or App.tsx
import { BrowserRouter } from 'react-router-dom';
import { AuthProvider } from '@/contexts/AuthContext';
import { registerTemplate } from '@/pages/RequestDetail/templates';
import { customTemplates } from './customTemplates';
function App() {
// Register custom templates on app load
useEffect(() => {
customTemplates.forEach(registerTemplate);
}, []);
return (
<BrowserRouter>
<AuthProvider>
<Routes>
{/* Public Routes */}
<Route path="/" element={<HomePage />} />
<Route path="/login" element={<LoginPage />} />
{/* Protected Routes */}
<Route element={<ProtectedRoute />}>
<Route path="/dashboard" element={<DashboardPage />} />
{/* Universal Request Detail Route */}
<Route
path="/request/:requestId"
element={<RequestDetailTemplated />}
/>
{/* Type-specific routes (optional) */}
<Route
path="/dealer/claim/:requestId"
element={<RequestDetailTemplated template="dealerClaim" />}
/>
<Route
path="/vendor/order/:requestId"
element={<RequestDetailTemplated template="vendor" />}
/>
{/* Catch all */}
<Route path="*" element={<NotFoundPage />} />
</Route>
</Routes>
</AuthProvider>
</BrowserRouter>
);
}
export default App;
/**
* Helper Functions
*/
// Navigate to request with appropriate template
export function navigateToRequest(
navigate: NavigateFunction,
requestId: string,
request?: any
) {
if (request?.category === 'claim-management') {
navigate(`/dealer/claim/${requestId}`);
} else if (request?.category === 'vendor') {
navigate(`/vendor/order/${requestId}`);
} else {
navigate(`/request/${requestId}`);
}
}
// Get request URL with appropriate template
export function getRequestUrl(requestId: string, request?: any): string {
if (request?.category === 'claim-management') {
return `/dealer/claim/${requestId}`;
} else if (request?.category === 'vendor') {
return `/vendor/order/${requestId}`;
} else {
return `/request/${requestId}`;
}
}
// Check if user can access template
export function canAccessTemplate(
templateId: string,
user: any,
request: any
): boolean {
const template = getTemplate(templateId);
return template?.canAccess?.(user, request) ?? true;
}
/**
* Usage in Components
*/
// Example: Dashboard request list
function RequestList() {
const navigate = useNavigate();
const requests = useRequests();
return (
<div className="request-list">
{requests.map(request => (
<div
key={request.requestId}
onClick={() => navigateToRequest(navigate, request.requestId, request)}
className="request-item"
>
<h3>{request.title}</h3>
<p>{request.description}</p>
<span className="badge">{request.category}</span>
</div>
))}
</div>
);
}
// Example: Link generation
function RequestLink({ request }: { request: any }) {
const url = getRequestUrl(request.requestId, request);
return (
<Link to={url} className="request-link">
View Request {request.requestId}
</Link>
);
}
/**
* TypeScript Types for Integration
*/
interface NavigationOptions {
requestId: string;
template?: string;
request?: any;
queryParams?: Record<string, string>;
}
function navigateToRequestAdvanced(
navigate: NavigateFunction,
options: NavigationOptions
) {
const { requestId, template, request, queryParams } = options;
let url: string;
if (template) {
url = `/request/${requestId}?template=${template}`;
} else if (request) {
url = getRequestUrl(requestId, request);
} else {
url = `/request/${requestId}`;
}
if (queryParams) {
const params = new URLSearchParams(queryParams);
url += `${url.includes('?') ? '&' : '?'}${params.toString()}`;
}
navigate(url);
}
/**
* Notes:
*
* 1. Always prefer automatic template selection over explicit template prop
* 2. Use explicit template only when necessary (e.g., deep links)
* 3. Register custom templates at app startup
* 4. Use navigation helpers for consistent routing
* 5. Handle access control at route level
*/