HANDBOOK_GUIDE2026-06-28
Credit Card Approval Prediction: End-to-End Machine Learning Guide
By Rayan Syed
40 min read
Part 8: Frontend User Interface Files
To create a clean interface, we split our frontend assets into three files: index.html, style.css, and script.js.
8.1 How the Frontend Connects with the Backend
Web applications operate on a Client-Server Architecture.
- The Client (Frontend): This is the user interface running in the browser (
index.html,style.css,script.js). Its job is to collect information from the user and display results. - The Server (Backend): This is our Flask script (
app.py) running on our local machine. It listens for incoming HTTP requests, feeds features to our machine learning model, and returns the prediction. - The Communication (HTTP POST & JSON): When the user clicks the submit button, the frontend does not reload the page. Instead, JavaScript packages the form inputs into a JSON dictionary and sends it via an HTTP POST request to the
/predictURL on the Flask server. Once the server responds with a success or rejection state, the webpage updates itself dynamically.
Frontend Template (templates/index.html)
Save this layout configuration inside templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Credit Card Approval Predictor</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<div class="container">
<h2>Credit Card Eligibility Predictor</h2>
<form id="predictionForm">
<label for="gender">Gender:</label>
<select id="gender" required>
<option value="0">Female</option>
<option value="1">Male</option>
</select>
<label for="own_car">Owns a Car?</label>
<select id="own_car" required>
<option value="0">No</option>
<option value="1">Yes</option>
</select>
<label for="own_realty">Owns Real Estate / Property?</label>
<select id="own_realty" required>
<option value="0">No</option>
<option value="1">Yes</option>
</select>
<label for="children">Number of Children:</label>
<input type="number" id="children" min="0" value="0" required>
<label for="income">Annual Income ($):</label>
<input type="number" id="income" min="0" required>
<label for="income_type">Income Type:</label>
<select id="income_type" required>
<option value="4">Working</option>
<option value="0">Commercial associate</option>
<option value="1">Pensioner</option>
<option value="2">State servant</option>
<option value="3">Student</option>
</select>
<label for="education">Highest Education Level:</option>
<select id="education" required>
<option value="4">Secondary / secondary special</option>
<option value="1">Higher education</option>
<option value="2">Incomplete higher</option>
<option value="3">Lower secondary</option>
<option value="0">Academic degree</option>
</select>
<label for="family_status">Family Status:</label>
<select id="family_status" required>
<option value="1">Married</option>
<option value="3">Single / not married</option>
<option value="0">Civil marriage</option>
<option value="2">Separated</option>
<option value="4">Widow</option>
</select>
<label for="housing_type">Housing Type:</label>
<select id="housing_type" required>
<option value="1">House / apartment</option>
<option value="5">With parents</option>
<option value="2">Municipal apartment</option>
<option value="4">Rented apartment</option>
<option value="3">Office apartment</option>
<option value="0">Co-op apartment</option>
</select>
<label for="occupation">Occupation Type:</label>
<select id="occupation" required>
<option value="18">Unknown</option>
<option value="8">Laborers</option>
<option value="3">Core staff</option>
<option value="14">Sales staff</option>
<option value="10">Managers</option>
<option value="4">Drivers</option>
<option value="6">High skill tech staff</option>
</select>
<label for="family_size">Family Size:</label>
<input type="number" id="family_size" min="1" value="1" required>
<label for="age">Age (Years):</label>
<input type="number" id="age" min="18" max="100" required>
<label for="years_employed">Years Employed:</label>
<input type="number" id="years_employed" min="0" step="0.1" value="0" required>
<label for="unemployed">Is Unemployed?</label>
<select id="unemployed" required>
<option value="0">No</option>
<option value="1">Yes</option>
</select>
<button type="submit">Predict Eligibility</button>
</form>
<div id="result"></div>
</div>
<script src="/static/script.js"></script>
</body>
</html>
Style Sheet (static/style.css)
Save this CSS configuration inside static/style.css to build our form wrapper:
body {
background-color: #0a0a0c;
color: #e4e4e7;
font-family: system-ui, -apple-system, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px 0;
}
.container {
background-color: #121214;
border: 1px solid #27272a;
padding: 32px;
border-radius: 16px;
width: 360px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
}
h2 {
text-align: center;
margin-bottom: 24px;
font-size: 1.5rem;
color: #ffffff;
}
label {
display: block;
margin-bottom: 6px;
font-size: 0.85rem;
font-weight: 500;
color: #a1a1aa;
}
input, select, button {
width: 100%;
margin-bottom: 16px;
padding: 10px;
border-radius: 8px;
border: 1px solid #27272a;
background-color: #1a1a1e;
color: #ffffff;
box-sizing: border-box;
font-size: 0.9rem;
transition: all 0.2s;
}
input:focus, select:focus {
border-color: #3b82f6;
outline: none;
}
button {
background-color: #2563eb;
color: white;
border: none;
font-weight: 650;
cursor: pointer;
margin-top: 10px;
}
button:hover {
background-color: #1d4ed8;
}
#result {
margin-top: 15px;
padding: 12px;
border-radius: 8px;
text-align: center;
font-weight: bold;
font-size: 0.95rem;
display: none;
}
.success {
background-color: rgba(16, 185, 129, 0.15);
border: 1px solid rgba(16, 185, 129, 0.4);
color: #34d399;
}
.danger {
background-color: rgba(239, 68, 68, 0.15);
border: 1px solid rgba(239, 68, 68, 0.4);
color: #f87171;
}
Application Logic Script (static/script.js)
Save this JS module inside static/script.js:
document.getElementById('predictionForm').addEventListener('submit', async (e) => {
e.preventDefault();
const resultDiv = document.getElementById('result');
resultDiv.style.display = 'none';
// Pack input form values into a JSON payload
const payload = {
gender: document.getElementById('gender').value,
own_car: document.getElementById('own_car').value,
own_realty: document.getElementById('own_realty').value,
children: document.getElementById('children').value,
income: document.getElementById('income').value,
income_type: document.getElementById('income_type').value,
education: document.getElementById('education').value,
family_status: document.getElementById('family_status').value,
housing_type: document.getElementById('housing_type').value,
occupation: document.getElementById('occupation').value,
family_size: document.getElementById('family_size').value,
age: document.getElementById('age').value,
years_employed: document.getElementById('years_employed').value,
unemployed: document.getElementById('unemployed').value
};
try {
// Send POST request containing payload to the prediction endpoint
const response = await fetch('/predict', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const result = await response.json();
resultDiv.style.display = 'block';
if (result.approved) {
resultDiv.className = 'success';
resultDiv.innerText = 'Application Status: APPROVED';
} else {
resultDiv.className = 'danger';
resultDiv.innerText = 'Application Status: REJECTED';
}
} catch (err) {
resultDiv.className = 'danger';
resultDiv.innerText = 'Error processing credit application.';
console.error(err);
}
});
8.2 Understanding the Script Execution
Let’s break down the logic of this script:
e.preventDefault(): Prevents the browser from reloading the page when you click the submit button. This allows us to handle the form processing silently in the background.payload: Gathers all values from form fields (e.g.incomeandage) and formats them into a single JavaScript object. The keys in this object match the keys in our Python request parser insideapp.py.fetch('/predict', ...): Starts a secure asynchronous HTTP connection. It sends the payload to our backend server as a JSON string (JSON.stringify(payload)) with headers identifying the content type.response.json(): Waits for the server to reply and parses the returned JSON string back into a readable JavaScript dictionary.- Result Banner Update: Displays the
#resultcontainer and applies the appropriate CSS styles. Ifresult.approvedistrue, it displays a green success banner; iffalse, it shows a red rejection banner.