diff --git a/README.md b/README.md deleted file mode 100644 index b38dbd20..00000000 --- a/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# Learning Managment System - -## Step 1: Project Setup - -### Create a new directory for your project and navigate into it. -```bash -mkdir learning-management-app -cd learning-management-app -``` -### Initialize a new Node.js project. -```bash -npm init -y -``` -### Install necessary dependencies. -```bash -npm install express mysql ejs bcryptjs express-session express-validator -``` - -## Step 2: Set up the Backend - -### Create a `server.js` file in your project directory. - -### Create a MySQL database named `learning_management` - -#### Create users table -```bash --- Create users table -CREATE TABLE users ( - id INT AUTO_INCREMENT PRIMARY KEY, - username VARCHAR(255) UNIQUE, - password VARCHAR(255), - email VARCHAR(255) UNIQUE, - full_name VARCHAR(255) -); -``` - -#### Create courses table -```bash --- Create courses table -CREATE TABLE courses ( - id INT AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(255) -); - --- Insert sample data into courses table -INSERT INTO courses (name) VALUES -('Introduction to HTML'), -('CSS Fundamentals'), -('JavaScript Basics'); -``` - -#### Create leaderboard table -```bash --- Create leaderboard table -CREATE TABLE leaderboard ( - id INT AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(255), - score INT -); - --- Insert sample data into leaderboard table -INSERT INTO leaderboard (name, score) VALUES -('John Doe', 100), -('Jane Smith', 90), -('Michael Brown', 85), -('Emily Jones', 80); -``` - -### Run the server. -```bash -node server.js -``` - -## Step 3: Frontend Setup - -### Create an `index.html` file for the frontend. - -### Create a `course-content.html` file for the course content. - -### Create a `leader-board.html` file for the leader board. - -### Create a `style.css` file to style your HTML. - -### Create a `script.js` file to handle frontend interactions. - -## Step 4: Testing -Open your web browser and navigate to http://localhost:3000. - -# Hackathon Instructions -Finish up the project by: -1. creating functionality for the logged in user to select their preferred courses. -2. store the selection in the database -3. create a page where the selected courses for each specific logged in user is displayed. - -## Submission Guidelines -Fork this repository and clone it to your local machine. -Create a new branch with your GitHub username (git checkout -b username). -Complete the tasks. -Commit your changes and push them to your forked repository. -Submit a pull request to the main repository for review. - -Happy hacking! 🚀 diff --git a/course-content.html b/course-content.html deleted file mode 100644 index d9b262e7..00000000 --- a/course-content.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - Course Content - - - -
-

Course Name

- -
-
- -
- - - - - - diff --git a/coursecontent.html b/coursecontent.html new file mode 100644 index 00000000..17e3d5db --- /dev/null +++ b/coursecontent.html @@ -0,0 +1,64 @@ + + + + + + Course Content - My Website + + + + + + + + +
+

Software Design

+

This course covers the principles and practices of software design, including design patterns, object-oriented design, and software architecture.

+ + +
+

Enroll in this Course

+
+ +
+ + +
+ + +
+
+ + +
+

Course Materials

+
+

Module 1: Introduction to Software Design

+

In this module, you will learn about the basics of software design, including the importance of design patterns and software architecture.

+ Introduction to Software Design +
+ +
+

Module 2: Object-Oriented Design

+

This module covers object-oriented design principles, such as encapsulation, inheritance, and polymorphism.

+ Object-Oriented Design +
+ +
+

Module 3: Design Patterns

+

Learn about various design patterns, including Singleton, Factory, and Observer patterns, and how to implement them.

+ Design Patterns +
+ + +
+
+ + + \ No newline at end of file diff --git a/dashboard.html b/dashboard.html index ba3eb99e..73502eb2 100644 --- a/dashboard.html +++ b/dashboard.html @@ -3,31 +3,39 @@ - Dashboard - + Dashboard - Learning management system + -
-

Welcome to Your Dashboard

- -
-
-
-

Hello, !

-

Welcome to your personalized dashboard.

-
-
- - - + + + + +
+
+

Welcome, [Username]

+

Email: [user@example.com]

+
+ +
+
+ +
+

Current Courses

+
+

Software Design

+

This course covers the principles and practices of software design, including design patterns, object-oriented design, and software architecture.

+ +
+ +
+
+ - + \ No newline at end of file diff --git a/index.html b/index.html index 1e0080d9..3ac6e30e 100644 --- a/index.html +++ b/index.html @@ -3,28 +3,62 @@ - Learning Management App - + Learning management system + -

Learning Management App

-
+ + + + +
+

Software Design Course

+

This course covers the principles and practices of software design, including design patterns, object-oriented design, and software architecture.

+
+ + +

Register

- - - - - - -
+ + +
+ + +
+ + +
+ + +
+
+ + +

Login

- - - - -
- -
- +
+ +
+ + +
+ + +
+
+ + +
+

Logout

+
+ +
+
+ - + \ No newline at end of file diff --git a/leader-board.html b/leader-board.html deleted file mode 100644 index 3cddc3ee..00000000 --- a/leader-board.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - Leaderboard - - - -
-

Leaderboard

- -
-
- -
- - - - - - diff --git a/leaderboard.html b/leaderboard.html new file mode 100644 index 00000000..56ebcf28 --- /dev/null +++ b/leaderboard.html @@ -0,0 +1,85 @@ + + + + + + Leader Board - My Website + + + + + + + + +
+

Leader Board

+ + +
+

Organizations

+ + + + + + + + + + + + + + + + + + + + + + +
OrganizationPoints
Organization A1500
Organization B1400
Organization C1300
+
+ + +
+

Teachers

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
TeacherModulePoints
John DoeSoftware Design950
Jane SmithDatabase Systems900
Emily JohnsonWeb Development870
+
+
+ + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..7bbaaddd --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "glms", + "version": "1.0.0", + "description": "", + "main": "script.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/script.js b/script.js index 7293d9e6..87d47888 100644 --- a/script.js +++ b/script.js @@ -1,207 +1,23 @@ -// scripts.js -document.addEventListener('DOMContentLoaded', () => { - const registerForm = document.getElementById('register-form'); - const loginForm = document.getElementById('login-form'); - const logoutForm = document.getElementById('logout-form'); - - registerForm.addEventListener('submit', async (e) => { - e.preventDefault(); - const formData = new FormData(registerForm); - const username = formData.get('username'); - const password = formData.get('password'); - const email = formData.get('email'); - const full_name = formData.get('full_name'); - try { - const response = await fetch('/register', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ username, password, email, full_name }) - }); - if (response.ok) { - alert('Registration successful'); - } else { - alert('Registration failed'); - } - } catch (error) { - console.error('Error:', error); - } - }); - - loginForm.addEventListener('submit', async (e) => { - e.preventDefault(); - const formData = new FormData(loginForm); - const username = formData.get('username'); - const password = formData.get('password'); - try { - const response = await fetch('/login', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ username, password }) - }); - if (response.ok) { - alert('Login successful'); - } else { - alert('Invalid username or password'); - } - } catch (error) { - console.error('Error:', error); - } - }); - - logoutForm.addEventListener('submit', async (e) => { - e.preventDefault(); - try { - const response = await fetch('/logout', { - method: 'POST' - }); - if (response.ok) { - alert('Logout successful'); - } else { - alert('Logout failed'); - } - } catch (error) { - console.error('Error:', error); - } - }); - - // Check if the current page is the course content page - if (window.location.pathname === '/course-content') { - // Call the fetchCourseContent function - fetchCourseContent(); - } - - // Check if the current page is the course content page - if (window.location.pathname === '/leader-board') { - // Fetch course content from server - fetchLeaderboardData(); - } - - // Check if the current page is the course content page - if (window.location.pathname === '/dashboard') { - //fetch Logged in user's full name - fetchFullName(); - } -}); - -function fetchCourseContent() { - // Get course ID from URL parameter (assuming course ID is passed in the URL) - const urlParams = new URLSearchParams(window.location.search); - const courseId = urlParams.get('id'); - - // Make AJAX request to fetch course content from server - fetch(`/course/${courseId}`) - .then(response => { - if (!response.ok) { - throw new Error('Network response was not ok'); - } - return response.json(); - }) +document.addEventListener("DOMContentLoaded", () => { + const userId = 1; // Example user ID + + fetch(`/api/user/courses?userId=${userId}`) + .then(response => response.json()) .then(data => { - // Display course content on the page - displayCourseContent(data); - }) - .catch(error => { - console.error('Error fetching course content:', error); - }); -} - -function displayCourseContent(courseContent) { - // Get the course name element - const courseNameElement = document.getElementById('course-name'); - // Set the course name - courseNameElement.textContent = courseContent.name; - - // Get the course content element - const courseContentElement = document.getElementById('course-content'); - // Clear previous content - courseContentElement.innerHTML = ''; - - // Loop through the modules and display them - courseContent.modules.forEach(module => { - const moduleSection = document.createElement('section'); - moduleSection.innerHTML = ` -

${module.title}

-

${module.description}

- - `; - courseContentElement.appendChild(moduleSection); - }); -} - -function fetchLeaderboardData() { - // Make AJAX request to fetch leaderboard data from server - fetch('/leaderboard') - .then(response => { - if (!response.ok) { - throw new Error('Network response was not ok'); - } - return response.json(); - }) - .then(data => { - // Display leaderboard data on the page - displayLeaderboardData(data); - }) - .catch(error => { - console.error('Error fetching leaderboard data:', error); - }); -} - -function displayLeaderboardData(leaderboardData) { - // Get the leaderboard element - const leaderboardElement = document.getElementById('leaderboard'); - // Clear previous content - leaderboardElement.innerHTML = ''; - - // Create a table to display leaderboard data - const table = document.createElement('table'); - table.innerHTML = ` - - Rank - Name - Score - - `; - - // Loop through the leaderboard data and add rows to the table - leaderboardData.forEach((entry, index) => { - const row = document.createElement('tr'); - row.innerHTML = ` - ${index + 1} - ${entry.name} - ${entry.score} - `; - table.appendChild(row); - }); - - // Append the table to the leaderboard element - leaderboardElement.appendChild(table); -} - -function fetchFullName() { - // Make AJAX request to fetch the user's full name from the server - fetch('/get-fullname') - .then(response => { - if (!response.ok) { - throw new Error('Network response was not ok'); - } - return response.json(); - }) - .then(data => { - // Display the user's full name on the dashboard - displayFullName(data.fullName); + const coursesContainer = document.querySelector('.courses-container'); + + data.courses.forEach(course => { + const courseElement = document.createElement('div'); + courseElement.classList.add('course'); + + courseElement.innerHTML = ` +

${course.title}

+

${course.description}

+ + `; + + coursesContainer.appendChild(courseElement); + }); }) - .catch(error => { - console.error('Error fetching user full name:', error); - }); -} - -function displayFullName(fullName) { - // Get the element where the full name will be displayed - const fullNameElement = document.getElementById('user-fullname'); - // Set the inner HTML of the element to the user's full name - fullNameElement.textContent = fullName; -} \ No newline at end of file + .catch(error => console.error('Error fetching user courses:', error)); +}); diff --git a/server.js b/server.js index 2b854861..b9559593 100644 --- a/server.js +++ b/server.js @@ -1,168 +1,46 @@ -// 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 { check, validationResult } = require('express-validator'); const app = express(); - -// Configure session middleware -app.use(session({ - secret: 'secret-key', - resave: false, - saveUninitialized: true -})); +const PORT = process.env.PORT || 3000; // Create MySQL connection const connection = mysql.createConnection({ host: 'localhost', - user: 'root', - password: '', - database: 'learning_management' + user: 'geofrey', + password: '1234', + database: 'learning management system' }); // Connect to MySQL connection.connect((err) => { if (err) { - console.error('Error connecting to MySQL: ' + err.stack); + console.error('Error connecting to MySQL:', err); return; } - console.log('Connected to MySQL as id ' + connection.threadId); + console.log('Connected to MySQL database'); }); -// Serve static files from the default directory -app.use(express.static(__dirname)); - -// Set up middleware to parse incoming JSON data -app.use(express.json()); -app.use(bodyParser.json()); -app.use(express.urlencoded({ extended: true })); -app.use(bodyParser.urlencoded({ extended: true })); - -// Define routes -app.get('/', (req, res) => { - res.sendFile(__dirname + '/index.html'); -}); - - - -// Define a User representation for clarity -const User = { - 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); - }, - getUserByUsername: function(username, callback) { - connection.query('SELECT * FROM ' + this.tableName + ' WHERE username = ?', username, 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('username').custom(async (value) => { - const user = await User.getUserByUsername(value); - if (user) { - throw new Error('Username already exists'); - } - }), -], 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.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) => { - 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'); - } - }); +// Serve static files from the "public" directory +app.use(express.static('public')); + +// Example endpoint to fetch user courses from MySQL +app.get('/api/user/courses', (req, res) => { + // Example query to fetch user courses from MySQL + const userId = req.query.userId; // Assuming userId is passed as a query parameter + const query = `SELECT * FROM courses WHERE user_id = ${userId}`; + + // Execute the query + connection.query(query, (err, results) => { + if (err) { + console.error('Error executing MySQL query:', err); + res.status(500).json({ error: 'Internal server error' }); + return; } + res.json({ courses: results }); }); }); -// Logout route -app.post('/logout', (req, res) => { - req.session.destroy(); - 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 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); - }); - }); - -// Start server -const PORT = process.env.PORT || 3000; +// Start the server app.listen(PORT, () => { - console.log(`Server running on port ${PORT}`); -}); \ No newline at end of file + console.log(`Server is running on port ${PORT}`); +}); diff --git a/style.css b/style.css deleted file mode 100644 index 1e1b20da..00000000 --- a/style.css +++ /dev/null @@ -1,74 +0,0 @@ -/* styles.css */ -body { - font-family: Arial, sans-serif; - margin: 0; - padding: 0; - display: flex; - flex-direction: column; - align-items: center; -} - -form { - margin-top: 20px; - display: flex; - flex-direction: column; - align-items: center; -} - -input, button { - margin-top: 10px; - padding: 5px; -} - -header { - background-color: #333; - color: #fff; - padding: 20px; - text-align: center; -} - -nav ul { - list-style-type: none; - margin: 0; - padding: 0; -} - -nav ul li { - display: inline; - margin-right: 20px; -} - -main { - padding: 20px; -} - -footer { - background-color: #333; - color: #fff; - padding: 20px; - text-align: center; -} - -/* Course content page styles */ -section { - margin-bottom: 30px; - border-bottom: 1px solid #ccc; - padding-bottom: 20px; -} - -h2 { - color: #333; - font-size: 24px; -} - -p { - color: #666; - font-size: 16px; - line-height: 1.5; -} - -iframe { - width: 100%; - height: 400px; - margin-top: 20px; -} \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 00000000..d7daa5ec --- /dev/null +++ b/styles.css @@ -0,0 +1,271 @@ +/* styles.css */ +body { + font-family: Arial, sans-serif; +} + +nav { + background-color: #333; + overflow: hidden; +} + +nav a { + float: left; + display: block; + color: #f2f2f2; + text-align: center; + padding: 14px 16px; + text-decoration: none; +} + +nav a:hover { + background-color: #ddd; + color: black; +} + +.course-container { + max-width: 800px; + margin: 20px auto; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f9f9f9; +} + +.course-container h2 { + text-align: center; +} + +.form-container { + max-width: 300px; + margin: 20px auto; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f9f9f9; +} + +.form-container h2 { + text-align: center; +} + +.form-container label { + display: block; + margin-bottom: 8px; +} + +.form-container input { + width: 100%; + padding: 8px; + margin-bottom: 12px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.form-container button { + width: 100%; + padding: 10px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.form-container button:hover { + background-color: #45a049; +} + +.dashboard-container { + max-width: 800px; + margin: 20px auto; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f9f9f9; +} + +.user-info { + text-align: center; + margin-bottom: 20px; +} + +.user-info h2 { + margin-bottom: 5px; +} + +.user-info p { + margin-bottom: 20px; +} + +.user-info form button { + padding: 10px 20px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.user-info form button:hover { + background-color: #45a049; +} + +.courses-container { + margin-top: 20px; +} + +.courses-container h2 { + text-align: center; + margin-bottom: 20px; +} + +.course { + border: 1px solid #ccc; + border-radius: 5px; + padding: 15px; + margin-bottom: 20px; + background-color: #fff; +} + +.course h3 { + margin-bottom: 10px; +} + +.course p { + margin-bottom: 15px; +} + +.course button { + padding: 10px 20px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.course button:hover { + background-color: #45a049; +} + +.course-content-container { + max-width: 800px; + margin: 20px auto; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f9f9f9; +} + +.enrollment-container { + margin-bottom: 30px; +} + +.enrollment-container h2 { + text-align: center; +} + +.enrollment-container form { + max-width: 400px; + margin: 0 auto; +} + +.enrollment-container label { + display: block; + margin-bottom: 8px; +} + +.enrollment-container input { + width: 100%; + padding: 8px; + margin-bottom: 12px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.enrollment-container button { + width: 100%; + padding: 10px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.enrollment-container button:hover { + background-color: #45a049; +} + +.materials-container { + margin-top: 20px; +} + +.materials-container h2 { + text-align: center; + margin-bottom: 20px; +} + +.material { + border: 1px solid #ccc; + border-radius: 5px; + padding: 15px; + margin-bottom: 20px; + background-color: #fff; +} + +.material h3 { + margin-bottom: 10px; +} + +.material p { + margin-bottom: 15px; +} + +.material img { + max-width: 100%; + height: auto; + border-radius: 5px; +} +.leaderboard-container { + max-width: 800px; + margin: 20px auto; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f9f9f9; +} + +.leaderboard-container h1 { + text-align: center; + margin-bottom: 20px; +} + +.organization-container, .teacher-container { + margin-bottom: 30px; +} + +.organization-container h2, .teacher-container h2 { + text-align: center; + margin-bottom: 15px; +} + +table { + width: 100%; + border-collapse: collapse; + margin-bottom: 20px; +} + +table th, table td { + border: 1px solid #ccc; + padding: 10px; + text-align: left; +} + +table th { + background-color: #f2f2f2; +} + +table tbody tr:nth-child(even) { + background-color: #f9f9f9; +} \ No newline at end of file