From 6286ebbdb35fd7b6e65ed4c048a084c1b69fa00b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:44:30 +0000 Subject: [PATCH 1/9] Initial plan From dd784a2c66237f0b261c3277f2dc79f1463d83fc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:52:59 +0000 Subject: [PATCH 2/9] Fix ActorEditor component initialization order to resolve ReferenceError Co-authored-by: litlfred <662242+litlfred@users.noreply.github.com> --- src/components/ActorEditor.js | 1854 ++++++++++++++++----------------- 1 file changed, 927 insertions(+), 927 deletions(-) diff --git a/src/components/ActorEditor.js b/src/components/ActorEditor.js index a614ba34ce..709a78e800 100644 --- a/src/components/ActorEditor.js +++ b/src/components/ActorEditor.js @@ -3,985 +3,985 @@ import { useNavigate } from 'react-router-dom'; import actorDefinitionService from '../services/actorDefinitionService'; import { PageLayout, useDAKParams } from './framework'; -const ActorEditor = () => { - const navigate = useNavigate(); - const pageParams = useDAKParams(); - - // For now, we'll set editActorId to null since it's not in URL params - // This could be enhanced later to support URL-based actor editing - const editActorId = null; - - // State management - ALL HOOKS MUST BE AT THE TOP - const [actorDefinition, setActorDefinition] = useState(null); - const [loading, setLoading] = useState(true); - const [saving, setSaving] = useState(false); - const [errors, setErrors] = useState({}); - const [showPreview, setShowPreview] = useState(false); - const [fshPreview, setFshPreview] = useState(''); - const [stagedActors, setStagedActors] = useState([]); - const [showActorList, setShowActorList] = useState(false); - const [activeTab, setActiveTab] = useState('basic'); - - // Initialize component - const initializeEditor = useCallback(async () => { - setLoading(true); - - try { - if (editActorId) { - // Load existing actor definition from staging ground - const actorData = actorDefinitionService.getFromStagingGround(editActorId); - if (actorData) { - setActorDefinition(actorData.actorDefinition); - } else { - setActorDefinition(actorDefinitionService.createEmptyActorDefinition()); - } - } else { - // Create new actor definition - setActorDefinition(actorDefinitionService.createEmptyActorDefinition()); - } - - // Load staged actors list - const staged = actorDefinitionService.listStagedActors(); - setStagedActors(staged); - - } catch (error) { - console.error('Error initializing actor editor:', error); - setErrors({ initialization: 'Failed to initialize editor' }); - } finally { - setLoading(false); - } - }, [editActorId]); - - useEffect(() => { - // Only initialize if we have valid page parameters - if (!pageParams.error && !pageParams.loading) { - initializeEditor(); - } - }, [pageParams.error, pageParams.loading, initializeEditor]); - - // Handle form field changes - const handleFieldChange = useCallback((field, value) => { - setActorDefinition(prev => ({ - ...prev, - [field]: value - })); +// Basic Info Tab Component - MUST BE DEFINED BEFORE ActorEditor +const BasicInfoTab = ({ actorDefinition, errors, onFieldChange }) => ( +
+

Basic Information

- // Clear field-specific errors - if (errors[field]) { - setErrors(prev => { - const newErrors = { ...prev }; - delete newErrors[field]; - return newErrors; - }); - } - }, [errors]); - - // Handle nested field changes - const handleNestedFieldChange = useCallback((parentField, index, field, value) => { - setActorDefinition(prev => { - const newDefinition = { ...prev }; - if (!newDefinition[parentField]) { - newDefinition[parentField] = []; - } - if (!newDefinition[parentField][index]) { - newDefinition[parentField][index] = {}; - } - newDefinition[parentField][index][field] = value; - return newDefinition; - }); - }, []); - - // Add new item to array field - const addArrayItem = useCallback((field, defaultItem = {}) => { - setActorDefinition(prev => ({ - ...prev, - [field]: [...(prev[field] || []), defaultItem] - })); - }, []); +
+ + onFieldChange('id', e.target.value)} + className={errors.id ? 'error' : ''} + placeholder="e.g., primary-care-physician" + pattern="[a-zA-Z][a-zA-Z0-9_-]*" + /> + {errors.id && {errors.id}} + Unique identifier (letters, numbers, underscores, hyphens only) +
- // Remove item from array field - const removeArrayItem = useCallback((field, index) => { - setActorDefinition(prev => ({ - ...prev, - [field]: prev[field].filter((_, i) => i !== index) - })); - }, []); +
+ + onFieldChange('name', e.target.value)} + className={errors.name ? 'error' : ''} + placeholder="e.g., Primary Care Physician" + /> + {errors.name && {errors.name}} +
- // Validate form data - const validateForm = useCallback(() => { - const newErrors = {}; - - if (!actorDefinition?.id) { - newErrors.id = 'Actor ID is required'; - } - - if (!actorDefinition?.name) { - newErrors.name = 'Actor name is required'; - } - - if (!actorDefinition?.description) { - newErrors.description = 'Actor description is required'; - } - - if (!actorDefinition?.type) { - newErrors.type = 'Actor type is required'; - } - - // Validate roles - if (actorDefinition?.roles) { - actorDefinition.roles.forEach((role, index) => { - if (!role.code) { - newErrors[`roles.${index}.code`] = 'Role code is required'; - } - if (!role.display) { - newErrors[`roles.${index}.display`] = 'Role display name is required'; - } - if (!role.system) { - newErrors[`roles.${index}.system`] = 'Role system is required'; - } - }); - } - - // Validate qualifications - if (actorDefinition?.qualifications) { - actorDefinition.qualifications.forEach((qual, index) => { - if (!qual.code) { - newErrors[`qualifications.${index}.code`] = 'Qualification code is required'; - } - if (!qual.display) { - newErrors[`qualifications.${index}.display`] = 'Qualification display name is required'; - } - }); - } - - setErrors(newErrors); - return Object.keys(newErrors).length === 0; - }, [actorDefinition]); +
+ +