Spaces:
Running
Running
import os | |
import streamlit as st | |
from streamlit_extras.add_vertical_space import add_vertical_space | |
from streamlit_option_menu import option_menu | |
st.title("Utilidades") | |
# Menu aninhado usando streamlit-option-menu na horizontal | |
nested_menu = option_menu( | |
menu_title=None, | |
options=[ | |
"Incidências radiológicas", "TFG", "Coelho e Savassi", "Escore de Risco Global", "Noripurun", | |
], | |
icons=['lungs', 'nephrology', 'clinical_notes', 'heart', 'syrenge'], | |
menu_icon="cast", | |
default_index=0, | |
orientation="horizontal", | |
) | |
# Conteúdo das subpáginas | |
if nested_menu == "Incidências radiológicas": | |
st.header("Apoio clínico na solicitação de radiografias!") | |
c1, c2, c3, c4 = st.columns([1, 3, 3, 1]) | |
with c1: | |
st.markdown("") | |
with c2: | |
st.header(":blue[Incidências Radiográficas] ☢️") | |
with c3: | |
st.image("icon/rx2.svg", width=400) | |
with c4: | |
st.markdown("") | |
add_vertical_space() | |
# # Descrição com estilo e emojis | |
st.markdown(""" | |
##### ✅ **Vamos melhorar a visualização das incidências médicas!** | |
""") | |
def exibir_incidencias(regiao, incidencias): | |
st.markdown(f"## {regiao}") | |
for incidencia in incidencias: | |
st.markdown(f"- {incidencia}") | |
add_vertical_space(3) | |
st.markdown("### 🧍♂️ Selecione a Região do Corpo:") | |
incidencias_radiograficas = { | |
"👨⚕️ Tórax e Vias Aéreas": [ | |
"👨⚕️ Tórax - PA e Lateral", | |
"🦴 Esterno – OAD e Lateral", | |
"🦴 Art. Esterno-Clavicular – PA, OAD e OAE", | |
"🦴 Costelas Posteriores – AP, OPD e OPE", | |
"🦴 Costelas Anteriores – PA, OAD e OPE", | |
"👃 Vias aéreas superiores - AP e Lateral", | |
], | |
"💢 Abdome e Pelve": [ | |
"💢 Abdome - AP em Decúbito Dorsal", | |
"💢 RAA - Tórax PA, Abdome em Decúbito Dorsal e Abdome em AP Ortostrica", | |
"🦵 Pelves (Bacia) - AP e AP perna de Rã, para traumatismo apenas AP", | |
"🦵 Quadril - AP e Axial Lateral", | |
"🦴 Art. Sacro-Ilíaca – Axial AP e Oblíquas", | |
], | |
"✋ Membros Superiores": [ | |
"✋ Dedos da mão do 2º ao 5º - PA, Lateral e Oblíqua", | |
"👍 Polegar - AP, Lateral e Oblíqua", | |
"🖐️ Mão - PA, Lateral e Oblíqua", | |
"✊ Mão e Punho para Idade Óssea - PA Comparativa", | |
"✊ Punho - PA, Lateral e Oblíqua", | |
"🦴 Antebraço - AP e Lateral", | |
"🦴 Cotovelo - AP e Lateral", | |
"🦴 Úmero - AP e Lateral", | |
"💪 Ombro - AP com rotação externa e interna", | |
"💪 Ombro em traumatismo - AP com rotação neutra, Lateral escapular ou Transtorácica", | |
"🦴 Clavícula - AP e AP Axial", | |
"🦴 Art. Acromioclavicular - AP Bilateral com e sem estresse", | |
"🦴 Escápula - AP e Lateral", | |
], | |
"🦵 Membros Inferiores": [ | |
"🦶 Dedos dos pés - AP, Lateral e Oblíqua", | |
"🦶 Pé - AP, Lateral e Oblíqua", | |
"🦶 Calcâneo - Axial e Lateral", | |
"🦵 Tornozelo - AP, AP do encaixe, Lateral e Oblíqua", | |
"🦿 Joelho - AP, Lateral e Oblíqua", | |
"🦿 Patela - PA, Lateral e Tangencial", | |
"🦿 Perna - AP e Lateral", | |
"🦿 Fêmur – AP e Lateral", | |
], | |
"🦴 Coluna Vertebral": [ | |
"🦴 Coluna Cervical - Axial AP, Transoral, Lateral e Oblíqua", | |
"🦴 Coluna Dorsal ou Torácica - AP e Lateral", | |
"🦴 Coluna Lombar - AP, Lateral e Oblíqua", | |
"🦴 Sacro e Cóccix - Axial AP e Lateral", | |
"🦴 Rotina para Escoliose – AP e Lateral", | |
"🦴 Rotina para Fusão Vertebral – AP com inclinação Esquerda e Direita Lateral com Hiperextensão e Hiperflexão", | |
], | |
"🦷 Cabeça e Face": [ | |
"👤 Crânio - AP Axial, PA e Lateral", | |
"👃 Ossos da Face - Caldwell, Waters e Lateral", | |
"👂 Ossos Nasais - Waters e Lateral", | |
"👄 Mandíbula - Axial Lateral, PA e Axial AP", | |
"🧠 Seios da Face - Caldwell, Waters e Lateral", | |
"👂 Arcos Zigomáticos – Axial AP Submentovertice e Tangencial", | |
"👂 Pirâmide – Rhêse, Caldwell e Waters", | |
"🦴 ATM's – Axial Lateral e Oblíqua Axial Lateral", | |
"🦴 Mastoides – Oblíqua Axial Lateral, Oblíqua Axial Anterior e Axial AP", | |
"🦴 Sela Turcica – Axial AP e Lateral", | |
] | |
} | |
cx1, cx2 = st.columns([1, 1]) | |
with cx1: | |
st.markdown("") | |
regioes = list(incidencias_radiograficas.keys()) | |
regiao_escolhida = st.radio("", regioes) | |
with cx2: | |
if regiao_escolhida: | |
exibir_incidencias( | |
regiao_escolhida, | |
incidencias_radiograficas[regiao_escolhida]) | |
st.markdown(""" | |
--- | |
Desenvolvedor ☕ **Dr. Guilherme** | |
""") | |
elif nested_menu == "TFG": | |
import pathlib | |
import streamlit as st | |
import streamlit.components.v1 as components | |
from streamlit_extras.add_vertical_space import add_vertical_space | |
st.header("Calculadora TFG") | |
static_dir = pathlib.Path('static').absolute() | |
html_with_js= '' | |
def estilo(): | |
css_file_path = static_dir / 'styles.css' | |
if css_file_path.exists(): | |
with open(css_file_path, "r", encoding="utf-8") as f: | |
st_css = st.html(f"<style>{f.read()}</style>") | |
return st_css | |
else: | |
st.error(f"CSS file not found: {css_file_path}") | |
return None | |
def linha_vertical(altura=300, cor='black', espessura=2): | |
""" | |
Cria uma linha vertical | |
""" | |
css = f""" | |
<style> | |
.linha-vertical {{ | |
border-left: {espessura}px solid {cor}; | |
height: {altura}px; | |
position: absolute; | |
left: 50%; | |
margin-left: -{espessura/2}px; | |
}} | |
</style> | |
""" | |
html = f"{css}<div class='linha-vertical'></div>" | |
linha=st.markdown(html, unsafe_allow_html=True) | |
return linha | |
def calc(html_with_js): | |
html_with_js = ''' | |
<!DOCTYPE html> | |
<html lang="pt-BR"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Calculadora CKD-EPI</title> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> | |
<style> | |
body { | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
background-color: #e0e5ec; | |
color: #333; | |
line-height: 1.6; | |
padding: 20px; | |
margin: 0; | |
} | |
.container { | |
width: 300px; | |
max-height: 600px; | |
margin: 0 auto; | |
background-color: #e0e5ec; | |
border-radius: 20px; | |
padding: 20px; | |
box-shadow: | |
8px 8px 15px #a3b1c6, | |
-8px -8px 15px #ffffff; | |
} | |
h2 { | |
color: #4a4a4a; | |
text-shadow: 2px 2px 4px rgba(255,255,255,0.5); | |
text-align: center; | |
margin-bottom: 20px; | |
} | |
.input-group { | |
margin-bottom: 20px; | |
position: relative; | |
} | |
.input-group label { | |
display: block; | |
margin-bottom: 5px; | |
color: #4a4a4a; | |
padding-left: 40px; | |
} | |
.input-field { | |
width: 50%; | |
padding: 12px 20px; | |
margin-left: 50px; | |
border: none; | |
border-radius: 25px; | |
background-color: #e0e5ec; | |
color: #333; | |
font-size: 16px; | |
box-shadow: | |
inset 5px 5px 10px #a3b1c6, | |
inset -5px -5px 10px #ffffff; | |
} | |
.icon-wrapper { | |
position: absolute; | |
left: 0; | |
top: 0; | |
width: 36px; | |
height: 36px; | |
background-color: #e0e5ec; | |
border-radius: 50%; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
box-shadow: | |
5px 5px 10px #a3b1c6, | |
-5px -5px 10px #ffffff; | |
} | |
.input-icon { | |
color: #4a4a4a; | |
font-size: 18px; | |
} | |
.toggle-container { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-bottom: 20px; | |
} | |
.toggle-switch { | |
position: relative; | |
display: inline-block; | |
width: 60px; | |
height: 34px; | |
} | |
.toggle-switch input { | |
opacity: 0; | |
width: 0; | |
height: 0; | |
} | |
.slider { | |
position: absolute; | |
cursor: pointer; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background-color: #e0e5ec; | |
transition: .4s; | |
border-radius: 34px; | |
box-shadow: | |
inset 4px 4px 6px #a3b1c6, | |
inset -4px -4px 6px #ffffff; | |
} | |
.slider:before { | |
position: absolute; | |
content: ""; | |
height: 26px; | |
width: 26px; | |
left: 4px; | |
bottom: 4px; | |
background-color: #e0e5ec; | |
transition: .4s; | |
border-radius: 50%; | |
box-shadow: | |
2px 2px 3px #a3b1c6, | |
-2px -2px 3px #ffffff; | |
} | |
input:checked + .slider:before { | |
transform: translateX(26px); | |
} | |
.button-group { | |
display: flex; | |
justify-content: space-between; | |
margin-top: 20px; | |
} | |
.button { | |
flex: 1; | |
padding: 12px 24px; | |
background-color: #e0e5ec; | |
border: none; | |
border-radius: 50px; | |
color: #4a4a4a; | |
font-weight: bold; | |
text-decoration: none; | |
transition: all 0.3s ease; | |
box-shadow: | |
5px 5px 10px #a3b1c6, | |
-5px -5px 10px #ffffff; | |
cursor: pointer; | |
margin: 0 5px; | |
} | |
.button:hover { | |
box-shadow: | |
inset 5px 5px 10px #a3b1c6, | |
inset -5px -5px 10px #ffffff; | |
} | |
#result { | |
display: none; | |
margin-top: 10px; | |
padding: 10px; | |
border-radius: 15px; | |
background-color: #e0e5ec; | |
box-shadow: | |
inset 5px 5px 10px #a3b1c6, | |
inset -5px -5px 10px #ffffff; | |
} | |
#result h3 { | |
margin-top: 0; | |
color: #4a4a4a; | |
} | |
} | |
.toggle-container { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-bottom: 20px; | |
} | |
.gender-label { | |
display: flex; | |
align-items: center; | |
color: #4a4a4a; | |
} | |
.gender-icon { | |
margin-right: 5px; | |
font-size: 18px; | |
} | |
.toggle-switch { | |
position: relative; | |
display: inline-block; | |
width: 60px; | |
height: 34px; | |
} | |
.toggle-switch input { | |
opacity: 0; | |
width: 0; | |
height: 0; | |
} | |
.slider { | |
position: absolute; | |
cursor: pointer; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background-color: #e0e5ec; | |
transition: .4s; | |
border-radius: 34px; | |
box-shadow: | |
inset 4px 4px 6px #a3b1c6, | |
inset -4px -4px 6px #ffffff; | |
} | |
.slider:before { | |
position: absolute; | |
content: ""; | |
height: 26px; | |
width: 26px; | |
left: 4px; | |
bottom: 4px; | |
background-color: #e0e5ec; | |
transition: .4s; | |
border-radius: 50%; | |
box-shadow: | |
2px 2px 3px #a3b1c6, | |
-2px -2px 3px #ffffff; | |
} | |
input:checked + .slider:before { | |
transform: translateX(26px); | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h2>Calculadora CKD-EPI</h2> | |
<form id="ckd-epi-form"> | |
<div class="input-group"> | |
<div class="icon-wrapper"> | |
<i class="fas fa-birthday-cake input-icon"></i> | |
</div> | |
<label for="age">Idade</label> | |
<input type="number" id="age" class="input-field" required> | |
</div> | |
<div class="toggle-container"> | |
<span class="gender-label"> | |
<i class="fas fa-mars gender-icon"></i> | |
Masculino | |
</span> | |
<label class="toggle-switch"> | |
<input type="checkbox" id="gender-toggle"> | |
<span class="slider"></span> | |
</label> | |
<span class="gender-label"> | |
<i class="fas fa-venus gender-icon"></i> | |
Feminino | |
</span> | |
</div> | |
<div class="input-group"> | |
<div class="icon-wrapper"> | |
<i class="fas fa-vial input-icon"></i> | |
</div> | |
<label for="serumCreatinine">Creatinina Sérica (mg/dL)</label> | |
<input type="number" id="serumCreatinine" class="input-field" step="0.01" required> | |
</div> | |
<div class="button-group"> | |
<button type="button" id="calcular" class="button">Calcular</button> | |
<button type="button" id="clear-button" class="button">Limpar</button> | |
</div> | |
</form> | |
<div id="result"></div> | |
</div> | |
<script> | |
document.getElementById("calcular").addEventListener("click", calculate); | |
function calculate() { | |
const age = parseFloat(document.getElementById("age").value); | |
const serumCreatinine = parseFloat(document.getElementById("serumCreatinine").value); | |
const gender = document.getElementById('gender-toggle').checked ? 'female' : 'male'; | |
if (!isNaN(age) && !isNaN(serumCreatinine)) { | |
let A, B = 0; | |
if (serumCreatinine <= 0.7) { | |
A = gender === "male" ? 0.9 : 0.7; | |
B = gender === "male" ? -0.302 : -0.241; | |
} else { | |
A = gender === "male" ? 0.9 : 0.7; | |
B = -1.2; | |
} | |
let result = 142 * Math.pow((serumCreatinine/A), B) * Math.pow(0.9938, age); | |
if (gender == 'female') result = result * 1.012; | |
const stage = getCKDStage(result); | |
const resultElement = document.getElementById('result'); | |
resultElement.innerHTML = ` | |
<h4>Resultado:</h4> | |
<p>eGFR CKD-EPI: <strong><span class="h3">${result.toFixed(0)} <span class="h4">mL/min/1.73 m²</span></span></strong></p> | |
<p>Estágio DRC: <strong>${stage}</strong></p> | |
`; | |
resultElement.style.display = 'block'; | |
} else { | |
alert("Por favor, preencha todos os campos corretamente."); | |
} | |
} | |
function getCKDStage(gfr) { | |
if (gfr >= 90) return "Estágio 1"; | |
if (gfr >= 60) return "Estágio 2"; | |
if (gfr >= 45) return "Estágio 3a"; | |
if (gfr >= 30) return "Estágio 3b"; | |
if (gfr >= 15) return "Estágio 4"; | |
return "Estágio 5"; | |
} | |
document.getElementById('clear-button').addEventListener('click', function() { | |
document.getElementById('ckd-epi-form').reset(); | |
document.getElementById('result').innerHTML = ''; | |
document.getElementById('result').style.display = 'none'; | |
}); | |
</script> | |
</body> | |
</html> | |
''' | |
calculadora = components.html(html_with_js, width=400,height=900) | |
return calculadora | |
def icon_close(): | |
st.markdown(""" | |
<style> | |
.stKey-icon-wrapper { | |
position: absolute; | |
left: -22px; | |
top: 0; | |
width: 180px; | |
height: 180px; | |
background-color: #e0e5ec; | |
border-radius: 50%; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
padding: 5px; | |
box-shadow: | |
5px 5px 10px #a3b1c6, | |
-5px -5px 10px #ffffff; | |
} | |
.stKey-icon-wrapper img { | |
width: 24px; | |
height: 24px; | |
filter: invert(20%) sepia(10%) saturate(2076%) hue-rotate(86deg) brightness(95%) contrast(86%); | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
with st.container(): | |
st.markdown('<div class="stKey-icon-wrapper">', unsafe_allow_html=True) | |
st.image('icon/rim.svg', use_container_width=False, width=140) | |
icon_top= st.markdown('</div>', unsafe_allow_html=True) | |
return icon_top | |
estilo() | |
cx1,cx2,cx3=st.columns([3,1,6]) | |
with cx1: | |
icon_close() | |
with cx2: | |
st.write('') | |
cx3.title(''' | |
:blue[Calculadora TFG] :blue[| CKD-EPI] 📝 | |
''' ) | |
c1, c2, c3, c4 = st.columns([2,0.5,3,3]) | |
with c1: | |
calc(html_with_js) | |
with c2: | |
add_vertical_space() | |
# linha_vertical(altura=800, cor='#73A6E2', espessura=2) | |
with c3: | |
expander = st.expander("Estágios da DRC", expanded=False, icon='📝') | |
expander.write(''' | |
# Estagios da IRC: | |
- **Estágio 1:** | |
- TFG ≥ 90 mL/min/1.73m² | |
- (Função renal normal ou aumentada) | |
- **Estágio 2:** | |
- TFG 60-89 mL/min/1.73m² | |
- (Diminuição leve da função renal) | |
- **Estágio 3a:** | |
- TFG 45-59 mL/min/1.73m² | |
- (Diminuição leve a moderada da função renal) | |
- **Estágio 3b:** | |
- TFG 30-44 mL/min/1.73m² | |
- :blue[(Diminuição moderada a severa da função renal)] | |
- **Estágio 4:** | |
- TFG 15-29 mL/min/1.73m² | |
- :orange[(Diminuição severa da função renal)] | |
- **Estágio 5:** | |
- TFG < 15 mL/min/1.73m² | |
- :red[(Falência renal)] | |
''') | |
with c4: | |
recomendacoes= (''' | |
## Recomendações gerais para pacientes com DRC | |
:green[As diretrizes KDIGO 2024 incorporou a TFG e a albuminúria como fatores críticos.] | |
:blue[**1. Estágios 1 e 2 (TFG ≥ 60 mL/min/1,73m²):**] | |
###### Monitoramento Regular: Avaliação periódica da função renal e da albuminúria é recomendada para detectar progressão da doença. | |
###### Controle de Fatores de Risco: Controle rigoroso da pressão arterial e glicemia, especialmente em pacientes com diabetes, é essencial. | |
###### Modificações no Estilo de Vida: Incentivar dieta saudável, cessação do tabagismo e atividade física regular. | |
:blue[**2. Estágio 3a e 3b (TFG 30-59 mL/min/1,73m²):**] | |
###### Ajuste de Medicamentos: Revisão e ajuste de dosagens de medicamentos que são excretados pelos rins. | |
###### Avaliação de Risco Cardiovascular: A albuminúria e a TFG devem ser usadas para avaliar o risco cardiovascular e ajustar o tratamento. | |
###### Referência a Nefrologista: Considerar encaminhamento para um nefrologista para manejo especializado. | |
:blue[**3. Estágio 4 (TFG 15-29 mL/min/1,73m²):**] | |
###### Preparação para Terapia de Substituição Renal: Discussão sobre opções de diálise e transplante renal deve ser iniciada. | |
###### Monitoramento Intensivo: Acompanhamento mais frequente para monitorar a progressão da doença e complicações associadas. | |
:blue[**4. Estágio 5 (TFG < 15 mL/min/1,73m²):**] | |
###### Terapia de Substituição Renal: Início de diálise ou avaliação para transplante renal. | |
###### Cuidados Paliativos: Considerar cuidados paliativos para pacientes que não são candidatos a diálise ou transplante. | |
_Além disso, a quantificação da albuminúria é crucial em todos os estágios | |
para guiar decisões terapêuticas, como a escolha de medicamentos anti- | |
hipertensivos. A avaliação individualizada, considerando a situação clínica | |
do paciente, é fundamental para o manejo eficaz da DRC._ | |
''') | |
with st.expander(label='Recomendações', expanded=False, icon="🔥"): | |
st.markdown(recomendacoes, unsafe_allow_html=True) | |
st.markdown(""" | |
--- | |
Desenvolvedor ☕ **Dr. Guilherme** | |
""") | |
elif nested_menu == "Coelho e Savassi": | |
import pandas as pd | |
import streamlit as st | |
st.header("Escala de Risco de Coelho e Savassi") | |
STYLE = "static/style.css" | |
with open(STYLE, "r", encoding="utf-8") as f: | |
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True) | |
STYLE = "static/styles.html" | |
with open(STYLE, "r", encoding="utf-8") as f: | |
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True) | |
# CSS personalizado | |
st.markdown(""" | |
<style> | |
.stCheckbox { | |
font-size: 18px; | |
} | |
.stButton > button { | |
width: 100%; | |
} | |
.risk-result { | |
font-size: 24px; | |
font-weight: bold; | |
padding: 10px; | |
border-radius: 5px; | |
margin-top: 20px; | |
} | |
.risk-menor { | |
background-color: #2ecc71; | |
color: white; | |
} | |
.risk-medio { | |
background-color: #f39c12; | |
color: white; | |
} | |
.risk-maior { | |
background-color: #e74c3c; | |
color: white; | |
} | |
.risk-maximo { | |
background-color: #c0392b; | |
color: white; | |
} | |
</style> | |
""", | |
unsafe_allow_html=True) | |
# Título | |
st.title("📊 Calculadora da Escala de Risco de Coelho e Savassi") | |
# Criando colunas para organizar o layout | |
col1, col2, col3, col4 = st.columns([2,2,3,2]) | |
# Fatores de risco | |
fatores = [{ | |
"id": "acamado", | |
"label": "🛏️ Acamado", | |
"peso": 3 | |
}, { | |
"id": "deficienciaFisica", | |
"label": "♿ Deficiência física", | |
"peso": 3 | |
}, { | |
"id": "deficienciaMental", | |
"label": "🧠 Deficiência mental", | |
"peso": 3 | |
}, { | |
"id": "baixoSaneamento", | |
"label": "🚽 Baixas condições de saneamento", | |
"peso": 3 | |
}, { | |
"id": "desnutricaoGrave", | |
"label": "⚖️ Desnutrição grave", | |
"peso": 3 | |
}, { | |
"id": "drogadicao", | |
"label": "💊 Drogadição", | |
"peso": 2 | |
}, { | |
"id": "desemprego", | |
"label": "💼 Desemprego", | |
"peso": 2 | |
}, { | |
"id": "analfabetismo", | |
"label": "📚 Analfabetismo", | |
"peso": 1 | |
}, { | |
"id": "menorSeisMeses", | |
"label": "👶 Menor de 6 meses", | |
"peso": 1 | |
}, { | |
"id": "maiorSetentaAnos", | |
"label": "👴 Maior de 70 anos", | |
"peso": 1 | |
}, { | |
"id": "hipertensao", | |
"label": "❤️ Hipertensão arterial sistêmica", | |
"peso": 1 | |
}, { | |
"id": "diabetes", | |
"label": "💉 Diabetes mellitus", | |
"peso": 1 | |
}] | |
# Criando checkboxes para os fatores de risco | |
with col1: | |
st.subheader("Fatores de Risco") | |
checkboxes = {} | |
for fator in fatores: | |
checkboxes[fator["id"]] = st.checkbox(fator["label"]) | |
with col2: | |
st.subheader("Informações Adicionais") | |
num_comodos = st.number_input("🏠 Número de cômodos", min_value=1, value=1) | |
num_moradores = st.number_input("👥 Número de moradores", | |
min_value=1, | |
value=1) | |
# Botão para calcular o risco | |
if st.button("Calcular Risco", use_container_width=True, icon="🧮️" ): | |
pontuacao_total = sum(fator["peso"] for fator in fatores | |
if checkboxes[fator["id"]]) | |
# Cálculo do escore de cômodos por pessoa | |
escore_comodo_pessoa = num_comodos / num_moradores | |
if escore_comodo_pessoa < 1: | |
pontuacao_total += 3 | |
# Determinação da classificação de risco | |
if pontuacao_total <= 4: | |
classificacao = "Risco Menor" | |
classe_css = "risk-menor" | |
icone = "✅" | |
elif pontuacao_total <= 6: | |
classificacao = "Risco Médio" | |
classe_css = "risk-medio" | |
icone = "⚠️" | |
elif pontuacao_total <= 8: | |
classificacao = "Risco Maior" | |
classe_css = "risk-maior" | |
icone = "🚨" | |
else: | |
classificacao = "Risco Máximo" | |
classe_css = "risk-maximo" | |
icone = "☠️" | |
# Exibição do resultado | |
st.markdown(f""" | |
<div class='risk-result {classe_css}'> | |
{icone} Classificação: {classificacao}<br> | |
📊 Pontuação: {pontuacao_total}<br> | |
🏠 Cômodos por pessoa: {escore_comodo_pessoa:.2f} | |
</div> | |
""", | |
unsafe_allow_html=True) | |
st.subheader("Detalhes da Pontuação") | |
detalhes = [] | |
for fator in fatores: | |
if checkboxes[fator["id"]]: | |
detalhes.append({"Fator": fator["label"], "Peso": fator["peso"]}) | |
if escore_comodo_pessoa < 1: | |
detalhes.append({"Fator": "🏠 Menos de 1 cômodo por pessoa", "Peso": 3}) | |
df_detalhes = pd.DataFrame(detalhes) | |
st.table(df_detalhes) | |
with col3, st.expander("Sobre a Escala de Risco de Coelho e Savassi", icon='❤️', expanded=False): | |
st.markdown(""" | |
--- | |
### Sobre a Escala de Risco de Coelho e Savassi | |
A Escala de Risco de Coelho e Savassi é uma ferramenta utilizada na Atenção Primária à Saúde no Brasil para avaliar o risco familiar em territórios de saúde. | |
Ela foi desenvolvida pelos médicos brasileiros Marcos Alencar Abaide Balbinotti Coelho e Maria Inês Ribeiro de Miranda Savassi. | |
#### Como interpretar os resultados: | |
- **Risco Menor (≤ 4 pontos)**: Acompanhamento de rotina | |
- **Risco Médio (5-6 pontos)**: Acompanhamento programado | |
- **Risco Maior (7-8 pontos)**: Acompanhamento prioritário | |
- **Risco Máximo (≥ 9 pontos)**: Acompanhamento intensivo | |
Esta calculadora é uma ferramenta de apoio e não substitui a avaliação profissional. | |
""") | |
with col4: | |
st.write('') | |
elif nested_menu == "Escore de Risco Global": | |
import numpy as np | |
import pandas as pd | |
import streamlit as st | |
cxc1, cxc2, cxc3 = st.columns([2, 1.5, 1.5]) | |
# Título | |
with cxc1: | |
st.header("Escore de Risco Global") | |
st.markdown("Recomendado pela Sociedade Brasileira de Cardiologia ❤️") | |
with cxc2: | |
st.image("icon/cardio.svg", width=100) | |
# CSS melhorado | |
st.markdown(""" | |
<style> | |
.st-key-risco button { | |
width: 30%; | |
} | |
.st-key-veridade input { | |
display: grid; | |
width: 100px; | |
border: 1px solid #ccc; | |
} | |
.risk-result { | |
padding: 20px; | |
border-radius: 10px; | |
margin: 20px 0; | |
font-size: 1.1em; | |
} | |
.risk-baixo { | |
background-color: #d4edda; | |
color: #155724; | |
border: 1px solid #c3e6cb; | |
} | |
.risk-intermediario { | |
background-color: #fff3cd; | |
color: #856404; | |
border: 1px solid #ffeeba; | |
} | |
.risk-alto { | |
background-color: #fff3cd; | |
color: #856404; | |
border: 1px solid #ffeeba; | |
} | |
.risk-muito-alto { | |
background-color: #f8d7da; | |
color: #721c24; | |
border: 1px solid #f5c6cb; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
def get_recomendacao_estatina(risco, pontos, idade, diabetes): | |
""" | |
Determina a recomendação de estatinas baseada no risco cardiovascular e características do paciente | |
""" | |
if risco == "Muito Alto": | |
return """ | |
### 🔴 Recomendação: Estatina de Alta Intensidade | |
- Atorvastatina 40-80 mg ou | |
- Rosuvastatina 20-40 mg | |
**Objetivo:** Redução ≥50% do LDL-C, com meta de LDL-C <70 mg/dL | |
""" | |
elif risco == "Alto": | |
return """ | |
### 🔴 Recomendação: Estatina de Alta Intensidade | |
- Atorvastatina 40-80 mg ou | |
- Rosuvastatina 20-40 mg | |
**Alternativa se não tolerada:** | |
### 🔵 Estatina de Intensidade Moderada | |
- Atorvastatina 10-20 mg ou | |
- Rosuvastatina 5-10 mg ou | |
- Sinvastatina 20-40 mg | |
""" | |
elif risco == "Intermediário": | |
base_rec = """ | |
### 🔵 Recomendação: Estatina de Intensidade Moderada | |
- Atorvastatina 10-20 mg ou | |
- Rosuvastatina 5-10 mg ou | |
- Sinvastatina 20-40 mg | |
""" | |
if diabetes and 40 <= idade <= 75: | |
base_rec += "\n\n**Nota:** Devido à presença de diabetes, considerar intensificar para estatina de alta intensidade se houver outros fatores de risco." | |
return base_rec | |
else: # Baixo risco | |
if diabetes and 40 <= idade <= 75: | |
return """ | |
### 🔵 Recomendação: Estatina de Intensidade Moderada | |
- Atorvastatina 10-20 mg ou | |
- Rosuvastatina 5-10 mg ou | |
- Sinvastatina 20-40 mg | |
**Nota:** Recomendação baseada na presença de diabetes. | |
""" | |
else: | |
return """ | |
### 🟢 Considerar Estatina de Baixa Intensidade | |
- Sinvastatina 10 mg ou | |
- Pravastatina 10-20 mg | |
**Nota:** A necessidade de estatina deve ser avaliada individualmente pelo médico considerando outros fatores de risco. | |
""" | |
# Criando colunas para organizar o layout | |
col1, col2, col3, col4, col5 = st.columns([1,0.5,1,0.2,2.5]) | |
with col1: | |
st.subheader("Dados Pessoais") | |
sexo = st.radio("Sexo", ["Masculino", "Feminino"]) | |
idade = st.number_input("Idade", min_value=30, max_value=74, value=30, key='idade') | |
tabagismo = st.checkbox("Tabagismo") | |
diabetes = st.checkbox("Diabetes") | |
with col2: | |
st.write('') | |
with col3: | |
st.subheader("Dados Clínicos") | |
colesterol_total = st.number_input("Colesterol Total (mg/dL)", | |
min_value=0, | |
max_value=600, | |
help="Valor normal: < 200 mg/dL") | |
hdl = st.number_input("HDL Colesterol (mg/dL)", | |
min_value=0, | |
max_value=100, | |
value=50, | |
help="Valor ideal: > 40 mg/dL") | |
pas = st.number_input("Pressão Arterial Sistólica (mmHg)", | |
min_value=0, | |
max_value=300, | |
help="Valor normal: < 130 mmHg") | |
with col4: | |
st.write('') | |
with col5: | |
st.subheader("Calcular resultado") | |
def calcular_erg(sexo, idade, tabagismo, diabetes, colesterol_total, hdl, pas): | |
pontos = 0 | |
# Idade | |
if sexo == "Masculino": | |
if idade < 35: | |
pontos -= 1 | |
elif 35 <= idade <= 39: | |
pontos += 0 | |
elif 40 <= idade <= 44: | |
pontos += 1 | |
elif 45 <= idade <= 49: | |
pontos += 2 | |
elif 50 <= idade <= 54: | |
pontos += 3 | |
elif 55 <= idade <= 59: | |
pontos += 4 | |
elif 60 <= idade <= 64: | |
pontos += 5 | |
elif 65 <= idade <= 69: | |
pontos += 6 | |
else: | |
pontos += 7 | |
else: # Feminino | |
if idade < 35: | |
pontos -= 9 | |
elif 35 <= idade <= 39: | |
pontos -= 4 | |
elif 40 <= idade <= 44: | |
pontos += 0 | |
elif 45 <= idade <= 49: | |
pontos += 3 | |
elif 50 <= idade <= 54: | |
pontos += 6 | |
elif 55 <= idade <= 59: | |
pontos += 7 | |
elif 60 <= idade <= 69: | |
pontos += 8 | |
else: | |
pontos += 8 | |
# Colesterol Total | |
if sexo == "Masculino": | |
if colesterol_total < 160: | |
pontos -= 3 | |
elif 160 <= colesterol_total <= 199: | |
pontos += 0 | |
elif 200 <= colesterol_total <= 239: | |
pontos += 1 | |
elif 240 <= colesterol_total <= 279: | |
pontos += 2 | |
else: | |
pontos += 3 | |
else: # Feminino | |
if colesterol_total < 160: | |
pontos -= 2 | |
elif 160 <= colesterol_total <= 199: | |
pontos += 0 | |
elif 200 <= colesterol_total <= 239: | |
pontos += 1 | |
elif 240 <= colesterol_total <= 279: | |
pontos += 2 | |
else: | |
pontos += 3 | |
# HDL (mesmo para ambos os sexos) | |
if hdl < 40: | |
pontos += 2 | |
elif 40 <= hdl <= 49: | |
pontos += 1 | |
elif 50 <= hdl <= 59: | |
pontos += 0 | |
else: | |
pontos -= 2 | |
# Pressão Arterial Sistólica | |
if pas < 120: | |
pontos += 0 | |
elif 120 <= pas <= 129: | |
pontos += 1 | |
elif 130 <= pas <= 139: | |
pontos += 2 | |
elif 140 <= pas <= 159: | |
pontos += 3 | |
else: | |
pontos += 4 | |
# Diabetes | |
if diabetes: | |
if sexo == "Masculino": | |
pontos += 4 | |
else: | |
pontos += 6 | |
# Tabagismo | |
if tabagismo: | |
if sexo == "Masculino": | |
pontos += 4 | |
else: | |
pontos += 3 | |
return pontos | |
if st.button("Calcular", icon='📝', key='risco'): | |
# Validações | |
if colesterol_total == 0: | |
st.error("Por favor, insira um valor válido para o Colesterol Total") | |
elif pas == 0: | |
st.error("Por favor, insira um valor válido para a Pressão Arterial") | |
else: | |
pontos = calcular_erg(sexo, idade, tabagismo, diabetes, colesterol_total, | |
hdl, pas) | |
if pontos < 5: | |
risco = "Baixo" | |
classe_css = "risk-baixo" | |
probabilidade = "< 5%" | |
elif 5 <= pontos <= 10: | |
risco = "Intermediário" | |
classe_css = "risk-intermediario" | |
probabilidade = "5 a 10%" | |
elif 11 <= pontos <= 20: | |
risco = "Alto" | |
classe_css = "risk-alto" | |
probabilidade = "10 a 20%" | |
else: | |
risco = "Muito Alto" | |
classe_css = "risk-muito-alto" | |
probabilidade = "> 20%" | |
# Exibição do resultado | |
st.markdown(f""" | |
<div class='risk-result {classe_css}'> | |
<strong>Risco Cardiovascular:</strong> {risco}<br> | |
<strong>Pontuação:</strong> {pontos}<br> | |
<strong>Probabilidade de evento cardiovascular em 10 anos:</strong> {probabilidade} | |
</div> | |
""", unsafe_allow_html=True) | |
# Após exibir o resultado do risco, adicionar: | |
st.markdown("---") | |
st.subheader("💊 Recomendação de Estatinas") | |
if idade > 75: | |
st.warning(""" | |
**Atenção:** Para pacientes acima de 75 anos, a terapia com estatinas deve ser individualizada, | |
considerando benefícios e riscos potenciais. Recomenda-se geralmente estatinas de intensidade moderada. | |
""") | |
recomendacao = get_recomendacao_estatina(risco, pontos, idade, diabetes) | |
st.markdown(recomendacao) | |
st.info(""" | |
**Observações importantes:** | |
1. Recomendações baseadas em diretrizes, mas a decisão final deve ser individualizada pelo médico. | |
2. Monitorar níveis de transaminases antes de iniciar as estatinas. | |
3. Reavaliar níveis lipídicos 1-3 meses após início da terapia. | |
4. Em caso de intolerância, considerar alternativas como ácido bempedoico ou inibidores de PCSK9. | |
5. Estatinas são contraindicadas na gestação. | |
""") | |
# Se diabetes presente, adicionar informação específica | |
if diabetes: | |
st.markdown(""" | |
**Nota sobre Diabetes:** | |
- Para pacientes com diabetes entre 40-75 anos, é recomendada pelo menos estatina de intensidade moderada. | |
- Se houver múltiplos fatores de risco, considerar estatina de alta intensidade com meta de redução ≥50% do LDL-C. | |
""") | |
# Informações adicionais | |
st.info(""" | |
**Interpretação das Faixas de Risco:** | |
- **Baixo:** < 5% de chance de evento cardiovascular em 10 anos | |
- **Intermediário:** 5-10% de chance de evento cardiovascular em 10 anos | |
- **Alto:** 10-20% de chance de evento cardiovascular em 10 anos | |
- **Muito Alto:** > 20% de chance de evento cardiovascular em 10 anos | |
""") | |
def tab_final(idade, sexo, colesterol_total, hdl, pas, diabetes, tabagismo): | |
# Tabela de detalhes | |
st.subheader("Detalhes da Avaliação") | |
detalhes = [{ | |
"Fator de Risco": "Idade", | |
"Valor": f"{idade} anos" | |
}, { | |
"Fator de Risco": "Sexo", | |
"Valor": sexo | |
}, { | |
"Fator de Risco": "Colesterol Total", | |
"Valor": f"{colesterol_total} mg/dL" | |
}, { | |
"Fator de Risco": "HDL Colesterol", | |
"Valor": f"{hdl} mg/dL" | |
}, { | |
"Fator de Risco": "Pressão Arterial Sistólica", | |
"Valor": f"{pas} mmHg" | |
}, { | |
"Fator de Risco": "Diabetes", | |
"Valor": "Sim" if diabetes else "Não" | |
}, { | |
"Fator de Risco": "Tabagismo", | |
"Valor": "Sim" if tabagismo else "Não" | |
}] | |
df_detalhes = pd.DataFrame(detalhes) | |
df_paciente = st.dataframe(df_detalhes, hide_index=True) | |
return df_paciente | |
tab_final(idade, sexo, colesterol_total, hdl, pas, diabetes, tabagismo) | |
def estat(): | |
with st.expander("Intensidade das Estatinas", icon='💊', expanded=False): | |
st.markdown(""" | |
| Intensidade | Estatinas e Doses | | |
|-------------|-------------------| | |
| **Alta** | - Atorvastatina 40-80 mg | | |
| | - Rosuvastatina 20-40 mg | | |
| **Moderada** | - Atorvastatina 10-20 mg | | |
| | - Rosuvastatina 5-10 mg | | |
| | - Sinvastatina 20-40 mg | | |
| | - Pravastatina 40-80 mg | | |
| | - Lovastatina 40 mg | | |
| | - Fluvastatina XL 80 mg | | |
| | - Pitavastatina 1-4 mg | | |
| **Baixa** | - Sinvastatina 10 mg | | |
| | - Pravastatina 10-20 mg | | |
| | - Lovastatina 20 mg | | |
| | - Fluvastatina 20-40 mg | | |
**As estatinas de alta intensidade reduzem o LDL-C em ≥50%, as de | |
intensidade moderada em 30-49%, e as de baixa intensidade em <30%.** | |
""", unsafe_allow_html=True) | |
def estatinas(): | |
with st.expander("Intensidade das Estatinas", icon='💊', expanded=False): | |
st.markdown(""" | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+Oriya:[email protected]&display=swap'); | |
body { | |
text-align: justify; | |
font-family: 'Noto Serif Oriya', serif; | |
} | |
.noto-serif-oriya-400 { | |
font-family: "Noto Serif Oriya", serif; | |
font-optical-sizing: auto; | |
font-weight: 400; | |
font-style: normal; | |
} | |
p { | |
margin-bottom: 15px; | |
} | |
</style> | |
# Estatinas | |
<div style="text-align: justify"> | |
- Diretrizes 2024: American College of Cardiology (ACC), American Heart Association (AHA) e American Diabetes Association (ADA). | |
- Evidências de ensaios clínicos randomizados e meta-análises: Eficácia das estatinas na redução de eventos cardiovasculares ateroscleróticos (ASCVD). | |
## Início da Terapia com Estatinas | |
***1. Prevenção Primária:*** | |
- **:red[Pacientes com DM:]** | |
- :blue[DM entre 40-75a], sem ASCVD → Estatina de intensidade moderada + mudanças no estilo de vida. | |
- :blue[DM entre 20-39a], com fatores de risco adicionais para ASCVD → Pode ser razoável iniciar estatina. | |
- :blue[DM entre 40-75a], com ↑↑↑ risco cardiovascular → Estatinas de alta intensidade → ↓↓LDL-C em ≥50% do valor basal. Objetivo → LDL-C <70 mg/dL.<sup>[1]</sup> | |
- **:green[Pacientes sem DM:]** | |
- ACC/AHA → Estatinas de intensidade moderada a alta em pacientes com risco de ASCVD a 10 anos ≥7,5% | |
- NICE e USPSTF → Iniciar estatinas se o risco for ≥10%.<sup>[2]</sup> | |
***2. Prevenção Secundária:*** | |
- Pacientes com ASCVD: | |
- Todos com ASCVD → Iniciar ou continuar estatinas de alta intensidade, a menos que haja contraindicações.<sup>[3-4]</sup> | |
- Se estatina de alta intensidade for contraindicada ou não tolerada, → Estatina de intensidade moderada.<sup>[4]</sup> | |
***3. Intensidade da Terapia com Estatinas:*** | |
- 🔴 :red[Alta Intensidade] ↓↓LDL-C em ≥50%.<sup>[5-6]</sup> | |
- 🔵 :blue[Moderada]: ↓↓LDL-C em 30-49%.<sup>[5-6]</sup> | |
- 🟢 :green[Baixa Intensidade]: ↓↓LDL-C em <30%.<sup>[6]</sup> | |
***4. Monitoramento e Ajustes:*** | |
- Inicial: | |
- Níveis de transaminases, antes de iniciar estatinas. | |
- Níveis de lipídios → Devem ser reavaliados 1-3 meses após o início da terapia.<sup>[2]</sup> | |
- Ajustes: | |
- Se resposta inadequada, → Considerar adição de ezetimiba ou inibidores de PCSK9, especialmente em pacientes de alto risco.<sup>[1][7]</sup> | |
***5. Considerações Especiais:*** | |
- Idosos (>75 anos): | |
- Terapia com estatinas de intensidade moderada, considerar benefícios e riscos potenciais.<sup>[1][5]</sup> | |
- Intolerância às Estatinas: | |
- Alternativas → Ácido bempedoico ou inibidores de PCSK9.<sup>[1]</sup> | |
***6. Contraindicações:*** | |
- :red[Gravidez:] | |
- Estatinas são contraindicadas na gestação.<sup>[1]</sup> | |
##### Referências: | |
<sup> | |
1. Cardiovascular Disease and Risk Management: Standards of Care in Diabetes-2024. | |
Diabetes Care. 2024;47(Suppl 1):S179-S218. doi:10.2337/dc24-S010. | |
</sup> | |
<br><br> | |
<sup> | |
2. Hyperlipidemia: Drugs for Cardiovascular Risk Reduction in Adults. | |
Last AR, Ference JD, Menzel ER. | |
American Family Physician. 2017;95(2):78-87. | |
</sup> | |
<br><br> | |
<sup> | |
3. 2013 ACCF/AHA Guideline for the Management of ST-elevation Myocardial Infarction: A Report of the American College of Cardiology Foundation/American Heart Association Task Force on Practice Guidelines. | |
O 'Gara PT, Kushner FG, Ascheim DD, et al. | |
</sup> | |
<br><br> | |
<sup> | |
4. 2018 AHA/ACC/AACVPR/AAPA/ABC/ACPM/ADA/AGS/APhA/ASPC/NLA/PCNA Guideline on the Management of Blood Cholesterol: A Report of the American College of Cardiology/American Heart Association Task Force on Clinical Practice Guidelines. | |
Grundy SM, Stone NJ, Bailey AL, et al. | |
Journal of the American College of Cardiology. 2019;73(24):e285-e350. doi:10.1016/j.jacc.2018.11.003. | |
</sup> | |
</div> | |
""", unsafe_allow_html=True | |
) | |
cft1, cft2, cft3 = st.columns([1, 2, 1]) | |
with cft1: | |
estat() | |
with cft2: | |
estatinas() | |
with cft3: | |
st.write('') | |
elif nested_menu == "Noripurun": | |
import pathlib | |
import streamlit as st | |
import streamlit.components.v1 as components | |
from streamlit_extras.add_vertical_space import add_vertical_space | |
st.header("Noripurun") | |
static_dir = pathlib.Path('static').absolute() | |
html_with_js= '' | |
def estil(): | |
css_file_path = static_dir / 'styles.css' | |
if css_file_path.exists(): | |
with open(css_file_path, "r", encoding="utf-8") as f: | |
st_css = st.html(f"<style>{f.read()}</style>") | |
return st_css | |
else: | |
st.error(f"CSS file not found: {css_file_path}") | |
return None | |
def noripurun(html_with_js): | |
html_with_js = ''' | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
:root { | |
--primary-color: #2196F3; | |
--bg-color: #e0e5ec; | |
--text-color: #2d4059; | |
--shadow-light: #ffffff; | |
--shadow-dark: #a3b1c6; | |
} | |
body { | |
background-color: var(--bg-color); | |
color: var(--text-color); | |
font-family: 'Segoe UI', Arial, sans-serif; | |
line-height: 1.6; | |
margin: 0; | |
padding: 20px; | |
} | |
.calculator-container { | |
max-width: 800px; | |
margin: 40px auto; | |
padding: 30px; | |
background: var(--bg-color); | |
border-radius: 20px; | |
box-shadow: | |
8px 8px 15px var(--shadow-dark), | |
-8px -8px 15px var(--shadow-light); | |
} | |
.header { | |
text-align: center; | |
margin-bottom: 30px; | |
} | |
.header h2 { | |
color: var(--primary-color); | |
margin: 0; | |
padding: 15px; | |
border-radius: 10px; | |
box-shadow: | |
inset 5px 5px 10px var(--shadow-dark), | |
inset -5px -5px 10px var(--shadow-light); | |
} | |
.info-box, .details-box { | |
padding: 20px; | |
margin: 20px 0; | |
border-radius: 15px; | |
box-shadow: | |
inset 5px 5px 10px var(--shadow-dark), | |
inset -5px -5px 10px var(--shadow-light); | |
} | |
.form-group { | |
margin: 25px 0; | |
} | |
label { | |
display: block; | |
margin-bottom: 10px; | |
font-weight: 600; | |
color: var(--text-color); | |
} | |
input, select { | |
width: 60%; | |
padding: 12px; | |
border: none; | |
border-radius: 10px; | |
background: var(--bg-color); | |
box-shadow: | |
inset 5px 5px 10px var(--shadow-dark), | |
inset -5px -5px 10px var(--shadow-light); | |
color: var(--text-color); | |
font-size: 16px; | |
transition: all 0.3s ease; | |
} | |
input:focus, select:focus { | |
outline: none; | |
box-shadow: | |
inset 3px 3px 5px var(--shadow-dark), | |
inset -3px -3px 5px var(--shadow-light); | |
} | |
.calculate-btn { | |
width: 100%; | |
padding: 15px; | |
border: none; | |
border-radius: 10px; | |
background: var(--bg-color); | |
color: var(--primary-color); | |
font-size: 18px; | |
font-weight: bold; | |
cursor: pointer; | |
box-shadow: | |
5px 5px 10px var(--shadow-dark), | |
-5px -5px 10px var(--shadow-light); | |
transition: all 0.3s ease; | |
} | |
.calculate-btn:hover { | |
box-shadow: | |
3px 3px 5px var(--shadow-dark), | |
-3px -3px 5px var(--shadow-light); | |
} | |
.calculate-btn:active { | |
box-shadow: | |
inset 3px 3px 5px var(--shadow-dark), | |
inset -3px -3px 5px var(--shadow-light); | |
} | |
.result-box { | |
margin-top: 30px; | |
padding: 20px; | |
border-radius: 15px; | |
box-shadow: | |
inset 5px 5px 10px var(--shadow-dark), | |
inset -5px -5px 10px var(--shadow-light); | |
} | |
.formula-box { | |
background: var(--bg-color); | |
padding: 20px; | |
border-radius: 10px; | |
box-shadow: | |
inset 3px 3px 5px var(--shadow-dark), | |
inset -3px -3px 5px var(--shadow-light); | |
font-family: monospace; | |
font-size: 14px; | |
line-height: 1.8; | |
} | |
table { | |
width: 100%; | |
border-spacing: 10px; | |
border-collapse: separate; | |
margin: 20px 0; | |
} | |
th, td { | |
padding: 10px; | |
text-align: left; | |
background: var(--bg-color); | |
border-radius: 12px; | |
box-shadow: | |
1px 1px 2px var(--shadow-dark), | |
-1px -1px 2px var(--shadow-light); | |
} | |
th { | |
background: var(--primary-color); | |
color: white; | |
font-weight: 600; | |
} | |
.alert { | |
padding: 15px; | |
margin: 15px 0; | |
border-radius: 10px; | |
background: #fff3e0; | |
box-shadow: | |
3px 3px 5px var(--shadow-dark), | |
-3px -3px 5px var(--shadow-light); | |
} | |
.warning { | |
background: #ffebee; | |
} | |
.dilution-info { | |
background: var(--bg-color); | |
padding: 15px; | |
margin: 15px 0; | |
border-radius: 10px; | |
box-shadow: | |
inset 3px 3px 5px var(--shadow-dark), | |
inset -3px -3px 5px var(--shadow-light); | |
} | |
.info-grid { | |
display: flex; | |
gap: 20px; | |
} | |
details { | |
flex: 1; | |
} | |
summary { | |
cursor: pointer; | |
} | |
section { | |
display: flex; | |
flex-direction: row; | |
gap: 20px; | |
} | |
@media (max-width: 768px) { | |
.info-grid { | |
grid-template-columns: 1fr; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="calculator-container"> | |
<div class="header"> | |
<h2>Calculadora de Dose - Noripurum</h2> | |
<strong>Parâmetros Importantes:</strong> | |
</div> | |
<div class="info-box"> | |
<div class="info-grid"> | |
<details> | |
<summary><h4>Limites de Dose:</h4></summary> | |
<ul> | |
<li>Dose máxima por aplicação: 200mg</li> | |
<li>Dose máxima semanal: 500mg</li> | |
<li>Intervalo mínimo entre doses: 24h</li> | |
</ul> | |
</details> | |
<details> | |
<summary><h4>Diluição e Administração:</h4></summary> | |
<ul> | |
<li>Diluição mínima: 100mL SF 0,9% por ampola</li> | |
<li>Tempo mínimo de infusão: 15 min/ampola</li> | |
<li>Administrar exclusivamente em SF 0,9%</li> | |
</ul> | |
</details> | |
<details> | |
<summary><h4>Reserva de Ferro:</h4></summary> | |
<ul> | |
<li>Pacientes < 35kg: 15mg/kg</li> | |
<li>Pacientes ≥ 35kg: 500mg fixo</li> | |
</ul> | |
</details> | |
</div> | |
</div> | |
<section> | |
<div class="form-group"> | |
<label for="peso">Peso do Paciente (kg):</label> | |
<input type="number" id="peso" min="0" step="0.1" required> | |
</div> | |
<div class="form-group"> | |
<label for="hb-atual">Hemoglobina Atual (g/dL):</label> | |
<input type="number" id="hb-atual" min="0" step="0.1" required> | |
</div> | |
<div class="form-group"> | |
<label for="hb-alvo">Hemoglobina Alvo (g/dL):</label> | |
<select id="hb-alvo" required> | |
<option value="12">12 g/dL</option> | |
<option value="13">13 g/dL</option> | |
<option value="14">14 g/dL</option> | |
<option value="15">15 g/dL</option> | |
</select> | |
</div> | |
</section> | |
<small style="color: #666; display:grid">Padrão: 12 g/dL (mulheres) / 13 g/dL (homens)</small> | |
<div style="display: grid; justify-content: center;"> | |
<button class="calculate-btn" onclick="calcularDose()">Calcular Dose</button> | |
</div> | |
<div id="resultado" class="result-box"> | |
<div id="alert-box"></div> | |
<div class="details-box"> | |
<strong>Detalhes do Cálculo:</strong> | |
<div id="calculo-detalhado"></div> | |
</div> | |
<div class="result-item"> | |
<strong>Déficit Total de Ferro:</strong> <span id="deficit-total"></span> | |
</div> | |
<div class="result-item"> | |
<strong>Esquema de Administração Recomendado:</strong> | |
<div id="esquema-admin"></div> | |
</div> | |
</div> | |
</div> | |
<script> | |
function calcularDose() { | |
// Obter e validar valores de entrada | |
const peso = parseFloat(document.getElementById('peso').value); | |
const hbAtual = parseFloat(document.getElementById('hb-atual').value); | |
const hbAlvo = parseFloat(document.getElementById('hb-alvo').value); | |
if (!validarEntradas(peso, hbAtual, hbAlvo)) { | |
return; | |
} | |
// Cálculos principais | |
const reservaFerro = calcularReservaFerro(peso); | |
const dhb = hbAlvo - hbAtual; | |
const deficitTotal = Math.round((peso * dhb * 2.4) + reservaFerro); | |
// Exibir resultados | |
mostrarResultados(peso, hbAtual, hbAlvo, dhb, reservaFerro, deficitTotal); | |
criarEsquemaAdministracao(deficitTotal); | |
mostrarAlertas(hbAtual, hbAlvo, deficitTotal); | |
} | |
function validarEntradas(peso, hbAtual, hbAlvo) { | |
if (!peso || !hbAtual || !hbAlvo) { | |
alert('Por favor, preencha todos os campos!'); | |
return false; | |
} | |
if (peso <= 0 || hbAtual <= 0 || hbAlvo <= 0) { | |
alert('Os valores devem ser maiores que zero!'); | |
return false; | |
} | |
return true; | |
} | |
function calcularReservaFerro(peso) { | |
return peso < 35 ? Math.round(peso * 15) : 500; | |
} | |
function mostrarResultados(peso, hbAtual, hbAlvo, dhb, reservaFerro, deficitTotal) { | |
document.getElementById('resultado').style.display = 'block'; | |
const calculoHtml = ` | |
<p><strong>Fórmula utilizada:</strong></p> | |
<div class="formula-box"> | |
Déficit Total = (Peso × ΔHb × 2.4) + Reserva de Ferro<br> | |
Onde:<br> | |
- Peso = ${peso} kg<br> | |
- ΔHb (diferença de Hb) = ${hbAlvo} - ${hbAtual.toFixed(1)} = ${dhb.toFixed(1)} g/dL<br> | |
- Reserva de Ferro = ${reservaFerro} mg (${peso < 35 ? '15mg/kg' : 'fixo 500mg'})<br> | |
<br> | |
Cálculo: (${peso} × ${dhb.toFixed(1)} × 2.4) + ${reservaFerro} = ${deficitTotal} mg | |
</div>`; | |
document.getElementById('calculo-detalhado').innerHTML = calculoHtml; | |
document.getElementById('deficit-total').textContent = `${deficitTotal}mg`; | |
} | |
function criarEsquemaAdministracao(deficitTotal) { | |
const numDoses = Math.ceil(deficitTotal / 200); | |
const dosesPorSemana = Math.min(2, numDoses); | |
const numSemanas = Math.ceil(numDoses / dosesPorSemana); | |
let esquemaHtml = ` | |
<table> | |
<tr> | |
<th>Semana</th> | |
<th>Terça-feira</th> | |
<th>Sexta-feira</th> | |
<th>Total Semanal</th> | |
</tr>`; | |
let ferroRestante = deficitTotal; | |
for (let semana = 1; semana <= numSemanas; semana++) { | |
const doseTerca = calcularDoseSemanal(ferroRestante); | |
ferroRestante -= doseTerca; | |
const doseSexta = calcularDoseSemanal(ferroRestante); | |
ferroRestante -= doseSexta; | |
esquemaHtml += ` | |
<tr> | |
<td>${semana}</td> | |
<td>${formatarDose(doseTerca)}</td> | |
<td>${formatarDose(doseSexta)}</td> | |
<td>${doseTerca + doseSexta}mg</td> | |
</tr>`; | |
} | |
esquemaHtml += '</table>'; | |
document.getElementById('esquema-admin').innerHTML = esquemaHtml; | |
} | |
function calcularDoseSemanal(ferroRestante) { | |
if (ferroRestante <= 0) return 0; | |
// Arredonda para múltiplos de 100 e limita a 200mg | |
return Math.min(200, Math.round(Math.min(ferroRestante, 200) / 100) * 100); | |
} | |
function formatarDose(dose) { | |
if (dose <= 0) return '-'; | |
const numAmpolas = dose / 100; | |
return `${dose}mg (${numAmpolas} ${numAmpolas === 1 ? 'ampola' : 'ampolas'})`; | |
} | |
function mostrarAlertas(hbAtual, hbAlvo, deficitTotal) { | |
let alertas = []; | |
if (hbAtual >= hbAlvo) { | |
alertas.push(` | |
<div class="alert warning"> | |
ATENÇÃO: Hemoglobina atual maior ou igual à meta. | |
Verificar necessidade real de reposição. | |
</div>`); | |
} | |
if (deficitTotal > 1000) { | |
alertas.push(` | |
<div class="alert"> | |
Tratamento prolongado necessário. | |
Considerar reavaliação após 4-6 semanas de tratamento. | |
</div>`); | |
} | |
document.getElementById('alert-box').innerHTML = alertas.join(''); | |
} | |
</script> | |
</body> | |
</html> | |
''' | |
noripurun = components.html(html_with_js, width=1600,height=1600) | |
return noripurun | |
noripurun(html_with_js) | |
#estil() | |