import React, { useState, useEffect } from 'react'; import { CustomSelectControl } from "../../../../../components/ui/custom-select-control"; import type { CustomSelectOption } from "../../../../../components/ui/custom-select-control"; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { Card, CardBody, CardDivider, CardHeader } from '../../../../../components/ui/wp-card'; import { InputControl } from '../../../../../components/ui/input-control'; import { Divider } from '../../../../../components/ui/divider'; import { DismissibleAlert } from '../../../../../components/ui/dismissible-alert'; import { Heading } from '../../../../../components/ui/heading'; import { Flex, FlexItem } from '../../../../../components/ui/flex'; import { Spacer } from '../../../../../components/ui/spacer'; import { TabPanel } from '../../../../../components/ui/tab-panel'; import { useForm, FormProvider, useFieldArray, Controller } from 'react-hook-form'; import { Consent, Reference } from 'fhir/r4'; import { Check, PlusCircle, Trash2 } from 'lucide-react'; import { IValueSet, useAuthServiceContext, useConsentServiceContext, usePatientServiceContext, useValueSetServiceContext } from '../../../../../services'; import { AppHeader, AppSpinner, FhirCode, FhirCodeableConcept, FhirPeriod, FhirReference, ProfileLayoutContainer } from '../../../../../components'; import FhirValueSetSearch from '../../../../../components/FhirValueSetSearch/FhirValueSetSearch.tsx'; const EditConsentPage: React.FC = () => { const { consentId } = useParams<{ consentId: string }>(); const navigate = useNavigate(); const { state } = useLocation(); const { currentUser, getUserType } = useAuthServiceContext(); const { patientState } = usePatientServiceContext(); const { fetchConsent, transformToFhirConsent, transformFromFhirConsent, createConsent, updateConsent, setConsentsList, setShouldReload, setLastUpserted, setUnsaved } = useConsentServiceContext(); const { fetchValueSet, valueSetUrls } = useValueSetServiceContext(); const [loading, setLoading] = useState(false); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); const [consent, setConsent] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); // value sets const [consentStateCodes, setConsentStateCodes] = useState([]); const [consentScope, setConsentScope] = useState([]); const [consentCategory, setConsentCategory] = useState([]); const [consentPolicy, setConsentPolicy] = useState([]); const [consentProvisionType, setConsentProvisionType] = useState([]); const [securityRoleType, setSecurityRoleType] = useState([]); const [consentAction, setConsentAction] = useState([]); const [securityLabels, setSecurityLabels] = useState([]); const [purposeOfUse, setPurposeOfUse] = useState([]); const [consentDataMeaning, setConsentDataMeaning] = useState([]); const isNew = consentId === 'new'; const spacerMargin = '24px'; useEffect(() => { const loadValueSets = async () => { const [ consentStateCodesValueSet, consentScopeValueSet, consentCategoryValueSet, consentPolicyValueSet, consentProvisionTypeValueSet, securityRoleTypeValueSet, consentActionValueSet, securityLabelsValueSet, purposeOfUseValueSet, consentDataMeaningValueSet, ] = await Promise.all([ fetchValueSet(valueSetUrls.consentStateCodes), fetchValueSet(valueSetUrls.consentScope), fetchValueSet(valueSetUrls.consentCategory), fetchValueSet(valueSetUrls.consentPolicy), fetchValueSet(valueSetUrls.consentProvisionType), fetchValueSet(valueSetUrls.securityRoleType), fetchValueSet(valueSetUrls.consentAction), fetchValueSet(valueSetUrls.securityLabels), fetchValueSet(valueSetUrls.purposeOfUse), fetchValueSet(valueSetUrls.consentDataMeaning), ]); setConsentStateCodes(consentStateCodesValueSet); setConsentScope(consentScopeValueSet); setConsentCategory(consentCategoryValueSet); setConsentPolicy(consentPolicyValueSet); setConsentProvisionType(consentProvisionTypeValueSet); setSecurityRoleType(securityRoleTypeValueSet); setConsentAction(consentActionValueSet); setSecurityLabels(securityLabelsValueSet); setPurposeOfUse(purposeOfUseValueSet); setConsentDataMeaning(consentDataMeaningValueSet); }; loadValueSets(); }, [fetchValueSet, valueSetUrls]); const methods = useForm({ defaultValues: { status: '', scope: null, category: [], policyRule: null, dateTime: '', organization: [], sourceAttachment: { title: '', url: '' }, sourceReference: { reference: '', display: '' }, sourceType: 'none', provision: { type: 'permit', actor: [], action: [], purpose: [], data: [] } } }); const { watch, control, handleSubmit, getValues, setValue, reset } = methods; const actorFieldArray = useFieldArray({ control, name: 'provision.actor' }); const actionFieldArray = useFieldArray({ control, name: 'provision.action' }); const purposeFieldArray = useFieldArray({ control, name: 'provision.purpose' }); const dataFieldArray = useFieldArray({ control, name: 'provision.data' }); const organizationFieldArray = useFieldArray({ control, name: 'organization' }); const sourceType = watch('sourceType'); useEffect(() => { const loadConsent = async () => { if (isNew || consent) return; const { consent: consentState } = state ?? {}; if (consentState) { const formData = transformFromFhirConsent(consentState); reset(formData); setConsent(consentState); return; } setLoading(true); try { const fetchedConsent = await fetchConsent(consentId as string); const formData = transformFromFhirConsent(fetchedConsent); reset(formData); setConsent(fetchedConsent); } catch (err) { console.error('Error loading consent:', err); setError('Could not load consent. Try again.'); } finally { setLoading(false); } }; loadConsent(); }, [consentId, fetchConsent, transformFromFhirConsent]); const onSubmit = async (data: any) => { // if (!patientState) { // setError('Patient information is missing. Please try again.'); // return; // } setSubmitting(true); setError(null); try { let result: Consent; if (isNew) { result = await createConsent(transformToFhirConsent(data, patientState)); setConsentsList(prev => [...prev, result]); navigate(-1); } else { result = await updateConsent({ id: consent?.id, ...transformToFhirConsent(data, patientState) }); setConsentsList(prev => prev.map(p => p.id === result.id ? result : p)); } // setLastUpserted(result.id); } catch (err: any) { console.error(`Error ${isNew ? 'creating' : 'updating'} consent:`, err); setError(`Failed to ${isNew ? 'create' : 'update'} consent. Please try again.`); } finally { setSubmitting(false); // setShouldReload(true); // setUnsaved(false); } }; const addActor = () => { actorFieldArray.append({ role: null, reference: { reference: '', display: '' } }); }; const removeActor = (index: number) => { actorFieldArray.remove(index); }; const canAddActor = () => { return true; }; const addAction = () => { actionFieldArray.append({ system: '', code: '', display: '' }); }; const removeAction = (index: number) => { actionFieldArray.remove(index); }; const canAddAction = () => { return true; }; const addPurpose = () => { purposeFieldArray.append({ system: '', code: '', display: '' }); }; const removePurpose = (index: number) => { purposeFieldArray.remove(index); }; const canAddPurpose = () => { return true; }; const addData = () => { dataFieldArray.append({ meaning: '', reference: { reference: '', display: '' } }); }; const removeData = (index: number) => { dataFieldArray.remove(index); }; const canAddData = () => { return true; }; const addOrganization = () => { organizationFieldArray.append({ reference: '', display: '' }); }; const removeOrganization = (index: number) => { organizationFieldArray.remove(index); }; const canAddOrganization = () => { return true; }; if (loading) { return ( ); } return (
{!isNew && ( )} {error && ( <> setError(null)}> {error} )} {/* status */} {/* scope */} {/* category */} {/* dateTime */} ( )}/> {(tab) => { // organizations if (tab.name === 'organizations') { return (
{organizationFieldArray.fields.length === 0 && ( <> Organizations No organizations added yet. )} {(organizationFieldArray.fields as any[]).map((org: Reference, index: number) => (

Organization {index + 1}

{index === organizationFieldArray.fields.length - 1 && ( )}
))}
); } // source if (tab.name === 'source') { return (
{/* sourceType */} ( { field.onChange(newValue.selectedItem.key); }}/> )}/> {sourceType === 'attachment' && ( <> ( )}/> ( )}/> )} {sourceType === 'reference' && ( <> )} {/* policyRule */}
); } // provisions if (tab.name === 'provisions') { return (
{/* provision.type */} {/* provision.period */} {/* provision.dataPeriod */} {/* Actors */} Actors - Who/what controlled by this rule {actorFieldArray.fields.length === 0 && ( <> No actors added yet. )} {(actorFieldArray.fields as any[]).map((actor, index: number) => (

Actor {index + 1}

))} {actorFieldArray.fields.length > 0 && ( )} {/* provision.action */} {/* provision.securityLabel */} {/* provision.purpose */} {/* provision.class */} {/* provision.code */} {/* Data */} Data {dataFieldArray.fields.length === 0 && ( <> No data added yet. )} {(dataFieldArray.fields as any[]).map((data, index: number) => (

Data {index + 1}

))} {dataFieldArray.fields.length > 0 && ( )}
); } }}
); }; export default EditConsentPage;