To get a general overview of VetCalc, my motivations behind it and my experience at Hackbright in general, please check out the interview I did with Course Report: https://www.coursereport.com/blog/stacey-s-final-project-at-hackbright-academy
VetCalc is a social network for the veterinary industry where users can save, share and calculate drug doses. The calculator provides a visualisation of the amount of tablets or liquid required per dose, allowing for more informed decisions when selecting drug concentration. A label is automatically generated and can be texted directly to the client, reducing communication errors. Users can save other vets' preferred doses to their own page for future reference. While nurses can prescribe according to a vet’s preferences, they cannot save their own doses. Interaction between users is enabled through private messaging and following. VetCalc saves vets approximately 5 hours a week and reduces medical mistakes.
As a practicing veterinarian, I was frustrated with the amount of time I spent looking up drug doses. Once I would find a dose I liked, if I didn't use it for a while, I would need to look it up all over again. Deciding on a drug dose isn't as simple as just consulting a textbook. Usually the textbook ranges are quite large and it can be difficult to decide where to go within the range. Deciding on a dose often involves consulting multiple texbooks (since they can all have different ranges) and consulting with colleagues or specialists from other hospitals on what their preferred dose is. Both vets and nurses are responsible for calculating the actual amount of drug required for a given dose, which can lead to another subset of complications regarding miscalculations. For example, overdosing or underdosing or not sending the correct total amount of drug home with the patient. Mistakes made here can have severe consequences.
- Python
- Flask
- Javascript
- React
- Socketio
- HTML
- CSS
- Amazon S3
- Pillow
- Anime.js
- Lodash
- React Rangeslider
There is a lot that goes into deciding on a drug dose and I wanted my database to reflect this. I spent a long time thinking about and working through an ideal datamodel. In the time I had for the scoped version of this project, there wasn't enough time to implement every table and feature I wanted, but I plan to continue working towards the more complex version after Hackbright.
I will be working towards having a datamodel more like this in the future.
These tables relate to users:
These tables store information related to drug doses:
Since drug names can be difficult to spell, I wanted to implement an autocomplete search. I researched and implemented a data structure called a trie. This tutorial was a really helpful guide in making some practice tries before adding them to my real site. After I added the first one to the main drug search page, I thought it was so much fun that I had to add it to the other pages too. I added extra nodes to the user search page to allow searching by first name, last name or username.
Private messaging is implemented with socketio and javascript in the frontend and flask-socketio in the backend. This was quite difficult to deploy, as the sockets communicate with http, but the site is deployed with https. The sockets also kept defaulting to long polling, which made for an extremely unpleasant messaging experience!
To trigger the AJAX request for the infinite scroll, I added an event listener that detects when the user scrolls to the top of the page. When the request is sent to the server a paginated database query retrieves next 10 messages. When no messages are left to be returned, a "No more messages" notification appears at the top.
When a message is emitted to a chat room, users that are connected to the socket emit a confirmation back to the server. If a confirmation is sent by the message recipient, then the seen status is updated in the database to true. If the message recipient isn't connected to the socket, a confirmation is not sent and the seen status remains false in the database. The next time the user refreshes or reloads another page, a notification icon will show in their navbar. When a user loads a conversation, all the messages are set to seen.
Visualise the number of tablets required per dose. You can choose whether the tablets can be halved or quartered, or can only be taken whole. I created the illusion of a syringe being filled by adding a CSS clip path over a normal box animation. This tool was extremely helpful in creating the path.
As you use the calculator page, the label instructions at the bottom update according to the state of the rest of the page. You can customize the label further before texting it to the client if there is extra information you want to include.
Labels are subject to degradation. They fade, become smudged and owners throw out the packaging. When label instructions are unclear or non-existent, an owner's reliance on memory drastically increases the risk of medical mistakes.
Users can create a network of other veterinary professionals through following. Follower-followee relationships are stored in an association table in the database. In the future I want to build up the social media feature to have a special relationship between vets and nurses, where a nurse can indicate the vet they are working for in a particular shift and automatically are suggested that vet's preferred doses.
Vets can add their own preferred drug doses, which get stored in the personal_doses data table and displayed on their profile page.
Users can save other user's doses to their own profile page for future reference. For example,
Users can upload their own profile pictures. The pictures are resized using the python library, Pillow into both thumbnail and a larger profile page size. They're then added to an Amazon S3 bucket. Since a presigned url was being sent to S3 to retrieve the images every time they were needed from the site, it resulted in a lot of flickering. Which was particularly noticable in the chat. I extended the expiry date on the URLs and implemented client side caching to resolve this.
Vets and nurses have distinct accounts. Veterinarians can utilize all features of the app. While nurses arae unable to set their own preferred doses, they can save preferred doses from the vets they work with. In the future I plan to build out this feature into special, vet-nurse connections where nurses can set who they are working with on a shift, and automatically get shown that vet's preferred doses.
- Adding real drug doses. The drug names displayed on the drug search page were scraped using Beautiful Soup, but textbook they were retrieved from was not machine readable enough to make scraping a possibility. For this reason all textbook doses, contraindications and interactions are randomly generated to provide a proof of concept only.
- Account editing - currently there is no settings page. A user cannot update their email, name etc.
- Optimize for mobile - Vets, especially large animal vets are constantly on the go.
There are many more features I have in mind that I would like to build out, but these are 2 major ones holding the app back from being functional in practice. Although users can currently save an calculate their own preferred doses, having randomly generated "textbook doses" is risky.
I think these user flow diagrams I mapped out at the beginning of the project give a good idea of where I want to take the project in the future:
A huge thank you to the authors of these blog posts and tutorials:
- A brilliant blog post on websockets
- Flask followers tutorial - Miguel Grinberg's tutorials helped me so much during this project. Especially in the support he provides for flask-socketio. During deployment I spent quite a long time reading through the github issues on flask-socketio and found his answers incredibly useful.
Image credits:
- Syringe image on calculator page - Icon made by Freepik from www.flaticon.com
- Stethoscope logo - https://cutthatdesign.com/2018/04/nurse-stethoscope-heartbeat-design-set/
- Landing page photos - All photos from unsplash.com
MIT Stacey Carter 2019