import { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { Separator } from '@/components/ui/separator'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { motion, AnimatePresence } from 'framer-motion'; import { TemplateSelectionModal } from '@/components/modals/TemplateSelectionModal'; import { ArrowLeft, ArrowRight, Upload, X, User, Clock, FileText, Check, Users, Zap, Shield, Target, Flame, TrendingUp, DollarSign, AlertCircle, CheckCircle, Info, Rocket, Plus, Minus, Eye, Lightbulb, Settings } from 'lucide-react'; import { format } from 'date-fns'; interface CreateRequestProps { onBack?: () => void; onSubmit?: (requestData: any) => void; } interface RequestTemplate { id: string; name: string; description: string; category: string; icon: React.ComponentType; estimatedTime: string; commonApprovers: string[]; suggestedSLA: number; priority: 'high' | 'medium' | 'low'; fields: { amount?: boolean; vendor?: boolean; timeline?: boolean; impact?: boolean; }; } const REQUEST_TEMPLATES: RequestTemplate[] = [ { id: 'custom', name: 'Custom Request', description: 'Create a custom request for unique business needs with full flexibility to define your own workflow and requirements', category: 'General', icon: Lightbulb, estimatedTime: 'Variable', commonApprovers: [], suggestedSLA: 3, priority: 'medium', fields: {} }, { id: 'existing-template', name: 'Existing Template', description: 'Use a pre-configured template with predefined approval workflows, timelines, and requirements for faster processing', category: 'Templates', icon: FileText, estimatedTime: '1-2 days', commonApprovers: ['Department Head', 'Manager'], suggestedSLA: 2, priority: 'medium', fields: { timeline: true } } ]; const MOCK_USERS = [ { id: '1', name: 'Mike Johnson', role: 'Team Lead', avatar: 'MJ', department: 'Operations', email: 'mike.johnson@royalenfield.com', level: 2, canClose: false }, { id: '2', name: 'Lisa Wong', role: 'Finance Manager', avatar: 'LW', department: 'Finance', email: 'lisa.wong@royalenfield.com', level: 3, canClose: false }, { id: '3', name: 'David Kumar', role: 'Department Head', avatar: 'DK', department: 'IT', email: 'david.kumar@royalenfield.com', level: 4, canClose: true }, { id: '4', name: 'Anna Smith', role: 'Marketing Coordinator', avatar: 'AS', department: 'Marketing', email: 'anna.smith@royalenfield.com', level: 1, canClose: false }, { id: '5', name: 'John Doe', role: 'Budget Analyst', avatar: 'JD', department: 'Finance', email: 'john.doe@royalenfield.com', level: 2, canClose: false }, { id: '6', name: 'Sarah Chen', role: 'Marketing Manager', avatar: 'SC', department: 'Marketing', email: 'sarah.chen@royalenfield.com', level: 3, canClose: false }, { id: '7', name: 'Emily Davis', role: 'Creative Director', avatar: 'ED', department: 'Marketing', email: 'emily.davis@royalenfield.com', level: 3, canClose: false }, { id: '8', name: 'Robert Kim', role: 'Legal Counsel', avatar: 'RK', department: 'Legal', email: 'robert.kim@royalenfield.com', level: 4, canClose: true }, { id: '9', name: 'Jennifer Lee', role: 'CEO', avatar: 'JL', department: 'Executive', email: 'jennifer.lee@royalenfield.com', level: 5, canClose: true }, { id: '10', name: 'Michael Brown', role: 'CFO', avatar: 'MB', department: 'Finance', email: 'michael.brown@royalenfield.com', level: 5, canClose: true } ]; // User levels - keeping for future use // const USER_LEVELS = [ // { level: 1, name: 'Junior Level', description: 'Junior staff and coordinators', color: 'bg-gray-100 text-gray-800' }, // { level: 2, name: 'Mid Level', description: 'Team leads and supervisors', color: 'bg-blue-100 text-blue-800' }, // { level: 3, name: 'Senior Level', description: 'Managers and senior staff', color: 'bg-green-100 text-green-800' }, // { level: 4, name: 'Executive Level', description: 'Department heads and directors', color: 'bg-orange-100 text-orange-800' }, // { level: 5, name: 'C-Suite Level', description: 'Executive leadership', color: 'bg-purple-100 text-purple-800' } // ]; // SLA Templates - keeping for future use // const SLA_TEMPLATES = [ // { id: 'urgent', name: 'Urgent', hours: 4, description: 'Critical business impact', color: 'bg-red-100 text-red-800' }, // { id: 'high', name: 'High Priority', hours: 24, description: 'High business impact', color: 'bg-orange-100 text-orange-800' }, // { id: 'medium', name: 'Medium Priority', hours: 72, description: 'Moderate business impact', color: 'bg-yellow-100 text-yellow-800' }, // { id: 'low', name: 'Low Priority', hours: 120, description: 'Low business impact', color: 'bg-green-100 text-green-800' }, // { id: 'custom', name: 'Custom SLA', hours: 0, description: 'Define your own timeline', color: 'bg-blue-100 text-blue-800' } // ]; const STEP_NAMES = [ 'Template Selection', 'Basic Information', 'Approval Workflow', 'Participants & Access', 'Documents & Attachments', 'Review & Submit' ]; export function CreateRequest({ onBack, onSubmit }: CreateRequestProps) { const [currentStep, setCurrentStep] = useState(1); const [selectedTemplate, setSelectedTemplate] = useState(null); const [emailInput, setEmailInput] = useState(''); const [showTemplateModal, setShowTemplateModal] = useState(false); const [newUserData, setNewUserData] = useState({ name: '', email: '', role: '', department: '', level: 1 }); const [formData, setFormData] = useState({ // Template and basic info template: '', title: '', description: '', category: '', // Details priority: '', urgency: '', businessImpact: '', amount: '', currency: 'USD', vendor: '', timeline: '', // SLA and dates slaTemplate: '', slaHours: 0, customSlaHours: 0, slaEndDate: undefined as Date | undefined, expectedCompletionDate: undefined as Date | undefined, breachEscalation: true, reminderSchedule: '50' as '25' | '50' | '75', // Workflow workflowType: 'sequential' as 'sequential' | 'parallel', requiresAllApprovals: true, escalationEnabled: true, reminderEnabled: true, minimumLevel: 1, maxLevel: 1, // Participants approvers: [] as any[], approverCount: 1, spectators: [] as any[], ccList: [] as any[], invitedUsers: [] as any[], // Access settings allowComments: true, allowDocumentUpload: true, // Documents documents: [] as File[], // Additional metadata tags: [] as string[], relatedRequests: [] as string[], costCenter: '', project: '' }); const totalSteps = STEP_NAMES.length; const updateFormData = (field: string, value: any) => { setFormData(prev => ({ ...prev, [field]: value })); }; const validateEmail = (email: string) => { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); }; const createUserFromEmail = (email: string, name: string = '', role: string = '', department: string = '', level: number = 1) => { const avatar = name ? name.split(' ').map(n => (n?.[0] || '')).join('').toUpperCase() : email.split('@')[0]?.substring(0, 2).toUpperCase() || 'XX'; return { id: `temp-${Date.now()}-${Math.random()}`, name: name || email.split('@')[0], email, role: role || 'External User', department: department || 'External', avatar, level, canClose: level >= 4, isInvited: true }; }; const getPriorityIcon = (priority: string) => { switch (priority) { case 'high': return ; case 'medium': return ; case 'low': return ; default: return ; } }; const isStepValid = () => { switch (currentStep) { case 1: return selectedTemplate !== null; case 2: return formData.title.trim() !== '' && formData.description.trim() !== '' && formData.priority !== ''; case 3: return (formData.approverCount || 1) > 0 && formData.approvers.length === (formData.approverCount || 1) && formData.approvers.every(approver => { if (!approver || !approver.email) return false; // Check TAT validation based on type const tatType = approver.tatType || 'hours'; if (tatType === 'hours') { return approver.tat && approver.tat > 0 && approver.tat <= 720; } else if (tatType === 'days') { return approver.tat && approver.tat > 0 && approver.tat <= 30; } return false; }); case 4: return true; // Participants are optional except approvers case 5: return true; // Documents are optional case 6: return true; // Review & Submit default: return false; } }; const nextStep = () => { if (currentStep < totalSteps && isStepValid()) { setCurrentStep(currentStep + 1); } }; const prevStep = () => { if (currentStep > 1) { setCurrentStep(currentStep - 1); } }; const selectTemplate = (template: RequestTemplate) => { setSelectedTemplate(template); updateFormData('template', template.id); updateFormData('category', template.category); updateFormData('priority', template.priority); // Auto-suggest SLA const suggestedDate = new Date(); suggestedDate.setDate(suggestedDate.getDate() + template.suggestedSLA); updateFormData('slaEndDate', suggestedDate); // If user selected "Existing Template", show the template selection modal if (template.id === 'existing-template') { setShowTemplateModal(true); } }; const handleTemplateSelection = (templateId: string) => { // This will be handled by routing to the specific template wizard in App.tsx if (onSubmit) { onSubmit({ templateType: templateId }); } }; const addUser = (user: any, type: 'approvers' | 'spectators' | 'ccList' | 'invitedUsers') => { const currentList = formData[type]; if (!currentList.find((u: any) => u.id === user.id)) { const updatedList = [...currentList, user]; updateFormData(type, updatedList); // Update max level if adding approver if (type === 'approvers') { const maxApproverLevel = Math.max(...updatedList.map((a: any) => a.level), 0); updateFormData('maxLevel', maxApproverLevel); } } }; const removeUser = (userId: string, type: 'approvers' | 'spectators' | 'ccList' | 'invitedUsers') => { const currentList = formData[type]; const updatedList = currentList.filter((u: any) => u.id !== userId); updateFormData(type, updatedList); // Update max level if removing approver if (type === 'approvers') { const maxApproverLevel = Math.max(...updatedList.map((a: any) => a.level), 0); updateFormData('maxLevel', maxApproverLevel); } }; const addUserByEmail = () => { if (!validateEmail(emailInput)) return; // Check if user already exists const existingUser = [...MOCK_USERS, ...formData.invitedUsers].find(u => u.email === emailInput); if (existingUser) { setEmailInput(''); return existingUser; } // Create new user const newUser = createUserFromEmail( emailInput, newUserData.name, newUserData.role, newUserData.department, newUserData.level ); addUser(newUser, 'invitedUsers'); setEmailInput(''); setNewUserData({ name: '', email: '', role: '', department: '', level: 1 }); return newUser; }; const inviteAndAddUser = (type: 'approvers' | 'spectators' | 'ccList') => { const user = addUserByEmail(); if (user) { addUser(user, type); } }; const handleFileUpload = (event: React.ChangeEvent) => { const files = Array.from(event.target.files || []); updateFormData('documents', [...formData.documents, ...files]); }; const handleSubmit = () => { if (isStepValid()) { const requestData = { ...formData, template: selectedTemplate, id: `RE-REQ-${Date.now()}`, createdAt: new Date().toISOString(), status: 'pending' }; onSubmit?.(requestData); } }; const renderStepContent = () => { switch (currentStep) { case 1: return ( {/* Header Section */}

Choose Your Request Type

Start with a pre-built template for faster approvals, or create a custom request tailored to your needs.

{/* Template Cards Grid */}
{REQUEST_TEMPLATES.map((template) => ( selectTemplate(template)} >
{selectedTemplate?.id === template.id && (
)}
{template.name}
{template.category} {getPriorityIcon(template.priority)}

{template.description}

{template.estimatedTime}
{template.commonApprovers.length} approvers
))}
{/* Template Details Card - Only show when template is selected */} {selectedTemplate && ( {selectedTemplate.name} - Template Details

{selectedTemplate.suggestedSLA} days

{getPriorityIcon(selectedTemplate.priority)} {selectedTemplate.priority}

{selectedTemplate.estimatedTime}

{selectedTemplate.commonApprovers.map((approver, index) => ( {approver} ))}
)}
); case 2: return (

Basic Information

Provide the essential details for your {selectedTemplate?.name || 'request'}.

Be specific and descriptive. This will be visible to all participants.

updateFormData('title', e.target.value)} className="text-base h-12 border-2 border-gray-300 focus:border-blue-500 bg-white shadow-sm" />

Explain what you need approval for, why it's needed, and any relevant background information.