├── favicon.ico
├── src
├── images
│ ├── logo.png
│ └── test.png
├── css
│ └── login_signup.css
└── js
│ └── adminlte.min.js
├── README.md
├── user
├── src
│ ├── images
│ │ ├── AdminLTELogo.png
│ │ └── user2-160x160.jpg
│ ├── css
│ │ ├── sweetalert2.css
│ │ ├── login_signup.css
│ │ └── toastr.min.css
│ └── js
│ │ └── toastr.min.js
├── auth.php
├── includes
│ ├── footer.php
│ ├── js.php
│ ├── css.php
│ └── navbar.php
├── index.php
├── user.php
├── results.php
├── active_sessions.php
├── dropdown.php
├── fill_in_the_blank.php
├── matching.php
├── topics.php
├── true_false.php
├── test.php
└── question.php
├── signup
├── check_availability.php
└── index.php
├── logout
└── index.php
├── footer.php
├── config.php
├── index.php
├── header.php
├── database.sql
├── login
└── index.php
└── test.php
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/php-test-platform/main/favicon.ico
--------------------------------------------------------------------------------
/src/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/php-test-platform/main/src/images/logo.png
--------------------------------------------------------------------------------
/src/images/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/php-test-platform/main/src/images/test.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | ## This project is currently under development...
4 | 🚧 Work in progress! 🚧
5 |
6 | ---
7 |
--------------------------------------------------------------------------------
/user/src/images/AdminLTELogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/php-test-platform/main/user/src/images/AdminLTELogo.png
--------------------------------------------------------------------------------
/user/src/images/user2-160x160.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Iqbolshoh/php-test-platform/main/user/src/images/user2-160x160.jpg
--------------------------------------------------------------------------------
/user/auth.php:
--------------------------------------------------------------------------------
1 | checkUserSession('user');
7 |
--------------------------------------------------------------------------------
/user/includes/footer.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | Admin Panel
4 |
5 | Copyright © 2014-2025 Iqbolshoh.uz . All rights reserved.
6 |
--------------------------------------------------------------------------------
/user/includes/js.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/user/includes/css.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/signup/check_availability.php:
--------------------------------------------------------------------------------
1 | false];
8 |
9 | if (isset($_POST['email'])) {
10 | $email = $_POST['email'];
11 | $email_check = $query->select('users', 'email', 'email = ?', [$email], 's');
12 | if ($email_check) {
13 | $response['exists'] = true;
14 | }
15 | }
16 |
17 | if (isset($_POST['username'])) {
18 | $username = $_POST['username'];
19 | $username_check = $query->select('users', 'username', 'username = ?', [$username], 's');
20 | if ($username_check) {
21 | $response['exists'] = true;
22 | }
23 | }
24 |
25 | echo json_encode($response);
26 | exit;
27 |
--------------------------------------------------------------------------------
/user/src/css/sweetalert2.css:
--------------------------------------------------------------------------------
1 | .swal2-popup {
2 | font-family: 'Arial', sans-serif;
3 | }
4 |
5 | .swal2-title {
6 | color: #2c3e50;
7 | font-size: 1.5rem;
8 | }
9 |
10 | .swal2-html-container {
11 | color: #34495e;
12 | font-size: 1rem;
13 | }
14 |
15 | .swal2-confirm {
16 | background-color: #28a745;
17 | color: #fff;
18 | border: none;
19 | border-radius: 4px;
20 | padding: 0.5em 1em;
21 | margin-left: 10px;
22 | }
23 |
24 | .swal2-cancel {
25 | background-color: #dc3545;
26 | color: #fff;
27 | border: none;
28 | border-radius: 4px;
29 | padding: 0.5em 1em;
30 | margin-right: 10px;
31 | }
32 |
33 | .swal2-confirm:hover {
34 | background-color: #218838;
35 | }
36 |
37 | .swal2-cancel:hover {
38 | background-color: #c82333;
39 | }
--------------------------------------------------------------------------------
/logout/index.php:
--------------------------------------------------------------------------------
1 | delete('active_sessions', 'session_token = ?', [session_id()], 's');
8 |
9 | session_unset();
10 | $_SESSION = [];
11 | session_destroy();
12 | session_write_close();
13 |
14 | $cookies = ['username', 'session_token'];
15 | foreach ($cookies as $cookie) {
16 | if (isset($_COOKIE[$cookie])) {
17 | setcookie($cookie, '', [
18 | 'expires' => time() - 3600,
19 | 'path' => '/',
20 | 'secure' => true,
21 | 'httponly' => true,
22 | 'samesite' => 'Strict'
23 | ]);
24 | }
25 | }
26 |
27 | header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
28 | header("Pragma: no-cache");
29 | header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
30 |
31 | header("Location: ../login/");
32 | exit;
33 |
--------------------------------------------------------------------------------
/src/css/login_signup.css:
--------------------------------------------------------------------------------
1 | body {
2 | height: 100vh;
3 | display: flex;
4 | justify-content: center;
5 | align-items: center;
6 | font-family: 'Arial', sans-serif;
7 | margin: 0px;
8 | }
9 |
10 | .form-container {
11 | background-color: #fff;
12 | border-radius: 8px;
13 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
14 | padding: 30px;
15 | width: calc(100% - 40px);
16 | max-width: 450px;
17 | box-sizing: border-box;
18 | }
19 |
20 | h1 {
21 | margin: 0 0 20px;
22 | font-size: 24px;
23 | color: #333;
24 | }
25 |
26 | .form-group {
27 | margin-bottom: 15px;
28 | position: relative;
29 | }
30 |
31 | .form-group label {
32 | display: block;
33 | margin-bottom: 5px;
34 | font-weight: bold;
35 | color: #555;
36 | }
37 |
38 | .form-group input {
39 | width: 100%;
40 | padding: 10px;
41 | border: 1px solid #ddd;
42 | border-radius: 4px;
43 | box-sizing: border-box;
44 | font-size: 16px;
45 | }
46 |
47 | .form-group .password-container {
48 | display: flex;
49 | align-items: center;
50 | }
51 |
52 | .form-group .password-container input {
53 | flex: 1;
54 | padding-right: 40px;
55 | }
56 |
57 | .form-group .password-toggle {
58 | position: absolute;
59 | right: 10px;
60 | font-size: 18px;
61 | cursor: pointer;
62 | border: none;
63 | background: transparent;
64 | }
65 |
66 | .form-group #submit {
67 | width: 100%;
68 | background-color: #007bff;
69 | color: #fff;
70 | border: none;
71 | padding: 12px 15px;
72 | border-radius: 4px;
73 | font-size: 18px;
74 | cursor: pointer;
75 | transition: background-color 0.3s;
76 | }
77 |
78 | .form-group #submit:hover {
79 | background-color: #0056b3;
80 | }
81 |
82 | .text-center {
83 | text-align: center;
84 | margin-top: 15px;
85 | }
86 |
87 | .text-center a {
88 | color: #007bff;
89 | text-decoration: none;
90 | }
91 |
92 | .text-center a:hover {
93 | text-decoration: underline;
94 | }
95 |
96 | #email-message,
97 | #username-message {
98 | color: red;
99 | font-size: 14px;
100 | margin-top: 5px;
101 | }
--------------------------------------------------------------------------------
/user/src/css/login_signup.css:
--------------------------------------------------------------------------------
1 | body {
2 | height: 100vh;
3 | display: flex;
4 | justify-content: center;
5 | align-items: center;
6 | font-family: 'Arial', sans-serif;
7 | margin: 0px;
8 | }
9 |
10 | .form-container {
11 | background-color: #fff;
12 | border-radius: 8px;
13 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
14 | padding: 30px;
15 | width: calc(100% - 40px);
16 | max-width: 450px;
17 | box-sizing: border-box;
18 | }
19 |
20 | h1 {
21 | margin: 0 0 20px;
22 | font-size: 24px;
23 | color: #333;
24 | }
25 |
26 | .form-group {
27 | margin-bottom: 15px;
28 | position: relative;
29 | }
30 |
31 | .form-group label {
32 | display: block;
33 | margin-bottom: 5px;
34 | font-weight: bold;
35 | color: #555;
36 | }
37 |
38 | .form-group input {
39 | width: 100%;
40 | padding: 10px;
41 | border: 1px solid #ddd;
42 | border-radius: 4px;
43 | box-sizing: border-box;
44 | font-size: 16px;
45 | }
46 |
47 | .form-group .password-container {
48 | display: flex;
49 | align-items: center;
50 | }
51 |
52 | .form-group .password-container input {
53 | flex: 1;
54 | padding-right: 40px;
55 | }
56 |
57 | .form-group .password-toggle {
58 | position: absolute;
59 | right: 10px;
60 | font-size: 18px;
61 | cursor: pointer;
62 | border: none;
63 | background: transparent;
64 | }
65 |
66 | .form-group #submit {
67 | width: 100%;
68 | background-color: #007bff;
69 | color: #fff;
70 | border: none;
71 | padding: 12px 15px;
72 | border-radius: 4px;
73 | font-size: 18px;
74 | cursor: pointer;
75 | transition: background-color 0.3s;
76 | }
77 |
78 | .form-group #submit:hover {
79 | background-color: #0056b3;
80 | }
81 |
82 | .text-center {
83 | text-align: center;
84 | margin-top: 15px;
85 | }
86 |
87 | .text-center a {
88 | color: #007bff;
89 | text-decoration: none;
90 | }
91 |
92 | .text-center a:hover {
93 | text-decoration: underline;
94 | }
95 |
96 | #email-message,
97 | #username-message {
98 | color: red;
99 | font-size: 14px;
100 | margin-top: 5px;
101 | }
--------------------------------------------------------------------------------
/footer.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
28 |
29 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/config.php:
--------------------------------------------------------------------------------
1 | '/user/'
12 | ];
13 |
14 | class Database
15 | {
16 | private $conn;
17 |
18 | public function __construct()
19 | {
20 | $this->conn = new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
21 |
22 | if ($this->conn->connect_error) {
23 | die("Database connection error: " . $this->conn->connect_error);
24 | }
25 | }
26 |
27 | public function __destruct()
28 | {
29 | if ($this->conn) {
30 | $this->conn->close();
31 | }
32 | }
33 |
34 | public function executeQuery($sql, $params = [], $types = "")
35 | {
36 | $result = $this->conn->prepare($sql);
37 |
38 | if (!$result) {
39 | return "SQL error: " . $this->conn->error;
40 | }
41 |
42 | if ($params) {
43 | $result->bind_param($types, ...$params);
44 | }
45 |
46 | if (!$result->execute()) {
47 | return "Execution error: " . $result->error;
48 | }
49 |
50 | return $result;
51 | }
52 |
53 | function validate($value)
54 | {
55 | return htmlspecialchars(trim(stripslashes($value)), ENT_QUOTES, 'UTF-8');
56 | }
57 |
58 | public function select($table, $columns = "*", $condition = "", $params = [], $types = "")
59 | {
60 | $sql = "SELECT $columns FROM $table" . ($condition ? " WHERE $condition" : "");
61 | $result = $this->executeQuery($sql, $params, $types);
62 |
63 | if (is_string($result)) {
64 | return $result;
65 | }
66 |
67 | return $result->get_result()->fetch_all(MYSQLI_ASSOC);
68 | }
69 |
70 | public function insert($table, $data)
71 | {
72 | $keys = implode(', ', array_keys($data));
73 | $placeholders = implode(', ', array_fill(0, count($data), '?'));
74 | $sql = "INSERT INTO $table ($keys) VALUES ($placeholders)";
75 | $types = str_repeat('s', count($data));
76 |
77 | $result = $this->executeQuery($sql, array_values($data), $types);
78 | if (is_string($result)) {
79 | return $result;
80 | }
81 |
82 | return $this->conn->insert_id;
83 | }
84 |
85 | public function update($table, $data, $condition = "", $params = [], $types = "")
86 | {
87 | $set = implode(", ", array_map(function ($k) {
88 | return "$k = ?";
89 | }, array_keys($data)));
90 | $sql = "UPDATE $table SET $set" . ($condition ? " WHERE $condition" : "");
91 | $types = str_repeat('s', count($data)) . $types;
92 |
93 | $result = $this->executeQuery($sql, array_merge(array_values($data), $params), $types);
94 | if (is_string($result)) {
95 | return $result;
96 | }
97 |
98 | return $this->conn->affected_rows;
99 | }
100 |
101 | public function delete($table, $condition = "", $params = [], $types = "")
102 | {
103 | $sql = "DELETE FROM $table" . ($condition ? " WHERE $condition" : "");
104 |
105 | $result = $this->executeQuery($sql, $params, $types);
106 | if (is_string($result)) {
107 | return $result;
108 | }
109 |
110 | return $this->conn->affected_rows;
111 | }
112 |
113 | public function hashPassword($password)
114 | {
115 | return hash_hmac('sha256', $password, 'iqbolshoh');
116 | }
117 |
118 | public function checkUserSession($role)
119 | {
120 | if (($_SESSION['loggedin'] ?? false) !== true || ($_SESSION['role'] ?? '') !== $role) {
121 | header("Location: " . SITE_PATH . "/login/");
122 | exit;
123 | }
124 |
125 | if (!$this->select('active_sessions', '*', 'session_token = ?', [session_id()], 's')) {
126 | header("Location: " . SITE_PATH . "/logout/");
127 | exit;
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/user/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | $user = $query->select('users', '*')[0];
4 | $topics = $query->select('lessons', '*')[0];
5 | $results = $query->select('results', '*');
6 |
7 | $tests = count($query->select('test', '*'));
8 | $tru_falses = count($query->select('tru_false', '*'));
9 | $dropdowns = count($query->select('dropdown', '*'));
10 | $fill_in_the_blanks = count($query->select('fill_in_the_blank', '*'));
11 | $matchings = count($query->select('matching', '*'));
12 | $answers = count($query->select('answers', '*'));
13 |
14 | $question = $tests + $tru_falses + $dropdowns + $fill_in_the_blanks + $matchings + $answers;
15 |
16 | ?>
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | AdminLTE 3 | Dashboard
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | "Home", "url" => "./"],
39 | ["title" => "Dashboard", "url" => "#"],
40 | );
41 | pagePath('Dashboard', $arr);
42 | ?>
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
= $user['first_name'] ?>
53 |
54 |
= $user['email'] ?>
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
= count($topics) . ' Topics' ?>
68 |
69 |
Available in the system
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
= $question ?>
82 |
83 |
Total number of questions.
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
= count($results) ?>
97 |
98 |
People passed the test.
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Test Platform
8 |
9 |
10 |
11 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | Welcome to Test Platform
132 | Create your own tests, improve your skills, and share them with others.
133 |
134 | Create Test
135 | My Tests
136 |
137 |
138 |
139 |
140 |
141 |
142 | Test Platform provides a comprehensive environment where you can create
143 | personalized tests on various topics. Whether you're preparing for exams or enhancing your skills, you
144 | can design quizzes, share them with others, and track progress. Join us to create, share, and test your
145 | knowledge while helping others do the same!
146 |
147 |
148 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/header.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
161 |
162 |
163 |
184 |
185 |
--------------------------------------------------------------------------------
/user/user.php:
--------------------------------------------------------------------------------
1 | select('users', '*', "id = $user_id");
15 |
16 | $user = $result[0];
17 | if ($_SERVER['REQUEST_METHOD'] === 'POST') {
18 | $first_name = $_POST['first_name'];
19 | $last_name = $_POST['last_name'];
20 | $email = $_POST['email'];
21 | $username = $_POST['username'];
22 | $password = $_POST['password'];
23 |
24 | $_SESSION['first_name'] = $first_name;
25 | $_SESSION['last_name'] = $last_name;
26 |
27 | if (!empty($password)) {
28 | $password = $query->hashPassword($password);
29 | $query->update('users', [
30 | 'first_name' => $first_name,
31 | 'last_name' => $last_name,
32 | 'email' => $email,
33 | 'username' => $username,
34 | 'password' => $password
35 | ], "id = $user_id");
36 | } else {
37 | $query->update('users', [
38 | 'first_name' => $first_name,
39 | 'last_name' => $last_name,
40 | 'email' => $email,
41 | 'username' => $username
42 | ], "id = $user_id");
43 | }
44 |
45 | header("Location: " . $_SERVER['HTTP_REFERER']);
46 | exit;
47 | }
48 | ?>
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | AdminLTE 3 | User settings
60 |
61 |
62 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | "Home", "url" => "./"],
109 | ["title" => "User settings", "url" => "#"],
110 | );
111 | pagePath('User settings', $arr);
112 | ?>
113 |
114 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/user/results.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $lesson_id = isset($_GET['lesson_id']) ? intval($_GET['lesson_id']) : 0;
5 |
6 | if ($lesson_id > 0) {
7 | $results = $query->select('results', '*', "lesson_id = $lesson_id");
8 | } else {
9 | $lessons = $query->select('lessons', '*', '1');
10 | }
11 | ?>
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Results
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | "Home", "url" => "./"],
33 | ["title" => "Results", "url" => "#"],
34 | );
35 | pagePath('Results', $arr);
36 | ?>
37 |
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 | №
52 | Lesson Name
53 | Actions
54 |
55 |
56 |
57 | $lesson): ?>
58 |
59 | = $key + 1 ?>
60 |
61 | = $lesson['title'] ?>
62 |
63 |
64 | View Results
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | №
75 | Participant Name
76 | Total Questions
77 | Answered Questions
78 | Percentage
79 |
80 |
81 |
82 | $result): ?>
83 |
84 | = $key + 1 ?>
85 | = $result['participant_name'] ?>
86 | = $result['total_questions'] ?>
87 | = $result['answered_questions'] ?>
88 |
89 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
Back to Lessons
105 |
106 |
No data available.
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/user/active_sessions.php:
--------------------------------------------------------------------------------
1 | checkUserSession('user');
7 |
8 | $sessions = $query->select('active_sessions', '*', 'user_id = ?', [$_SESSION['user_id']], 'i');
9 |
10 | if (isset($_GET['token'])) {
11 | $query->delete('active_sessions', 'user_id = ? AND session_token = ?', [$_SESSION['user_id'], $_GET['token']], 'is');
12 | header('Location: ' . $_SERVER['PHP_SELF']);
13 | exit;
14 | }
15 |
16 | if (isset($_POST['update_session'])) {
17 | $device_name = $_POST['device_name'];
18 |
19 | $query->update(
20 | 'active_sessions',
21 | ['device_name' => $device_name],
22 | 'session_token = ? AND user_id = ?',
23 | [session_id(), $_SESSION['user_id']],
24 | 'si'
25 | );
26 |
27 | header('Location: ' . $_SERVER['PHP_SELF']);
28 | exit;
29 | }
30 | ?>
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | №
56 | Device Name
57 | IP Address
58 | Last Activity
59 | Action
60 |
61 |
62 |
63 | $session): ?>
64 |
65 | = $index + 1 ?>
66 |
67 |
68 |
69 |
70 |
71 |
73 | Edit
74 |
75 |
76 |
78 | Remove
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/database.sql:
--------------------------------------------------------------------------------
1 | DROP DATABASE IF EXISTS test_platform;
2 |
3 | CREATE DATABASE IF NOT EXISTS test_platform;
4 |
5 | USE test_platform;
6 |
7 | CREATE TABLE IF NOT EXISTS users (
8 | id INT PRIMARY KEY AUTO_INCREMENT,
9 | first_name VARCHAR(30) NOT NULL,
10 | last_name VARCHAR(30) NOT NULL,
11 | email VARCHAR(100) NOT NULL UNIQUE,
12 | username VARCHAR(30) NOT NULL UNIQUE,
13 | password VARCHAR(255) NOT NULL,
14 | profile_picture VARCHAR(255) DEFAULT 'default.png',
15 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
16 | );
17 |
18 | CREATE TABLE IF NOT EXISTS subjects (
19 | id INT PRIMARY KEY AUTO_INCREMENT,
20 | user_id INT,
21 | title VARCHAR(100) NOT NULL,
22 | description VARCHAR(255) NOT NULL,
23 | url VARCHAR(255) NOT NULL,
24 | FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
25 | );
26 |
27 | CREATE TABLE IF NOT EXISTS test (
28 | id INT PRIMARY KEY AUTO_INCREMENT,
29 | subject_id INT,
30 | question TEXT NOT NULL,
31 | FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE CASCADE
32 | );
33 |
34 | CREATE TABLE IF NOT EXISTS test_options (
35 | id INT PRIMARY KEY AUTO_INCREMENT,
36 | test_id INT NOT NULL,
37 | option_text VARCHAR(255) NOT NULL,
38 | is_correct BOOLEAN DEFAULT FALSE,
39 | FOREIGN KEY (test_id) REFERENCES test(id) ON DELETE CASCADE
40 | );
41 |
42 | CREATE TABLE IF NOT EXISTS tru_false (
43 | id INT PRIMARY KEY AUTO_INCREMENT,
44 | subject_id INT,
45 | statement TEXT NOT NULL,
46 | is_true BOOLEAN NOT NULL,
47 | FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE CASCADE
48 | );
49 |
50 | CREATE TABLE IF NOT EXISTS dropdown (
51 | id INT PRIMARY KEY AUTO_INCREMENT,
52 | subject_id INT,
53 | question TEXT NOT NULL,
54 | correct_answer VARCHAR(255) NOT NULL,
55 | FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE CASCADE
56 | );
57 |
58 | CREATE TABLE IF NOT EXISTS fill_in_the_blank (
59 | id INT PRIMARY KEY AUTO_INCREMENT,
60 | subject_id INT,
61 | sentence TEXT NOT NULL,
62 | correct_answer VARCHAR(255) NOT NULL,
63 | FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE CASCADE
64 | );
65 |
66 | CREATE TABLE IF NOT EXISTS matching (
67 | id INT PRIMARY KEY AUTO_INCREMENT,
68 | subject_id INT,
69 | left_side TEXT NOT NULL,
70 | right_side TEXT NOT NULL,
71 | FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE CASCADE
72 | );
73 |
74 | CREATE TABLE IF NOT EXISTS results (
75 | id INT PRIMARY KEY AUTO_INCREMENT,
76 | subject_id INT,
77 | participant_name VARCHAR(255) NOT NULL,
78 | total_questions INT NOT NULL,
79 | answered_questions INT NOT NULL,
80 | FOREIGN KEY (subject_id) REFERENCES subjects(id) ON DELETE CASCADE
81 | );
82 |
83 | -- Login: iqbolshoh
84 | -- Password: Iqbolshoh$7
85 | INSERT INTO
86 | users (
87 | first_name,
88 | last_name,
89 | email,
90 | username,
91 | password
92 | )
93 | VALUES
94 | (
95 | 'Iqbolshoh',
96 | 'Ilhomjonov',
97 | 'iilhomjonov777@gmail.com',
98 | 'iqbolshoh',
99 | '1f254bb82e64bde20137a2922989f6f57529c98e34d146b523a47898702b7231'
100 | );
101 |
102 | INSERT INTO
103 | subjects (user_id, title, description, url)
104 | VALUES
105 | (
106 | 1,
107 | 'Mathematics',
108 | 'Learn advanced mathematics including calculus, algebra, and geometry.',
109 | 'mathematics'
110 | ),
111 | (
112 | 1,
113 | 'Physics',
114 | 'Explore the fundamentals of physics, including mechanics, thermodynamics, and optics.',
115 | 'physics'
116 | ),
117 | (
118 | 1,
119 | 'Computer Science',
120 | 'Study programming, data structures, algorithms, and web development.',
121 | 'computer-science'
122 | ),
123 | (
124 | 1,
125 | 'Chemistry',
126 | 'Dive into organic, inorganic, and physical chemistry with hands-on experiments.',
127 | 'chemistry'
128 | ),
129 | (
130 | 1,
131 | 'History',
132 | 'Learn about world history from ancient civilizations to modern times.',
133 | 'history'
134 | );
135 |
136 | -- Inserting test questions into the 'test' table
137 | INSERT INTO
138 | test (subject_id, question)
139 | VALUES
140 | (1, 'What is the derivative of x^2?'),
141 | (2, 'What is Newtons Second Law of Motion?'),
142 | (
143 | 3,
144 | 'What is the time complexity of a binary search?'
145 | ),
146 | (4, 'What is the chemical formula of water?'),
147 | (
148 | 5,
149 | 'Who was the first president of the United States?'
150 | );
151 |
152 | INSERT INTO
153 | test_options (test_id, option_text, is_correct)
154 | VALUES
155 | (1, '2x', TRUE),
156 | (1, 'x^2', FALSE),
157 | (1, 'x', FALSE),
158 | (1, '1/x', FALSE),
159 | (2, 'F = ma', TRUE),
160 | (2, 'F = m/v', FALSE),
161 | (2, 'F = mv', FALSE),
162 | (2, 'F = m^2', FALSE),
163 | (3, 'O(log n)', TRUE),
164 | (3, 'O(n)', FALSE),
165 | (3, 'O(n^2)', FALSE),
166 | (3, 'O(1)', FALSE),
167 | (4, 'H2O', TRUE),
168 | (4, 'CO2', FALSE),
169 | (4, 'O2', FALSE),
170 | (4, 'CH4', FALSE),
171 | (5, 'George Washington', TRUE),
172 | (5, 'Abraham Lincoln', FALSE),
173 | (5, 'Thomas Jefferson', FALSE),
174 | (5, 'Franklin Pierce', FALSE);
175 |
176 | INSERT INTO
177 | tru_false (subject_id, statement, is_true)
178 | VALUES
179 | (
180 | 1,
181 | 'The sum of angles in a triangle is always 180 degrees.',
182 | TRUE
183 | ),
184 | (
185 | 2,
186 | 'Einstein developed the theory of relativity after Newton.',
187 | FALSE
188 | ),
189 | (
190 | 3,
191 | 'The binary search algorithm works on unsorted arrays.',
192 | FALSE
193 | ),
194 | (4, 'Water expands when it freezes.', TRUE),
195 | (
196 | 5,
197 | 'The Roman Empire was founded in 27 BC.',
198 | TRUE
199 | );
200 |
201 | -- Inserting dropdown questions into the 'dropdown' table
202 | INSERT INTO
203 | dropdown (subject_id, question, correct_answer)
204 | VALUES
205 | (1, 'What is the integral of 1/x?', 'ln(x)'),
206 | (2, 'What is the unit of force?', 'Newton'),
207 | (
208 | 3,
209 | 'What is the main feature of object-oriented programming?',
210 | 'Encapsulation'
211 | ),
212 | (
213 | 4,
214 | 'What is the symbol for gold in the periodic table?',
215 | 'Au'
216 | ),
217 | (5, 'When did World War II end?', '1945');
218 |
219 | -- Inserting fill-in-the-blank questions into the 'fill_in_the_blank' table
220 | INSERT INTO
221 | fill_in_the_blank (subject_id, sentence, correct_answer)
222 | VALUES
223 | (
224 | 1,
225 | 'The area of a circle is calculated using the formula ___.',
226 | 'πr^2'
227 | ),
228 | (
229 | 2,
230 | 'Einstein\'s famous equation is E = ___.',
231 | 'mc^2'
232 | ),
233 | (
234 | 3,
235 | 'The best programming language for web development is ___.',
236 | 'JavaScript'
237 | ),
238 | (
239 | 4,
240 | 'The chemical element with the atomic number 6 is ___.',
241 | 'Carbon'
242 | ),
243 | (
244 | 5,
245 | 'The Declaration of Independence was signed in the year ___.',
246 | '1776'
247 | );
248 |
249 | -- Inserting matching questions into the 'matching' table
250 | INSERT INTO
251 | matching (subject_id, left_side, right_side)
252 | VALUES
253 | (1, 'Pythagoras Theorem', 'a^2 + b^2 = c^2'),
254 | (
255 | 2,
256 | 'Law of Inertia',
257 | 'An object will remain at rest or in motion unless acted upon by an external force'
258 | ),
259 | (
260 | 3,
261 | 'Sorting Algorithm',
262 | 'O(n log n) time complexity'
263 | ),
264 | (4, 'Element H', 'Hydrogen'),
265 | (5, 'Ancient Egypt', 'Pyramids');
--------------------------------------------------------------------------------
/user/dropdown.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $lessonid = isset($_GET['lessonid']) ? intval($_GET['lessonid']) : null;
5 |
6 | if ($lessonid !== null) {
7 | $lessons_test = $query->select('lessons', '*', "id = '$lessonid'");
8 | } else {
9 | $lessons_test = [];
10 | }
11 |
12 | $dropdowns = [];
13 | if ($lessonid) {
14 | $dropdowns = $query->select('dropdown', '*', "lesson_id = '$lessonid'");
15 | }
16 |
17 | if ($_SERVER['REQUEST_METHOD'] === 'POST') {
18 | if (isset($_POST['add_dropdown'])) {
19 | $question = $_POST['question'];
20 | $correct_answer = $_POST['correct_answer'];
21 | $lesson_id = intval($_POST['lesson_id']);
22 |
23 | $query->insert('dropdown', [
24 | 'lesson_id' => $lesson_id,
25 | 'question' => $question,
26 | 'correct_answer' => $correct_answer
27 | ]);
28 | }
29 |
30 | if (isset($_POST['update_dropdown'])) {
31 | foreach ($_POST['id'] as $id) {
32 | $id = intval($id);
33 | $question = $_POST['question'][$id];
34 | $correct_answer = $_POST['correct_answer'][$id];
35 |
36 | $query->update('dropdown', [
37 | 'question' => $question,
38 | 'correct_answer' => $correct_answer
39 | ], "id = '$id'");
40 | }
41 | }
42 |
43 | header("Location: " . $_SERVER['PHP_SELF'] . "?lessonid=$lessonid");
44 | exit;
45 | }
46 |
47 | if (isset($_GET['delete_id'])) {
48 | $delete_id = intval($_GET['delete_id']);
49 | $query->delete('dropdown', "id = '$delete_id'");
50 | header("Location: " . $_SERVER['PHP_SELF'] . "?lessonid=$lessonid");
51 | exit;
52 | }
53 | ?>
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | Dropdown
63 |
64 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | "Home", "url" => "./"], ["title" => "Dropdown", "url" => "#"]];
102 | pagePath('Dropdown', $arr);
103 | ?>
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
Add Dropdown
112 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | Question:
132 | = $dropdown['question'] ?>
133 |
134 |
135 | Correct Answer:
136 |
137 |
138 |
141 |
142 |
143 |
Update All
144 |
145 |
146 |
147 |
148 |
149 | select('lessons', '*'); ?>
150 |
151 |
152 | Select a Lesson
153 |
154 | -- Select a Lesson --
155 | $lesson): ?>
156 | >
157 | = $index + 1 . ". " . $lesson['title'] ?>
158 |
159 |
160 |
161 |
162 |
163 |
164 | Select Lesson
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/user/src/css/toastr.min.css:
--------------------------------------------------------------------------------
1 | .toast-title {
2 | font-weight: 700
3 | }
4 |
5 | .toast-message {
6 | -ms-word-wrap: break-word;
7 | word-wrap: break-word
8 | }
9 |
10 | .toast-message a,
11 | .toast-message label {
12 | color: #FFF
13 | }
14 |
15 | .toast-message a:hover {
16 | color: #CCC;
17 | text-decoration: none
18 | }
19 |
20 | .toast-close-button {
21 | position: relative;
22 | right: -.3em;
23 | top: -.3em;
24 | float: right;
25 | font-size: 20px;
26 | font-weight: 700;
27 | color: #FFF;
28 | -webkit-text-shadow: 0 1px 0 #fff;
29 | text-shadow: 0 1px 0 #fff;
30 | opacity: .8;
31 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
32 | filter: alpha(opacity=80);
33 | line-height: 1
34 | }
35 |
36 | .toast-close-button:focus,
37 | .toast-close-button:hover {
38 | color: #000;
39 | text-decoration: none;
40 | cursor: pointer;
41 | opacity: .4;
42 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
43 | filter: alpha(opacity=40)
44 | }
45 |
46 | .rtl .toast-close-button {
47 | left: -.3em;
48 | float: left;
49 | right: .3em
50 | }
51 |
52 | button.toast-close-button {
53 | padding: 0;
54 | cursor: pointer;
55 | background: 0 0;
56 | border: 0;
57 | -webkit-appearance: none
58 | }
59 |
60 | .toast-top-center {
61 | top: 0;
62 | right: 0;
63 | width: 100%
64 | }
65 |
66 | .toast-bottom-center {
67 | bottom: 0;
68 | right: 0;
69 | width: 100%
70 | }
71 |
72 | .toast-top-full-width {
73 | top: 0;
74 | right: 0;
75 | width: 100%
76 | }
77 |
78 | .toast-bottom-full-width {
79 | bottom: 0;
80 | right: 0;
81 | width: 100%
82 | }
83 |
84 | .toast-top-left {
85 | top: 12px;
86 | left: 12px
87 | }
88 |
89 | .toast-top-right {
90 | top: 12px;
91 | right: 12px
92 | }
93 |
94 | .toast-bottom-right {
95 | right: 12px;
96 | bottom: 12px
97 | }
98 |
99 | .toast-bottom-left {
100 | bottom: 12px;
101 | left: 12px
102 | }
103 |
104 | #toast-container {
105 | position: fixed;
106 | z-index: 999999;
107 | pointer-events: none
108 | }
109 |
110 | #toast-container * {
111 | -moz-box-sizing: border-box;
112 | -webkit-box-sizing: border-box;
113 | box-sizing: border-box
114 | }
115 |
116 | #toast-container>div {
117 | position: relative;
118 | pointer-events: auto;
119 | overflow: hidden;
120 | margin: 0 0 6px;
121 | padding: 15px 15px 15px 50px;
122 | width: 300px;
123 | -moz-border-radius: 3px;
124 | -webkit-border-radius: 3px;
125 | border-radius: 3px;
126 | background-position: 15px center;
127 | background-repeat: no-repeat;
128 | -moz-box-shadow: 0 0 12px #999;
129 | -webkit-box-shadow: 0 0 12px #999;
130 | box-shadow: 0 0 12px #999;
131 | color: #FFF;
132 | opacity: .8;
133 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
134 | filter: alpha(opacity=80)
135 | }
136 |
137 | #toast-container>div.rtl {
138 | direction: rtl;
139 | padding: 15px 50px 15px 15px;
140 | background-position: right 15px center
141 | }
142 |
143 | #toast-container>div:hover {
144 | -moz-box-shadow: 0 0 12px #000;
145 | -webkit-box-shadow: 0 0 12px #000;
146 | box-shadow: 0 0 12px #000;
147 | opacity: 1;
148 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
149 | filter: alpha(opacity=100);
150 | cursor: pointer
151 | }
152 |
153 | #toast-container>.toast-info {
154 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=) !important
155 | }
156 |
157 | #toast-container>.toast-error {
158 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=) !important
159 | }
160 |
161 | #toast-container>.toast-success {
162 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==) !important
163 | }
164 |
165 | #toast-container>.toast-warning {
166 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=) !important
167 | }
168 |
169 | #toast-container.toast-bottom-center>div,
170 | #toast-container.toast-top-center>div {
171 | width: 300px;
172 | margin-left: auto;
173 | margin-right: auto
174 | }
175 |
176 | #toast-container.toast-bottom-full-width>div,
177 | #toast-container.toast-top-full-width>div {
178 | width: 96%;
179 | margin-left: auto;
180 | margin-right: auto
181 | }
182 |
183 | .toast {
184 | background-color: #030303
185 | }
186 |
187 | .toast-success {
188 | background-color: #51A351
189 | }
190 |
191 | .toast-error {
192 | background-color: #BD362F
193 | }
194 |
195 | .toast-info {
196 | background-color: #2F96B4
197 | }
198 |
199 | .toast-warning {
200 | background-color: #F89406
201 | }
202 |
203 | .toast-progress {
204 | position: absolute;
205 | left: 0;
206 | bottom: 0;
207 | height: 4px;
208 | background-color: #000;
209 | opacity: .4;
210 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
211 | filter: alpha(opacity=40)
212 | }
213 |
214 | @media all and (max-width:240px) {
215 | #toast-container>div {
216 | padding: 8px 8px 8px 50px;
217 | width: 11em
218 | }
219 |
220 | #toast-container>div.rtl {
221 | padding: 8px 50px 8px 8px
222 | }
223 |
224 | #toast-container .toast-close-button {
225 | right: -.2em;
226 | top: -.2em
227 | }
228 |
229 | #toast-container .rtl .toast-close-button {
230 | left: -.2em;
231 | right: .2em
232 | }
233 | }
234 |
235 | @media all and (min-width:241px) and (max-width:480px) {
236 | #toast-container>div {
237 | padding: 8px 8px 8px 50px;
238 | width: 18em
239 | }
240 |
241 | #toast-container>div.rtl {
242 | padding: 8px 50px 8px 8px
243 | }
244 |
245 | #toast-container .toast-close-button {
246 | right: -.2em;
247 | top: -.2em
248 | }
249 |
250 | #toast-container .rtl .toast-close-button {
251 | left: -.2em;
252 | right: .2em
253 | }
254 | }
255 |
256 | @media all and (min-width:481px) and (max-width:768px) {
257 | #toast-container>div {
258 | padding: 15px 15px 15px 50px;
259 | width: 25em
260 | }
261 |
262 | #toast-container>div.rtl {
263 | padding: 15px 50px 15px 15px
264 | }
265 | }
--------------------------------------------------------------------------------
/user/fill_in_the_blank.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $lessonid = isset($_GET['lessonid']) ? intval($_GET['lessonid']) : null;
5 |
6 | if ($lessonid !== null) {
7 | $lessons_test = $query->select('lessons', '*', "id = '$lessonid'");
8 | } else {
9 | $lessons_test = [];
10 | }
11 |
12 | $edit_blank_id = isset($_GET['edit_blank_id']) ? intval($_GET['edit_blank_id']) : null;
13 |
14 | $blanks = [];
15 | if ($lessonid !== null) {
16 | $blanks = $query->select('fill_in_the_blank', '*', "lesson_id = '$lessonid'");
17 | }
18 |
19 | $edit_blank = null;
20 | if ($edit_blank_id !== null) {
21 | $edit_blank = $query->select('fill_in_the_blank', '*', "id = $edit_blank_id")[0] ?? null;
22 | }
23 |
24 | if ($_SERVER['REQUEST_METHOD'] === 'POST') {
25 | if (isset($_POST['add_blank'])) {
26 | $sentence = $_POST['sentence'];
27 | $correct_answer = $_POST['correct_answer'];
28 |
29 | $blank_id = $query->insert('fill_in_the_blank', [
30 | 'lesson_id' => $lessonid,
31 | 'sentence' => $sentence,
32 | 'correct_answer' => $correct_answer
33 | ]);
34 | } elseif (isset($_POST['update_blank'])) {
35 | $blank_id = $_POST['blank_id'];
36 | $sentence = $_POST['sentence'];
37 | $correct_answer = $_POST['correct_answer'];
38 |
39 | $query->update('fill_in_the_blank', [
40 | 'sentence' => $sentence,
41 | 'correct_answer' => $correct_answer
42 | ], "id = $blank_id");
43 | }
44 | header("Location: ?lessonid=$lessonid");
45 | exit;
46 | }
47 |
48 | if (isset($_GET['delete_id'])) {
49 | $delete_id = $_GET['delete_id'];
50 | $query->delete('fill_in_the_blank', "id = '$delete_id'");
51 | header("Location: ?lessonid=$lessonid");
52 | exit;
53 | }
54 | ?>
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | AdminLTE 3 | Fill in the Blank
65 |
66 |
67 |
68 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | "Home", "url" => "./"],
121 | ["title" => "Fill in the Blank", "url" => "#"],
122 | );
123 | pagePath('Fill in the Blank', $arr);
124 | ?>
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | = $edit_blank ? 'Edit Blank' : 'Add New Blank' ?>
134 |
135 |
136 | Sentence with Blank
137 | = $edit_blank['sentence'] ?? '' ?>
138 |
139 |
140 | Correct Answer
141 |
142 |
143 |
144 |
145 | Save Blank
146 |
147 |
148 |
149 |
150 |
153 |
154 |
155 |
156 | №
157 | Sentence
158 | Actions
159 |
160 |
161 |
162 | $blank): ?>
163 |
164 | = $index + 1 ?>
165 |
166 | = $blank['sentence'] ?>
167 |
168 |
169 | Edit
170 | Delete
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | select('lessons', '*'); ?>
181 |
182 |
183 | Select a Lesson
184 |
185 | -- Select a Lesson --
186 | $lesson): ?>
187 | >
188 | = $index + 1 . ". " . $lesson['title'] ?>
189 |
190 |
191 |
192 |
193 |
194 |
195 | Select Lesson
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
--------------------------------------------------------------------------------
/login/index.php:
--------------------------------------------------------------------------------
1 | select('users', 'id, role', "username = ?", [$username], 's')[0] ?? null;
21 |
22 | if (!empty($user)) {
23 | $_SESSION['loggedin'] = true;
24 | $_SESSION['user_id'] = $user['id'];
25 | $_SESSION['username'] = $username;
26 | $_SESSION['role'] = $user['role'];
27 |
28 | $active_sessions = $query->select("active_sessions", "*", "session_token = ?", [session_id()], "s");
29 |
30 | if (!empty($active_sessions)) {
31 | $query->update(
32 | "active_sessions",
33 | ['last_activity' => date('Y-m-d H:i:s')],
34 | "session_token = ?",
35 | [session_id()],
36 | "s"
37 | );
38 | }
39 |
40 | if (isset(ROLES[$user['role']])) {
41 | header("Location: " . SITE_PATH . ROLES[$_SESSION['role']]);
42 | exit;
43 | }
44 | }
45 | }
46 |
47 | $_SESSION['csrf_token'] ??= bin2hex(random_bytes(32));
48 |
49 | function get_user_info()
50 | {
51 | $user_agent = $_SERVER['HTTP_USER_AGENT'];
52 |
53 | $devices = [
54 | 'iPhone' => 'iPhone',
55 | 'iPad' => 'iPad',
56 | 'Macintosh|Mac OS X' => 'Mac',
57 | 'Windows NT 10.0' => 'Windows 10 PC',
58 | 'Windows NT 6.3' => 'Windows 8.1 PC',
59 | 'Windows NT 6.2' => 'Windows 8 PC',
60 | 'Windows NT 6.1' => 'Windows 7 PC',
61 | 'Android' => 'Android Phone',
62 | 'Linux' => 'Linux Device',
63 | ];
64 |
65 | foreach ($devices as $regex => $device) {
66 | if (preg_match("/$regex/i", $user_agent)) {
67 | return $device;
68 | }
69 | }
70 |
71 | return "Unknown Device";
72 | }
73 |
74 | if (
75 | $_SERVER["REQUEST_METHOD"] === "POST" &&
76 | isset($_POST['submit']) &&
77 | isset($_POST['csrf_token']) &&
78 | isset($_SESSION['csrf_token']) &&
79 | hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])
80 | ) {
81 |
82 | $username = strtolower(trim($_POST['username']));
83 | $password = $query->hashPassword($_POST['password']);
84 | $user = $query->select('users', '*', "username = ? AND password = ?", [$username, $password], 'ss')[0] ?? null;
85 |
86 | if (!empty($user)) {
87 | $_SESSION['loggedin'] = true;
88 | $_SESSION['user_id'] = $user['id'];
89 | $_SESSION['username'] = $user['username'];
90 | $_SESSION['role'] = $user['role'];
91 |
92 | $cookies = [
93 | 'username' => $username,
94 | 'session_token' => session_id()
95 | ];
96 |
97 | foreach ($cookies as $name => $value) {
98 | setcookie($name, $value, [
99 | 'expires' => time() + (86400 * 30),
100 | 'path' => '/',
101 | 'secure' => true,
102 | 'httponly' => true,
103 | 'samesite' => 'Strict'
104 | ]);
105 | }
106 |
107 | $query->insert('active_sessions', [
108 | 'user_id' => $user['id'],
109 | 'device_name' => get_user_info(),
110 | 'ip_address' => $_SERVER['REMOTE_ADDR'],
111 | 'last_activity' => date('Y-m-d H:i:s'),
112 | 'session_token' => session_id()
113 | ]);
114 |
115 | $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
116 |
117 | $redirectPath = SITE_PATH . ROLES[$_SESSION['role']];
118 | ?>
119 |
122 |
125 |
128 |
132 |
135 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | Login
147 |
148 |
149 |
150 |
151 |
152 |
181 |
182 |
235 |
236 |
237 |
--------------------------------------------------------------------------------
/user/matching.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $lessonid = isset($_GET['lessonid']) ? intval($_GET['lessonid']) : null;
5 |
6 | if ($lessonid !== null) {
7 | $lessons_test = $query->select('lessons', '*', "id = '$lessonid'");
8 | } else {
9 | $lessons_test = [];
10 | }
11 |
12 | $edit_matching_id = isset($_GET['edit_matching_id']) ? intval($_GET['edit_matching_id']) : null;
13 |
14 | $matchings = [];
15 | if ($lessonid !== null) {
16 | $matchings = $query->select('matching', '*', "lesson_id = '$lessonid'");
17 | }
18 |
19 | $edit_matching = null;
20 | if ($edit_matching_id !== null) {
21 | $edit_matching = $query->select('matching', '*', "id = $edit_matching_id")[0] ?? null;
22 | }
23 |
24 | if ($_SERVER['REQUEST_METHOD'] === 'POST') {
25 | if (isset($_POST['add_matching'])) {
26 | $left_side = $_POST['left_side'];
27 | $right_side = $_POST['right_side'];
28 |
29 | $matching_id = $query->insert('matching', [
30 | 'lesson_id' => $lessonid,
31 | 'left_side' => $left_side,
32 | 'right_side' => $right_side
33 | ]);
34 | } elseif (isset($_POST['update_matching'])) {
35 | $matching_id = $_POST['matching_id'];
36 | $left_side = $_POST['left_side'];
37 | $right_side = $_POST['right_side'];
38 |
39 | $query->update('matching', [
40 | 'left_side' => $left_side,
41 | 'right_side' => $right_side
42 | ], "id = $matching_id");
43 | }
44 | header("Location: ?lessonid=$lessonid");
45 | exit;
46 | }
47 |
48 | if (isset($_GET['delete_id'])) {
49 | $delete_id = $_GET['delete_id'];
50 | $query->delete('matching', "id = '$delete_id'");
51 | header("Location: ?lessonid=$lessonid");
52 | exit;
53 | }
54 | ?>
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | AdminLTE 3 | Matching
65 |
66 |
67 |
68 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | "Home", "url" => "./"],
121 | ["title" => "Matching", "url" => "#"],
122 | );
123 | pagePath('Matching', $arr);
124 | ?>
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | = $edit_matching ? 'Edit Matching' : 'Add New Matching' ?>
134 |
135 |
136 | Left Side
137 | = $edit_matching['left_side'] ?? '' ?>
138 |
139 |
140 | Right Side
141 |
142 |
143 |
144 |
145 | Save Matching
146 |
147 |
148 |
149 |
150 |
153 |
154 |
155 |
156 | №
157 | Left Side
158 | Right Side
159 | Actions
160 |
161 |
162 |
163 | $matching): ?>
164 |
165 | = $index + 1 ?>
166 |
167 | = $matching['left_side'] ?>
168 |
169 | = $matching['right_side'] ?>
170 |
171 | Edit
172 | Delete
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 | select('lessons', '*'); ?>
183 |
184 |
185 | Select a Lesson
186 |
187 | -- Select a Lesson --
188 | $lesson): ?>
189 | >
190 | = $index + 1 . ". " . $lesson['title'] ?>
191 |
192 |
193 |
194 |
195 |
196 |
197 | Select Lesson
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/user/topics.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $topics = $query->select('lessons', '*');
5 |
6 | if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['insert'])) {
7 | $title = $_POST['title'];
8 | $description = $_POST['description'];
9 |
10 | $insert = $query->insert('lessons', [
11 | 'title' => $title,
12 | 'description' => $description
13 | ]);
14 |
15 | if ($insert) {
16 | header("Location: ./topics.php");
17 | }
18 | }
19 |
20 | if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['delete'])) {
21 | $id = $_POST['id'];
22 | $delete = $query->delete('lessons', "id = $id");
23 |
24 | if ($delete) {
25 | header("Location: ./topics.php");
26 | }
27 | }
28 |
29 | if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['id'])) {
30 | $id = $_POST['id'] ?? null;
31 | $title = $_POST['title'] ?? null;
32 | $description = $_POST['description'] ?? null;
33 |
34 | $update = $query->update('lessons', [
35 | 'title' => $title,
36 | 'description' => $description
37 | ], "id = $id");
38 |
39 | if ($update) {
40 | header("Location: ./topics.php");
41 | }
42 | }
43 | ?>
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | AdminLTE 3 | Topics
53 |
54 |
55 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | "Home", "url" => "./"],
69 | ["title" => "Topics", "url" => "#"],
70 | );
71 | pagePath('Topics', $arr);
72 | ?>
73 |
74 |
75 |
76 |
77 |
78 |
79 |
82 |
83 |
84 |
85 | Title
86 |
87 |
88 |
89 | Description
90 |
91 |
92 | Add Topic
93 |
94 |
95 |
96 |
97 |
98 |
101 |
102 |
103 |
104 |
105 | №
106 | Title
107 | Description
108 | Actions
109 |
110 |
111 |
112 | ";
117 | echo "{$count} ";
118 | echo "{$topic['title']} ";
119 | echo "{$topic['description']} ";
120 | echo "
121 |
127 | Update
128 |
129 |
130 |
131 | Delete
132 |
133 | ";
134 | echo "";
135 | $count++;
136 | }
137 | } else {
138 | echo "No topics found. ";
139 | }
140 | ?>
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
162 |
163 |
164 |
165 | Title
166 |
167 |
168 |
169 | Description
170 |
171 |
172 |
173 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/user/true_false.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $lessonid = isset($_GET['lessonid']) ? intval($_GET['lessonid']) : null;
5 |
6 | if ($lessonid !== null) {
7 | $lessons_test = $query->select('lessons', '*', "id = '$lessonid'");
8 | } else {
9 | $lessons_test = [];
10 | }
11 |
12 | $true_false = [];
13 | if ($lessonid !== null) {
14 | $true_false = $query->select('tru_false', '*', "lesson_id = '$lessonid'");
15 | }
16 |
17 | if ($_SERVER['REQUEST_METHOD'] === 'POST') {
18 | if (isset($_POST['add_true_false'])) {
19 | $statement = ($_POST['statement']);
20 | $is_true = isset($_POST['is_true']) ? 1 : 0;
21 |
22 | $query->insert('tru_false', [
23 | 'lesson_id' => $lessonid,
24 | 'statement' => $statement,
25 | 'is_true' => $is_true
26 | ]);
27 |
28 | header("Location: true_false.php?lessonid=$lessonid");
29 | exit;
30 | }
31 |
32 | if (isset($_POST['update_true_false'])) {
33 | foreach ($_POST['statement'] as $id => $statement) {
34 | $statement = ($statement);
35 | $is_true = isset($_POST['is_true'][$id]) ? 1 : 0;
36 |
37 | $query->update('tru_false', [
38 | 'statement' => $statement,
39 | 'is_true' => $is_true
40 | ], "id = '$id'");
41 | }
42 | header("Location: true_false.php?lessonid=$lessonid");
43 | exit;
44 | }
45 | }
46 |
47 |
48 | if (isset($_GET['delete_id'])) {
49 | $delete_id = $_GET['delete_id'];
50 | $query->delete('tru_false', "id = '$delete_id'");
51 | header("Location: true_false.php?lessonid=$lessonid");
52 | exit;
53 | }
54 | ?>
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Admin | True/False
65 |
66 |
67 |
68 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | "Home", "url" => "./"],
149 | ["title" => "True/False", "url" => "#"],
150 | );
151 | pagePath('True/False', $arr);
152 | ?>
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
179 |
180 |
181 |
182 |
183 |
209 |
210 | Update Questions
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 | select('lessons', '*'); ?>
220 |
221 |
222 | Select a Lesson
223 |
224 | -- Select a Lesson --
225 | $lesson): ?>
226 | >
227 | = $index + 1 . ". " . $lesson['title'] ?>
228 |
229 |
230 |
231 |
232 |
233 |
234 | Select Lesson
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
--------------------------------------------------------------------------------
/user/includes/navbar.php:
--------------------------------------------------------------------------------
1 |
5 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | Home
42 |
43 |
44 | Logout
45 |
46 |
47 |
48 |
49 |
50 |
59 |
60 |
61 |
62 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/user/src/js/toastr.min.js:
--------------------------------------------------------------------------------
1 | ! function (e) {
2 | e(["jquery"], function (e) {
3 | return function () {
4 | function t(e, t, n) {
5 | return g({
6 | type: O.error,
7 | iconClass: m().iconClasses.error,
8 | message: e,
9 | optionsOverride: n,
10 | title: t
11 | })
12 | }
13 |
14 | function n(t, n) {
15 | return t || (t = m()), v = e("#" + t.containerId), v.length ? v : (n && (v = d(t)), v)
16 | }
17 |
18 | function o(e, t, n) {
19 | return g({
20 | type: O.info,
21 | iconClass: m().iconClasses.info,
22 | message: e,
23 | optionsOverride: n,
24 | title: t
25 | })
26 | }
27 |
28 | function s(e) {
29 | C = e
30 | }
31 |
32 | function i(e, t, n) {
33 | return g({
34 | type: O.success,
35 | iconClass: m().iconClasses.success,
36 | message: e,
37 | optionsOverride: n,
38 | title: t
39 | })
40 | }
41 |
42 | function a(e, t, n) {
43 | return g({
44 | type: O.warning,
45 | iconClass: m().iconClasses.warning,
46 | message: e,
47 | optionsOverride: n,
48 | title: t
49 | })
50 | }
51 |
52 | function r(e, t) {
53 | var o = m();
54 | v || n(o), u(e, o, t) || l(o)
55 | }
56 |
57 | function c(t) {
58 | var o = m();
59 | return v || n(o), t && 0 === e(":focus", t).length ? void h(t) : void(v.children().length && v.remove())
60 | }
61 |
62 | function l(t) {
63 | for (var n = v.children(), o = n.length - 1; o >= 0; o--) u(e(n[o]), t)
64 | }
65 |
66 | function u(t, n, o) {
67 | var s = !(!o || !o.force) && o.force;
68 | return !(!t || !s && 0 !== e(":focus", t).length) && (t[n.hideMethod]({
69 | duration: n.hideDuration,
70 | easing: n.hideEasing,
71 | complete: function () {
72 | h(t)
73 | }
74 | }), !0)
75 | }
76 |
77 | function d(t) {
78 | return v = e("
").attr("id", t.containerId).addClass(t.positionClass), v.appendTo(e(t.target)), v
79 | }
80 |
81 | function p() {
82 | return {
83 | tapToDismiss: !0,
84 | toastClass: "toast",
85 | containerId: "toast-container",
86 | debug: !1,
87 | showMethod: "fadeIn",
88 | showDuration: 300,
89 | showEasing: "swing",
90 | onShown: void 0,
91 | hideMethod: "fadeOut",
92 | hideDuration: 1e3,
93 | hideEasing: "swing",
94 | onHidden: void 0,
95 | closeMethod: !1,
96 | closeDuration: !1,
97 | closeEasing: !1,
98 | closeOnHover: !0,
99 | extendedTimeOut: 1e3,
100 | iconClasses: {
101 | error: "toast-error",
102 | info: "toast-info",
103 | success: "toast-success",
104 | warning: "toast-warning"
105 | },
106 | iconClass: "toast-info",
107 | positionClass: "toast-top-right",
108 | timeOut: 5e3,
109 | titleClass: "toast-title",
110 | messageClass: "toast-message",
111 | escapeHtml: !1,
112 | target: "body",
113 | closeHtml: '× ',
114 | closeClass: "toast-close-button",
115 | newestOnTop: !0,
116 | preventDuplicates: !1,
117 | progressBar: !1,
118 | progressClass: "toast-progress",
119 | rtl: !1
120 | }
121 | }
122 |
123 | function f(e) {
124 | C && C(e)
125 | }
126 |
127 | function g(t) {
128 | function o(e) {
129 | return null == e && (e = ""), e.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(//g, ">")
130 | }
131 |
132 | function s() {
133 | c(), u(), d(), p(), g(), C(), l(), i()
134 | }
135 |
136 | function i() {
137 | var e = "";
138 | switch (t.iconClass) {
139 | case "toast-success":
140 | case "toast-info":
141 | e = "polite";
142 | break;
143 | default:
144 | e = "assertive"
145 | }
146 | I.attr("aria-live", e)
147 | }
148 |
149 | function a() {
150 | E.closeOnHover && I.hover(H, D), !E.onclick && E.tapToDismiss && I.click(b), E.closeButton && j && j.click(function (e) {
151 | e.stopPropagation ? e.stopPropagation() : void 0 !== e.cancelBubble && e.cancelBubble !== !0 && (e.cancelBubble = !0), E.onCloseClick && E.onCloseClick(e), b(!0)
152 | }), E.onclick && I.click(function (e) {
153 | E.onclick(e), b()
154 | })
155 | }
156 |
157 | function r() {
158 | I.hide(), I[E.showMethod]({
159 | duration: E.showDuration,
160 | easing: E.showEasing,
161 | complete: E.onShown
162 | }), E.timeOut > 0 && (k = setTimeout(b, E.timeOut), F.maxHideTime = parseFloat(E.timeOut), F.hideEta = (new Date).getTime() + F.maxHideTime, E.progressBar && (F.intervalId = setInterval(x, 10)))
163 | }
164 |
165 | function c() {
166 | t.iconClass && I.addClass(E.toastClass).addClass(y)
167 | }
168 |
169 | function l() {
170 | E.newestOnTop ? v.prepend(I) : v.append(I)
171 | }
172 |
173 | function u() {
174 | if (t.title) {
175 | var e = t.title;
176 | E.escapeHtml && (e = o(t.title)), M.append(e).addClass(E.titleClass), I.append(M)
177 | }
178 | }
179 |
180 | function d() {
181 | if (t.message) {
182 | var e = t.message;
183 | E.escapeHtml && (e = o(t.message)), B.append(e).addClass(E.messageClass), I.append(B)
184 | }
185 | }
186 |
187 | function p() {
188 | E.closeButton && (j.addClass(E.closeClass).attr("role", "button"), I.prepend(j))
189 | }
190 |
191 | function g() {
192 | E.progressBar && (q.addClass(E.progressClass), I.prepend(q))
193 | }
194 |
195 | function C() {
196 | E.rtl && I.addClass("rtl")
197 | }
198 |
199 | function O(e, t) {
200 | if (e.preventDuplicates) {
201 | if (t.message === w) return !0;
202 | w = t.message
203 | }
204 | return !1
205 | }
206 |
207 | function b(t) {
208 | var n = t && E.closeMethod !== !1 ? E.closeMethod : E.hideMethod,
209 | o = t && E.closeDuration !== !1 ? E.closeDuration : E.hideDuration,
210 | s = t && E.closeEasing !== !1 ? E.closeEasing : E.hideEasing;
211 | if (!e(":focus", I).length || t) return clearTimeout(F.intervalId), I[n]({
212 | duration: o,
213 | easing: s,
214 | complete: function () {
215 | h(I), clearTimeout(k), E.onHidden && "hidden" !== P.state && E.onHidden(), P.state = "hidden", P.endTime = new Date, f(P)
216 | }
217 | })
218 | }
219 |
220 | function D() {
221 | (E.timeOut > 0 || E.extendedTimeOut > 0) && (k = setTimeout(b, E.extendedTimeOut), F.maxHideTime = parseFloat(E.extendedTimeOut), F.hideEta = (new Date).getTime() + F.maxHideTime)
222 | }
223 |
224 | function H() {
225 | clearTimeout(k), F.hideEta = 0, I.stop(!0, !0)[E.showMethod]({
226 | duration: E.showDuration,
227 | easing: E.showEasing
228 | })
229 | }
230 |
231 | function x() {
232 | var e = (F.hideEta - (new Date).getTime()) / F.maxHideTime * 100;
233 | q.width(e + "%")
234 | }
235 | var E = m(),
236 | y = t.iconClass || E.iconClass;
237 | if ("undefined" != typeof t.optionsOverride && (E = e.extend(E, t.optionsOverride), y = t.optionsOverride.iconClass || y), !O(E, t)) {
238 | T++, v = n(E, !0);
239 | var k = null,
240 | I = e("
"),
241 | M = e("
"),
242 | B = e("
"),
243 | q = e("
"),
244 | j = e(E.closeHtml),
245 | F = {
246 | intervalId: null,
247 | hideEta: null,
248 | maxHideTime: null
249 | },
250 | P = {
251 | toastId: T,
252 | state: "visible",
253 | startTime: new Date,
254 | options: E,
255 | map: t
256 | };
257 | return s(), r(), a(), f(P), E.debug && console && console.log(P), I
258 | }
259 | }
260 |
261 | function m() {
262 | return e.extend({}, p(), b.options)
263 | }
264 |
265 | function h(e) {
266 | v || (v = n()), e.is(":visible") || (e.remove(), e = null, 0 === v.children().length && (v.remove(), w = void 0))
267 | }
268 | var v, C, w, T = 0,
269 | O = {
270 | error: "error",
271 | info: "info",
272 | success: "success",
273 | warning: "warning"
274 | },
275 | b = {
276 | clear: r,
277 | remove: c,
278 | error: t,
279 | getContainer: n,
280 | info: o,
281 | options: {},
282 | subscribe: s,
283 | success: i,
284 | version: "2.1.4",
285 | warning: a
286 | };
287 | return b
288 | }()
289 | })
290 | }("function" == typeof define && define.amd ? define : function (e, t) {
291 | "undefined" != typeof module && module.exports ? module.exports = t(require("jquery")) : window.toastr = t(window.jQuery)
292 | });
293 | //# sourceMappingURL=toastr.js.map
--------------------------------------------------------------------------------
/user/test.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $lessonid = isset($_GET['lessonid']) ? intval($_GET['lessonid']) : null;
5 |
6 | if ($lessonid !== null) {
7 | $lessons_test = $query->select('lessons', '*', "id = '$lessonid'");
8 | } else {
9 | $lessons_test = [];
10 | }
11 |
12 | $edit_test_id = isset($_GET['edit_test_id']) ? intval($_GET['edit_test_id']) : null;
13 |
14 |
15 |
16 | $tests = [];
17 | if ($lessonid !== null) {
18 | $tests = $query->select('test', '*', "lesson_id = '$lessonid'");
19 | }
20 |
21 | $edit_test = null;
22 | if ($edit_test_id !== null) {
23 | $edit_test = $query->select('test', '*', "id = $edit_test_id")[0] ?? null;
24 | $edit_test_options = $query->select('test_options', '*', "test_id = $edit_test_id");
25 | }
26 |
27 | if ($_SERVER['REQUEST_METHOD'] === 'POST') {
28 | if (isset($_POST['add_test'])) {
29 | $question = $_POST['question'];
30 | $options = $_POST['options'];
31 | $correct_option = $_POST['correct_option'];
32 |
33 | $test_id = $query->insert('test', [
34 | 'lesson_id' => $lessonid,
35 | 'question' => $question
36 | ]);
37 |
38 | foreach ($options as $index => $option) {
39 | $query->insert('test_options', [
40 | 'test_id' => $test_id,
41 | 'option_text' => $option,
42 | 'is_correct' => ($correct_option == $index) ? 1 : 0
43 | ]);
44 | }
45 | } elseif (isset($_POST['update_test'])) {
46 | $test_id = $_POST['test_id'];
47 | $question = $_POST['question'];
48 | $options = $_POST['options'];
49 | $correct_option = $_POST['correct_option'];
50 |
51 | $query->update('test', ['question' => $question], "id = $test_id");
52 | $query->delete('test_options', "test_id = $test_id");
53 |
54 | foreach ($options as $index => $option) {
55 | $query->insert('test_options', [
56 | 'test_id' => $test_id,
57 | 'option_text' => $option,
58 | 'is_correct' => ($correct_option == $index) ? 1 : 0
59 | ]);
60 | }
61 | }
62 | header("Location: ?lessonid=$lessonid");
63 | exit;
64 | }
65 |
66 | if (isset($_GET['delete_id'])) {
67 | $delete_id = $_GET['delete_id'];
68 | $query->delete('test', "id = '$delete_id'");
69 | header("Location: ?lessonid=$lessonid");
70 | exit;
71 | }
72 | ?>
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | AdminLTE 3 | Test
83 |
84 |
85 |
86 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | "Home", "url" => "./"],
139 | ["title" => "Worksheet", "url" => "#"],
140 | );
141 | pagePath('Worksheet', $arr);
142 | ?>
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | = $edit_test ? 'Edit Test' : 'Add New Test' ?>
152 |
153 |
154 | Test Question
155 | = $edit_test['question'] ?? '' ?>
156 |
157 |
158 |
175 |
176 | Add Option
177 |
178 |
179 | Save Test
180 |
181 |
182 |
183 |
184 |
187 |
188 |
189 |
190 | №
191 | Question
192 | Actions
193 |
194 |
195 |
196 | $test): ?>
197 |
198 | = $index + 1 ?>
199 |
200 | = $test['question'] ?>
201 |
202 |
203 | Edit
204 | Delete
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 | select('lessons', '*'); ?>
215 |
216 |
217 | Select a Lesson
218 |
219 | -- Select a Lesson --
220 | $lesson): ?>
221 | >
222 | = $index + 1 . ". " . $lesson['title'] ?>
223 |
224 |
225 |
226 |
227 |
228 |
229 | Select Lesson
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
264 |
265 |
266 |
267 |
--------------------------------------------------------------------------------
/user/question.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $lessonid = isset($_GET['lessonid']) ? intval($_GET['lessonid']) : null;
5 |
6 | if ($lessonid !== null) {
7 | $lessons_test = $query->select('lessons', '*', "id = '$lessonid'");
8 | } else {
9 | $lessons_test = [];
10 | }
11 |
12 | $edit_question_id = isset($_GET['edit_question_id']) ? intval($_GET['edit_question_id']) : null;
13 |
14 | $questions = [];
15 | if ($lessonid !== null) {
16 | $questions = $query->select('questions', '*', "lesson_id = '$lessonid'");
17 | }
18 |
19 | $edit_question = null;
20 | if ($edit_question_id !== null) {
21 | $edit_question = $query->select('questions', '*', "id = $edit_question_id")[0] ?? null;
22 | $edit_answers = $query->select('answers', '*', "question_id = $edit_question_id");
23 | }
24 |
25 | if ($_SERVER['REQUEST_METHOD'] === 'POST') {
26 | if (isset($_POST['add_question'])) {
27 | $question_text = $_POST['question_text'];
28 | $question_id = $query->insert('questions', [
29 | 'lesson_id' => $lessonid,
30 | 'question_text' => $question_text
31 | ]);
32 |
33 | $answers = $_POST['answers'];
34 |
35 | foreach ($answers as $index => $answer) {
36 | $query->insert('answers', [
37 | 'question_id' => $question_id,
38 | 'answer_text' => $answer,
39 | ]);
40 | }
41 | } elseif (isset($_POST['update_question'])) {
42 | $question_id = $_POST['question_id'];
43 | $question_text = $_POST['question_text'];
44 | $query->update('questions', ['question_text' => $question_text], "id = $question_id");
45 |
46 | $query->delete('answers', "question_id = $question_id");
47 |
48 | $answers = $_POST['answers'];
49 |
50 | foreach ($answers as $index => $answer) {
51 | $query->insert('answers', [
52 | 'question_id' => $question_id,
53 | 'answer_text' => $answer
54 | ]);
55 | }
56 | }
57 | header("Location: ?lessonid=$lessonid");
58 | exit;
59 | }
60 |
61 | if (isset($_GET['delete_question_id'])) {
62 | $delete_question_id = $_GET['delete_question_id'];
63 | $query->delete('answers', "question_id = '$delete_question_id'");
64 | $query->delete('questions', "id = '$delete_question_id'");
65 | header("Location: ?lessonid=$lessonid");
66 | exit;
67 | }
68 | ?>
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | AdminLTE 3 | Test
79 |
80 |
81 |
82 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | "Home", "url" => "./"],
135 | ["title" => "Questions", "url" => "#"],
136 | );
137 | pagePath('Questions', $arr);
138 | ?>
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | = $edit_question ? 'Edit Question' : 'Add New Question' ?>
148 |
149 |
150 | Question Text
151 | = $edit_question['question_text'] ?? '' ?>
152 |
153 |
154 |
155 |
Answers:
156 |
157 | $answer): ?>
158 |
159 |
160 | Remove
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | Add Answer
171 |
172 |
173 | Save Question
174 |
175 |
176 |
177 |
178 |
181 |
182 |
183 |
184 | №
185 | Question
186 | Actions
187 |
188 |
189 |
190 | $question): ?>
191 |
192 | = $index + 1 ?>
193 |
194 |
195 | = $question['question_text'] ?>
196 |
197 | Edit
198 | Delete
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | select('lessons', '*'); ?>
209 |
210 |
211 | Select a Lesson
212 |
213 | -- Select a Lesson --
214 | $lesson): ?>
215 | >
216 | = $index + 1 . ". " . $lesson['title'] ?>
217 |
218 |
219 |
220 |
221 |
222 |
223 | Select Lesson
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
261 |
262 |
263 |
264 |
--------------------------------------------------------------------------------
/signup/index.php:
--------------------------------------------------------------------------------
1 | select('users', 'id, role', "username = ?", [$username], 's')[0] ?? null;
21 |
22 | if (!empty($user)) {
23 | $_SESSION['loggedin'] = true;
24 | $_SESSION['user_id'] = $user['id'];
25 | $_SESSION['username'] = $username;
26 | $_SESSION['role'] = $user['role'];
27 |
28 | $active_sessions = $query->select("active_sessions", "*", "session_token = ?", [session_id()], "s");
29 |
30 | if (!empty($active_sessions)) {
31 | $query->update(
32 | "active_sessions",
33 | ['last_activity' => date('Y-m-d H:i:s')],
34 | "session_token = ?",
35 | [session_id()],
36 | "s"
37 | );
38 | }
39 |
40 | if (isset(ROLES[$user['role']])) {
41 | header("Location: " . SITE_PATH . ROLES[$_SESSION['role']]);
42 | exit;
43 | }
44 | }
45 | }
46 |
47 | $_SESSION['csrf_token'] ??= bin2hex(random_bytes(32));
48 |
49 | function get_user_info()
50 | {
51 | $user_agent = $_SERVER['HTTP_USER_AGENT'];
52 |
53 | $devices = [
54 | 'iPhone' => 'iPhone',
55 | 'iPad' => 'iPad',
56 | 'Macintosh|Mac OS X' => 'Mac',
57 | 'Windows NT 10.0' => 'Windows 10 PC',
58 | 'Windows NT 6.3' => 'Windows 8.1 PC',
59 | 'Windows NT 6.2' => 'Windows 8 PC',
60 | 'Windows NT 6.1' => 'Windows 7 PC',
61 | 'Android' => 'Android Phone',
62 | 'Linux' => 'Linux Device',
63 | ];
64 |
65 | foreach ($devices as $regex => $device) {
66 | if (preg_match("/$regex/i", $user_agent)) {
67 | return $device;
68 | }
69 | }
70 |
71 | return "Unknown Device";
72 | }
73 |
74 | if (
75 | $_SERVER["REQUEST_METHOD"] === "POST" &&
76 | isset($_POST['submit']) &&
77 | isset($_POST['csrf_token']) &&
78 | isset($_SESSION['csrf_token']) &&
79 | hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])
80 | ) {
81 |
82 | $first_name = $query->validate($_POST['first_name']);
83 | $last_name = $query->validate($_POST['last_name']);
84 | $email = $query->validate(strtolower($_POST['email']));
85 | $username = $query->validate(strtolower($_POST['username']));
86 | $password = $query->hashPassword($_POST['password']);
87 | $role = 'user'; // default role is 'user'
88 |
89 | $data = [
90 | 'first_name' => $first_name,
91 | 'last_name' => $last_name,
92 | 'email' => $email,
93 | 'username' => $username,
94 | 'password' => $password,
95 | 'role' => $role,
96 | 'created_at' => date('Y-m-d H:i:s'),
97 | 'updated_at' => date('Y-m-d H:i:s')
98 | ];
99 |
100 | $user = $query->insert('users', $data);
101 |
102 | if (!empty($user)) {
103 | $user_id = $query->select('users', 'id', 'username = ?', [$username], 's')[0]['id'];
104 |
105 | $_SESSION['loggedin'] = true;
106 | $_SESSION['user_id'] = $user_id;
107 | $_SESSION['username'] = $username;
108 | $_SESSION['role'] = $role;
109 |
110 | $cookies = [
111 | 'username' => $username,
112 | 'session_token' => session_id()
113 | ];
114 |
115 | foreach ($cookies as $name => $value) {
116 | setcookie($name, $value, [
117 | 'expires' => time() + (86400 * 30),
118 | 'path' => '/',
119 | 'secure' => true,
120 | 'httponly' => true,
121 | 'samesite' => 'Strict'
122 | ]);
123 | }
124 |
125 | $query->insert('active_sessions', [
126 | 'user_id' => $user_id,
127 | 'device_name' => get_user_info(),
128 | 'ip_address' => $_SERVER['REMOTE_ADDR'],
129 | 'last_activity' => date('Y-m-d H:i:s'),
130 | 'session_token' => session_id()
131 | ]);
132 |
133 | $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
134 |
135 | $redirectPath = SITE_PATH . ROLES[$_SESSION['role']];
136 | ?>
137 |
140 |
143 |
146 |
150 |
153 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | Sign Up
165 |
166 |
167 |
168 |
169 |
170 |
212 |
213 |
305 |
306 |
307 |
--------------------------------------------------------------------------------
/test.php:
--------------------------------------------------------------------------------
1 | select('subjects', '*', "url = ?", [$url], 's');
9 |
10 | if (empty($subject)) {
11 | header('Location: ./');
12 | exit();
13 | }
14 |
15 | $subjectid = $subject[0]['id'];
16 |
17 | $tests = $query->select('test', '*', "subject_id = ?", [$subjectid], 'i');
18 | $tru_falses = $query->select('tru_false', '*', "subject_id = ?", [$subjectid], 'i');
19 | $dropdowns = $query->select('dropdown', '*', "subject_id = ?", [$subjectid], 'i');
20 | $fill_in_the_blanks = $query->select('fill_in_the_blank', '*', "subject_id = ?", [$subjectid], 'i');
21 |
22 | shuffle($tests);
23 | shuffle($tru_falses);
24 | shuffle($dropdowns);
25 | shuffle($fill_in_the_blanks);
26 |
27 | if ($_SERVER['REQUEST_METHOD'] == 'POST') {
28 | $correctAnswersCount = 0;
29 |
30 | foreach ($tests as $test) {
31 | $testid = $test['id'];
32 | $correctOption = $query->select('test_options', 'id', "test_id = $testid AND is_correct = 1");
33 |
34 | $correctAnswerId = $correctOption[0]['id'];
35 |
36 | if (isset($_POST["test_answer_$testid"]) && $_POST["test_answer_$testid"] == $correctAnswerId) {
37 | $correctAnswersCount++;
38 | }
39 | }
40 |
41 | foreach ($tru_falses as $tru_false) {
42 | $correctAnswer = $tru_false['is_true'];
43 | if (isset($_POST["tru_false_answer_{$tru_false['id']}"]) && $_POST["tru_false_answer_{$tru_false['id']}"] == $correctAnswer) {
44 | $correctAnswersCount++;
45 | }
46 | }
47 |
48 | foreach ($dropdowns as $dropdown) {
49 | $correctAnswer = $dropdown['correct_answer'];
50 | if (isset($_POST["dropdown_answer_{$dropdown['id']}"]) && $_POST["dropdown_answer_{$dropdown['id']}"] == $correctAnswer) {
51 | $correctAnswersCount++;
52 | }
53 | }
54 |
55 | foreach ($fill_in_the_blanks as $blank) {
56 | $correctAnswer = $blank['correct_answer'];
57 | if (isset($_POST["fill_in_the_blank_answer_{$blank['id']}"]) && strtolower(trim($_POST["fill_in_the_blank_answer_{$blank['id']}"])) == strtolower(trim($correctAnswer))) {
58 | $correctAnswersCount++;
59 | }
60 | }
61 |
62 | $totalQuestions = count($tests) + count($tru_falses) + count($dropdowns) + count($fill_in_the_blanks);
63 | $percentage = ($correctAnswersCount / $totalQuestions) * 100;
64 |
65 | // $query->insert('results', [
66 | // 'subject_id' => $subjectid,
67 | // // 'participant_name' => $participant_name,
68 | // 'answered_questions' => $correctAnswersCount,
69 | // 'total_questions' => $totalQuestions
70 | // ]);
71 | ?>
72 |
91 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Test | = $subject[0]['title'] ?>
102 |
103 |
104 |
105 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 | = $subject[0]['title'] ?>
370 | = $subject[0]['description'] ?>
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
Test Questions
381 |
382 | select('test_options', '*', "test_id = $testid");
385 | shuffle($options);
386 | ?>
387 |
388 |
389 | = ($test_count++) . ') ' . $test['question'] ?>
390 |
391 |
392 |
393 |
394 |
395 | = $option['option_text'] ?>
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
True/False Questions
411 |
412 |
413 |
414 |
415 | = ($test_count++) . ') ' . $tru_false['statement'] ?>
416 |
417 |
418 |
419 |
420 | True
422 |
423 |
424 | False
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
Dropdown Question
439 |
440 | $dropdown): ?>
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 | = ($test_count++) . ') ' . $dropdown['question'] ?>
449 |
450 |
451 |
453 | -- Select Section --
454 |
455 | = $dropdownOption ?>
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
Fill in the Blank Questions
468 |
469 |
470 |
471 |
472 | = ($test_count++) . ') ' . $blank['sentence'] ?>
473 |
474 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
--------------------------------------------------------------------------------
/src/js/adminlte.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * AdminLTE v3.0.4 (https://adminlte.io)
3 | * Copyright 2014-2020 Colorlib
4 | * Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE)
5 | */
6 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).adminlte={})}(this,(function(t){"use strict";var e=function(t){var e="ControlSidebar",i="lte.controlsidebar",n=t.fn[e],s={COLLAPSED:"collapsed.lte.controlsidebar",EXPANDED:"expanded.lte.controlsidebar"},o=".control-sidebar",a=".control-sidebar-content",r='[data-widget="control-sidebar"]',l=".main-header",c=".main-footer",d="control-sidebar-animate",h="control-sidebar-open",f="control-sidebar-slide-open",u="layout-fixed",g="layout-navbar-fixed",p="layout-sm-navbar-fixed",_="layout-md-navbar-fixed",m="layout-lg-navbar-fixed",v="layout-xl-navbar-fixed",C="layout-footer-fixed",y="layout-sm-footer-fixed",b="layout-md-footer-fixed",w="layout-lg-footer-fixed",x="layout-xl-footer-fixed",E={controlsidebarSlide:!0,scrollbarTheme:"os-theme-light",scrollbarAutoHide:"l"},A=function(){function e(t,e){this._element=t,this._config=e,this._init()}var n=e.prototype;return n.collapse=function(){this._config.controlsidebarSlide?(t("html").addClass(d),t("body").removeClass(f).delay(300).queue((function(){t(o).hide(),t("html").removeClass(d),t(this).dequeue()}))):t("body").removeClass(h);var e=t.Event(s.COLLAPSED);t(this._element).trigger(e)},n.show=function(){this._config.controlsidebarSlide?(t("html").addClass(d),t(o).show().delay(10).queue((function(){t("body").addClass(f).delay(300).queue((function(){t("html").removeClass(d),t(this).dequeue()})),t(this).dequeue()}))):t("body").addClass(h);var e=t.Event(s.EXPANDED);t(this._element).trigger(e)},n.toggle=function(){t("body").hasClass(h)||t("body").hasClass(f)?this.collapse():this.show()},n._init=function(){var e=this;this._fixHeight(),this._fixScrollHeight(),t(window).resize((function(){e._fixHeight(),e._fixScrollHeight()})),t(window).scroll((function(){(t("body").hasClass(h)||t("body").hasClass(f))&&e._fixScrollHeight()}))},n._fixScrollHeight=function(){var e={scroll:t(document).height(),window:t(window).height(),header:t(l).outerHeight(),footer:t(c).outerHeight()},i=Math.abs(e.window+t(window).scrollTop()-e.scroll),n=t(window).scrollTop(),s=!1,r=!1;t("body").hasClass(u)&&((t("body").hasClass(g)||t("body").hasClass(p)||t("body").hasClass(_)||t("body").hasClass(m)||t("body").hasClass(v))&&"fixed"===t(l).css("position")&&(s=!0),(t("body").hasClass(C)||t("body").hasClass(y)||t("body").hasClass(b)||t("body").hasClass(w)||t("body").hasClass(x))&&"fixed"===t(c).css("position")&&(r=!0),0===n&&0===i?(t(o).css("bottom",e.footer),t(o).css("top",e.header),t(o+", "+o+" "+a).css("height",e.window-(e.header+e.footer))):i<=e.footer?!1===r?(t(o).css("bottom",e.footer-i),t(o+", "+o+" "+a).css("height",e.window-(e.footer-i))):t(o).css("bottom",e.footer):n<=e.header?!1===s?(t(o).css("top",e.header-n),t(o+", "+o+" "+a).css("height",e.window-(e.header-n))):t(o).css("top",e.header):!1===s?(t(o).css("top",0),t(o+", "+o+" "+a).css("height",e.window)):t(o).css("top",e.header))},n._fixHeight=function(){var e=t(window).height(),i=t(l).outerHeight(),n=t(c).outerHeight();if(t("body").hasClass(u)){var s=e-i;(t("body").hasClass(C)||t("body").hasClass(y)||t("body").hasClass(b)||t("body").hasClass(w)||t("body").hasClass(x))&&"fixed"===t(c).css("position")&&(s=e-i-n),t(o+" "+a).css("height",s),"undefined"!=typeof t.fn.overlayScrollbars&&t(o+" "+a).overlayScrollbars({className:this._config.scrollbarTheme,sizeAutoCapable:!0,scrollbars:{autoHide:this._config.scrollbarAutoHide,clickScrolling:!0}})}},e._jQueryInterface=function(n){return this.each((function(){var s=t(this).data(i),o=t.extend({},E,t(this).data());if(s||(s=new e(this,o),t(this).data(i,s)),"undefined"===s[n])throw new Error(n+" is not a function");s[n]()}))},e}();return t(document).on("click",r,(function(e){e.preventDefault(),A._jQueryInterface.call(t(this),"toggle")})),t.fn[e]=A._jQueryInterface,t.fn[e].Constructor=A,t.fn[e].noConflict=function(){return t.fn[e]=n,A._jQueryInterface},A}(jQuery),i=function(t){var e="Layout",i=t.fn[e],n=".main-header",s=".main-sidebar",o=".main-sidebar .sidebar",a=".content-wrapper",r=".control-sidebar-content",l='[data-widget="control-sidebar"]',c=".main-footer",d='[data-widget="pushmenu"]',h=".login-box",f=".register-box",u="sidebar-focused",g="layout-fixed",p="control-sidebar-slide-open",_="control-sidebar-open",m={scrollbarTheme:"os-theme-light",scrollbarAutoHide:"l",panelAutoHeight:!0,loginRegisterAutoHeight:!0},v=function(){function e(t,e){this._config=e,this._element=t,this._init()}var i=e.prototype;return i.fixLayoutHeight=function(e){void 0===e&&(e=null);var i=0;(t("body").hasClass(p)||t("body").hasClass(_)||"control_sidebar"==e)&&(i=t(r).height());var s={window:t(window).height(),header:0!==t(n).length?t(n).outerHeight():0,footer:0!==t(c).length?t(c).outerHeight():0,sidebar:0!==t(o).length?t(o).height():0,control_sidebar:i},l=this._max(s),d=this._config.panelAutoHeight;!0===d&&(d=0),!1!==d&&(l==s.control_sidebar?t(a).css("min-height",l+d):l==s.window?t(a).css("min-height",l+d-s.header-s.footer):t(a).css("min-height",l+d-s.header)),t("body").hasClass(g)&&(!1!==d&&t(a).css("min-height",l+d-s.header-s.footer),"undefined"!=typeof t.fn.overlayScrollbars&&t(o).overlayScrollbars({className:this._config.scrollbarTheme,sizeAutoCapable:!0,scrollbars:{autoHide:this._config.scrollbarAutoHide,clickScrolling:!0}}))},i.fixLoginRegisterHeight=function(){if(0===t(h+", "+f).length)t("body, html").css("height","auto");else if(0!==t(h+", "+f).length){var e=t(h+", "+f).height();t("body").css("min-height")!==e&&t("body").css("min-height",e)}},i._init=function(){var e=this;this.fixLayoutHeight(),!0===this._config.loginRegisterAutoHeight?this.fixLoginRegisterHeight():Number.isInteger(this._config.loginRegisterAutoHeight)&&setInterval(this.fixLoginRegisterHeight,this._config.loginRegisterAutoHeight),t(o).on("collapsed.lte.treeview expanded.lte.treeview",(function(){e.fixLayoutHeight()})),t(d).on("collapsed.lte.pushmenu shown.lte.pushmenu",(function(){e.fixLayoutHeight()})),t(l).on("collapsed.lte.controlsidebar",(function(){e.fixLayoutHeight()})).on("expanded.lte.controlsidebar",(function(){e.fixLayoutHeight("control_sidebar")})),t(window).resize((function(){e.fixLayoutHeight()})),t("body.hold-transition").removeClass("hold-transition")},i._max=function(t){var e=0;return Object.keys(t).forEach((function(i){t[i]>e&&(e=t[i])})),e},e._jQueryInterface=function(i){return void 0===i&&(i=""),this.each((function(){var n=t(this).data("lte.layout"),s=t.extend({},m,t(this).data());n||(n=new e(t(this),s),t(this).data("lte.layout",n)),"init"===i||""===i?n._init():"fixLayoutHeight"!==i&&"fixLoginRegisterHeight"!==i||n[i]()}))},e}();return t(window).on("load",(function(){v._jQueryInterface.call(t("body"))})),t(o+" a").on("focusin",(function(){t(s).addClass(u)})),t(o+" a").on("focusout",(function(){t(s).removeClass(u)})),t.fn[e]=v._jQueryInterface,t.fn[e].Constructor=v,t.fn[e].noConflict=function(){return t.fn[e]=i,v._jQueryInterface},v}(jQuery),n=function(t){var e="PushMenu",i=".lte.pushmenu",n=t.fn[e],s={COLLAPSED:"collapsed"+i,SHOWN:"shown"+i},o={autoCollapseSize:992,enableRemember:!1,noTransitionAfterReload:!0},a='[data-widget="pushmenu"]',r="body",l="#sidebar-overlay",c=".wrapper",d="sidebar-collapse",h="sidebar-open",f="sidebar-closed",u=function(){function e(e,i){this._element=e,this._options=t.extend({},o,i),t(l).length||this._addOverlay(),this._init()}var n=e.prototype;return n.expand=function(){this._options.autoCollapseSize&&t(window).width()<=this._options.autoCollapseSize&&t(r).addClass(h),t(r).removeClass(d).removeClass(f),this._options.enableRemember&&localStorage.setItem("remember"+i,h);var e=t.Event(s.SHOWN);t(this._element).trigger(e)},n.collapse=function(){this._options.autoCollapseSize&&t(window).width()<=this._options.autoCollapseSize&&t(r).removeClass(h).addClass(f),t(r).addClass(d),this._options.enableRemember&&localStorage.setItem("remember"+i,d);var e=t.Event(s.COLLAPSED);t(this._element).trigger(e)},n.toggle=function(){t(r).hasClass(d)?this.expand():this.collapse()},n.autoCollapse=function(e){void 0===e&&(e=!1),this._options.autoCollapseSize&&(t(window).width()<=this._options.autoCollapseSize?t(r).hasClass(h)||this.collapse():1==e&&(t(r).hasClass(h)?t(r).removeClass(h):t(r).hasClass(f)&&this.expand()))},n.remember=function(){this._options.enableRemember&&(localStorage.getItem("remember"+i)==d?this._options.noTransitionAfterReload?t("body").addClass("hold-transition").addClass(d).delay(50).queue((function(){t(this).removeClass("hold-transition"),t(this).dequeue()})):t("body").addClass(d):this._options.noTransitionAfterReload?t("body").addClass("hold-transition").removeClass(d).delay(50).queue((function(){t(this).removeClass("hold-transition"),t(this).dequeue()})):t("body").removeClass(d))},n._init=function(){var e=this;this.remember(),this.autoCollapse(),t(window).resize((function(){e.autoCollapse(!0)}))},n._addOverlay=function(){var e=this,i=t("
",{id:"sidebar-overlay"});i.on("click",(function(){e.collapse()})),t(c).append(i)},e._jQueryInterface=function(i){return this.each((function(){var n=t(this).data("lte.pushmenu"),s=t.extend({},o,t(this).data());n||(n=new e(this,s),t(this).data("lte.pushmenu",n)),"string"==typeof i&&i.match(/collapse|expand|toggle/)&&n[i]()}))},e}();return t(document).on("click",a,(function(e){e.preventDefault();var i=e.currentTarget;"pushmenu"!==t(i).data("widget")&&(i=t(i).closest(a)),u._jQueryInterface.call(t(i),"toggle")})),t(window).on("load",(function(){u._jQueryInterface.call(t(a))})),t.fn[e]=u._jQueryInterface,t.fn[e].Constructor=u,t.fn[e].noConflict=function(){return t.fn[e]=n,u._jQueryInterface},u}(jQuery),s=function(t){var e="Treeview",i=t.fn[e],n={SELECTED:"selected.lte.treeview",EXPANDED:"expanded.lte.treeview",COLLAPSED:"collapsed.lte.treeview",LOAD_DATA_API:"load.lte.treeview"},s=".nav-item",o=".nav-treeview",a=".menu-open",r='[data-widget="treeview"]',l="menu-open",c="sidebar-collapse",d={trigger:r+" "+".nav-link",animationSpeed:300,accordion:!0,expandSidebar:!1,sidebarButtonSelector:'[data-widget="pushmenu"]'},h=function(){function e(t,e){this._config=e,this._element=t}var i=e.prototype;return i.init=function(){this._setupListeners()},i.expand=function(e,i){var s=this,r=t.Event(n.EXPANDED);if(this._config.accordion){var c=i.siblings(a).first(),d=c.find(o).first();this.collapse(d,c)}e.stop().slideDown(this._config.animationSpeed,(function(){i.addClass(l),t(s._element).trigger(r)})),this._config.expandSidebar&&this._expandSidebar()},i.collapse=function(e,i){var s=this,r=t.Event(n.COLLAPSED);e.stop().slideUp(this._config.animationSpeed,(function(){i.removeClass(l),t(s._element).trigger(r),e.find(a+" > "+o).slideUp(),e.find(a).removeClass(l)}))},i.toggle=function(e){var i=t(e.currentTarget),n=i.parent(),a=n.find("> "+o);if(a.is(o)||(n.is(s)||(a=n.parent().find("> "+o)),a.is(o))){e.preventDefault();var r=i.parents(s).first();r.hasClass(l)?this.collapse(t(a),r):this.expand(t(a),r)}},i._setupListeners=function(){var e=this;t(document).on("click",this._config.trigger,(function(t){e.toggle(t)}))},i._expandSidebar=function(){t("body").hasClass(c)&&t(this._config.sidebarButtonSelector).PushMenu("expand")},e._jQueryInterface=function(i){return this.each((function(){var n=t(this).data("lte.treeview"),s=t.extend({},d,t(this).data());n||(n=new e(t(this),s),t(this).data("lte.treeview",n)),"init"===i&&n[i]()}))},e}();return t(window).on(n.LOAD_DATA_API,(function(){t(r).each((function(){h._jQueryInterface.call(t(this),"init")}))})),t.fn[e]=h._jQueryInterface,t.fn[e].Constructor=h,t.fn[e].noConflict=function(){return t.fn[e]=i,h._jQueryInterface},h}(jQuery),o=function(t){var e="DirectChat",i=t.fn[e],n="toggled{EVENT_KEY}",s='[data-widget="chat-pane-toggle"]',o=".direct-chat",a="direct-chat-contacts-open",r=function(){function e(t,e){this._element=t}return e.prototype.toggle=function(){t(this._element).parents(o).first().toggleClass(a);var e=t.Event(n);t(this._element).trigger(e)},e._jQueryInterface=function(i){return this.each((function(){var n=t(this).data("lte.directchat");n||(n=new e(t(this)),t(this).data("lte.directchat",n)),n[i]()}))},e}();return t(document).on("click",s,(function(e){e&&e.preventDefault(),r._jQueryInterface.call(t(this),"toggle")})),t.fn[e]=r._jQueryInterface,t.fn[e].Constructor=r,t.fn[e].noConflict=function(){return t.fn[e]=i,r._jQueryInterface},r}(jQuery),a=function(t){var e="TodoList",i=t.fn[e],n='[data-widget="todo-list"]',s="done",o={onCheck:function(t){return t},onUnCheck:function(t){return t}},a=function(){function e(t,e){this._config=e,this._element=t,this._init()}var i=e.prototype;return i.toggle=function(e){e.parents("li").toggleClass(s),t(e).prop("checked")?this.check(e):this.unCheck(t(e))},i.check=function(t){this._config.onCheck.call(t)},i.unCheck=function(t){this._config.onUnCheck.call(t)},i._init=function(){var e=this;t(n).find("input:checkbox:checked").parents("li").toggleClass(s),t(n).on("change","input:checkbox",(function(i){e.toggle(t(i.target))}))},e._jQueryInterface=function(i){return this.each((function(){var n=t(this).data("lte.todolist"),s=t.extend({},o,t(this).data());n||(n=new e(t(this),s),t(this).data("lte.todolist",n)),"init"===i&&n[i]()}))},e}();return t(window).on("load",(function(){a._jQueryInterface.call(t(n))})),t.fn[e]=a._jQueryInterface,t.fn[e].Constructor=a,t.fn[e].noConflict=function(){return t.fn[e]=i,a._jQueryInterface},a}(jQuery),r=function(t){var e="CardWidget",i=".lte.cardwidget",n=t.fn[e],s={EXPANDED:"expanded"+i,COLLAPSED:"collapsed"+i,MAXIMIZED:"maximized"+i,MINIMIZED:"minimized"+i,REMOVED:"removed"+i},o="card",a="collapsed-card",r="collapsing-card",l="expanding-card",c="was-collapsed",d="maximized-card",h={DATA_REMOVE:'[data-card-widget="remove"]',DATA_COLLAPSE:'[data-card-widget="collapse"]',DATA_MAXIMIZE:'[data-card-widget="maximize"]',CARD:"."+o,CARD_HEADER:".card-header",CARD_BODY:".card-body",CARD_FOOTER:".card-footer",COLLAPSED:"."+a},f={animationSpeed:"normal",collapseTrigger:h.DATA_COLLAPSE,removeTrigger:h.DATA_REMOVE,maximizeTrigger:h.DATA_MAXIMIZE,collapseIcon:"fa-minus",expandIcon:"fa-plus",maximizeIcon:"fa-expand",minimizeIcon:"fa-compress"},u=function(){function e(e,i){this._element=e,this._parent=e.parents(h.CARD).first(),e.hasClass(o)&&(this._parent=e),this._settings=t.extend({},f,i)}var i=e.prototype;return i.collapse=function(){var e=this;this._parent.addClass(r).children(h.CARD_BODY+", "+h.CARD_FOOTER).slideUp(this._settings.animationSpeed,(function(){e._parent.addClass(a).removeClass(r)})),this._parent.find("> "+h.CARD_HEADER+" "+this._settings.collapseTrigger+" ."+this._settings.collapseIcon).addClass(this._settings.expandIcon).removeClass(this._settings.collapseIcon);var i=t.Event(s.COLLAPSED);this._element.trigger(i,this._parent)},i.expand=function(){var e=this;this._parent.addClass(l).children(h.CARD_BODY+", "+h.CARD_FOOTER).slideDown(this._settings.animationSpeed,(function(){e._parent.removeClass(a).removeClass(l)})),this._parent.find("> "+h.CARD_HEADER+" "+this._settings.collapseTrigger+" ."+this._settings.expandIcon).addClass(this._settings.collapseIcon).removeClass(this._settings.expandIcon);var i=t.Event(s.EXPANDED);this._element.trigger(i,this._parent)},i.remove=function(){this._parent.slideUp();var e=t.Event(s.REMOVED);this._element.trigger(e,this._parent)},i.toggle=function(){this._parent.hasClass(a)?this.expand():this.collapse()},i.maximize=function(){this._parent.find(this._settings.maximizeTrigger+" ."+this._settings.maximizeIcon).addClass(this._settings.minimizeIcon).removeClass(this._settings.maximizeIcon),this._parent.css({height:this._parent.height(),width:this._parent.width(),transition:"all .15s"}).delay(150).queue((function(){t(this).addClass(d),t("html").addClass(d),t(this).hasClass(a)&&t(this).addClass(c),t(this).dequeue()}));var e=t.Event(s.MAXIMIZED);this._element.trigger(e,this._parent)},i.minimize=function(){this._parent.find(this._settings.maximizeTrigger+" ."+this._settings.minimizeIcon).addClass(this._settings.maximizeIcon).removeClass(this._settings.minimizeIcon),this._parent.css("cssText","height:"+this._parent[0].style.height+" !important;width:"+this._parent[0].style.width+" !important; transition: all .15s;").delay(10).queue((function(){t(this).removeClass(d),t("html").removeClass(d),t(this).css({height:"inherit",width:"inherit"}),t(this).hasClass(c)&&t(this).removeClass(c),t(this).dequeue()}));var e=t.Event(s.MINIMIZED);this._element.trigger(e,this._parent)},i.toggleMaximize=function(){this._parent.hasClass(d)?this.minimize():this.maximize()},i._init=function(e){var i=this;this._parent=e,t(this).find(this._settings.collapseTrigger).click((function(){i.toggle()})),t(this).find(this._settings.maximizeTrigger).click((function(){i.toggleMaximize()})),t(this).find(this._settings.removeTrigger).click((function(){i.remove()}))},e._jQueryInterface=function(i){var n=t(this).data("lte.cardwidget"),s=t.extend({},f,t(this).data());n||(n=new e(t(this),s),t(this).data("lte.cardwidget","string"==typeof i?n:i)),"string"==typeof i&&i.match(/collapse|expand|remove|toggle|maximize|minimize|toggleMaximize/)?n[i]():"object"==typeof i&&n._init(t(this))},e}();return t(document).on("click",h.DATA_COLLAPSE,(function(e){e&&e.preventDefault(),u._jQueryInterface.call(t(this),"toggle")})),t(document).on("click",h.DATA_REMOVE,(function(e){e&&e.preventDefault(),u._jQueryInterface.call(t(this),"remove")})),t(document).on("click",h.DATA_MAXIMIZE,(function(e){e&&e.preventDefault(),u._jQueryInterface.call(t(this),"toggleMaximize")})),t.fn[e]=u._jQueryInterface,t.fn[e].Constructor=u,t.fn[e].noConflict=function(){return t.fn[e]=n,u._jQueryInterface},u}(jQuery),l=function(t){var e="CardRefresh",i=t.fn[e],n={LOADED:"loaded.lte.cardrefresh",OVERLAY_ADDED:"overlay.added.lte.cardrefresh",OVERLAY_REMOVED:"overlay.removed.lte.cardrefresh"},s="card",o={CARD:"."+s,DATA_REFRESH:'[data-card-widget="card-refresh"]'},a={source:"",sourceSelector:"",params:{},trigger:o.DATA_REFRESH,content:".card-body",loadInContent:!0,loadOnInit:!0,responseType:"",overlayTemplate:'
',onLoadStart:function(){},onLoadDone:function(t){return t}},r=function(){function e(e,i){if(this._element=e,this._parent=e.parents(o.CARD).first(),this._settings=t.extend({},a,i),this._overlay=t(this._settings.overlayTemplate),e.hasClass(s)&&(this._parent=e),""===this._settings.source)throw new Error("Source url was not defined. Please specify a url in your CardRefresh source option.")}var i=e.prototype;return i.load=function(){this._addOverlay(),this._settings.onLoadStart.call(t(this)),t.get(this._settings.source,this._settings.params,function(e){this._settings.loadInContent&&(""!=this._settings.sourceSelector&&(e=t(e).find(this._settings.sourceSelector).html()),this._parent.find(this._settings.content).html(e)),this._settings.onLoadDone.call(t(this),e),this._removeOverlay()}.bind(this),""!==this._settings.responseType&&this._settings.responseType);var e=t.Event(n.LOADED);t(this._element).trigger(e)},i._addOverlay=function(){this._parent.append(this._overlay);var e=t.Event(n.OVERLAY_ADDED);t(this._element).trigger(e)},i._removeOverlay=function(){this._parent.find(this._overlay).remove();var e=t.Event(n.OVERLAY_REMOVED);t(this._element).trigger(e)},i._init=function(e){var i=this;t(this).find(this._settings.trigger).on("click",(function(){i.load()})),this._settings.loadOnInit&&this.load()},e._jQueryInterface=function(i){var n=t(this).data("lte.cardrefresh"),s=t.extend({},a,t(this).data());n||(n=new e(t(this),s),t(this).data("lte.cardrefresh","string"==typeof i?n:i)),"string"==typeof i&&i.match(/load/)?n[i]():n._init(t(this))},e}();return t(document).on("click",o.DATA_REFRESH,(function(e){e&&e.preventDefault(),r._jQueryInterface.call(t(this),"load")})),t(document).ready((function(){t(o.DATA_REFRESH).each((function(){r._jQueryInterface.call(t(this))}))})),t.fn[e]=r._jQueryInterface,t.fn[e].Constructor=r,t.fn[e].noConflict=function(){return t.fn[e]=i,r._jQueryInterface},r}(jQuery),c=function(t){var e="Dropdown",i=t.fn[e],n=".navbar",s=".dropdown-menu",o=".dropdown-menu.show",a='[data-toggle="dropdown"]',r="dropdown-menu-right",l={},c=function(){function e(t,e){this._config=e,this._element=t}var i=e.prototype;return i.toggleSubmenu=function(){this._element.siblings().show().toggleClass("show"),this._element.next().hasClass("show")||this._element.parents(".dropdown-menu").first().find(".show").removeClass("show").hide(),this._element.parents("li.nav-item.dropdown.show").on("hidden.bs.dropdown",(function(e){t(".dropdown-submenu .show").removeClass("show").hide()}))},i.fixPosition=function(){var e=t(o);if(0!==e.length){e.hasClass(r)?(e.css("left","inherit"),e.css("right",0)):(e.css("left",0),e.css("right","inherit"));var i=e.offset(),n=e.width(),s=t(window).width()-i.left;i.left<0?(e.css("left","inherit"),e.css("right",i.left-5)):s ');e.data("autohide",this._config.autohide),e.data("animation",this._config.fade),this._config.class&&e.addClass(this._config.class),this._config.delay&&500!=this._config.delay&&e.data("delay",this._config.delay);var i=t('