TypeError: Cannot read properties of null when saving data in PHP web app

I’m working on a PHP web app where users input data, validate fields, preview images, and then save the data to MySQL. When submitting the form, I encounter the error:

TypeError: Cannot read properties of null (reading ‘value’)

This happens when I try to access form field values. How can I fix this issue?

function populateReviewSection() {
            const reviewContent = document.getElementById('reviewContent');
            reviewContent.innerHTML = ''; // Clear previous content

            // Helper function to format dates (if applicable)
            const formatDate = (dateStr) => {
                const date = new Date(dateStr);
                if (isNaN(date.getTime())) return 'Not provided';
                return date.toLocaleDateString(); // You can customize this format as needed
            };

            // Retrieve form data
            const firstname = document.getElementById('firstname').value;
            const surname = document.getElementById('surname').value;
            const email = document.getElementById('email').value;
            const dob = formatDate(document.getElementById('dob').value); // Format DOB
            const gender = document.querySelector('input[name="gender"]:checked')?.value || 'Not selected';
            const ridersImagePreview = document.getElementById('ridersImagePreview').src;
            const ridersImageName = document.getElementById('ridersImageName').textContent || 'No image selected';

            // Retrieve fields for GPS address, employment status, and nationality
            const gpsAddress = document.getElementById('riders_gpsAddress').value || 'Not provided';
            const employmentStatus = document.getElementById('employment_status').value || 'Not selected';
            const nationality = document.getElementById('nationality').value || 'Not selected';
            const homeTown = document.getElementById('home_town').value || 'Not provided';
            const phoneNumber = document.getElementById('phone_number').value || 'Not provided';
            const address = document.getElementById('address').value || 'Not provided';
            const stationId = document.getElementById('station_id').value || 'Not selected';

            // Step 2: Retrieve form data from Step 2
            const idCardType = document.getElementById('id_card_type').value || 'Not selected';
            const idCardNumber = document.getElementById('id_card_number').value || 'Not provided';
            const idCardExpiry = formatDate(document.getElementById('id_card_expiry').value); // Format ID card expiry
            const idCardImagePreview = document.getElementById('idCardImagePreview').src;
            const idCardBackImagePreview = document.getElementById('idCardBackImagePreview').src;

            const isRiderHavingLicense = document.getElementById('isRiderHavingLicense').value || 'Not selected';
            const licenseNumber = document.getElementById('license_number').value || 'Not provided';
            const licenseExpiryDate = formatDate(document.getElementById('license_expiry_date').value); // Format license expiry
            const licenseImagePreview = document.getElementById('licenseImagePreview').src;
            const licenseBackImagePreview = document.getElementById('licenseBackImagePreview').src;

            // Get values for the radio button groups
            const yearsAsRider = document.querySelector('input[name="years_as_rider"]:checked')?.value || 'Not selected';
            const ownMotorbike = document.querySelector('input[name="own_motorbike"]:checked')?.value || 'Not selected';
            const workingForPay = document.querySelector('input[name="working_for_pay"]:checked')?.value || 'Not selected';
            const business_model = document.getElementById('business_model').value || 'Not provided';
            const shareBike = document.querySelector('input[name="share_bike"]:checked')?.value || 'Not selected';

            // Populate the reviewContent div with the collected data
            reviewContent.innerHTML = `

                <!-- Rider's Image displayed above the text -->
                <div class="image-preview" style="text-align: center; margin-bottom: 20px;">
                    <h6><strong>Rider's Image</strong></h6>
                    <img src="${ridersImagePreview}" alt="Rider's Image" style="max-width: 300px; height: auto; display: block; margin-left: auto; margin-right: auto; border-radius: 8px;">
                    <p><strong>Image Name:</strong> ${ridersImageName}</p>
                </div>

                <div class="review-section">
                    <h6><strong>Personal Information</strong></h6>
                    <table class="table table-bordered">
                        <tr>
                            <th>First Name</th>
                            <td>${firstname}</td>
                        </tr>
                        <tr>
                            <th>Surname</th>
                            <td>${surname}</td>
                        </tr>
                        <tr>
                            <th>Email</th>
                            <td>${email}</td>
                        </tr>
                        <tr>
                            <th>Date of Birth</th>
                            <td>${dob}</td>
                        </tr>
                        <tr>
                            <th>Gender</th>
                            <td>${gender}</td>
                        </tr>
                    </table>
                </div>

                <div class="review-section">
                    <h6><strong>Rider's Details</strong></h6>
                    <table class="table table-bordered">
                        <tr>
                            <th>GPS Address</th>
                            <td>${gpsAddress}</td>
                        </tr>
                        <tr>
                            <th>Employment Status</th>
                            <td>${employmentStatus}</td>
                        </tr>
                        <tr>
                            <th>Nationality</th>
                            <td>${nationality}</td>
                        </tr>
                        <tr>
                            <th>Home Town</th>
                            <td>${homeTown}</td>
                        </tr>
                        <tr>
                            <th>Phone Number</th>
                            <td>${phoneNumber}</td>
                        </tr>
                        <tr>
                            <th>Address</th>
                            <td>${address}</td>
                        </tr>
                        <tr>
                            <th>Station</th>
                            <td>${stationId}</td>
                        </tr>
                    </table>
                </div>


                <div class="review-section">
                    <h6><strong>ID Card Information</strong></h6>
                    <table class="table table-bordered">
                        <tr>
                            <th>ID Card Type</th>
                            <td>${idCardType}</td>
                        </tr>
                        <tr>
                            <th>ID Card Number</th>
                            <td>${idCardNumber}</td>
                        </tr>
                        <tr>
                            <th>ID Card Expiry</th>
                            <td>${idCardExpiry}</td>
                        </tr>
                        <tr>
                            <th>ID Card Front</th>
                            <td><img src="${idCardImagePreview}" alt="ID Card Front" style="max-width: 200px; max-height: 200px;"></td>
                        </tr>
                        <tr>
                            <th>ID Card Back</th>
                            <td><img src="${idCardBackImagePreview}" alt="ID Card Back" style="max-width: 200px; max-height: 200px;"></td>
                        </tr>
                    </table>
                </div>

                <div class="review-section">
                    <h6><strong>License Information</strong></h6>
                    <table class="table table-bordered">
                        <tr>
                            <th>Has a License</th>
                            <td>${isRiderHavingLicense}</td>
                        </tr>
                        ${isRiderHavingLicense === 'Yes' ? `
                            <tr>
                                <th>License Number</th>
                                <td>${licenseNumber}</td>
                            </tr>
                            <tr>
                                <th>License Expiry</th>
                                <td>${licenseExpiryDate}</td>
                            </tr>
                            <tr>
                                <th>License Front</th>
                                <td><img src="${licenseImagePreview}" alt="License Front" style="max-width: 200px; max-height: 200px;"></td>
                            </tr>
                            <tr>
                                <th>License Back</th>
                                <td><img src="${licenseBackImagePreview}" alt="License Back" style="max-width: 200px; max-height: 200px;"></td>
                            </tr>
                        ` : ''}
                    </table>
                </div>

                <div class="review-section">
                    <h6><strong>Rider's Experience</strong></h6>
                    <table class="table table-bordered">
                        <tr>
                            <th>Number of Years as a Rider</th>
                            <td>${yearsAsRider} years</td>
                        </tr>
                        <tr>
                            <th>Do you own the motorbike?</th>
                            <td>${ownMotorbike}</td>
                        </tr>
                        <tr>
                            <th>Are you working for work and pay?</th>
                            <td>${workingForPay}</td>
                        </tr>
                        <tr>
                            <th>Your business model if not work and pay</th>
                            <td>${business_model}</td>
                        </tr>
                        <tr>
                            <th>Do you share the bike with another rider?</th>
                            <td>${shareBike}</td>
                        </tr>
                    </table>
                </div>

            `;
        }

        // Add a submit button to your HTML in the review step
        document.querySelector('#submit-form').addEventListener('click', function(e) {
            e.preventDefault();

            // Show SweetAlert2 confirmation dialog
            Swal.fire({
                title: 'Are you sure?',
                text: "You want to submit this rider information?",
                icon: 'question',
                showCancelButton: true,
                confirmButtonColor: '#3085d6',
                cancelButtonColor: '#d33',
                confirmButtonText: 'Yes, submit it!'
            }).then((result) => {
                if (result.isConfirmed) {
                    // Disable the submit button to prevent double submission
                    this.disabled = true;

                    // Show loading state
                    $(this).html('<i class="fas fa-spinner fa-spin"></i> Submitting...');

                    // Call the save function
                    saveRiderData();
                }
            });
        });

        // Update the saveRiderData function to properly collect all form data
        function saveRiderData() {
            // Create a data object instead of FormData
            const data = {
                firstname: document.getElementById('firstname').value,
                surname: document.getElementById('surname').value,
                email: document.getElementById('email').value,
                dob: document.getElementById('dob').value,
                gender: document.querySelector('input[name="gender"]:checked').value,
                gpsAddress: document.getElementById('riders_gpsAddress').value,
                employmentStatus: document.getElementById('employmentStatus').value,
                nationality: document.getElementById('nationality').value,
                homeTown: document.getElementById('home_town').value,
                phoneNumber: document.getElementById('phone_number').value,
                address: document.getElementById('address').value,
                stationId: document.getElementById('station_id').value
            };

            // Handle image files - convert to base64
            const promises = [];

            // Function to convert file to base64
            const fileToBase64 = (file) => {
                return new Promise((resolve, reject) => {
                    const reader = new FileReader();
                    reader.readAsDataURL(file);
                    reader.onload = () => resolve(reader.result);
                    reader.onerror = error => reject(error);
                });
            };

            // Add riders image
            const ridersImage = document.getElementById('ridersImage').files[0];
            if (ridersImage) {
                promises.push(
                    fileToBase64(ridersImage).then(base64 => {
                        data.ridersImagePreview = base64;
                    })
                );
            }

            // Add ID card images
            const idCardImage = document.getElementById('id_card_image').files[0];
            if (idCardImage) {
                promises.push(
                    fileToBase64(idCardImage).then(base64 => {
                        data.idCardImagePreview = base64;
                    })
                );
            }

            const idCardBackImage = document.getElementById('id_card_back_image').files[0];
            if (idCardBackImage) {
                promises.push(
                    fileToBase64(idCardBackImage).then(base64 => {
                        data.idCardBackImagePreview = base64;
                    })
                );
            }

            // License information
            data.isRiderHavingLicense = document.getElementById('isRiderHavingLicense').value;
            if (data.isRiderHavingLicense === 'Yes') {
                data.licenseNumber = document.getElementById('license_number').value;
                data.licenseExpiryDate = document.getElementById('license_expiry_date').value;

                const licenseImage = document.getElementById('license_image').files[0];
                if (licenseImage) {
                    promises.push(
                        fileToBase64(licenseImage).then(base64 => {
                            data.licenseImagePreview = base64;
                        })
                    );
                }

                const licenseBackImage = document.getElementById('license_back_image').files[0];
                if (licenseBackImage) {
                    promises.push(
                        fileToBase64(licenseBackImage).then(base64 => {
                            data.licenseBackImagePreview = base64;
                        })
                    );
                }
            }

            // Experience information
            data.yearsAsRider = document.querySelector('input[name="years_as_rider"]:checked').value;
            data.ownMotorbike = document.querySelector('input[name="own_motorbike"]:checked').value;
            data.workingForPay = document.querySelector('input[name="working_for_pay"]:checked').value;
            data.businessModel = document.getElementById('business_model').value;
            data.shareBike = document.querySelector('input[name="share_bike"]:checked').value;

            // Wait for all file conversions to complete
            Promise.all(promises)
                .then(() => {
                    // Send the data using fetch
                    return fetch('../API/save_rider_data.php', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(data)
                    });
                })
                .then(response => response.json())
                .then(data => {
                    console.log('Response data:', data);
                    if (data.status === 'success') {
                        Swal.fire({
                            icon: 'success',
                            title: 'Success!',
                            text: 'Rider information saved successfully!',
                            timer: 1500
                        }).then(() => {
                            window.location.href = 'riders_list.php';
                        });
                    } else {
                        throw new Error(data.message || 'Failed to save rider information');
                    }
                })
                .catch(error => {
                    console.error('Error:', error);
                    Swal.fire({
                        icon: 'error',
                        title: 'Error',
                        text: error.message
                    });
                    document.querySelector('#submit-form').disabled = false;
                    document.querySelector('#submit-form').innerHTML = 'Submit';
                });
        }


<?php
header('Content-Type: application/json');

// Include database connection
require 'connection.php';

// Start transaction
mysqli_begin_transaction($conn);

try {
    // Function to handle file upload
    function uploadFile($base64String, $uploadPath)
    {
        if (strpos($base64String, 'data:image') === 0) {
            $base64Image = explode(',', $base64String)[1];
            $imageData = base64_decode($base64Image);
            $fileName = uniqid() . '.jpg';
            $filePath = $uploadPath . $fileName;

            if (file_put_contents($filePath, $imageData)) {
                return $fileName;
            }
        }
        return null;
    }

    // Validate required fields
    $requiredFields = ['firstname', 'surname', 'email', 'dob', 'nationality', 'employment_status', 'phone_number'];
    $data = json_decode(file_get_contents('php://input'), true);

    foreach ($requiredFields as $field) {
        if (empty($data[$field])) {
            throw new Exception("Required field $field is missing");
        }
    }

    // Generate unique registration number
    $registrationNumber = 'RDR' . date('Y') . sprintf('%06d', rand(1, 999999));

    // Insert into Riders table
    $stmt = $conn->prepare("INSERT INTO Riders (
        registration_number, first_name, surname, home_town, nationality,
        employment_status, dob, gender, email, phone_number, gps_address,
        address, station_id, user_id
    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

    $stmt->bind_param(
        "ssssssssssssii",
        $registrationNumber,
        $data['firstname'],
        $data['surname'],
        $data['homeTown'],
        $data['nationality'],
        $data['employmentStatus'],
        $data['dob'],
        $data['gender'],
        $data['email'],
        $data['phoneNumber'],
        $data['gpsAddress'],
        $data['address'],
        $data['stationId'],
        $data['userId']
    );

    $stmt->execute();
    $riderId = $stmt->insert_id;

    // Upload and save passport picture
    if (!empty($data['ridersImagePreview'])) {
        $passportPicture = uploadFile($data['ridersImagePreview'], '../uploads/passport_pictures/');
        if ($passportPicture) {
            $stmt = $conn->prepare("INSERT INTO PassportPictures (rider_id, passport_picture) VALUES (?, ?)");
            $stmt->bind_param("is", $riderId, $passportPicture);
            $stmt->execute();
        }
    }

    // Insert ID Card information
    if (!empty($data['idCardType'])) {
        $idCardFront = uploadFile($data['idCardImagePreview'], '../uploads/id_cards/');
        $idCardBack = uploadFile($data['idCardBackImagePreview'], '../uploads/id_cards/');

        $stmt = $conn->prepare("INSERT INTO IDCards (
            rider_id, id_card_type, id_card_number, id_card_expiry,
            id_card_front_image, id_card_back_image
        ) VALUES (?, ?, ?, ?, ?, ?)");

        $stmt->bind_param(
            "isssss",
            $riderId,
            $data['idCardType'],
            $data['idCardNumber'],
            $data['idCardExpiry'],
            $idCardFront,
            $idCardBack
        );
        $stmt->execute();
    }

    // Insert License information
    $hasLicense = $data['isRiderHavingLicense'] === 'Yes';
    if ($hasLicense) {
        $licenseFront = uploadFile($data['licenseImagePreview'], '../uploads/licenses/');
        $licenseBack = uploadFile($data['licenseBackImagePreview'], '../uploads/licenses/');

        $stmt = $conn->prepare("INSERT INTO Licenses (
            rider_id, license_number, license_expiry_date, has_license,
            license_front_image, license_back_image
        ) VALUES (?, ?, ?, ?, ?, ?)");

        $stmt->bind_param(
            "ississ",
            $riderId,
            $data['licenseNumber'],
            $data['licenseExpiryDate'],
            $hasLicense,
            $licenseFront,
            $licenseBack
        );
        $stmt->execute();
    }

    // Insert Rider Experience
    $stmt = $conn->prepare("INSERT INTO RiderExperience (
        rider_id, years_as_rider, owns_motorbike, works_for_pay, shares_bike
    ) VALUES (?, ?, ?, ?, ?)");

    $stmt->bind_param(
        "issss",
        $riderId,
        $data['yearsAsRider'],
        $data['ownMotorbike'],
        $data['workingForPay'],
        $data['shareBike']
    );
    $stmt->execute();

    // Commit transaction
    mysqli_commit($conn);

    echo json_encode([
        'status' => 'success',
        'message' => 'Rider information saved successfully',
        'rider_id' => $riderId,
        'registration_number' => $registrationNumber
    ]);
} catch (Exception $e) {
    // Rollback transaction on error
    mysqli_rollback($conn);
    echo json_encode([
        'status' => 'error',
        'message' => $e->getMessage()
    ]);
}

// Close database connection
mysqli_close($conn);