Re_Figma_Code/src/pages/RequestDetail/examples/CustomTemplateExample.tsx

410 lines
10 KiB
TypeScript

/**
* Custom Template Example
*
* This file demonstrates how to create and use custom templates
* for specialized workflows and user types.
*/
import {
Star,
Workflow,
ClipboardList,
FileText,
Activity,
} from 'lucide-react';
import { RequestDetailTemplate } from '../types/template.types';
import { OverviewTab } from '../components/tabs/OverviewTab';
import { WorkflowTab } from '../components/tabs/WorkflowTab';
import { DocumentsTab } from '../components/tabs/DocumentsTab';
import { ActivityTab } from '../components/tabs/ActivityTab';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { toast } from 'sonner';
/**
* Example: Custom Tab Component
*/
export function CustomFeatureTab({ request, user, refreshDetails }: any) {
const handleCustomAction = async () => {
toast.info('Custom action triggered!');
await refreshDetails?.();
};
return (
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Star className="w-5 h-5 text-yellow-500" />
Custom Feature
</CardTitle>
<CardDescription>
This is a custom tab component for specialized workflows
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="p-4 bg-blue-50 rounded-lg">
<p className="text-sm text-blue-600 font-medium">Request ID</p>
<p className="text-lg font-bold text-blue-900">
{request?.requestId || 'N/A'}
</p>
</div>
<div className="p-4 bg-green-50 rounded-lg">
<p className="text-sm text-green-600 font-medium">User Role</p>
<p className="text-lg font-bold text-green-900">
{user?.role || 'N/A'}
</p>
</div>
</div>
<div className="border-t pt-4">
<h3 className="font-semibold mb-2">Custom Actions</h3>
<div className="flex gap-2">
<Button onClick={handleCustomAction}>
Execute Custom Action
</Button>
<Button variant="outline" onClick={refreshDetails}>
Refresh Data
</Button>
</div>
</div>
<div className="bg-gray-50 p-4 rounded-lg">
<p className="text-sm text-gray-600">
💡 <strong>Tip:</strong> You can add any custom logic, API calls, or UI components here.
This tab has access to all request data and user context.
</p>
</div>
</CardContent>
</Card>
</div>
);
}
/**
* Example: Marketing Campaign Template
*/
export const marketingCampaignTemplate: RequestDetailTemplate = {
id: 'marketingCampaign',
name: 'Marketing Campaign Request',
description: 'Template for marketing campaign approval workflows',
tabs: [
{
id: 'overview',
label: 'Overview',
icon: ClipboardList,
component: OverviewTab,
order: 1,
},
{
id: 'campaign',
label: 'Campaign Details',
icon: Star,
component: CustomFeatureTab,
order: 2,
},
{
id: 'workflow',
label: 'Approval Flow',
icon: Workflow,
component: WorkflowTab,
order: 3,
},
{
id: 'documents',
label: 'Creative Assets',
icon: FileText,
component: DocumentsTab,
order: 4,
},
{
id: 'activity',
label: 'Activity',
icon: Activity,
component: ActivityTab,
order: 5,
},
],
defaultTab: 'overview',
header: {
showBackButton: true,
showRefreshButton: true,
showShareSummaryButton: false,
},
quickActions: {
enabled: true,
customActions: [
{
id: 'schedule-campaign',
label: 'Schedule Campaign',
icon: Star,
action: async (context) => {
const { toast } = await import('sonner');
if (context.request?.status !== 'approved') {
toast.error('Campaign must be approved first');
return;
}
// TODO: Implement campaign scheduling
toast.success('Campaign scheduled successfully!');
},
visible: (context) => {
return (
context.request?.status === 'approved' &&
(context.user?.role === 'marketing' || context.isInitiator)
);
},
variant: 'default',
},
],
},
layout: {
showQuickActionsSidebar: true,
fullWidthTabs: [],
},
canAccess: (user, request) => {
const allowedRoles = ['marketing', 'admin'];
return (
allowedRoles.includes(user?.role) ||
user?.userId === request?.initiator?.userId
);
},
onInit: (context) => {
console.log('Marketing Campaign Template initialized');
// Example: Track analytics
// analytics.track('campaign_request_viewed', {
// requestId: context.request?.requestId,
// userId: context.user?.userId,
// });
},
};
/**
* Example: Finance Approval Template
*/
export const financeApprovalTemplate: RequestDetailTemplate = {
id: 'financeApproval',
name: 'Finance Approval Request',
description: 'Template for financial approval workflows with budget tracking',
tabs: [
{
id: 'overview',
label: 'Overview',
icon: ClipboardList,
component: OverviewTab,
order: 1,
},
{
id: 'workflow',
label: 'Workflow',
icon: Workflow,
component: WorkflowTab,
order: 2,
},
{
id: 'documents',
label: 'Financial Docs',
icon: FileText,
component: DocumentsTab,
order: 3,
},
{
id: 'activity',
label: 'Activity',
icon: Activity,
component: ActivityTab,
order: 4,
},
],
defaultTab: 'overview',
header: {
showBackButton: true,
showRefreshButton: true,
showShareSummaryButton: true,
},
quickActions: {
enabled: true,
},
layout: {
showQuickActionsSidebar: true,
fullWidthTabs: [],
},
canAccess: (user, request) => {
const allowedRoles = ['finance', 'cfo', 'admin'];
return (
allowedRoles.includes(user?.role) ||
user?.userId === request?.initiator?.userId ||
user?.department === 'finance'
);
},
};
/**
* Example: How to use custom templates
*/
export function CustomTemplateUsageExample() {
return (
<>
{/* Example 1: Explicit template selection */}
{/*
<RequestDetailTemplated
requestId="REQ-123"
template="marketingCampaign"
/>
*/}
{/* Example 2: Register custom template and let auto-selection work */}
{/*
import { registerTemplate } from '@/pages/RequestDetail/templates';
// Register at app startup
registerTemplate(marketingCampaignTemplate);
registerTemplate(financeApprovalTemplate);
// Then use normally - template will be auto-selected
<RequestDetailTemplated requestId="REQ-123" />
*/}
{/* Example 3: Update template selector for custom logic */}
{/*
// In templates/index.ts
export const selectTemplate: TemplateSelector = (user, request, routeParams) => {
// Marketing campaigns
if (request?.category === 'marketing-campaign') {
return 'marketingCampaign';
}
// Finance approvals
if (request?.type === 'financial-approval' || request?.amount > 100000) {
return 'financeApproval';
}
// Dealer claims
if (request?.category === 'claim-management') {
return 'dealerClaim';
}
// Default
return 'standard';
};
*/}
</>
);
}
/**
* Example: Conditional Tab Visibility
*/
export const conditionalTabExample: RequestDetailTemplate = {
id: 'conditionalExample',
name: 'Conditional Tab Example',
description: 'Shows how to conditionally show/hide tabs',
tabs: [
{
id: 'overview',
label: 'Overview',
icon: ClipboardList,
component: OverviewTab,
order: 1,
// Always visible
},
{
id: 'admin-only',
label: 'Admin Panel',
icon: Star,
component: CustomFeatureTab,
order: 2,
// Only visible to admins
visible: (context) => context.user?.role === 'admin',
},
{
id: 'closed-requests',
label: 'Closure Details',
icon: Star,
component: CustomFeatureTab,
order: 3,
// Only visible for closed requests
visible: (context) => context.isClosed,
},
{
id: 'initiator-only',
label: 'Initiator Actions',
icon: Star,
component: CustomFeatureTab,
order: 4,
// Only visible to request initiator
visible: (context) => context.isInitiator,
},
{
id: 'high-value',
label: 'Additional Approvals',
icon: Star,
component: CustomFeatureTab,
order: 5,
// Only visible for high-value requests
visible: (context) => {
const amount = context.request?.amount || 0;
return amount > 100000;
},
},
],
defaultTab: 'overview',
header: {
showBackButton: true,
showRefreshButton: true,
},
quickActions: {
enabled: true,
},
layout: {
showQuickActionsSidebar: true,
fullWidthTabs: [],
},
canAccess: () => true,
};
/**
* How to register these templates:
*
* 1. Import in templates/index.ts:
* import { marketingCampaignTemplate } from './examples/CustomTemplateExample';
*
* 2. Add to registry:
* export const templateRegistry = {
* standard: standardTemplate,
* dealerClaim: dealerClaimTemplate,
* marketingCampaign: marketingCampaignTemplate,
* // ...
* };
*
* 3. Update selector:
* export const selectTemplate = (user, request) => {
* if (request?.category === 'marketing') return 'marketingCampaign';
* // ...
* };
*/