import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card'; import { Button } from './ui/button'; import { Input } from './ui/input'; import { Label } from './ui/label'; import { Textarea } from './ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { Badge } from './ui/badge'; import { Avatar, AvatarFallback } from './ui/avatar'; import { Progress } from './ui/progress'; import { Switch } from './ui/switch'; import { Calendar } from './ui/calendar'; import { Popover, PopoverContent, PopoverTrigger } from './ui/popover'; import { Separator } from './ui/separator'; import { RadioGroup, RadioGroupItem } from './ui/radio-group'; import { Checkbox } from './ui/checkbox'; import { motion, AnimatePresence } from 'motion/react'; import { TemplateSelectionModal } from './modals/TemplateSelectionModal'; import { ArrowLeft, ArrowRight, Calendar as CalendarIcon, Upload, X, User, Clock, FileText, Check, Users, Star, Zap, Shield, Target, Flame, TrendingUp, Building, DollarSign, AlertCircle, CheckCircle, Info, Sparkles, Rocket, Plus, Minus, Eye, EyeOff, Search, Filter, Download, Globe, Lock, Lightbulb, PieChart, BarChart3, Activity, Settings } from 'lucide-react'; import { format } from 'date-fns'; interface NewRequestWizardProps { 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 } ]; 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' } ]; 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 NewRequestWizard({ onBack, onSubmit }: NewRequestWizardProps) { const [currentStep, setCurrentStep] = useState(1); const [selectedTemplate, setSelectedTemplate] = useState(null); const [userSearch, setUserSearch] = useState(''); const [showAdvanced, setShowAdvanced] = useState(false); const [emailInput, setEmailInput] = useState(''); const [showTemplateModal, setShowTemplateModal] = useState(false); const [newUserData, setNewUserData] = useState({ name: '', email: '', role: '', department: '', level: 1 }); const [showUserInvite, setShowUserInvite] = useState(false); 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 filteredUsers = MOCK_USERS.filter(user => user.name.toLowerCase().includes(userSearch.toLowerCase()) || user.role.toLowerCase().includes(userSearch.toLowerCase()) || user.department.toLowerCase().includes(userSearch.toLowerCase()) || user.email.toLowerCase().includes(userSearch.toLowerCase()) ); const validateEmail = (email: string) => { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); }; const getLevelInfo = (level: number) => { return USER_LEVELS.find(l => l.level === level) || USER_LEVELS[0]; }; 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(); 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 calculateSLAEndDate = (hours: number) => { const now = new Date(); const endDate = new Date(now.getTime() + (hours * 60 * 60 * 1000)); return endDate; }; const updateMaxLevel = () => { const maxApproverLevel = Math.max(...formData.approvers.map(a => a.level), 0); updateFormData('maxLevel', maxApproverLevel); }; 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') { setTimeout(updateMaxLevel, 0); } } }; const removeUser = (userId: string, type: 'approvers' | 'spectators' | 'ccList' | 'invitedUsers') => { const currentList = formData[type]; updateFormData(type, currentList.filter((u: any) => u.id !== userId)); // Update max level if removing approver if (type === 'approvers') { setTimeout(updateMaxLevel, 0); } }; 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 }); setShowUserInvite(false); return newUser; }; const inviteAndAddUser = (type: 'approvers' | 'spectators' | 'ccList') => { const user = addUserByEmail(); if (user && type !== 'invitedUsers') { 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.