Extensions
Custom Code
With custom code, you can create your own custom homepage to the EMR and patient portal and footer to the EMR. You have access to all the Avon backend variables and functions via Avon APIs and you can connect to your own APIs as well.
Here is an example of a custom code page that you could upload for the EMR homepage:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Basic Example with JSX</title>
<style>
body {
text-align: center;
font-size: 33px;
font-family: "Syne", sans-serif;
}
</style>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Syne:wght@400..800&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="container"></div>
<script src="https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@remix-run/router@1.7.1/dist/router.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-router@6.14.1/dist/umd/react-router.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-router-dom@6.14.1/dist/umd/react-router-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.22.9/babel.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
var exports = {};
</script>
<script type="text/babel">
function App() {
const [firstName, setFirstName] = React.useState("");
const [greeting, setGreeting] = React.useState("");
const [pulledAppointments, setPulledAppointments] =
React.useState(false);
const [appointmentsList, setAppointmentsList] = React.useState([]);
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const id = urlParams.get("id");
const lightBrandColor = urlParams.get("lightBrandColor");
const darkBrandColor = urlParams.get("darkBrandColor");
const backgroundColor = urlParams.get("backgroundColor");
const jwt = urlParams.get("jwt");
React.useEffect(() => {
const today = new Date();
const hour = today.getHours();
const wish = `Good ${
(hour < 12 && "Morning") || (hour < 17 && "Afternoon") || "Evening"
}`;
setGreeting(wish);
});
// Pull all appointments that include the user and start after that current time
React.useEffect(() => {
const listAppointmentsLink = `https://demo-api.avonhealth.com/v2/appointments`;
const currentTime = new Date().getTime();
const hourInMilliseconds = 60 * 60 * 1000;
(async () => {
const response = await axios.get(listAppointmentsLink, {
headers: {
// Auth
},
params: {
attendees: [id],
status: ["scheduled", "started", "completed"],
search_from: new Date(currentTime - hourInMilliseconds),
},
});
const appointmentsList = response.data.data;
// Filter to only the appointments that have the user as a host or attendee and end after the current time
setAppointmentsList(appointmentsList);
setPulledAppointments(true);
})();
}, [id, jwt]);
return (
<div
className="w-full h-screen font-playfair-display px-10 pt-8"
style={{ backgroundColor: `#${backgroundColor}` }}
>
<div className="px-2 pb-6 text-3xl flex justify-start">
{greeting}!
</div>
<div className="flex flex-col md:flex-row w-full text-sm">
<div className="w-full mx-2 flex flex-col justify-start">
<div
className={`rounded rounded-xl p-6`}
style={{
backgroundColor: `#${lightBrandColor}`,
}}
>
<div className="py-2 flex justify-start">
Welcome to Avon Health! Please be reminded of our practice
guidelines:
</div>
<div className="py-2 flex justify-start text-start">
<ul className="list-disc w-full ml-8">
<li>
For any medical questions or concerns related to your
treatment, we ask that you use our message feature in
the portal. We will address your queries within 72
hours.
</li>
<li>
In case of emergency, please dial 911. All appointments
are conducted via video call. If you need to reschedule
an appointment, we ask for a notice of 48 hours.
</li>
</ul>
</div>
</div>
<div className="flex flex-row">
<div className="w-full md:w-1/2 cursor-pointer">
<a
target="_top"
href="https://portal.avonhealth.com/chat?id=none"
>
<div className="bg-white shadow shadow-lg cursor-pointer p-6 mr-3 my-3">
<svg
className="m-auto my-6"
xmlns="http://www.w3.org/2000/svg"
width="50"
height="50"
viewBox="0 0 24 24"
>
<path d="M21.598 11.456c1.466 1.193 2.402 3.01 2.402 5.044 0 3.587-2.913 6.5-6.5 6.5-.817 0-1.599-.151-2.32-.427l6.418-11.117zm-11.903 8.409l-.363.634c-1.38 2.391-4.441 3.211-6.831 1.831-2.391-1.38-3.211-4.441-1.831-6.831l6.873-11.998c.931-1.613 2.626-2.511 4.365-2.501.839.005 1.688.221 2.466.67 1.842 1.063 2.752 3.125 2.441 5.108-.069.437-.196.869-.386 1.287-.98.124-1.909.415-2.756.843l.799-1.407c.828-1.434.336-3.271-1.098-4.099-1.434-.828-3.271-.335-4.099 1.099l-3.372 5.935 3.978 2.296c-.563 1.136-.879 2.415-.879 3.767 0 1.195.247 2.334.693 3.366zm3.75 1.714c-1.49-1.192-2.445-3.025-2.445-5.079 0-3.587 2.913-6.5 6.5-6.5.837 0 1.637.158 2.372.447l-6.427 11.132z" />
</svg>
Medication Refills
</div>
</a>
</div>
<div className="w-full md:w-1/2 cursor-pointer">
<a
target="_top"
href="https://portal.avonhealth.com/chat?id=none"
>
<div className="bg-white shadow shadow-lg cursor-pointer p-6 mr-3 my-3">
<svg
className="m-auto my-6"
xmlns="http://www.w3.org/2000/svg"
width="50"
height="50"
viewBox="0 0 24 24"
>
<path d="M19.619 21.671c-5.038 1.227-8.711-1.861-8.711-5.167 0-3.175 3.11-5.467 6.546-5.467 3.457 0 6.546 2.309 6.546 5.467 0 1.12-.403 2.22-1.117 3.073-.029 1 .558 2.435 1.088 3.479-1.419-.257-3.438-.824-4.352-1.385zm-10.711-5.167c0-4.117 3.834-7.467 8.546-7.467.886 0 1.74.119 2.544.338-.021-4.834-4.761-8.319-9.998-8.319-5.281 0-10 3.527-10 8.352 0 1.71.615 3.391 1.705 4.695.047 1.527-.851 3.718-1.661 5.313 2.168-.391 5.252-1.258 6.649-2.115.803.196 1.576.304 2.328.363-.067-.379-.113-.765-.113-1.16z"></path>
</svg>
Message My Care Team
</div>
</a>
</div>
</div>
</div>
<div className="w-full mx-2">
<div
className="rounded rounded-lg px-4 p-2 "
style={{ backgroundColor: "#00000019", color: "#00000099" }}
>
<div className="flex justify-center items-center text-sm">
My Upcoming Appointments
</div>
</div>
{!pulledAppointments && (
<div className="flex justify-center items-center text-sm mt-6">
Loading all of your upcoming appointments...
</div>
)}
{pulledAppointments && appointmentsList.length === 0 && (
<div>
<div className="flex justify-center items-center text-sm mt-6">
Looks like you have no upcoming appointments!
</div>
<a
target="_top"
href="https://portal.avonhealth.com/schedule/appointment-type"
>
<button
className="px-8 py-4 rounded rounded-full cursor-pointer mb-1 mt-6"
style={{
backgroundColor: `#${darkBrandColor}`,
color: "#FFF",
}}
>
Book an appointment
</button>
</a>
</div>
)}
{appointmentsList.map((appointment, i) => (
<React.Fragment key={appointment.id}>
<div
className="w-full text-sm flex flex-row justify-between items-center bg-white rounded rounded-xl shadhow shadhow-lg p-4 my-2"
style={{ boxShadow: `4px 4px #D3D3D3` }}
>
<div className="flex flex-row w-full">
<div className="flex flex-col mx-4 justify-start w-full">
<div className=" text-xl flex justify-start">
{appointment.name}
</div>
<div className="flex flex-row">
<div className="flex flex-row items-center my-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
className=""
>
<path
fill={`#5D9097`}
d="M20 20h-4v-4h4v4zm-6-10h-4v4h4v-4zm6 0h-4v4h4v-4zm-12 6h-4v4h4v-4zm6 0h-4v4h4v-4zm-6-6h-4v4h4v-4zm16-8v22h-24v-22h3v1c0 1.103.897 2 2 2s2-.897 2-2v-1h10v1c0 1.103.897 2 2 2s2-.897 2-2v-1h3zm-2 6h-20v14h20v-14zm-2-7c0-.552-.447-1-1-1s-1 .448-1 1v2c0 .552.447 1 1 1s1-.448 1-1v-2zm-14 2c0 .552-.447 1-1 1s-1-.448-1-1v-2c0-.552.447-1 1-1s1 .448 1 1v2z"
/>
</svg>
<div
className="ml-2 mr-6"
style={{ color: `#5D9097` }}
>
{new Date(
appointment.start_time
).toLocaleDateString("en-US", {
weekday: "short",
month: "short",
day: "numeric",
})}
</div>
</div>
<div className="flex flex-row items-center my-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
>
<path
fill={`#5D9097`}
d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm7 14h-8v-9h2v7h6v2z"
/>
</svg>
<div
className="ml-2 mr-4"
style={{ color: `#5D9097` }}
>
{new Date(
appointment.start_time
).toLocaleTimeString([], {
hour: "numeric",
minute: "2-digit",
})}
</div>
</div>
</div>
</div>
</div>
<div className="flex flex-col space-between text-xs">
<a
target="_blank"
href={appointment.video_call?.join_url ?? ""}
>
<div
className="px-2 py-2 rounded rounded-lg cursor-pointer mb-1"
style={{
background: `#${darkBrandColor}`,
color: "#FFF",
}}
>
<div className="flex flex-row items-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<path
fill="#FFF"
d="M16 18c0 1.104-.896 2-2 2h-12c-1.105 0-2-.896-2-2v-12c0-1.104.895-2 2-2h12c1.104 0 2 .896 2 2v12zm8-14l-6 6.223v3.554l6 6.223v-16z"
/>
</svg>
<div className="mx-2 px-4">Join</div>
</div>
</div>
</a>
</div>
</div>
</React.Fragment>
))}
</div>
</div>
</div>
);
}
setInterval(function () {
ReactDOM.render(<App />, document.getElementById("container"));
}, 50);
</script>
</body>
</html>