|
<!DOCTYPE html> |
|
<html lang="pt-BR"> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
|
<title>Comparador de Investimentos</title> |
|
<link |
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" |
|
rel="stylesheet" |
|
/> |
|
<style> |
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap'); |
|
:root { |
|
--clr-bg-light: #f9fafb; |
|
--clr-text-light: #222; |
|
--clr-bg-dark: #121212; |
|
--clr-text-dark: #eee; |
|
--clr-primary: #00c9a7; |
|
--clr-secondary: #007cf0; |
|
} |
|
body { |
|
font-family: 'Inter', sans-serif; |
|
margin: 0; |
|
padding: 0; |
|
min-height: 100vh; |
|
background: var(--clr-bg-dark); |
|
color: var(--clr-text-dark); |
|
transition: background 0.3s, color 0.3s; |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
justify-content: start; |
|
overflow-x: hidden; |
|
} |
|
body.light { |
|
background: var(--clr-bg-light); |
|
color: var(--clr-text-light); |
|
} |
|
header { |
|
width: 100%; |
|
max-width: 960px; |
|
margin: 32px 16px 12px; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
} |
|
h1 { |
|
font-size: 2.8rem; |
|
background: linear-gradient(to right, var(--clr-primary), var(--clr-secondary)); |
|
-webkit-background-clip: text; |
|
-webkit-text-fill-color: transparent; |
|
margin: 0; |
|
user-select: none; |
|
} |
|
button#toggleTheme { |
|
cursor: pointer; |
|
font-size: 1.6rem; |
|
background: none; |
|
border: none; |
|
color: var(--clr-primary); |
|
transition: color 0.3s ease; |
|
} |
|
button#toggleTheme:hover { |
|
color: var(--clr-secondary); |
|
} |
|
form { |
|
background: var(--clr-bg-dark); |
|
padding: 40px 48px; |
|
border-radius: 20px; |
|
box-shadow: 0 4px 25px rgba(0,0,0,0.65); |
|
max-width: 640px; |
|
width: 100%; |
|
margin-bottom: 48px; |
|
transition: background 0.3s; |
|
} |
|
body.light form { |
|
background: var(--clr-bg-light); |
|
box-shadow: 0 4px 20px rgba(0,0,0,0.1); |
|
} |
|
.form-group { |
|
margin-bottom: 24px; |
|
position: relative; |
|
} |
|
label { |
|
font-weight: 600; |
|
display: block; |
|
margin-bottom: 6px; |
|
} |
|
input[type=number], select { |
|
width: 100%; |
|
padding: 12px 44px 12px 16px; |
|
font-size: 1rem; |
|
border-radius: 10px; |
|
border: 1px solid #333; |
|
background-color: var(--clr-bg-dark); |
|
color: var(--clr-text-dark); |
|
transition: background-color 0.3s, color 0.3s, border-color 0.3s; |
|
} |
|
body.light input[type=number], body.light select { |
|
background-color: var(--clr-bg-light); |
|
color: var(--clr-text-light); |
|
border-color: #ccc; |
|
} |
|
input[type=number]:focus, select:focus { |
|
outline: none; |
|
border-color: var(--clr-primary); |
|
box-shadow: 0 0 5px var(--clr-primary); |
|
} |
|
.icon-input { |
|
position: absolute; |
|
right: 16px; |
|
top: 38px; |
|
font-size: 1.3rem; |
|
color: var(--clr-primary); |
|
pointer-events: none; |
|
} |
|
button[type=submit] { |
|
width: 100%; |
|
background: linear-gradient(135deg, var(--clr-primary), var(--clr-secondary)); |
|
border: none; |
|
border-radius: 14px; |
|
color: white; |
|
font-size: 1.2rem; |
|
font-weight: 700; |
|
padding: 16px 0; |
|
cursor: pointer; |
|
transition: transform 0.25s ease, box-shadow 0.25s ease; |
|
} |
|
button[type=submit]:hover { |
|
transform: translateY(-3px); |
|
box-shadow: 0 12px 30px rgba(0,201,167,0.5); |
|
} |
|
|
|
|
|
#drawer { |
|
position: fixed; |
|
top: 0; |
|
right: -400px; |
|
width: 400px; |
|
max-width: 90vw; |
|
height: 100vh; |
|
background: var(--clr-bg-dark); |
|
box-shadow: -4px 0 24px rgba(0,0,0,0.7); |
|
transition: right 0.35s ease; |
|
overflow-y: auto; |
|
padding: 24px 28px 48px; |
|
z-index: 1001; |
|
} |
|
body.light #drawer { |
|
background: var(--clr-bg-light); |
|
box-shadow: -4px 0 24px rgba(0,0,0,0.15); |
|
} |
|
#drawer.open { |
|
right: 0; |
|
} |
|
#drawer h2 { |
|
color: var(--clr-primary); |
|
font-weight: 700; |
|
margin-top: 0; |
|
margin-bottom: 20px; |
|
} |
|
#drawer p { |
|
line-height: 1.5; |
|
margin-bottom: 16px; |
|
color: inherit; |
|
} |
|
#drawer img { |
|
max-width: 100%; |
|
border-radius: 14px; |
|
box-shadow: 0 0 16px rgba(0,0,0,0.35); |
|
margin-bottom: 28px; |
|
} |
|
#drawerCloseBtn { |
|
position: absolute; |
|
top: 18px; |
|
right: 18px; |
|
background: transparent; |
|
border: none; |
|
font-size: 1.8rem; |
|
cursor: pointer; |
|
color: var(--clr-primary); |
|
transition: color 0.3s; |
|
} |
|
#drawerCloseBtn:hover { |
|
color: var(--clr-secondary); |
|
} |
|
|
|
|
|
#drawerOverlay { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100vw; |
|
height: 100vh; |
|
background: rgba(0,0,0,0.5); |
|
opacity: 0; |
|
pointer-events: none; |
|
transition: opacity 0.3s ease; |
|
z-index: 1000; |
|
} |
|
#drawerOverlay.open { |
|
opacity: 1; |
|
pointer-events: all; |
|
} |
|
|
|
@media (max-width: 700px) { |
|
#drawer { |
|
width: 100vw; |
|
} |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<header> |
|
<h1>Comparador de Investimentos</h1> |
|
<button id="toggleTheme" aria-label="Alternar tema claro/escuro"> |
|
<i class="fa-regular fa-sun"></i> |
|
</button> |
|
</header> |
|
|
|
<form method="POST" id="formSimulador"> |
|
<div class="form-group"> |
|
<label for="capital">Capital Inicial (R$)</label> |
|
<input type="number" name="capital" id="capital" step="1000" min="10000" placeholder="Ex: 400000" required /> |
|
<i class="fa-solid fa-wallet icon-input"></i> |
|
</div> |
|
|
|
<div class="form-group"> |
|
<label for="studio_ret">Retorno mensal do Studio (%)</label> |
|
<input type="number" name="studio_ret" id="studio_ret" step="0.1" min="0" max="5" placeholder="Ex: 1.0" required /> |
|
<i class="fa-solid fa-building icon-input"></i> |
|
</div> |
|
|
|
<div class="form-group"> |
|
<label for="valorizacao">Valorização anual do imóvel (%)</label> |
|
<input type="number" name="valorizacao" id="valorizacao" step="0.1" min="0" max="20" placeholder="Ex: 6.0" required /> |
|
<i class="fa-solid fa-chart-line icon-input"></i> |
|
</div> |
|
|
|
<div class="form-group"> |
|
<label for="franquia_ret">Lucro anual da Franquia (R$)</label> |
|
<input type="number" name="franquia_ret" id="franquia_ret" step="1000" min="0" placeholder="Ex: 20000" required /> |
|
<i class="fa-solid fa-shop icon-input"></i> |
|
</div> |
|
|
|
<div class="form-group"> |
|
<label for="acoes_ret">Retorno anual em Ações (%)</label> |
|
<input type="number" name="acoes_ret" id="acoes_ret" step="0.1" min="0" max="50" placeholder="Ex: 10.0" required /> |
|
<i class="fa-solid fa-chart-pie icon-input"></i> |
|
</div> |
|
|
|
<div class="form-group"> |
|
<label for="renda_fixa">Retorno anual Renda Fixa (%)</label> |
|
<input type="number" name="renda_fixa" id="renda_fixa" step="0.1" min="0" max="30" placeholder="Ex: 9.0" required /> |
|
<i class="fa-solid fa-coins icon-input"></i> |
|
</div> |
|
|
|
<div class="form-group"> |
|
<label for="inflacao">Inflação anual média esperada (%)</label> |
|
<input type="number" name="inflacao" id="inflacao" step="0.1" min="0" max="15" placeholder="Ex: 4.5" required /> |
|
<i class="fa-solid fa-percent icon-input"></i> |
|
</div> |
|
|
|
<button type="submit">📊 Simular Retorno</button> |
|
</form> |
|
|
|
|
|
<div id="drawer" aria-hidden="true" role="complementary" aria-label="Detalhes da Simulação"> |
|
<button id="drawerCloseBtn" aria-label="Fechar painel de resultados">×</button> |
|
<h2>📈 Resultado da Simulação</h2> |
|
<div id="resultadoTexto"> |
|
|
|
</div> |
|
<div id="resultadoGrafico"> |
|
|
|
</div> |
|
</div> |
|
|
|
<div id="drawerOverlay"></div> |
|
|
|
<script> |
|
const toggleThemeBtn = document.getElementById('toggleTheme'); |
|
const body = document.body; |
|
|
|
function updateThemeIcon() { |
|
if (body.classList.contains('light')) { |
|
toggleThemeBtn.innerHTML = '<i class="fa-regular fa-moon"></i>'; |
|
} else { |
|
toggleThemeBtn.innerHTML = '<i class="fa-regular fa-sun"></i>'; |
|
} |
|
} |
|
|
|
toggleThemeBtn.addEventListener('click', () => { |
|
body.classList.toggle('light'); |
|
updateThemeIcon(); |
|
}); |
|
updateThemeIcon(); |
|
|
|
|
|
const drawer = document.getElementById('drawer'); |
|
const drawerOverlay = document.getElementById('drawerOverlay'); |
|
const drawerCloseBtn = document.getElementById('drawerCloseBtn'); |
|
const form = document.getElementById('formSimulador'); |
|
const resultadoTexto = document.getElementById('resultadoTexto'); |
|
const resultadoGrafico = document.getElementById('resultadoGrafico'); |
|
|
|
function openDrawer() { |
|
drawer.classList.add('open'); |
|
drawerOverlay.classList.add('open'); |
|
drawer.setAttribute('aria-hidden', 'false'); |
|
} |
|
function closeDrawer() { |
|
drawer.classList.remove('open'); |
|
drawerOverlay.classList.remove('open'); |
|
drawer.setAttribute('aria-hidden', 'true'); |
|
} |
|
|
|
drawerCloseBtn.addEventListener('click', closeDrawer); |
|
drawerOverlay.addEventListener('click', closeDrawer); |
|
|
|
form.addEventListener('submit', async (e) => { |
|
e.preventDefault(); |
|
|
|
const formData = new FormData(form); |
|
|
|
|
|
try { |
|
const response = await fetch('/simular', { |
|
method: 'POST', |
|
body: formData, |
|
}); |
|
if (!response.ok) throw new Error('Erro na simulação'); |
|
const data = await response.json(); |
|
|
|
resultadoTexto.innerHTML = `<p>${data.texto.replace(/\n/g, '<br>')}</p>`; |
|
resultadoGrafico.innerHTML = `<img src="data:image/png;base64,${data.graficoBase64}" alt="Gráfico da simulação" />`; |
|
|
|
openDrawer(); |
|
} catch (err) { |
|
alert('Erro ao obter resultado da simulação. Tente novamente.'); |
|
console.error(err); |
|
} |
|
}); |
|
</script> |
|
</body> |
|
</html> |
|
|