Identify problem in the post request in html

I am working on a Flask application that manages therapy sessions for children. Each session can have multiple goals, and I recently updated my models and form handling. However, I’m encountering a 400 Bad Request error when submitting the form to update a session.

Problem:
The error message indicates that “At least one goal and its rating must be provided,” but I believe I am submitting the goals correctly.
Error logs :

2024-07-26T18:05:27.998440+00:00 app[web.1]: DEBUG:root:Full form data: ImmutableMultiDict([('session_id', '65'), ('therapy_type', 'Therapy 1'), ('session_date', '2024-08-03'), ('progress_rating[]', '8'), ('progress_update', 'asd'), ('activities_performed', 'asdad'), ('notes_comments', 'asd')])
2024-07-26T18:05:28.000630+00:00 app[web.1]: ERROR:root:Invalid form data: At least one goal and its rating must be provided.
2024-07-26T18:05:28.008888+00:00 heroku[router]: at=info method=POST path="/update_session/65" host=ams-chat-80db21a7820d.herokuapp.com request_id=cff68d03-618b-4b2c-8b5d-606f66332ce2 fwd="77.127.190.215" dyno=web.1 connect=0ms service=16ms status=400 bytes=236 protocol=https

this is the backed code :

# Models
class SessionDetail(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    child_id = db.Column(db.Integer, db.ForeignKey('child.id'), nullable=False)
    therapy_type = db.Column(db.String(150), nullable=False)
    session_date = db.Column(db.String(20), nullable=False)
    progress_update = db.Column(db.Text, nullable=True)
    activities_performed = db.Column(db.Text, nullable=True)
    notes_comments = db.Column(db.Text, nullable=True)
    goals = db.relationship('Goal', backref='session', lazy=True)

class Goal(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    session_id = db.Column(db.Integer, db.ForeignKey('session_detail.id'), nullable=False)
    description = db.Column(db.Text, nullable=False)
    rating = db.Column(db.Integer, nullable=False)

# Route to update session
@app.route('/update_session/<int:session_id>', methods=['POST'])
def update_session(session_id):
    session_detail = SessionDetail.query.get(session_id)
    if not session_detail:
        logging.error(f"Session with ID {session_id} not found.")
        return 'Session not found', 404

    try:
        logging.debug(f"Full form data: {request.form}")

        session_detail.therapy_type = request.form['therapy_type']
        session_detail.session_date = request.form['session_date']
        session_detail.progress_update = request.form['progress_update']
        session_detail.activities_performed = request.form.get('activities_performed')
        session_detail.notes_comments = request.form.get('notes_comments')
        
        # Delete existing goals
        Goal.query.filter_by(session_id=session_id).delete()

        # Add new goals
        setting_goals = request.form.getlist('setting_goals[]')
        progress_ratings = request.form.getlist('progress_rating[]')

        if not setting_goals or not progress_ratings:
            raise ValueError("At least one goal and its rating must be provided.")

        for goal, rating in zip(setting_goals, progress_ratings):
            new_goal = Goal(session_id=session_id, description=goal, rating=int(rating))
            db.session.add(new_goal)

        db.session.commit()
        logging.info(f"Session ID {session_id} successfully updated with {len(setting_goals)} goals.")
        
    except KeyError as e:
        logging.error(f"Missing form field: {e}")
        return f'Error updating session: Missing form field {e}', 400
    except ValueError as e:
        logging.error(f"Invalid form data: {e}")
        return f'Error updating session: {e}', 400
    except Exception as e:
        logging.error(f"Error updating session: {e}")
        return f'Error updating session: {e}', 500

    return redirect(url_for('child_sessions', child_id=session_detail.child_id))

This is the fronted code which contain the sessions Table and JS (which the exception is captured from ×ĒMore precisely in the ‘unction submitForm(form)’ function :

<body>
    <div class="profile-container">
        <h2>Sessions for {{ child.first_name }} {{ child.surname }}</h2>

        <!-- Back Button -->
        <div class="back-button-container">
            <a href="{{ url_for('children_progress') }}" class="btn-back">Back to Children's Progress</a>
        </div>

        <div class="table-container">
            <table>
                <thead>
                    <tr>
                        <th>Therapy Type</th>
                        <th>Session Date</th>
                        <th>Goals</th>
                        <th>Progress Update</th>
                        <th>Activities Performed</th>
                        <th>Notes/Comments</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                    {% for session in sessions %}
                    <tr>
                        <form method="post" action="{{ url_for('update_session', session_id=session.id) }}" onsubmit="return submitForm(this);">
                            <input type="hidden" name="session_id" value="{{ session.id }}">
                            <td>
                                <select name="therapy_type">
                                    <option value="Therapy 1" {% if session.therapy_type == 'Therapy 1' %}selected{% endif %}>Therapy 1</option>
                                    <option value="Therapy 2" {% if session.therapy_type == 'Therapy 2' %}selected{% endif %}>Therapy 2</option>
                                    <option value="Therapy 3" {% if session.therapy_type == 'Therapy 3' %}selected{% endif %}>Therapy 3</option>
                                    <option value="Therapy 4" {% if session.therapy_type == 'Therapy 4' %}selected{% endif %}>Therapy 4</option>
                                </select>
                            </td>
                            <td><input type="date" name="session_date" value="{{ session.session_date }}"></td>
                            <td>
                                <div class="goal-container">
                                    {% for goal in session.goals %}
                                    <div class="goal-item">
                                        <textarea class="expandable-textarea" name="setting_goals[]">{{ goal.description }}</textarea>
                                        <select name="progress_rating[]">
                                            <option value="" selected disabled>Choose rating</option>
                                            {% for i in range(1, 11) %}
                                            <option value="{{ i }}" {% if goal.rating == i %}selected{% endif %}>{{ i }}</option>
                                            {% endfor %}
                                        </select>
                                        <div class="goal-item-buttons">
                                            <button type="button" onclick="removeGoal(this)">Remove</button>
                                        </div>
                                    </div>
                                    {% endfor %}
                                    <button type="button" class="add-goal-button" onclick="addGoal(this)">Add Goal</button>
                                </div>
                            </td>
                            <td><textarea class="expandable-textarea" name="progress_update">{{ session.progress_update }}</textarea></td>
                            <td><textarea class="expandable-textarea" name="activities_performed">{{ session.activities_performed }}</textarea></td>
                            <td><textarea class="expandable-textarea" name="notes_comments">{{ session.notes_comments }}</textarea></td>
                            <td>
                                <button type="submit" name="update_session">Update</button>
                            </td>
                        </form>
                        <td>
                            <form method="post" action="{{ url_for('delete_session', session_id=session.id) }}" style="display:inline;">
                                <button type="submit" name="delete_session">Delete</button>
                            </form>
                        </td>
                    </tr>
                    {% endfor %}
                    <!-- Form for adding a new session -->
                    <form method="post" action="{{ url_for('add_session', child_id=child.id) }}" onsubmit="submitForm(this); return false;">
                        <td>
                            <select name="therapy_type" required>
                                <option value="Therapy 1">Therapy 1</option>
                                <option value="Therapy 2">Therapy 2</option>
                                <option value="Therapy 3">Therapy 3</option>
                                <option value="Therapy 4">Therapy 4</option>
                            </select>
                        </td>
                        <td><input type="date" name="session_date" required></td>
                        <td>
                            <div class="goal-container">
                                <div class="goal-item">
                                    <textarea class="expandable-textarea" name="setting_goals_new[]" required></textarea>
                                    <select name="progress_rating_new[]" required>
                                        <option value="" selected disabled>Choose rating</option>
                                        {% for i in range(1, 11) %}
                                        <option value="{{ i }}">{{ i }}</option>
                                        {% endfor %}
                                    </select>
                                    <div class="goal-item-buttons">
                                        <button type="button" onclick="removeGoal(this)">Remove</button>
                                    </div>
                                </div>
                                <button type="button" class="add-goal-button" onclick="addGoal(this, 'setting_goals_new[]', 'progress_rating_new[]')">Add Goal</button>
                            </div>
                        </td>
                        <td><textarea class="expandable-textarea" name="progress_update" required></textarea></td>
                        <td><textarea class="expandable-textarea" name="activities_performed"></textarea></td>
                        <td><textarea class="expandable-textarea" name="notes_comments"></textarea></td>
                        <td><button type="submit" name="add_session">Add</button></td>
                    </form>
                </tbody>
                
            </table>
        </div>

        <!-- Chart Container -->
        <div class="chart-container">
            <canvas id="progressChart"></canvas>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const formInputs = document.querySelectorAll('.login-form input[type="text"], .login-form input[type="password"], .profile-container form input[type="text"], .profile-container form input[type="tel"], .profile-container form select');
            
            formInputs.forEach(input => {
                input.addEventListener('focus', function() {
                    this.style.borderColor = '#007bff';
                });
    
                input.addEventListener('blur', function() {
                    this.style.borderColor = '#ddd';
                });
            });
    
            const submitButtons = document.querySelectorAll('.login-form input[type="submit"], .profile-container form button[type="submit"]');
            
            submitButtons.forEach(button => {
                button.addEventListener('mousedown', function() {
                    this.style.backgroundColor = '#004080';
                });
    
                button.addEventListener('mouseup', function() {
                    this.style.backgroundColor = '#007bff';
                });
            });
        });
    
        function addGoal(button, goalsName = 'setting_goals[]', ratingsName = 'progress_rating[]') {
    const goalContainer = button.closest('.goal-container');
    const goalCount = goalContainer.querySelectorAll('.goal-item').length;
    const newGoalItem = document.createElement('div');
    newGoalItem.className = 'goal-item';
    newGoalItem.innerHTML = `
        <textarea class="expandable-textarea" name="${goalsName.replace('[]', `[${goalCount}]`)}"></textarea>
        <select name="${ratingsName.replace('[]', `[${goalCount}]`)}">
            <option value="" selected disabled>Choose rating</option>
            ${[...Array(10).keys()].map(i => `<option value="${i+1}">${i+1}</option>`).join('')}
        </select>
        <div class="goal-item-buttons">
            <button type="button" onclick="removeGoal(this)">Remove</button>
        </div>
    `;
    goalContainer.insertBefore(newGoalItem, button);
}
    
        function removeGoal(button) {
            const goalItem = button.closest('.goal-item');
            goalItem.remove();
        }
    
    function submitForm(form) {
        console.log("Submitting form");
        const goalItems = form.querySelectorAll('.goal-item');
        const formData = new FormData(form);

        // Remove existing goals and ratings
        for (let key of formData.keys()) {
            if (key.startsWith('setting_goals') || key.startsWith('progress_rating')) {
                formData.delete(key);
            }
        }

        goalItems.forEach((goalItem, index) => {
            const goalText = goalItem.querySelector('textarea[name^="setting_goals"]').value;
            const goalRating = goalItem.querySelector('select[name^="progress_rating"]').value;
            
            if (goalText && goalRating) {
                formData.append(`setting_goals[${index}]`, goalText);
                formData.append(`progress_rating[${index}]`, goalRating);
            }
        });

        // Log form data for debugging
        console.log("Form data before submission:");
        for (let pair of formData.entries()) {
            console.log(pair[0] + ': ' + pair[1]);
        }

        // Use fetch to send the data
        fetch(form.action, {
            method: 'POST',
            body: formData
        })
        .then(response => {
            if (!response.ok) {
                return response.text().then(text => {
                    throw new Error(`Network response was not ok: ${text}`);
                });
            }
            return response.text();
        })
        .then(data => {
            console.log("Response:", data);
            window.location.reload();
        })
        .catch(error => {
            console.error('Error:', error);
        });

        return false; // Prevent default form submission
    }

    </script>
    
    
</body>

What I’ve Tried:

Ensured that the form data includes setting_goals[] and progress_rating[].(apperantly it still has a problem )
Added debugging statements to log the form data before submission.
Checked the backend logs to verify the form data received.
Network Console Logs (playlod) output aftersending the post request:

session_id: 65
therapy_type: Therapy 1
session_date: 2024-08-03
progress_rating[]: 8
progress_update: asd
activities_performed: asdad
notes_comments: asd