You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
288 lines
11 KiB
288 lines
11 KiB
import React from "react";
|
|
import { useEffect, useState } from "react";
|
|
import { Link, useParams, useLocation } from "react-router-dom";
|
|
import "./Index.css";
|
|
import { policy, needConsent } from "./ManageConnection";
|
|
import format from "date-fns/format";
|
|
|
|
const hasConsent = (patient, service) => {
|
|
let consent = patient.Consent.filter(x => x.ServiceID == service.ServiceID)[0]
|
|
|
|
if (!consent) {
|
|
return false
|
|
}
|
|
|
|
consent.ConsentGivenOn = format(new Date(consent.ConsentGivenOn), "yyyy-MM-dd")
|
|
return consent
|
|
}
|
|
|
|
const ConsentLink = ({patient, service, setConsentId}) => {
|
|
const consent = hasConsent(patient, service)
|
|
|
|
return (
|
|
<span>
|
|
(<a href="#" onClick={e => {
|
|
e.stopPropagation()
|
|
e.preventDefault()
|
|
setConsentId([patient, service])
|
|
}}>{ consent ? `toestemming gegeven op: ${format(new Date(consent.ConsentGivenOn), 'dd/MM/yyyy')}` : "toestemming vereist"}</a>)
|
|
</span>
|
|
)
|
|
}
|
|
|
|
const DropDown = ({patient, services, updateSubscription, loading, saveConsent, removeConsent}) => {
|
|
const [open, _setOpen] = useState(false)
|
|
const [consentId, setConsentId] = useState(false)
|
|
const close = () => {
|
|
_setOpen(false)
|
|
window.removeEventListener('click', close)
|
|
}
|
|
|
|
const setOpen = (x) => {
|
|
_setOpen(x)
|
|
window.addEventListener('click', close)
|
|
}
|
|
|
|
const isSubscribed = (patient, service) => {
|
|
const present = service.Subscriptions.map(x => x.ID).indexOf(patient.ID) != -1
|
|
|
|
return policy(service) == 'opt-out' ? !present : present
|
|
}
|
|
|
|
const applyPolicy = (checked, service) => {
|
|
return policy(service) == 'opt-out' ? !checked : checked
|
|
}
|
|
|
|
const systems = services.reduce((acc, cur) => {
|
|
if (!acc[cur.Connection.System]) {
|
|
acc[cur.Connection.System] = []
|
|
}
|
|
|
|
acc[cur.Connection.System].push(cur)
|
|
return acc
|
|
}, {})
|
|
|
|
return (
|
|
<div className={["c-dropdown", open ? "c-dropdown--open" : null].filter(Boolean).join(' ')}>
|
|
<a
|
|
className="c-button c-button--sm"
|
|
onClick={e => e.preventDefault() || e.stopPropagation() || setOpen(true)}
|
|
>
|
|
Aanmelden
|
|
</a>
|
|
<div
|
|
className="c-dropdown__options"
|
|
onClick={e => e.stopPropagation()}
|
|
>
|
|
{Object.keys(systems).map(sys => {
|
|
return (
|
|
<div className="c-dropdown__system" key={sys}>
|
|
{consentId ? <ConsentModal
|
|
close={_ => setConsentId(false)}
|
|
loading={loading}
|
|
service={consentId ? consentId[1] : null}
|
|
patient={consentId ? consentId[0] : null}
|
|
saveConsent={saveConsent}
|
|
removeConsent={removeConsent}
|
|
/> : null}
|
|
<span className="c-dropdown__system-option">{sys}</span>
|
|
<div className="c-dropdown__ul">
|
|
{
|
|
systems[sys].map( x => {
|
|
return (
|
|
<div className="c-dropdown__option" key={x.ID}>
|
|
<label className="c-dropdown__label">
|
|
<span><input
|
|
type="checkbox"
|
|
checked={isSubscribed(patient, x)}
|
|
disabled={loading}
|
|
readOnly={loading}
|
|
onChange={(e) => {
|
|
e.stopPropagation()
|
|
const enable = applyPolicy(e.target.checked, x)
|
|
updateSubscription(patient, x, enable)
|
|
enable && needConsent(x) && setConsentId([patient, x])
|
|
}} name="" id=""
|
|
/> {x.Name} {needConsent(x) ? <ConsentLink saveConsent={saveConsent} setConsentId={setConsentId} patient={patient} service={x}/> : null}</span>
|
|
</label>
|
|
</div>
|
|
)
|
|
})
|
|
}
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const ConsentModal = ({loading, close, service, patient, saveConsent, removeConsent}) => {
|
|
|
|
const [consent, setConsent] = useState(
|
|
hasConsent(patient, service)
|
|
? Object.assign({}, hasConsent(patient, service), {PatientID: patient.ID, EnableBrochure: !!hasConsent(patient, service).Brochure,})
|
|
: {
|
|
PatientID: patient.ID,
|
|
ServiceID: service.ServiceID,
|
|
ConsentGivenOn: format(new Date(), "yyyy-dd-MM"),
|
|
VerbalConsent: false,
|
|
EnableBrochure: false,
|
|
Brochure: "",
|
|
Brochureversion: "",
|
|
}
|
|
)
|
|
|
|
return (
|
|
<div className="c-modal-overlay" onClick={e => e.stopPropagation()}>
|
|
<div className="c-modal">
|
|
<a onClick={close} className="c-modal__close">x</a>
|
|
<div className="c-form-row">
|
|
<label htmlFor="">Toestemming gegeven op</label>
|
|
<input className="c-input" onChange={x => setConsent(Object.assign({}, consent, {ConsentGivenOn: x.target.value}))} value={consent.ConsentGivenOn} type="date"/>
|
|
</div>
|
|
<div className="c-form-row" style={{display: "flex"}}>
|
|
<input style={{marginRight: 5}} checked={consent.VerbalConsent} onChange={x => {
|
|
x.stopPropagation()
|
|
setConsent(Object.assign({}, consent, {VerbalConsent: x.target.checked}))
|
|
}} type="checkbox"/>
|
|
<label htmlFor="">Mondeling geïnformeerd</label>
|
|
</div>
|
|
<div className="c-form-row" style={{display: "flex"}}>
|
|
<input style={{marginRight: 5}} checked={consent.EnableBrochure} onChange={x => {
|
|
x.stopPropagation()
|
|
setConsent(Object.assign({}, consent, {EnableBrochure: x.target.checked}))
|
|
}} type="checkbox"/>
|
|
<label htmlFor="">Geïnformeerd d.m.v. brochure</label>
|
|
</div>
|
|
<div className="c-form-row">
|
|
<label htmlFor="" style={{opacity: consent.EnableBrochure ? 1 : 0.3}}>Brochure</label>
|
|
<input className="c-input" disabled={!consent.EnableBrochure} onChange={x => setConsent(Object.assign({}, consent, {Brochure: x.target.value}))} value={consent.Brochure} type="text"/>
|
|
</div>
|
|
<div className="c-form-row">
|
|
<label htmlFor="" style={{opacity: consent.EnableBrochure ? 1 : 0.3}}>Brochure versie</label>
|
|
<input className="c-input" disabled={!consent.EnableBrochure} onChange={x => setConsent(Object.assign({}, consent, {Brochureversion: x.target.value}))} value={consent.Brochureversion} type="text"/>
|
|
</div>
|
|
<div className="c-modal-buttons">
|
|
<button className="c-button c-button--default" disabled={loading} onClick={async x => {
|
|
await removeConsent(Object.assign({}, consent))
|
|
close()
|
|
}}>Toestemming intrekken</button>
|
|
<button className="c-button" disabled={loading} onClick={async x => {
|
|
await saveConsent(Object.assign({}, consent))
|
|
close()
|
|
}}>Opslaan</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const Patients = () => {
|
|
const location = useLocation()
|
|
const [loading, setLoading] = useState(false)
|
|
const [patients, setPatients] = useState([])
|
|
const [services, setServices] = useState([])
|
|
|
|
const updateServices = async () => fetch(`/api/services`).then(x => x.json()).then(x => setServices(x))
|
|
const updatePatients = async () => fetch(`/api/patients`).then(x => x.json()).then(x => setPatients(x))
|
|
|
|
useEffect(() => {
|
|
updatePatients()
|
|
}, [location])
|
|
|
|
useEffect(() => {
|
|
updateServices()
|
|
}, [location])
|
|
|
|
const updateSubscription = async (patient, service, active) => {
|
|
setLoading(true)
|
|
await fetch(`/api/services/${service.ID}/subscriptions`, {
|
|
method: "POST",
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({active: active, patient: patient.ID})
|
|
})
|
|
|
|
await updateServices()
|
|
|
|
setLoading(false)
|
|
}
|
|
|
|
const saveConsent = async (consent) => {
|
|
setLoading(true)
|
|
|
|
consent.ConsentGivenOn = new Date(consent.ConsentGivenOn)
|
|
if (!consent.EnableBrochure) {
|
|
consent.Brochure = ""
|
|
consent.Brochureversion = ""
|
|
}
|
|
|
|
await fetch(`/api/patients/${consent.PatientID}/consent`, {
|
|
method: "POST",
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(consent)
|
|
})
|
|
|
|
await updatePatients()
|
|
|
|
setLoading(false)
|
|
}
|
|
|
|
const removeConsent = async (consent) => {
|
|
setLoading(true)
|
|
|
|
if (consent.ID) {
|
|
await fetch(`/api/patients/${consent.PatientID}/consent/${consent.ID}`, {
|
|
method: "DELETE"
|
|
})
|
|
}
|
|
|
|
|
|
await updatePatients()
|
|
|
|
setLoading(false)
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<h1 className="t-page-header">Patienten</h1>
|
|
<table className="c-table" style={{width: "initial"}}>
|
|
<thead>
|
|
<tr>
|
|
<th style={{width: 200}}>Naam</th>
|
|
<th style={{width: 200}}>Geboortedatum</th>
|
|
<th style={{width: 200}}>BSN</th>
|
|
<th>Acties</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{patients.map(x => {
|
|
return (<tr key={x.ID}>
|
|
|
|
<td>{x.Name}</td>
|
|
<td>{x.Birthdate}</td>
|
|
<td>{x.ExternalId}</td>
|
|
<td>
|
|
{services.length ? <DropDown
|
|
updateSubscription={updateSubscription}
|
|
patient={x}
|
|
services={services}
|
|
loading={loading}
|
|
saveConsent={saveConsent}
|
|
removeConsent={removeConsent}
|
|
/> : null}
|
|
</td>
|
|
</tr>)
|
|
})}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Patients; |