stroke_model / templates /index.html
omaralaa2004's picture
Update templates/index.html
2838bad verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stroke Risk Prediction</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<style>
:root {
--primary-color: #4e54c8;
--secondary-color: #8f94fb;
--success-color: #23ce6b;
--danger-color: #ff6b6b;
--light-bg: #f9f9ff;
--dark-text: #333344;
}
body {
background: linear-gradient(to right, var(--primary-color), var(--secondary-color));
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: var(--dark-text);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px 0;
}
.container {
max-width: 900px;
background-color: rgba(255, 255, 255, 0.95);
padding: 40px;
border-radius: 20px;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
backdrop-filter: blur(5px);
}
h1 {
background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-weight: 700;
margin-bottom: 30px;
text-align: center;
font-size: 2.5rem;
}
.form-group {
margin-bottom: 25px;
position: relative;
}
.form-control {
border-radius: 10px;
padding: 12px 15px;
border: 2px solid #e0e0ff;
transition: all 0.3s ease;
}
.form-control:focus {
box-shadow: 0 0 0 3px rgba(78, 84, 200, 0.2);
border-color: var(--primary-color);
}
label {
font-weight: 600;
margin-bottom: 8px;
display: block;
color: var(--primary-color);
}
.btn-predict {
background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
border: none;
width: 100%;
padding: 15px;
font-size: 18px;
margin-top: 20px;
border-radius: 10px;
font-weight: 600;
color: white;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.btn-predict:hover {
transform: translateY(-3px);
box-shadow: 0 7px 14px rgba(78, 84, 200, 0.3);
}
.btn-predict:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 5px;
height: 5px;
background: rgba(255, 255, 255, 0.5);
opacity: 0;
border-radius: 100%;
transform: scale(1, 1) translate(-50%, -50%);
transform-origin: 50% 50%;
}
.btn-predict:focus:not(:active)::after {
animation: ripple 1s ease-out;
}
@keyframes ripple {
0% {
transform: scale(0, 0);
opacity: 0.5;
}
100% {
transform: scale(20, 20);
opacity: 0;
}
}
.result-container {
margin-top: 40px;
padding: 30px;
border-radius: 15px;
display: none;
transform: translateY(20px);
transition: all 0.5s ease;
}
.high-risk {
background-color: rgba(255, 107, 107, 0.2);
border: 2px solid var(--danger-color);
}
.low-risk {
background-color: rgba(35, 206, 107, 0.2);
border: 2px solid var(--success-color);
}
.form-section {
padding: 20px;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
margin-bottom: 25px;
background-color: white;
}
.section-title {
border-bottom: 2px solid #e0e0ff;
padding-bottom: 10px;
margin-bottom: 20px;
color: var(--primary-color);
font-weight: 600;
}
.progress-bar {
height: 8px;
background-color: #e0e0ff;
border-radius: 4px;
margin-bottom: 30px;
position: relative;
}
.progress-fill {
height: 100%;
border-radius: 4px;
background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
width: 0;
transition: width 0.3s ease;
}
.step-indicator {
display: flex;
justify-content: center;
margin-bottom: 30px;
}
.step {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #e0e0ff;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
color: var(--dark-text);
margin: 0 10px;
position: relative;
transition: all 0.3s ease;
}
.step.active {
background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
color: white;
transform: scale(1.1);
}
.step.completed {
background: var(--success-color);
color: white;
}
.step-line {
position: absolute;
height: 3px;
background-color: #e0e0ff;
top: 20px;
left: 40px;
width: calc(100% - 100px);
z-index: -1;
}
.form-nav {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.btn-nav {
padding: 10px 20px;
border-radius: 10px;
background: white;
border: 2px solid #e0e0ff;
color: var(--primary-color);
font-weight: 600;
transition: all 0.3s ease;
}
.btn-nav:hover {
background: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.form-step {
display: none;
}
.form-step.active {
display: block;
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.loader {
display: none;
width: 48px;
height: 48px;
border: 5px solid var(--primary-color);
border-bottom-color: transparent;
border-radius: 50%;
box-sizing: border-box;
animation: rotation 1s linear infinite;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
@keyframes rotation {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
transform: translate(-50%, -50%) rotate(360deg);
}
}
.info-tooltip {
display: inline-block;
width: 18px;
height: 18px;
background-color: #e0e0ff;
color: var(--primary-color);
border-radius: 50%;
text-align: center;
line-height: 18px;
font-size: 12px;
margin-left: 5px;
cursor: pointer;
position: relative;
}
.info-tooltip .tooltip-text {
visibility: hidden;
width: 200px;
background-color: #333;
color: white;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
font-size: 12px;
font-weight: normal;
}
.info-tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
.summary-label {
font-weight: 600;
color: var(--primary-color);
}
.summary-value {
color: var(--dark-text);
}
</style>
</head>
<body>
<div class="container animate__animated animate__fadeIn">
<div class="step-indicator">
<div class="step active" id="step-1">1</div>
<div class="step" id="step-2">2</div>
<div class="step" id="step-3">3</div>
<div class="step-line"></div>
</div>
<h1>Stroke Risk Prediction</h1>
<div class="progress-bar">
<div class="progress-fill" id="progress-bar"></div>
</div>
<form id="prediction-form">
<div class="form-step active" id="form-step-1">
<div class="form-section">
<h3 class="section-title">Personal Information</h3>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="age">Age <span class="info-tooltip">i<span class="tooltip-text">Enter your age in years</span></span></label>
<input type="number" class="form-control" id="age" name="age" required min="0" max="120" step="0.1">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="gender">Gender <span class="info-tooltip">i<span class="tooltip-text">Select your gender</span></span></label>
<select class="form-control" id="gender" name="gender" required>
<option value="">Select Gender</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Other">Other</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="ever_married">Ever Married <span class="info-tooltip">i<span class="tooltip-text">Have you ever been married?</span></span></label>
<select class="form-control" id="ever_married" name="ever_married" required>
<option value="">Select</option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="residence_type">Residence Type <span class="info-tooltip">i<span class="tooltip-text">Urban or rural area</span></span></label>
<select class="form-control" id="residence_type" name="residence_type" required>
<option value="">Select</option>
<option value="Urban">Urban</option>
<option value="Rural">Rural</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="work_type">Work Type <span class="info-tooltip">i<span class="tooltip-text">Type of employment</span></span></label>
<select class="form-control" id="work_type" name="work_type" required>
<option value="">Select Work Type</option>
<option value="Private">Private</option>
<option value="Self-employed">Self-employed</option>
<option value="Govt_job">Government Job</option>
<option value="Never_worked">Never worked</option>
</select>
</div>
</div>
</div>
</div>
<div class="form-nav">
<div></div>
<button type="button" class="btn btn-nav" id="next-1">Next <i class="fas fa-arrow-right"></i></button>
</div>
</div>
<div class="form-step" id="form-step-2">
<div class="form-section">
<h3 class="section-title">Health Information</h3>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="hypertension">Hypertension <span class="info-tooltip">i<span class="tooltip-text">Do you have hypertension?</span></span></label>
<select class="form-control" id="hypertension" name="hypertension" required>
<option value="">Select</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="heart_disease">Heart Disease <span class="info-tooltip">i<span class="tooltip-text">Do you have heart disease?</span></span></label>
<select class="form-control" id="heart_disease" name="heart_disease" required>
<option value="">Select</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="avg_glucose_level">Avg. Glucose Level <span class="info-tooltip">i<span class="tooltip-text">Normal fasting blood sugar is under 100 mg/dL</span></span></label>
<input type="number" class="form-control" id="avg_glucose_level" name="avg_glucose_level" required min="0" step="0.01">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="bmi">BMI <span class="info-tooltip">i<span class="tooltip-text">Body Mass Index (weight in kg / height in m²)</span></span></label>
<input type="number" class="form-control" id="bmi" name="bmi" required min="0" max="100" step="0.01">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="smoking_status">Smoking Status <span class="info-tooltip">i<span class="tooltip-text">Your smoking habits</span></span></label>
<select class="form-control" id="smoking_status" name="smoking_status" required>
<option value="">Select Smoking Status</option>
<option value="formerly smoked">Formerly Smoked</option>
<option value="never smoked">Never Smoked</option>
<option value="smokes">Currently Smokes</option>
<option value="Unknown">Unknown</option>
</select>
</div>
</div>
</div>
</div>
<div class="form-nav">
<button type="button" class="btn btn-nav" id="prev-2">Previous</button>
<button type="button" class="btn btn-nav" id="next-2">Next</button>
</div>
</div>
<div class="form-step" id="form-step-3">
<div class="form-section">
<h3 class="section-title">Summary</h3>
<p>Please review your information below before submitting:</p>
<div class="row">
<div class="col-md-6">
<p><span class="summary-label">Age:</span> <span class="summary-value" id="summary-age"></span></p>
<p><span class="summary-label">Gender:</span> <span class="summary-value" id="summary-gender"></span></p>
<p><span class="summary-label">Ever Married:</span> <span class="summary-value" id="summary-married"></span></p>
<p><span class="summary-label">Residence Type:</span> <span class="summary-value" id="summary-residence"></span></p>
<p><span class="summary-label">Work Type:</span> <span class="summary-value" id="summary-work"></span></p>
</div>
<div class="col-md-6">
<p><span class="summary-label">Hypertension:</span> <span class="summary-value" id="summary-hypertension"></span></p>
<p><span class="summary-label">Heart Disease:</span> <span class="summary-value" id="summary-heart"></span></p>
<p><span class="summary-label">Avg. Glucose Level:</span> <span class="summary-value" id="summary-glucose"></span> mg/dL</p>
<p><span class="summary-label">BMI:</span> <span class="summary-value" id="summary-bmi"></span></p>
<p><span class="summary-label">Smoking Status:</span> <span class="summary-value" id="summary-smoking"></span></p>
</div>
</div>
</div>
<div class="form-nav">
<button type="button" class="btn btn-nav" id="prev-3">Previous</button>
<button type="submit" class="btn btn-predict">Predict Stroke Risk</button>
</div>
</div>
</form>
<div id="result" class="result-container animate__animated">
<h3 id="result-title" class="text-center mb-4">Prediction Result</h3>
<p id="prediction-result" class="text-center fs-4 fw-bold"></p>
<div class="text-center mt-4">
<button type="button" class="btn btn-nav" id="start-over">Start Over</button>
</div>
</div>
</div>
<div class="overlay" id="loading-overlay">
<div class="loader"></div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js"></script>
<script>
$(document).ready(function() {
let currentStep = 1;
const totalSteps = 3;
// Update progress bar
function updateProgressBar() {
const progressPercent = ((currentStep - 1) / (totalSteps - 1)) * 100;
$('#progress-bar').css('width', progressPercent + '%');
}
// Navigate to next step
function nextStep() {
if (validateStep(currentStep)) {
$(`#form-step-${currentStep}`).removeClass('active');
currentStep++;
$(`#form-step-${currentStep}`).addClass('active animate__animated animate__fadeIn');
// Update step indicators
$(`.step`).removeClass('active');
$(`#step-${currentStep}`).addClass('active');
// Mark previous steps as completed
for (let i = 1; i < currentStep; i++) {
$(`#step-${i}`).addClass('completed');
}
updateProgressBar();
// If final step, update summary
if (currentStep === 3) {
updateSummary();
}
}
}
// Navigate to previous step
function prevStep() {
$(`#form-step-${currentStep}`).removeClass('active');
currentStep--;
$(`#form-step-${currentStep}`).addClass('active animate__animated animate__fadeIn');
// Update step indicators
$(`.step`).removeClass('active');
$(`#step-${currentStep}`).addClass('active');
updateProgressBar();
}
// Validate current step
function validateStep(step) {
let isValid = true;
$(`#form-step-${step} input, #form-step-${step} select`).each(function() {
if ($(this).prop('required') && !$(this).val()) {
isValid = false;
$(this).addClass('is-invalid');
} else {
$(this).removeClass('is-invalid');
}
});
return isValid;
}
// Update summary before submission
function updateSummary() {
$('#summary-age').text($('#age').val() || 'Not specified');
$('#summary-gender').text($('#gender').val() || 'Not specified');
$('#summary-married').text($('#ever_married').val() || 'Not specified');
$('#summary-residence').text($('#residence_type').val() || 'Not specified');
$('#summary-work').text($('#work_type').val() || 'Not specified');
$('#summary-hypertension').text($('#hypertension').val() === '1' ? 'Yes' : $('#hypertension').val() === '0' ? 'No' : 'Not specified');
$('#summary-heart').text($('#heart_disease').val() === '1' ? 'Yes' : $('#heart_disease').val() === '0' ? 'No' : 'Not specified');
$('#summary-glucose').text($('#avg_glucose_level').val() || 'Not specified');
$('#summary-bmi').text($('#bmi').val() || 'Not specified');
$('#summary-smoking').text($('#smoking_status').val() || 'Not specified');
}
// Navigation button click handlers
$('#next-1').click(nextStep);
$('#next-2').click(nextStep);
$('#prev-2').click(prevStep);
$('#prev-3').click(prevStep);
// Start over button
$('#start-over').click(function() {
$('#prediction-form')[0].reset();
$('#result').removeClass('animate__fadeIn').addClass('animate__fadeOut');
setTimeout(function() {
$('#result').hide().removeClass('animate__fadeOut');
// Reset to first step
$('.form-step').removeClass('active');
$('#form-step-1').addClass('active');
currentStep = 1;
// Reset step indicators
$('.step').removeClass('active completed');
$('#step-1').addClass('active');
updateProgressBar();
}, 500);
});
// Field validation on input change
$('input, select').on('change', function() {
if ($(this).prop('required') && !$(this).val()) {
$(this).addClass('is-invalid');
} else {
$(this).removeClass('is-invalid');
}
});
// Form submission with animation
$('#prediction-form').on('submit', function(e) {
e.preventDefault();
if (validateStep(currentStep)) {
console.log("Form validated, initiating prediction request");
$('#loading-overlay').fadeIn();
// Collect form data
const formData = {
age: $('#age').val(),
gender: $('#gender').val(),
ever_married: $('#ever_married').val(),
residence_type: $('#residence_type').val(),
work_type: $('#work_type').val(),
hypertension: $('#hypertension').val(),
heart_disease: $('#heart_disease').val(),
avg_glucose_level: $('#avg_glucose_level').val(),
bmi: $('#bmi').val(),
smoking_status: $('#smoking_status').val()
};
console.log("Form data collected:", formData);
// Send data to Flask backend
$.ajax({
url: '/predict',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ input: formData }),
beforeSend: function() {
console.log("Sending AJAX request to /predict");
},
success: function(response) {
console.log("Received response:", response);
$('#loading-overlay').fadeOut();
if (response.success) {
console.log("Prediction successful, rendering result");
$('#prediction-result').text(response.prediction);
$('#result').removeClass('high-risk low-risk');
if (response.prediction === 'Stroke Risk') {
$('#result').addClass('high-risk');
} else {
$('#result').addClass('low-risk');
}
$('#result').show().removeClass('animate__fadeOut').addClass('animate__fadeIn');
$('#prediction-form').hide();
} else {
console.error("Prediction failed:", response.error);
alert('Error: ' + response.error);
$('#result').hide();
}
},
error: function(xhr, status, error) {
console.error("AJAX request failed:", { status: status, error: error, response: xhr.responseText });
$('#loading-overlay').fadeOut();
$('#prediction-result').text("Error occurred while processing your request.");
$('#result').removeClass('high-risk low-risk').addClass('high-risk');
$('#result').show().removeClass('animate__fadeOut').addClass('animate__fadeIn');
$('#prediction-form').hide();
},
complete: function() {
console.log("AJAX request completed");
}
});
} else {
console.log("Form validation failed");
}
});
});
</script>
</body>
</html>