BACK_TO_LOGS// STEP_8_OF_10
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 /predict URL 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. income and age) and formats them into a single JavaScript object. The keys in this object match the keys in our Python request parser inside app.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 #result container and applies the appropriate CSS styles. If result.approved is true, it displays a green success banner; if false, it shows a red rejection banner.