'use client'; import { useState, ComponentType } from 'react'; import { X } from 'lucide-react'; export interface ActivityTypeOption { value: string; label: string; icon: ComponentType; } export interface OutcomeOption { value: string; label: string; } export interface LogActivityFormData { type: string; title: string; description: string; outcome: string | undefined; durationMinutes: number | undefined; occurredAt: string; } export interface LogActivityDialogProps { activityTypes: ActivityTypeOption[]; outcomeOptions: OutcomeOption[]; defaultType?: string; onSubmit: (data: LogActivityFormData) => Promise; onClose: () => void; isSubmitting?: boolean; /** Activity types for which outcome is required */ outcomeRequiredTypes?: string[]; /** Activity types for which duration field is shown */ durationTypes?: string[]; /** Activity types with follow-up checkbox, mapped to outcome values that trigger it */ followUpOutcomes?: string[]; title?: string; submitLabel?: string; submittingLabel?: string; } export function LogActivityDialog({ activityTypes, outcomeOptions, defaultType, onSubmit, onClose, isSubmitting = false, outcomeRequiredTypes = ['call', 'meeting'], durationTypes = ['call', 'meeting'], followUpOutcomes = ['callback_later', 'scheduled_meeting'], title = 'Log Activity', submitLabel = 'Log Activity', submittingLabel = 'Logging...', }: LogActivityDialogProps) { const initialType = defaultType || activityTypes[0]?.value || ''; const [activityType, setActivityType] = useState(initialType); const [formData, setFormData] = useState({ title: '', description: '', outcome: undefined as string | undefined, durationMinutes: undefined as number | undefined, occurredAt: new Date().toISOString().slice(0, 16), }); const [errors, setErrors] = useState>({}); const [createFollowUp, setCreateFollowUp] = useState(false); const showOutcome = outcomeRequiredTypes.includes(activityType); const showDuration = durationTypes.includes(activityType); const showFollowUp = followUpOutcomes.length > 0 && formData.outcome !== undefined && followUpOutcomes.includes(formData.outcome); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const newErrors: Record = {}; if (!formData.title.trim()) { newErrors.title = 'Title is required'; } if (showOutcome && !formData.outcome) { newErrors.outcome = 'Outcome is required for this activity type'; } if (Object.keys(newErrors).length > 0) { setErrors(newErrors); return; } try { await onSubmit({ type: activityType, title: formData.title, description: formData.description, outcome: formData.outcome, durationMinutes: formData.durationMinutes, occurredAt: formData.occurredAt ? new Date(formData.occurredAt).toISOString() : new Date().toISOString(), }); } catch (error) { console.error('Failed to log activity:', error); } }; const handleChange = ( field: keyof typeof formData, value: string | number | undefined ) => { setFormData((prev) => ({ ...prev, [field]: value })); if (errors[field]) { setErrors((prev) => ({ ...prev, [field]: undefined as any })); } }; const currentTypeLabel = activityTypes.find((t) => t.value === activityType)?.label || ''; return (
{/* Header */}

{title}

{/* Form */}
{/* Activity Type Selection */}
{activityTypes.map(({ value, label, icon: Icon }) => ( ))}
{/* Title */}
handleChange('title', e.target.value)} className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ errors.title ? 'border-red-500' : 'border-gray-300' }`} placeholder={`${currentTypeLabel} with...`} /> {errors.title && (

{errors.title}

)}
{/* Date/Time and Duration */}
handleChange('occurredAt', e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
{showDuration && (
handleChange( 'durationMinutes', e.target.value ? parseInt(e.target.value) : undefined ) } className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="30" min="1" />
)}
{/* Outcome */} {showOutcome && (
{errors.outcome && (

{errors.outcome}

)}
)} {/* Description */}