Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions course-selection.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Select Courses</title>
<link rel="stylesheet" href="styles.css"> <!-- Include your CSS file -->
</head>
<body>
<header>
<h1>Select Your Courses</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/dashboard">Dashboard</a></li>
<!-- Add more navigation links as needed -->
</ul>
</nav>
</header>
<main>
<form id="course-selection-form">
<div class="courses">
<label><input type="checkbox" name="courses" value="Math"> Math</label>
<label><input type="checkbox" name="courses" value="Science"> Science</label>
<label><input type="checkbox" name="courses" value="History"> History</label>
<label><input type="checkbox" name="courses" value="Art"> Art</label>
</div>
<button type="submit">Save Selection</button>
</form>
</main>
<footer>
<p>&copy; 2024 Your LMS</p>
</footer>
<script src="script.js"></script> <!-- Include your JavaScript file -->
</body>
</html>
50 changes: 50 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,54 @@
// scripts.js

document.addEventListener('DOMContentLoaded', () => {
// Existing form event listeners...

// Event listener for course selection form
const courseSelectionForm = document.getElementById('course-selection-form');
if (courseSelectionForm) {
courseSelectionForm.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(courseSelectionForm);
const courses = [];
formData.forEach((value, key) => {
if (key === 'courses') courses.push(value);
});
try {
const response = await fetch('/select-courses', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ courses })
});
if (response.ok) {
alert('Course selection saved successfully');
} else {
alert('Failed to save course selection');
}
} catch (error) {
console.error('Error:', error);
}
});
}

// Fetch and display selected courses for the user
const coursesList = document.getElementById('courses-list');
if (coursesList) {
fetch('/get-selected-courses')
.then(response => response.json())
.then(data => {
data.courses.forEach(course => {
const li = document.createElement('li');
li.textContent = course;
coursesList.appendChild(li);
});
});
}

// Existing functionality for course content, leaderboard, and fetching user full name...
});

document.addEventListener('DOMContentLoaded', () => {
const registerForm = document.getElementById('register-form');
const loginForm = document.getElementById('login-form');
Expand Down
174 changes: 118 additions & 56 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// server.js
const express = require('express');
const session = require('express-session');
const bcrypt = require('bcryptjs');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const mysql = require('mysql2');
const { check, validationResult } = require('express-validator');

const app = express();

// Configure session middleware
Expand All @@ -18,7 +18,7 @@ app.use(session({
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
password: 'lex',
database: 'learning_management'
});

Expand All @@ -45,14 +45,12 @@ app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});



// Define a User representation for clarity
const User = {
tableName: 'users',
tableName: 'users',
createUser: function(newUser, callback) {
connection.query('INSERT INTO ' + this.tableName + ' SET ?', newUser, callback);
},
},
getUserByEmail: function(email, callback) {
connection.query('SELECT * FROM ' + this.tableName + ' WHERE email = ?', email, callback);
},
Expand All @@ -61,77 +59,86 @@ const User = {
}
};

// Define a Course representation for clarity
const Course = {
tableName: 'courses',
getAllCourses: function(callback) {
connection.query('SELECT * FROM ' + this.tableName, callback);
}
};

// Registration route
app.post('/register', [
// Validate email and username fields
check('email').isEmail(),
check('username').isAlphanumeric().withMessage('Username must be alphanumeric'),

// Custom validation to check if email and username are unique
check('email').custom(async (value) => {
const user = await User.getUserByEmail(value);
if (user) {
throw new Error('Email already exists');
}
check('email').custom((value, { req }) => {
return new Promise((resolve, reject) => {
User.getUserByEmail(value, (err, user) => {
if (err) throw err;
if (user.length > 0) {
reject(new Error('Email already exists'));
} else {
resolve(true);
}
});
});
}),
check('username').custom(async (value) => {
const user = await User.getUserByUsername(value);
if (user) {
throw new Error('Username already exists');
}
check('username').custom((value, { req }) => {
return new Promise((resolve, reject) => {
User.getUserByUsername(value, (err, user) => {
if (err) throw err;
if (user.length > 0) {
reject(new Error('Username already exists'));
} else {
resolve(true);
}
});
});
}),
], async (req, res) => {
// Check for validation errors
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}

// Hash the password
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(req.body.password, saltRounds);

// Create a new user object
const newUser = {
email: req.body.email,
username: req.body.username,
password: hashedPassword,
full_name: req.body.full_name
};

// Insert user into MySQL
User.createUser(newUser, (error, results, fields) => {
if (error) {
console.error('Error inserting user: ' + error.message);
return res.status(500).json({ error: error.message });
console.error('Error inserting user: ' + error.message);
return res.status(500).json({ error: error.message });
}
console.log('Inserted a new user with id ' + results.insertId);
res.status(201).json(newUser);
});
});
});

// Login route
app.post('/login', (req, res) => {
const { username, password } = req.body;
// Retrieve user from database
connection.query('SELECT * FROM users WHERE username = ?', [username], (err, results) => {
User.getUserByUsername(username, (err, results) => {
if (err) throw err;
if (results.length === 0) {
res.status(401).send('Invalid username or password');
} else {
const user = results[0];
// Compare passwords
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
// Store user in session
req.session.user = user;
res.send('Login successful');
} else {
res.status(401).send('Invalid username or password');
}
});
return res.status(401).send('Invalid username or password');
}
const user = results[0];
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
req.session.user = user;
res.send('Login successful');
} else {
res.status(401).send('Invalid username or password');
}
});
});
});

Expand All @@ -141,28 +148,83 @@ app.post('/logout', (req, res) => {
res.send('Logout successful');
});

//Dashboard route
app.get('/dashboard', (req, res) => {
// Assuming you have middleware to handle user authentication and store user information in req.user
const userFullName = req.user.full_name;
res.render('dashboard', { fullName: userFullName });
// Route to fetch user full name for dashboard
app.get('/get-fullname', (req, res) => {
if (req.session.user) {
res.json({ fullName: req.session.user.full_name });
} else {
res.status(401).send('Unauthorized');
}
});

// Route to save selected courses for a user
app.post('/select-courses', (req, res) => {
const userId = req.session.user.id;
const courses = req.body.courses;

const sql = 'INSERT INTO user_courses (user_id, course_id) VALUES ?';
const values = courses.map(courseId => [userId, courseId]);
connection.query(sql, [values], (err, result) => {
if (err) {
console.error('Error inserting selected courses:', err);
return res.status(500).send('Error saving course selection');
}
res.send('Course selection saved successfully');
});
});

// Route to fetch selected courses for a user
app.get('/get-selected-courses', (req, res) => {
const userId = req.session.user.id;
const sql = `
SELECT c.name
FROM user_courses uc
JOIN courses c ON uc.course_id = c.id
WHERE uc.user_id = ?
`;
connection.query(sql, [userId], (err, results) => {
if (err) {
console.error('Error fetching selected courses:', err);
return res.status(500).send('Error fetching selected courses');
}
const courses = results.map(row => row.name);
res.json({ courses });
});
});

// Route to retrieve course content
app.get('/course/:id', (req, res) => {
const courseId = req.params.id;
const sql = 'SELECT * FROM courses WHERE id = ?';
db.query(sql, [courseId], (err, result) => {
if (err) {
throw err;
}
// Send course content as JSON response
res.json(result);
connection.query(sql, [courseId], (err, result) => {
if (err) {
throw err;
}
res.json(result);
});
});
});

// Route to fetch leaderboard data
app.get('/leaderboard', (req, res) => {
const sql = `
SELECT u.username AS name, SUM(score) AS score
FROM user_courses uc
JOIN users u ON uc.user_id = u.id
GROUP BY u.id
ORDER BY score DESC
LIMIT 10
`;
connection.query(sql, (err, results) => {
if (err) {
console.error('Error fetching leaderboard data:', err);
return res.status(500).send('Error fetching leaderboard data');
}
res.json(results);
});
});

// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
});