Add backend to repo

This commit is contained in:
Artur Savitskiy 2024-03-04 16:07:16 +01:00
parent a57f557f20
commit 331f59e459
74 changed files with 705 additions and 89 deletions

View File

@ -0,0 +1,38 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/strings.php');
$method = $_SERVER['REQUEST_METHOD'];
if ('POST' === $method) {
parse_str(file_get_contents('php://input'), $_POST);
}
$connection = connect();
$returnValue = array();
$querystr = "SELECT * FROM li_courses ORDER BY name";
$result = mysqli_query($connection, $querystr);
if($result->num_rows !== 0) {
while ($row = mysqli_fetch_object($result)) {
$student = (object) [
'cid' => $row->cid,
'name' => $row->name . ' ' . $row->description,
'diffname' => $row->diffname,
];
array_push($returnValue, $student);
}
}
mysqli_free_result($result);
echo json_encode($returnValue);
?>

View File

@ -0,0 +1,36 @@
<?php
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/strings.php');
$connection = connect();
$cid = intval($_GET["cid"]);
$date = mysqli_real_escape_string($connection, $_GET["date"]);
$returnValue = array();
$querystr = "SELECT * FROM li_enroll, li_students
WHERE li_enroll.sid = li_students.sid
AND li_enroll.cid = $cid
AND li_enroll.begin < '{$date}'
AND li_enroll.end > '{$date}'";
$result = mysqli_query($connection, $querystr);
if($result->num_rows !== 0) {
while ($row = mysqli_fetch_object($result)) {
$student = (object) [
'sid' => $row->sid,
'firstname' => $row->firstname,
'lastname' => $row->lastname,
];
array_push($returnValue, $student);
}
}
mysqli_free_result($result);
echo json_encode($returnValue);
?>

View File

@ -0,0 +1,50 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/tools.php');
$method = $_SERVER['REQUEST_METHOD'];
if ('POST' === $method) {
parse_str(file_get_contents('php://input'), $_POST);
}
$connection = connect();
$sid = intval($_POST["sid"]);
$enrollments = json_decode($_POST["enrollments"]);
if (!is_array($enrollments)) {
die('No array provided');
}
if ($sid == -1) {
$result = mysqli_query($connection, "SELECT MAX(sid) as maxid FROM li_students");
if($result->num_rows !== 0) {
$row = mysqli_fetch_object($result);
$sid = $row->maxid;
}
}
$querystr = "DELETE FROM li_enroll WHERE sid={$sid}";
mysqli_query($connection, $querystr);
foreach ($enrollments as $enrollment) {
$cid = intval($enrollment->cid);
$begin = escape($connection, $enrollment->begin);
$end = escape($connection, $enrollment->end);
if(empty($end)) { $end = '2100-01-01'; }
$querystr = "INSERT INTO li_enroll VALUES({$cid}, {$sid}, '{$begin}', '{$end}')";
mysqli_query($connection, $querystr);
}
echo json_encode('{ "result": "true" }');
?>

View File

@ -0,0 +1,25 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/strings.php');
$method = $_SERVER['REQUEST_METHOD'];
if ('POST' === $method) {
parse_str(file_get_contents('php://input'), $_POST);
}
$connection = connect();
$sid = intval($_POST["sid"]);
$querystr = "DELETE FROM li_students WHERE sid=${sid}";
mysqli_query($connection, $querystr);
echo json_encode('{ "result": "true" }');
?>

View File

@ -0,0 +1,61 @@
<?php
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/strings.php');
$connection = connect();
$returnValue = array();
$querystr = "SELECT * FROM li_students";
$result = mysqli_query($connection, $querystr);
if($result->num_rows !== 0) {
while ($row = mysqli_fetch_object($result)) {
$student = (object) [
'sid' => $row->sid,
'firstname' => $row->firstname,
'lastname' => $row->lastname,
'birthday' => $row->birthday,
'gender' => $row->gender,
'street' => $row->street,
'house' => $row->house,
'house_suffix' => $row->house_suffix,
'zip' => $row->zip,
'city' => $row->city,
'phone' => $row->phone,
'email' => $row->email,
'enrollments' => array()
];
$querystr2 = "SELECT * FROM li_enroll, li_courses
WHERE li_enroll.cid = li_courses.cid
AND li_enroll.sid = {$student->sid}";
$result2 = mysqli_query($connection, $querystr2);
if($result2->num_rows !== 0) {
while ($row = mysqli_fetch_object($result2)) {
$begin = new DateTime($row->begin);
$end = new DateTime($row->end);
$enrollment = (object) [
'cid' => $row->cid,
'name' => $row->name . ' ' . $row->description,
'diffname' => $row->diffname,
'begin' => $begin->format('Y-m-d'),
'end' => $end->format('Y-m-d')
];
array_push($student->enrollments, $enrollment);
}
}
array_push($returnValue, $student);
}
}
mysqli_free_result($result);
header("Access-Control-Allow-Origin: *");
echo json_encode($returnValue);
?>

View File

@ -0,0 +1,48 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/tools.php');
$method = $_SERVER['REQUEST_METHOD'];
if ('POST' === $method) {
parse_str(file_get_contents('php://input'), $_POST);
}
$connection = connect();
$sid = intval($_POST["sid"]);
$firstname = escape($connection, $_POST["firstname"]);
$lastname = escape($connection, $_POST["lastname"]);
$birthday = escape($connection, $_POST["birthday"]);
$gender = intval($_POST["gender"]);
$street = escape($connection, $_POST["street"]);
$house = intval($_POST["house"]);
$house_suffix = escape($connection, $_POST["house_suffix"]);
$zip = escape($connection, $_POST["zip"]);
$city = escape($connection, $_POST["city"]);
$phone = escape($connection, $_POST["phone"]);
$email = escape($connection, $_POST["email"]);
$querystr = "SELECT * FROM li_students
WHERE li_students.sid = ${sid}";
$result = mysqli_query($connection, $querystr);
if($result->num_rows !== 0) {
$querystr = "UPDATE li_students SET firstname='${firstname}', lastname='${lastname}', birthday='${birthday}',
gender=${gender}, street='${street}', house=${house}, house_suffix='${house_suffix}',
zip='${zip}', city='${city}', phone='${phone}', email='${email}'
WHERE sid=${sid}";
} else {
$querystr = "INSERT INTO li_students (firstname, lastname, birthday, gender, street, house, house_suffix, zip, city, phone, email)
VALUES('{$firstname}', '{$lastname}', '{$birthday}', {$gender}, '{$street}', {$house}, '{$house_suffix}', '{$zip}', '{$city}', '{$phone}', '{$email}')";
}
$result = mysqli_query($connection, $querystr);
echo json_encode('{ "result": "' . $result . '" }');
?>

View File

@ -0,0 +1,30 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/strings.php');
$method = $_SERVER['REQUEST_METHOD'];
if ('POST' === $method) {
parse_str(file_get_contents('php://input'), $_POST);
}
$connection = connect();
$date = mysqli_real_escape_string($connection, $_POST["date"]);
$cid = intval($_POST["cid"]);
$sid = intval($_POST["sid"]);
$querystr = "DELETE FROM li_visits
WHERE cid={$cid}
AND sid={$sid}
AND date='{$date}'";
mysqli_query($connection, $querystr);
echo json_encode('{ "result": "true" }');
?>

View File

@ -0,0 +1,87 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/strings.php');
$method = $_SERVER['REQUEST_METHOD'];
if ('POST' === $method) {
parse_str(file_get_contents('php://input'), $_POST);
}
$connection = connect();
$date = mysqli_real_escape_string($connection, $_POST["date"]);
$time = mysqli_real_escape_string($connection, $_POST["time"]);
$dow = (new DateTime($date))->format('w');
$querystr = "SELECT * FROM li_plan, li_courses
WHERE li_plan.cid=li_courses.cid
AND li_plan.day={$dow}
AND li_plan.begin < '{$time}'
AND li_plan.end > '{$time}'";
$result = mysqli_query($connection, $querystr);
if($result->num_rows !== 0) {
while ($row = mysqli_fetch_object($result)) {
$begin = new DateTime($row->begin);
$end = new DateTime($row->end);
$returnValue = (object) [
'cid' => $row->cid,
'name' => $row->name . ' ' . $row->description,
'date' => $date,
'begin' => $begin->format('H:i'),
'end' => $end->format('H:i'),
'students' => array()
];
break;
}
$querystr = "SELECT *, 1 AS visited FROM li_enroll, li_students
WHERE li_enroll.sid = li_students.sid
AND li_enroll.cid = {$returnValue->cid}
AND li_enroll.begin <= '{$date}'
AND li_enroll.end >= '{$date}'
AND EXISTS(SELECT * FROM li_visits
WHERE li_visits.sid = li_enroll.sid
AND li_visits.cid = li_enroll.cid
AND li_visits.date = '{$date}')
UNION
SELECT *, 0 AS visited FROM li_enroll, li_students
WHERE li_enroll.sid = li_students.sid
AND li_enroll.cid = {$returnValue->cid}
AND li_enroll.begin <= '{$date}'
AND li_enroll.end >= '{$date}'
AND NOT EXISTS(SELECT * FROM li_visits
WHERE li_visits.sid = li_enroll.sid
AND li_visits.cid = li_enroll.cid
AND li_visits.date = '{$date}')
ORDER BY lastname, firstname";
$result2 = mysqli_query($connection, $querystr);
if($result2->num_rows !== 0) {
while ($row = mysqli_fetch_object($result2)) {
$student = (object) [
'sid' => $row->sid,
'firstname' => $row->firstname,
'lastname' => $row->lastname,
'visited' => $row->visited
];
array_push($returnValue->students, $student);
}
}
}
mysqli_free_result($result);
echo json_encode($returnValue);
?>

View File

@ -0,0 +1,26 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
require_once('../../utils/config.php');
require_once('../../utils/db.php');
require_once('../../utils/strings.php');
$method = $_SERVER['REQUEST_METHOD'];
if ('POST' === $method) {
parse_str(file_get_contents('php://input'), $_POST);
}
$connection = connect();
$date = mysqli_real_escape_string($connection, $_POST["date"]);
$cid = intval($_POST["cid"]);
$sid = intval($_POST["sid"]);
$querystr = "INSERT INTO li_visits VALUES({$cid}, {$sid}, '{$date}')";
mysqli_query($connection, $querystr);
echo json_encode('{ "result": "true" }');
?>

11
backend/utils/config.php Normal file
View File

@ -0,0 +1,11 @@
<?php
define('DB_SERVER','mysql');
define('DB_USER','db308647');
define('DB_PASSWORD','1&9r9t6u1r0');
define('DB_NAME','db308647');
define('IMAGE_PATH', dirname($_SERVER["REQUEST_URI"]) . '/images/');
define('MAGIC_WORD', 'AED717B292EE4F08A0AEE4EBA4B1B1FA');
define('MAGIC_DATE', 'YmdHi');
?>

35
backend/utils/db.php Normal file
View File

@ -0,0 +1,35 @@
<?php
function connect()
{
$db_server = DB_SERVER;
$db_benutzer = DB_USER;
$db_passwort = DB_PASSWORD;
$db_name = DB_NAME;
# Verbindungsaufbau
if($connection = mysqli_connect($db_server, $db_benutzer, $db_passwort)) {
# echo 'Server-Verbindung erfolgreich, w&auml;hle Datenbank aus...';
if(mysqli_select_db($connection, $db_name)) {
# echo 'Datenbank erfolgreich ausgew&auml;lt, alle Tests abgeschlossen.';
mysqli_set_charset($connection, 'utf8');
}
else {
echo 'Die angegebene Datenbank konnte nicht ausgew&auml;hlt werden, bitte die Eingabe pr&uuml;fen!';
}
return $connection;
}
else {
echo 'Verbindung nicht m&ouml;glich, bitte Daten pr&uuml;fen!';
echo 'MYSQL-Fehler: '.mysqli_connect_error();
}
}
function disconnect()
{
if( $connection ) {
mysqli_close($connection);
}
}

27
backend/utils/strings.php Normal file
View File

@ -0,0 +1,27 @@
<?php
$operation_success = "Operation erfolgreich!";
$operation_result = "Ergebnis";
$access_denied = "Sie sind nicht berechtigt um auf diesen Teil der Seite zuzugreifen!";
$week = array( 1 => 'Montag',
2 => 'Dienstag',
3 => 'Mittwoch',
4 => 'Donnerstag',
5 => 'Freitag',
6 => 'Samstag',
7 => 'Sonntag' );
$month = array( 1 => 'Januar',
2 => 'Februar',
3 => 'M&auml;rz',
4 => 'April',
5 => 'Mai',
6 => 'Juni',
7 => 'Juli',
8 => 'August',
9 => 'September',
10 => 'Oktober',
11 => 'November',
12 => 'Dezember' );
?>

46
backend/utils/tools.php Normal file
View File

@ -0,0 +1,46 @@
<?php
function umlaute($string) {
$string = str_replace("ä", "&auml;", $string);
$string = str_replace("ü", "&uuml;", $string);
$string = str_replace("ö", "&ouml;", $string);
$string = str_replace("Ä", "&Auml;", $string);
$string = str_replace("Ü", "&Uuml;", $string);
$string = str_replace("Ö", "&Ouml;", $string);
return $string;
}
function escape($connection, $string) {
return str_replace('\n','', trim(mysqli_real_escape_string($connection, $string)));
}
function timeLessThan($hour1, $minute1, $hour2, $minute2) {
$val1 = $hour1 * 60 + $minute1;
$val2 = $hour2 * 60 + $minute2;
if( $val1 < $val2 ){
return true;
} else {
return false;
}
}
function timeI2S( $hour, $minute, $separator ) {
return str_pad($hour, 2, '0') . $separator . str_pad($minute, 2, '0');
}
function stepCount($hour1, $minute1, $hour2, $minute2, $intervall) {
$val1 = $hour1 * 60 + $minute1;
$val2 = $hour2 * 60 + $minute2;
$retval = (($val2 - $val1) / $intervall);
return $retval;
}
function login( $token ) {
$expectedToken = sha1( MAGIC_WORD . date(MAGIC_DATE) );
return ($expectedToken === $token);
}
?>

View File

View File

@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"@angular/animations": "~13.1.0",
"@angular/cdk": "^13.1.0",
"@angular/common": "~13.1.0",
"@angular/compiler": "~13.1.0",
"@angular/core": "~13.1.0",
@ -354,7 +355,6 @@
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-13.1.0.tgz",
"integrity": "sha512-OOMDmXnCpodYMEbRro8FUcXqQ8UN3lU/OXnuuDhHOJIrb7loizSGKkJdaVLZtM9ygH7qbOxRhkC2efjmtIn48g==",
"peer": true,
"dependencies": {
"tslib": "^2.3.0"
},
@ -371,8 +371,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
"integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
"optional": true,
"peer": true
"optional": true
},
"node_modules/@angular/cli": {
"version": "13.1.4",
@ -2979,9 +2978,9 @@
}
},
"node_modules/adjust-sourcemap-loader/node_modules/loader-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"dependencies": {
"big.js": "^5.2.2",
@ -3275,9 +3274,9 @@
}
},
"node_modules/babel-loader/node_modules/json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"dependencies": {
"minimist": "^1.2.0"
@ -3287,9 +3286,9 @@
}
},
"node_modules/babel-loader/node_modules/loader-utils": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
"dev": true,
"dependencies": {
"big.js": "^5.2.2",
@ -4466,9 +4465,9 @@
}
},
"node_modules/decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==",
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
"integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
"dev": true,
"engines": {
"node": ">=0.10"
@ -4816,9 +4815,9 @@
}
},
"node_modules/engine.io": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
"integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
"dev": true,
"dependencies": {
"@types/cookie": "^0.4.1",
@ -6030,9 +6029,9 @@
"dev": true
},
"node_modules/http-cache-semantics": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
"dev": true
},
"node_modules/http-deceiver": {
@ -6885,9 +6884,9 @@
"dev": true
},
"node_modules/json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"bin": {
"json5": "lib/cli.js"
@ -9645,9 +9644,9 @@
}
},
"node_modules/resolve-url-loader/node_modules/loader-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"dependencies": {
"big.js": "^5.2.2",
@ -10872,9 +10871,9 @@
}
},
"node_modules/ua-parser-js": {
"version": "0.7.32",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz",
"integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==",
"version": "0.7.35",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz",
"integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==",
"dev": true,
"funding": [
{
@ -11796,7 +11795,6 @@
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-13.1.0.tgz",
"integrity": "sha512-OOMDmXnCpodYMEbRro8FUcXqQ8UN3lU/OXnuuDhHOJIrb7loizSGKkJdaVLZtM9ygH7qbOxRhkC2efjmtIn48g==",
"peer": true,
"requires": {
"parse5": "^5.0.0",
"tslib": "^2.3.0"
@ -11806,8 +11804,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
"integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
"optional": true,
"peer": true
"optional": true
}
}
},
@ -13732,9 +13729,9 @@
},
"dependencies": {
"loader-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@ -13937,18 +13934,18 @@
},
"dependencies": {
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
}
},
"loader-utils": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@ -14818,9 +14815,9 @@
}
},
"decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==",
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
"integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
"dev": true
},
"deep-equal": {
@ -15095,9 +15092,9 @@
}
},
"engine.io": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
"integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
"dev": true,
"requires": {
"@types/cookie": "^0.4.1",
@ -15990,9 +15987,9 @@
"dev": true
},
"http-cache-semantics": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
"dev": true
},
"http-deceiver": {
@ -16616,9 +16613,9 @@
"dev": true
},
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"jsonc-parser": {
@ -18583,9 +18580,9 @@
},
"dependencies": {
"loader-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
"integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@ -19489,9 +19486,9 @@
"dev": true
},
"ua-parser-js": {
"version": "0.7.32",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz",
"integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==",
"version": "0.7.35",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz",
"integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==",
"dev": true
},
"unicode-canonical-property-names-ecmascript": {

View File

@ -11,6 +11,7 @@
"private": true,
"dependencies": {
"@angular/animations": "~13.1.0",
"@angular/cdk": "^13.1.0",
"@angular/common": "~13.1.0",
"@angular/compiler": "~13.1.0",
"@angular/core": "~13.1.0",

View File

@ -2,10 +2,12 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { StudentListComponent } from './components/students/student-list/student-list.component';
import { VisitsComponent } from './components/visits/visits.component';
import { VisitsDatetimeComponent } from './components/visits/visits-datetime/visits-datetime.component';
const routes: Routes = [
{ path: 'students', component: StudentListComponent },
{ path: 'visits', component: VisitsComponent },
{ path: 'select', component: VisitsDatetimeComponent },
{ path: 'visits/:date/:time', component: VisitsComponent },
{ path: '**', redirectTo: 'students' }
];

View File

@ -16,6 +16,10 @@ import { EnrollPipe } from './pipes/enroll.pipe';
import { VisitsComponent } from './components/visits/visits.component';
import { StudentEditComponent } from './components/students/student-edit/student-edit.component';
import { StudentEnrollComponent } from './components/students/student-enroll/student-enroll.component';
import { VisitsDatetimeComponent } from './components/visits/visits-datetime/visits-datetime.component';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
@NgModule({
declarations: [
@ -27,7 +31,8 @@ import { StudentEnrollComponent } from './components/students/student-enroll/stu
NamePipe,
EnrollPipe,
VisitsComponent,
StudentEnrollComponent
StudentEnrollComponent,
VisitsDatetimeComponent
],
imports: [
BrowserModule,
@ -38,6 +43,10 @@ import { StudentEnrollComponent } from './components/students/student-enroll/stu
MatTableModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatDatepickerModule,
MatFormFieldModule,
MatRippleModule,
MatNativeDateModule,
],
providers: [],
bootstrap: [AppComponent]

View File

@ -0,0 +1,4 @@
<div>
<mat-calendar [(selected)]="selected"></mat-calendar>
<p>Selected date: {{selected}}</p>
</div>

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VisitsDatetimeComponent } from './visits-datetime.component';
describe('VisitsDatetimeComponent', () => {
let component: VisitsDatetimeComponent;
let fixture: ComponentFixture<VisitsDatetimeComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ VisitsDatetimeComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(VisitsDatetimeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,17 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'li-visits-datetime',
templateUrl: './visits-datetime.component.html',
styleUrls: ['./visits-datetime.component.scss']
})
export class VisitsDatetimeComponent implements OnInit {
selected: Date = new Date();
constructor() { }
ngOnInit(): void {
}
}

View File

View File

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 948 B

68
frontend/src/styles.scss Normal file
View File

@ -0,0 +1,68 @@
/* Provide sufficient contrast against white background */
@import "~bootstrap-icons/font/bootstrap-icons.css";
a {
color: #0366d6;
}
code {
color: #e01a76;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
html,
body {
height: 100%;
}
body {
background-color: rgb(245, 126, 32);
margin: 0;
font-family: Roboto, "Helvetica Neue", sans-serif;
}
.mat-calendar-body-cell-content {
background-color: #1861ac;
color: #fff;
font-weight: bold;
font-size: 2em;
}
.mat-calendar-table {
border: 1px solid white;
}
.mat-calendar-table-header {
tr {
th {
padding-top: 2em;
}
th.mat-calendar-table-header-divider {
padding: 0;
}
}
}
.mat-calendar-controls,
.mat-calendar-table-header,
.mat-calendar-body-label {
color: #fff;
font-size: 2em;
}
.mat-calendar-previous-button,
.mat-calendar-next-button,
.mat-calendar-period-button {
font-size: 2em;
height: 2em;
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}

View File

@ -1,27 +0,0 @@
/* Provide sufficient contrast against white background */
@import "~bootstrap-icons/font/bootstrap-icons.css";
a {
color: #0366d6;
}
code {
color: #e01a76;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
html,
body {
height: 100%;
}
body {
background-color: rgb(245, 126, 32);
margin: 0;
font-family: Roboto, "Helvetica Neue", sans-serif;
}