the clo performance data table is showing whether the clo has been achieved or not, but the problem is when i click the ok button it just doesn’t insert any data to the sql table and shows “No CLO data received” even though the data is shown.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<title>CLO Analysis Report</title>
<style>
body {
font-family: Arial, sans-serif;
}
.container {
margin-top: 20px;
}
table {
width: 100%;
margin-top: 20px;
}
th, td {
text-align: center;
vertical-align: middle;
}
.table-section {
margin-top: 40px;
}
</style>
</head>
<body>
<div class="container">
<h2 class="text-center">CLO Analysis Report</h2>
<div class="card mt-3">
<div class="card-body">
<h4>Course Details</h4>
<p><strong>Course Code:</strong> <span id="courseCode"></span></p>
<p><strong>Course Name:</strong> <span id="courseName"></span></p>
<p><strong>Programme:</strong> <span id="programme"></span></p>
<p><strong>Lecturer Name:</strong> <span id="lecturerName"></span></p>
<p><strong>Semester:</strong> <span id="semester"></span></p>
<p><strong>Total Students:</strong> <span id="totalStudents"></span></p>
</div>
</div>
<!-- CLO Benchmark Table -->
<div id="clo-benchmark-section" class="table-section">
<h3>% of Students Achieving the Benchmark for Each CLO</h3>
<table class="table table-bordered" id="clo-benchmark-table">
<thead>
<tr>
<th>Learning Outcome</th>
<th>Benchmark</th>
<th>% Achieved</th>
<th>Remark</th>
</tr>
</thead>
<tbody>
<!-- CLO Benchmark Rows will be dynamically added here -->
</tbody>
</table>
</div>
<!-- LO Benchmark Table -->
<div id="lo-benchmark-section" class="table-section">
<h3>% of Students Achieving the Total Learning Outcomes</h3>
<table class="table table-bordered" id="lo-benchmark-table">
<thead>
<tr>
<th>Total LOs</th>
<th>Number of Students Achieved</th>
<th>% Achieved</th>
</tr>
</thead>
<tbody>
<!-- LO Benchmark Rows will be dynamically added here -->
</tbody>
</table>
</div>
<!-- SQL Table -->
<div class="table-section">
<h3>CLO Performance Data</h3>
<form id="submitCLOForm" action="store_clo_data.php" method="POST">
<input type="hidden" name="course_code" id="hiddenCourseCode">
<input type="hidden" name="course_name" id="hiddenCourseName">
<input type="hidden" name="programme" id="hiddenProgramme">
<input type="hidden" name="lecturer_name" id="hiddenLecturerName">
<input type="hidden" name="semester" id="hiddenSemester">
<table class="table table-bordered">
<thead>
<tr>
<th>Student Name</th>
<th>Student ID</th>
<th>CLO1</th>
<th>CLO2</th>
<th>CLO3</th>
<th>CLO4</th>
<th>CLO5</th>
<th>CLO6</th>
<th>Total CLO</th>
<th>U</th>
<th>P</th>
</tr>
</thead>
<tbody id="cloDataTable">
<!-- Rows dynamically added -->
</tbody>
</table>
<button type="submit" class="btn btn-primary btn-submit" id="okButton">OK</button>
</form>
</div>
</div>
<script>
let studentData;
document.addEventListener("DOMContentLoaded", function () {
studentData = JSON.parse(localStorage.getItem("studentData"));
console.log("Student Data:", studentData);
const moduleData = JSON.parse(localStorage.getItem("moduleData"));
if (!studentData || studentData.length === 0) {
console.error("No student data found in localStorage.");
return;
}
if (!studentData || studentData.length === 0 || !moduleData || !moduleData.courseworkRows) {
alert("Missing data! Please return to the main or student page to input the required data.");
return;
}
// Populate Course Details
document.getElementById("courseCode").textContent = moduleData.courseCode;
document.getElementById("courseName").textContent = moduleData.courseName;
document.getElementById("programme").textContent = moduleData.programme;
document.getElementById("lecturerName").textContent = moduleData.lecturerName;
document.getElementById("semester").textContent = moduleData.semester;
document.getElementById("totalStudents").textContent = moduleData.totalStudents;
// Populate hidden inputs
document.getElementById("hiddenCourseCode").value = moduleData.courseCode || "";
document.getElementById("hiddenCourseName").value = moduleData.courseName || "";
document.getElementById("hiddenProgramme").value = moduleData.programme || "";
document.getElementById("hiddenLecturerName").value = moduleData.lecturerName || "";
document.getElementById("hiddenSemester").value = moduleData.semester || "";
console.log("Raw Coursework Weight:", moduleData.courseworkWeight);
console.log("Raw Exam Weight:", moduleData.examWeight);
const courseworkWeight = parseFloat(moduleData.courseworkWeight || "0") / 100;
const examWeight = parseFloat(moduleData.examWeight || "0") / 100;
const totalCLOs = 6; // Fixed number of CLOs (CLO1 to CLO6)
if (courseworkWeight === 0 || examWeight === 0) {
console.error("Weights are zero or missing. Check moduleData:", moduleData);
alert("Error: Coursework or exam weights are missing or invalid. Please check your inputs.");
return;
}
console.log("Student Data:", studentData);
console.log("Module Data:", moduleData);
console.log("Coursework Weight:", courseworkWeight);
console.log("Exam Weight:", examWeight);
const cloBenchmarks = calculateCLOBenchmarks(studentData, moduleData, courseworkWeight, examWeight, totalCLOs);
const loBenchmarks = calculateLOBenchmarks(studentData, totalCLOs);
console.log("CLO Benchmarks:", cloBenchmarks);
console.log("LO Benchmarks:", loBenchmarks);
populateCLOBenchmarkTable(cloBenchmarks, studentData.length);
populateLOBenchmarkTable(loBenchmarks, studentData.length);
populateCLODataTable(studentData, totalCLOs);
});
function calculateCLOBenchmarks(studentData, moduleData, courseworkWeight, examWeight, totalCLOs) {
const cloBenchmarks = Array(totalCLOs).fill(0).map(() => ({ total: 0, achieved: 0 }));
studentData.forEach(student => {
console.log("Processing student:", student);
// Process Coursework
student.coursework.forEach((score, index) => {
const cwRow = moduleData.courseworkRows[index];
if (cwRow && cwRow.clos) { // Ensure cwRow and cwRow.clos exist
cwRow.clos.forEach(clo => {
const cloIndex = parseInt(clo.lo.replace("LO", "")) - 1;
const weightedScore = (score * courseworkWeight * clo.percent) / 100;
cloBenchmarks[cloIndex].total += weightedScore;
});
}
});
// Process Final Exam
student.finalExam.forEach((score, index) => {
const feRow = moduleData.finalExamRows[index];
if (feRow && feRow.clos) { // Ensure feRow and feRow.clos exist
feRow.clos.forEach(clo => {
const cloIndex = parseInt(clo.lo.replace("LO", "")) - 1;
const weightedScore = (score * examWeight * clo.percent) / 100;
cloBenchmarks[cloIndex].total += weightedScore;
});
}
});
// Check if benchmarks are achieved for each CLO
cloBenchmarks.forEach((clo, index) => {
const totalScore = student.coursework[index] + student.finalExam[index];
console.log(`CLO${index + 1} - Total Score for Student:`, totalScore);
if (totalScore >= 50) {
clo.achieved++;
console.log(`CLO${index + 1} - Benchmark Achieved`);
}
});
});
return cloBenchmarks;
}
function calculateLOBenchmarks(studentData, totalCLOs) {
const loBenchmarks = Array(totalCLOs).fill(0);
studentData.forEach(student => {
const totalLOScores = Array(totalCLOs).fill(0);
student.coursework.forEach(score => {
totalLOScores[0] += score;
});
student.finalExam.forEach(score => {
totalLOScores[1] += score;
});
console.log("Total LO Scores for Student:", totalLOScores);
const achievedLOCount = totalLOScores.filter(score => score >= 50).length;
loBenchmarks[achievedLOCount - 1]++;
console.log("Achieved LO Count for Student:", achievedLOCount);
});
return loBenchmarks;
}
function populateCLOBenchmarkTable(cloBenchmarks, totalStudents) {
const cloBenchmarkTable = document.getElementById("clo-benchmark-table").querySelector("tbody");
cloBenchmarks.forEach((clo, index) => {
const percentAchieved = clo.total ? ((clo.achieved / totalStudents) * 100).toFixed(2) : 0;
const remark = percentAchieved >= 50 ? "Achieved" : "Review Needed";
cloBenchmarkTable.innerHTML += `
<tr>
<td>CLO${index + 1}</td>
<td>${(clo.total / totalStudents).toFixed(2)}</td>
<td>${percentAchieved}%</td>
<td>${remark}</td>
</tr>
`;
});
}
function populateLOBenchmarkTable(loBenchmarks, totalStudents) {
const loBenchmarkTable = document.getElementById("lo-benchmark-table").querySelector("tbody");
loBenchmarks.forEach((count, index) => {
const percentAchieved = ((count / totalStudents) * 100).toFixed(2);
loBenchmarkTable.innerHTML += `
<tr>
<td>${index + 1} LOs</td>
<td>${count}</td>
<td>${percentAchieved}%</td>
</tr>
`;
});
loBenchmarkTable.innerHTML += `
<tr class="table-primary">
<td>Total</td>
<td>${totalStudents}</td>
<td>100%</td>
</tr>
`;
}
function populateCLODataTable(studentData, totalCLOs) {
const tableBody = document.getElementById("cloDataTable");
studentData.forEach((student, idx) => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${student.name || `Student ${idx + 1}`}</td>
<td><input type="text" name="student_ids[]" class="form-control" placeholder="Enter ID"></td>
`;
for (let i = 0; i < totalCLOs; i++) {
row.innerHTML += `<td>${i < student.coursework.length && student.coursework[i] >= 50 ? "Achieved" : "No"}</td>`;
}
tableBody.appendChild(row);
});
}
// Populate CLO Performance Table
const cloTable = document.getElementById("cloDataTable");
studentData.forEach((student, index) => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${student.name || `Student ${index + 1}`}</td>
<td><input type="text" name="student_ids[]" class="form-control" required placeholder="Enter ID"></td>
<td>${student.coursework[0] >= 50 ? "Achieved" : "No"}</td>
<td>${student.coursework[1] ? (student.coursework[1] >= 50 ? "Achieved" : "No") : "NA"}</td>
<td>${student.finalExam[0] >= 50 ? "Achieved" : "No"}</td>
<td>${student.finalExam[1] ? (student.finalExam[1] >= 50 ? "Achieved" : "No") : "NA"}</td>
<td>NA</td>
<td>NA</td>
<td>${student.coursework.filter(m => m >= 50).length + student.finalExam.filter(m => m >= 50).length}</td>
<td>${student.coursework[0] >= 50 || student.finalExam[0] >= 50 ? "Achieved" : "No"}</td>
<td>${student.coursework[1] >= 50 || student.finalExam[1] >= 50 ? "Achieved" : "No"}</td>
`;
cloTable.appendChild(row);
});
document.getElementById("okButton").addEventListener("click", function () {
const tableRows = document.querySelectorAll("#cloDataTable tr");
const cloData = [];
tableRows.forEach(row => {
// Extract Student ID
const studentId = row.querySelector("input[name='student_ids[]']")?.value.trim() || "";
// Extract CLO1-CLO6 (columns 3 to 8)
const cloCells = Array.from(row.querySelectorAll("td")).slice(2, 8); // CLO1=td[2], CLO6=td[7]
const cloResults = cloCells.map(cell => cell.textContent.trim());
// Extract Total CLO (column 9)
const totalClo = row.cells[8]?.textContent.trim() || "0";
cloData.push({
student_id: studentId,
clo1: cloResults[0] || "No",
clo2: cloResults[1] || "No",
clo3: cloResults[2] || "No",
clo4: cloResults[3] || "No",
clo5: cloResults[4] || "No",
clo6: cloResults[5] || "No",
total_clo: totalClo
});
});
// Append CLO data to the form
const form = document.getElementById("submitCLOForm");
const cloDataField = document.createElement("input");
cloDataField.type = "hidden";
cloDataField.name = "clo_data";
cloDataField.value = JSON.stringify(cloData);
form.appendChild(cloDataField);
form.submit();
});
// Function to create hidden input fields
function createHiddenField(name, value) {
const input = document.createElement("input");
input.type = "hidden";
input.name = name;
input.value = value;
return input;
}
</script>
</body>
</html>
the php code to insert the data
<?php
include 'db.php';
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$courseCode = $_POST['course_code'] ?? 'N/A';
$courseName = $_POST['course_name'] ?? 'N/A';
$programme = $_POST['programme'] ?? 'N/A';
$lecturerName = $_POST['lecturer_name'] ?? 'N/A';
$semester = $_POST['semester'] ?? 'N/A';
// Decode CLO data
$cloData = isset($_POST['clo_data']) ? json_decode($_POST['clo_data'], true) : [];
if (json_last_error() !== JSON_ERROR_NONE) {
die("Invalid CLO data: " . json_last_error_msg());
}
if (empty($cloData)) {
die("No CLO data received.");
}
// Prepare SQL
$stmt = $conn->prepare(
"INSERT INTO clo_performance
(student_id, course_code, course_name, programme, lecturer_name, semester, clo1, clo2, clo3, clo4, clo5, clo6, total_clo)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
foreach ($cloData as $entry) {
$stmt->bind_param(
"sssssssssssss",
$entry['student_id'],
$courseCode,
$courseName,
$programme,
$lecturerName,
$semester,
$entry['clo1'],
$entry['clo2'],
$entry['clo3'],
$entry['clo4'],
$entry['clo5'],
$entry['clo6'],
$entry['total_clo']
);
$stmt->execute();
}
$stmt->close();
echo "Data stored successfully!";
} else {
echo "Invalid request method.";
}
$conn->close();
?>
sql table
CREATE TABLE clo_performance (
id INT AUTO_INCREMENT PRIMARY KEY,
student_id VARCHAR(50) NOT NULL,
course_code VARCHAR(50) NOT NULL,
course_name VARCHAR(255) NOT NULL,
programme VARCHAR(50) NOT NULL,
lecturer_name VARCHAR(255) NOT NULL,
semester VARCHAR(50) NOT NULL,
clo1 VARCHAR(20),
clo2 VARCHAR(20),
clo3 VARCHAR(20),
clo4 VARCHAR(20),
clo5 VARCHAR(20),
clo6 VARCHAR(20),
total_clo INT,
domain_u VARCHAR(20),
domain_p VARCHAR(20)
);
i expected it to insert data into the sql table and all i got is “No CLO data received” and no data was inserted.
