Adding info on hover over svg feature and CHA2_DS2-VASc calculator
This commit is contained in:
@@ -12,7 +12,7 @@ export default function LayoutClient({children} : {children:React.ReactNode}){
|
||||
<Navbar navbarToggle={setNavbar}/>
|
||||
<Sidemenu isNavOpen={navbar}/>
|
||||
<div className="content w-full flex justify-center px-4 pb-6">
|
||||
<div className="max-w-2xl overflow-x-hidden">
|
||||
<div className="max-w-2xl">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,4 +70,10 @@
|
||||
|
||||
.animate-ecg {
|
||||
animation: ecgMove 6s linear infinite;
|
||||
}
|
||||
.tooltip::before {
|
||||
max-width: 90vw;
|
||||
left: 50% !important;
|
||||
transform: translateX(-50%) !important;
|
||||
white-space: normal;
|
||||
}
|
||||
@@ -6,6 +6,12 @@ import { Analytics } from "@vercel/analytics/next"
|
||||
export const metadata: Metadata = {
|
||||
title: "CalcForCardiac",
|
||||
description: "A zero friction and zero login medical calculator made by Saksham Vitwekar (SomeTroller77)",
|
||||
authors:[{name:"Saksham Vitwekar"}],
|
||||
openGraph:{
|
||||
title:"CalcForCardiac",
|
||||
description:"A mininal friction and zero login medical calculator especially for cardiologists",
|
||||
images:["/calcforcardiac_logo.png"]
|
||||
}
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { useState } from "react";
|
||||
import { Input } from "./calculators/types";
|
||||
|
||||
export default function InputComponent({id, type, inputOptions, min, max, required, defaultUnit, unitOptions, name, placeholder, handleDataChange} : Input){
|
||||
export default function InputComponent({id, type, inputOptions, min, max, required, defaultUnit, unitOptions, name, placeholder, handleDataChange, info} : Input){
|
||||
const [showError, setErrorStatus] = useState(false);
|
||||
const [error, setError] = useState<string>();
|
||||
const [option, setOption] = useState<string>("");
|
||||
@@ -10,7 +10,22 @@ export default function InputComponent({id, type, inputOptions, min, max, requir
|
||||
return(
|
||||
<>
|
||||
<fieldset className="fieldset">
|
||||
<legend className="fieldset-legend text-black">{name}</legend>
|
||||
<legend className="fieldset-legend text-black">{ typeof info === "string" ?
|
||||
<>
|
||||
<div className="tooltip inline-block max-w-[140px] overflow-visible" data-tip={info}>
|
||||
<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-4 h-4" viewBox="0 0 416.979 416.979"
|
||||
>
|
||||
<g>
|
||||
<path d="M356.004,61.156c-81.37-81.47-213.377-81.551-294.848-0.182c-81.47,81.371-81.552,213.379-0.181,294.85
|
||||
c81.369,81.47,213.378,81.551,294.849,0.181C437.293,274.636,437.375,142.626,356.004,61.156z M237.6,340.786
|
||||
c0,3.217-2.607,5.822-5.822,5.822h-46.576c-3.215,0-5.822-2.605-5.822-5.822V167.885c0-3.217,2.607-5.822,5.822-5.822h46.576
|
||||
c3.215,0,5.822,2.604,5.822,5.822V340.786z M208.49,137.901c-18.618,0-33.766-15.146-33.766-33.765
|
||||
c0-18.617,15.147-33.766,33.766-33.766c18.619,0,33.766,15.148,33.766,33.766C242.256,122.755,227.107,137.901,208.49,137.901z"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div></> : null
|
||||
} {name} {defaultUnit ? `(${defaultUnit})` : null} </legend>
|
||||
<input type="number"
|
||||
id={id}
|
||||
className="input bg-white border-solid border-black"
|
||||
@@ -44,7 +59,22 @@ export default function InputComponent({id, type, inputOptions, min, max, requir
|
||||
} else if(type === "select"){
|
||||
return(
|
||||
<fieldset className="fieldset">
|
||||
<legend className="fieldset-legend text-black">{name}</legend>
|
||||
<legend className="fieldset-legend text-black"> { info ?
|
||||
<>
|
||||
<div className="tooltip inline-block" data-tip={info}>
|
||||
<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-4 h-4" viewBox="0 0 416.979 416.979"
|
||||
>
|
||||
<g>
|
||||
<path d="M356.004,61.156c-81.37-81.47-213.377-81.551-294.848-0.182c-81.47,81.371-81.552,213.379-0.181,294.85
|
||||
c81.369,81.47,213.378,81.551,294.849,0.181C437.293,274.636,437.375,142.626,356.004,61.156z M237.6,340.786
|
||||
c0,3.217-2.607,5.822-5.822,5.822h-46.576c-3.215,0-5.822-2.605-5.822-5.822V167.885c0-3.217,2.607-5.822,5.822-5.822h46.576
|
||||
c3.215,0,5.822,2.604,5.822,5.822V340.786z M208.49,137.901c-18.618,0-33.766-15.146-33.766-33.765
|
||||
c0-18.617,15.147-33.766,33.766-33.766c18.619,0,33.766,15.148,33.766,33.766C242.256,122.755,227.107,137.901,208.49,137.901z"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div></> : null
|
||||
} {name} {defaultUnit ? `(${defaultUnit})` : null} </legend>
|
||||
<select value={option}
|
||||
className="select bg-white border-solid border-black"
|
||||
onChange={(e) => {
|
||||
@@ -65,8 +95,23 @@ export default function InputComponent({id, type, inputOptions, min, max, requir
|
||||
)
|
||||
}else if(type === "checkbox"){
|
||||
return(
|
||||
<fieldset className="fieldset bg-white bg-base-100 border border-base-300 rounded-box w-full min-w-0 p-2">
|
||||
<legend className="fieldset-legend text-black">{name}</legend>
|
||||
<fieldset className="fieldset bg-white bg-base-100 border border-base-300 rounded-box w-full min-w-0 p-2 overflow-visible">
|
||||
<legend className="fieldset-legend text-black overflow-visible"> {name} {defaultUnit ? `(${defaultUnit})` : null} { info ?
|
||||
<>
|
||||
<div className="tooltip ml-1 tooltip-top sm:tooltip-left ml-1" data-tip={info}>
|
||||
<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-4 h-4" viewBox="0 0 416.979 416.979"
|
||||
>
|
||||
<g>
|
||||
<path d="M356.004,61.156c-81.37-81.47-213.377-81.551-294.848-0.182c-81.47,81.371-81.552,213.379-0.181,294.85
|
||||
c81.369,81.47,213.378,81.551,294.849,0.181C437.293,274.636,437.375,142.626,356.004,61.156z M237.6,340.786
|
||||
c0,3.217-2.607,5.822-5.822,5.822h-46.576c-3.215,0-5.822-2.605-5.822-5.822V167.885c0-3.217,2.607-5.822,5.822-5.822h46.576
|
||||
c3.215,0,5.822,2.604,5.822,5.822V340.786z M208.49,137.901c-18.618,0-33.766-15.146-33.766-33.765
|
||||
c0-18.617,15.147-33.766,33.766-33.766c18.619,0,33.766,15.148,33.766,33.766C242.256,122.755,227.107,137.901,208.49,137.901z"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div></> : null
|
||||
}</legend>
|
||||
<label className="label flex gap-3 items-start w-full">
|
||||
<input type="checkbox"
|
||||
className="checkbox checkbox-neutral border-solid border-black mt-1 shrink-0"
|
||||
|
||||
@@ -8,7 +8,6 @@ export default function Section({sectionName, Calculators, id} : {sectionName:st
|
||||
useEffect(() => {
|
||||
const bookmarkedStr:string = localStorage.getItem("bookmarks") || "[]";
|
||||
const bookmarkedObj : {section:string, id:string}[] = JSON.parse(bookmarkedStr);
|
||||
console.log(bookmarkedObj);
|
||||
setBookmarks(bookmarkedObj);
|
||||
}, [])
|
||||
return(
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
import { Calculator, Input, Interpretation, Values } from "../types";
|
||||
|
||||
const parameters:Input[] = [
|
||||
{
|
||||
id:"chf",
|
||||
name:"CHF/LV dysfunction",
|
||||
type:"checkbox",
|
||||
placeholder:"Whether the patient has CHF or LV dysfunction",
|
||||
required:true
|
||||
},
|
||||
{
|
||||
id:"hypertension",
|
||||
name:"Hypertension",
|
||||
type:"checkbox",
|
||||
placeholder:"Whether the patient has hypertension",
|
||||
required:true
|
||||
},
|
||||
{
|
||||
id:"age",
|
||||
name:"age",
|
||||
type:"number",
|
||||
placeholder:"Enter the age",
|
||||
required:true,
|
||||
min: 18,
|
||||
max: 95
|
||||
},
|
||||
{
|
||||
id:"dm",
|
||||
name:"Diabetes Mellitus",
|
||||
placeholder:"Whether the patient has diabetes",
|
||||
type:"checkbox",
|
||||
required:true
|
||||
},
|
||||
{
|
||||
id:"ischemia",
|
||||
name:"Prior ischemia",
|
||||
placeholder:"Whether the patient had prior ischemic event",
|
||||
type:"checkbox",
|
||||
required:true
|
||||
},
|
||||
{
|
||||
id:"vd",
|
||||
name:"Vascular Disease",
|
||||
placeholder:"Whether the patient has any vascular disease",
|
||||
info:"Myocardial Infarction, Peripheral Vascular Disease etc.",
|
||||
type:"checkbox",
|
||||
required:true
|
||||
},
|
||||
{
|
||||
id:"gender",
|
||||
name:"Gender",
|
||||
placeholder:"Select the gender",
|
||||
type:"select",
|
||||
required:true,
|
||||
inputOptions:[
|
||||
{
|
||||
label:"Male",
|
||||
value:"male"
|
||||
},
|
||||
{
|
||||
label:"Female",
|
||||
value:"female"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const cha2ds2 : Calculator = {
|
||||
id:"cha2ds2",
|
||||
name:"CHA₂DS₂-VASc Score",
|
||||
desc:"CHA₂DS₂-VASc Score is a clinical prediction tool used to estimate the risk of stroke in patients with non-valvular atrial fibrillation (AF).",
|
||||
inputs:parameters,
|
||||
calc_func:(values : Values):number => {
|
||||
const chf = values.chf as boolean;
|
||||
const hypertension = values.hypertension as boolean;
|
||||
const age = values.age as number;
|
||||
const dm = values.dm as boolean;
|
||||
const ischemia = values.ischemia as boolean;
|
||||
const vd = values.vd as boolean;
|
||||
const gender = values.gender as "male" | "female";
|
||||
var score = 0;
|
||||
if(chf) score++;
|
||||
if(hypertension) score++
|
||||
if(age >= 75) score = score + 2;
|
||||
if(dm) score++;
|
||||
if(ischemia) score = score + 2;
|
||||
if(vd) score ++;
|
||||
if(age >= 65 && age < 75) score++;
|
||||
if(gender === "female") score++;
|
||||
return score;
|
||||
},
|
||||
interpret_func:(score : number):Interpretation => {
|
||||
if(score === 0){
|
||||
return {
|
||||
level:"low",
|
||||
message:"The stroke risk % for the patient is 0.2%"
|
||||
}
|
||||
}
|
||||
if(score === 1){
|
||||
return {
|
||||
level:"low",
|
||||
message:"The stroke risk % for the patient is 0.6%"
|
||||
}
|
||||
}
|
||||
if(score === 2){
|
||||
return {
|
||||
level:"low",
|
||||
message:"The stroke risk % for the patient is 2.2%"
|
||||
}
|
||||
}
|
||||
if(score === 3){
|
||||
return {
|
||||
level:"low",
|
||||
message:"The stroke risk % for the patient is 3.2%"
|
||||
}
|
||||
}
|
||||
if(score === 4){
|
||||
return {
|
||||
level:"moderate",
|
||||
message:"The stroke risk % for the patient is 4.8%"
|
||||
}
|
||||
}
|
||||
if(score === 5){
|
||||
return {
|
||||
level:"moderate",
|
||||
message:"The stroke risk % for the patient is 7.2%"
|
||||
}
|
||||
}
|
||||
if(score === 6){
|
||||
return {
|
||||
level:"moderate",
|
||||
message:"The stroke risk % for the patient is 9.7%"
|
||||
}
|
||||
}
|
||||
if(score === 7){
|
||||
return {
|
||||
level:"high",
|
||||
message:"The stroke risk % for the patient is 11.2%"
|
||||
}
|
||||
}
|
||||
if(score === 8){
|
||||
return {
|
||||
level:"high",
|
||||
message:"The stroke risk % for the patient is 10.8%"
|
||||
}
|
||||
}
|
||||
if(score === 9){
|
||||
return {
|
||||
level:"severe",
|
||||
message:"The stroke risk % for the patient is 12.2"
|
||||
}
|
||||
}
|
||||
return {
|
||||
level:"none",
|
||||
message:"invalid values"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,14 +10,15 @@ const parameters:Input[] = [
|
||||
},
|
||||
{
|
||||
id:"isCAD",
|
||||
name:"Known Coronary Artery Disease (stenosis >= 50%)",
|
||||
placeholder:"Whether the patient has a known CAD with more than 50% stenosis",
|
||||
name:"Known Coronary Artery Disease",
|
||||
placeholder:"Whether the patient has a known CAD with more than or equal to 50% stenosis",
|
||||
type:"checkbox"
|
||||
},
|
||||
{
|
||||
id:"cadRiskFactors",
|
||||
name:"CAD Risk Factors",
|
||||
placeholder:"Whether the patient has 3 or more than 3 CAD Risk Factors (Family history of CAD, Hypertension, Hypercholesterolemia, Diabetes, Smoker)",
|
||||
placeholder:"Whether the patient has 3 or more than 3 CAD Risk Factors",
|
||||
info:"Hypertension, hypercholesterolemia, diabetes, family history of CAD, or current smoker",
|
||||
type:"checkbox"
|
||||
},
|
||||
{
|
||||
@@ -41,8 +42,9 @@ const parameters:Input[] = [
|
||||
{
|
||||
id:"biomarkers",
|
||||
name:"Elevated Serum cardiac biomarkers",
|
||||
placeholder:"Whether the patient has Elevated Serum cardiac biomarkers (Troponin levels, creatine kinase etc)",
|
||||
type:"checkbox"
|
||||
placeholder:"Whether the patient has Elevated Serum cardiac biomarkers",
|
||||
type:"checkbox",
|
||||
info:"Troponin levels, creatine kinase"
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -4,18 +4,20 @@ const parameters : Input[] = [
|
||||
{
|
||||
id:"sbp",
|
||||
name:"Systolic Blood Pressure",
|
||||
placeholder:"Enter the Systolic Blood Pressure in mmHg",
|
||||
placeholder:"Enter the Systolic Blood Pressure",
|
||||
type:"number",
|
||||
required:true,
|
||||
min:0
|
||||
min:0,
|
||||
defaultUnit:"mmHg",
|
||||
},
|
||||
{
|
||||
id:"dbp",
|
||||
name:"Diastolic Blood Pressure",
|
||||
placeholder:"Enter the Disatolic Blood Pressure in mmHg",
|
||||
placeholder:"Enter the Disatolic Blood Pressure",
|
||||
type:"number",
|
||||
required:true,
|
||||
min:0
|
||||
min:0,
|
||||
defaultUnit:"mmHg"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Section } from "./types";
|
||||
import { MELD } from "./Utilities/MELD";
|
||||
import { MAP } from "./General Cardiology/MAP";
|
||||
import { TIMI } from "./Emergency/TIMI_score";
|
||||
import { cha2ds2 } from "./Arrhythmias and Anti-Coagulation/CHA2DS2-VASc-score";
|
||||
|
||||
export const CalculatorRegistry : Record<string, Section> = {
|
||||
generalCardiology:{
|
||||
@@ -15,6 +16,15 @@ export const CalculatorRegistry : Record<string, Section> = {
|
||||
MAP
|
||||
]
|
||||
},
|
||||
arrhythmias:{
|
||||
id:"arrhythmias",
|
||||
displayName:"Arrhythmias & Anti-Coagulation",
|
||||
textColor:"#ccc",
|
||||
svg:"",
|
||||
calculators:[
|
||||
cha2ds2
|
||||
]
|
||||
},
|
||||
emergency:{
|
||||
id:"emergency",
|
||||
displayName:"Emergency",
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface Input{
|
||||
required?:boolean,
|
||||
defaultUnit?:string,
|
||||
unitOptions?:string[],
|
||||
info?: string,
|
||||
handleDataChange?:Function
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user