dienstplancreator git · main
Dienstplan (roster) creator, PHP/JS web app
JavaScript 50% PHP 40.5% CSS 8.5%git clone https://git.christianimmanuel.de/web-tools/dienstplancreator.gitwget https://git.christianimmanuel.de/web-tools/dienstplancreator/archive/dienstplancreator.tar.gzinitial
README.md | 2 +- admin.php | 169 ++ api/account/addUser.php | 29 + api/account/addUserDefaultData.php | 36 + api/account/getAll.php | 16 + api/account/getAllDefaultData.php | 16 + api/account/removeUser.php | 23 + api/account/updateName.php | 28 + api/account/updatePassword.php | 26 + api/closingtime_persons/add.php | 31 + api/closingtime_persons/get.php | 17 + api/closingtime_persons/getWherePerson.php | 17 + api/closingtime_persons/remove.php | 20 + api/closingtime_persons/removeAll.php | 21 + api/closingtimes/add.php | 35 + api/closingtimes/get.php | 17 + api/closingtimes/getAll.php | 16 + api/closingtimes/getLawful.php | 16 + api/closingtimes/remove.php | 21 + api/closingtimes/update.php | 35 + api/config/db_inc.php | 51 + api/departments/add.php | 30 + api/departments/get.php | 17 + api/departments/remove.php | 21 + api/departments/update.php | 33 + api/institution/add.php | 27 + api/institution/addClean.php | 25 + api/institution/get.php | 19 + api/institution/getAll.php | 16 + api/institution/remove.php | 19 + api/institution/switch.php | 19 + api/institution/switchAs.php | 19 + api/login.php | 35 + api/logout.php | 16 + api/objects/.department_class.php.swp | Bin 0 -> 12288 bytes api/objects/account_class.php | 531 +++++ api/objects/closingtime_class.php | 202 ++ api/objects/closingtime_person_class.php | 182 ++ api/objects/department_class.php | 125 ++ api/objects/institution_class.php | 255 +++ api/objects/person_active_class.php | 365 ++++ api/objects/person_betterment_class.php | 161 ++ api/objects/person_change_class.php | 437 ++++ api/objects/person_class.php | 223 ++ api/objects/person_hours_class.php | 487 +++++ api/objects/person_illnes_class.php | 163 ++ api/objects/person_overtime_class.php | 155 ++ api/objects/person_overtime_manual_class.php | 197 ++ api/objects/person_vacation_class.php | 186 ++ api/objects/roster_active_class.php | 39 + api/objects/roster_changes_class.php | 144 ++ api/objects/roster_class.php | 115 + api/objects/roster_editable_cell_right_class.php | 132 ++ api/objects/roster_editable_row_bottom_class.php | 133 ++ api/objects/roster_editable_row_top_class.php | 133 ++ api/objects/roster_person_info_class.php | 141 ++ api/objects/settings_class.php | 162 ++ api/objects/settings_labels_class.php | 101 + api/objects/shift_class.php | 529 +++++ api/objects/shift_labels_class.php | 116 + api/objects/test_class.php | 19 + api/person_betterments/add.php | 35 + api/person_betterments/get.php | 17 + api/person_betterments/getWhereDate.php | 17 + api/person_betterments/remove.php | 21 + api/person_changes/add.php | 34 + api/person_changes/get.php | 17 + api/person_changes/getWhereKey.php | 17 + api/person_changes/getWhereKeyValue.php | 17 + api/person_changes/getWhereYearweekDayKey.php | 17 + api/person_changes/getWhereYearweekKey.php | 17 + api/person_changes/remove.php | 20 + api/person_changes/removeWhereKey.php | 21 + api/person_changes/removeWhereYearweekDayKey.php | 20 + api/person_changes/updateWhereDayKey.php | 38 + api/person_changes/updateWhereKey.php | 37 + api/person_changes/updateWhereYearweekDayKey.php | 40 + api/person_changes/updateWhereYearweekGeDayKey.php | 39 + api/person_changes/updateWhereYearweekGeKey.php | 39 + api/person_changes/updateWhereYearweekKey.php | 38 + api/person_hours/getAll.php | 30 + api/person_hours/update.php | 37 + api/person_illnes/add.php | 34 + api/person_illnes/get.php | 17 + api/person_illnes/remove.php | 22 + api/person_illnes/update.php | 35 + api/person_overtimes/add.php | 33 + api/person_overtimes/getWhereYearweek.php | 17 + api/person_overtimes/getWhereYearweekLe.php | 17 + api/person_overtimes/remove.php | 21 + api/person_overtimes/removeWhereYearweekLt.php | 21 + api/person_overtimes/update.php | 33 + api/person_overtimes_manual/add.php | 33 + api/person_overtimes_manual/get.php | 17 + api/person_overtimes_manual/getWhereYearweek.php | 17 + api/person_overtimes_manual/getWhereYearweekLe.php | 17 + api/person_overtimes_manual/remove.php | 21 + .../removeWhereYearweekLt.php | 21 + api/person_overtimes_manual/update.php | 34 + api/person_vacations/add.php | 34 + api/person_vacations/get.php | 17 + api/person_vacations/remove.php | 22 + api/person_vacations/update.php | 36 + api/persons/add.php | 37 + api/persons/get.php | 17 + api/persons/getAll.php | 16 + api/persons/remove.php | 22 + api/persons/update.php | 36 + api/persons/updateWhere.php | 33 + api/persons_active/getActive.php | 17 + api/persons_active/getAllActive.php | 17 + api/persons_active/getAllActiveIdAndName.php | 17 + api/persons_active/getAllRemoved.php | 17 + api/persons_active/getRemoved.php | 17 + api/persons_active/getUserActive.php | 17 + api/roster/get.php | 17 + api/roster/getYearweeks.php | 16 + api/roster/remove.php | 21 + api/roster/update.php | 36 + api/roster/updateWhere.php | 31 + api/roster_active/get.php | 17 + api/roster_changes/getWhereYearweek.php | 23 + api/roster_changes/getWhereYearweekDay.php | 24 + api/roster_changes/getWhereYearweekLeDay.php | 24 + api/roster_changes/remove.php | 21 + api/roster_changes/update.php | 36 + api/roster_editable_cell_right/add.php | 32 + api/roster_editable_cell_right/get.php | 17 + api/roster_editable_cell_right/getWhereId.php | 17 + api/roster_editable_cell_right/remove.php | 21 + api/roster_editable_cell_right/update.php | 32 + api/roster_editable_row_bottom/add.php | 33 + api/roster_editable_row_bottom/get.php | 17 + api/roster_editable_row_bottom/getWhereId.php | 17 + api/roster_editable_row_bottom/remove.php | 21 + api/roster_editable_row_bottom/update.php | 32 + api/roster_editable_row_top/add.php | 33 + api/roster_editable_row_top/get.php | 17 + api/roster_editable_row_top/getWhereId.php | 17 + api/roster_editable_row_top/remove.php | 21 + api/roster_editable_row_top/update.php | 32 + api/roster_person_info/.remove.php.swp | Bin 0 -> 12288 bytes api/roster_person_info/add.php | 34 + api/roster_person_info/get.php | 25 + api/roster_person_info/getAll.php | 23 + api/roster_person_info/remove.php | 22 + api/roster_person_info/update.php | 34 + api/settings/add.php | 41 + api/settings/get.php | 22 + api/settings/getAll.php | 18 + api/settings/update.php | 32 + api/settings_labels/add.php | 32 + api/settings_labels/get.php | 17 + api/settings_labels/update.php | 33 + api/shift_labels/add.php | 33 + api/shift_labels/get.php | 16 + api/shift_labels/remove.php | 21 + api/shift_labels/update.php | 34 + api/shifts/add.php | 36 + api/shifts/getWherePerson.php | 17 + api/shifts/getWhereYearweek.php | 17 + api/shifts/getWhereYearweekDay.php | 17 + api/shifts/getWhereYearweekDayPerson.php | 17 + api/shifts/getWhereYearweekPerson.php | 17 + api/shifts/removeWhereDayPerson.php | 22 + api/shifts/removeWhereId.php | 22 + api/shifts/removeWhereYearweekDay.php | 22 + api/shifts/removeWhereYearweekDayPerson.php | 22 + api/shifts/removeWhereYearweekDayPersonStart.php | 22 + api/shifts/removeWhereYearweekGeDayPerson.php | 22 + api/shifts/test.php | 30 + .../updateEndWhereYearweekDayPersonStart.php | 36 + api/shifts/updateEndWhereYearweekEndGt.php | 36 + .../updateStartWhereYearweekDayPersonStart.php | 36 + api/shifts/updateStartWhereYearweekStartLt.php | 36 + api/shifts/updateWhereId.php | 34 + createDataDienstplanDB.sh | 162 ++ dataToDatabase.html | 18 + dienstplan-example | 1 + favicon.ico | 0 fix | 3 + fontawesome/LICENSE.txt | 165 ++ fontawesome/bundle/regular/calendar.svg | 1 + fontawesome/bundle/solid/arrow-right.svg | 1 + fontawesome/bundle/solid/calendar.svg | 1 + fontawesome/bundle/solid/chevron-left.svg | 1 + fontawesome/bundle/solid/chevron-right.svg | 1 + fontawesome/bundle/solid/gear.svg | 1 + fontawesome/bundle/solid/question.svg | 1 + fontawesome/bundle/solid/right-from-bracket.svg | 1 + fontawesome/bundle/solid/user-gear.svg | 1 + fontawesome/bundle/solid/user.svg | 1 + index.php | 637 ++++++ js/.copy-person-shifts.js.swp | Bin 0 -> 65536 bytes js/.person.js.swp | Bin 0 -> 126976 bytes js/.roster.js.swp | Bin 0 -> 118784 bytes js/administration.js | 296 +++ js/closing-time.js | 346 +++ js/console.js | 162 ++ js/copy-person-shifts.js | 668 ++++++ js/database/.persons.js.swp | Bin 0 -> 20480 bytes js/database/account-institution-admin.js | 9 + js/database/account.js | 9 + js/database/closingtime.js | 135 ++ js/database/data-to-database.js | 117 + js/database/database.js | 44 + js/database/departments.js | 39 + js/database/institutions.js | 53 + js/database/list.sh | 4 + js/database/person_changes.js | 126 ++ js/database/persons.js | 272 +++ js/database/roster-changes.js | 51 + js/database/roster.js | 195 ++ js/database/settings.js | 127 ++ js/database/settings.js.orig | 130 ++ js/database/shift-labels.js | 57 + js/database/shifts.js | 128 ++ js/fixdata.js | 525 +++++ js/get-lawful-vacations.js | 162 ++ js/person.js | 2257 ++++++++++++++++++++ js/popup.js | 43 + js/roster-person-menu.js | 252 +++ js/roster.js | 1868 ++++++++++++++++ js/scroll.js | 58 + js/settings.js | 1389 ++++++++++++ js/shortcuts.js | 25 + js/startpage.js | 121 ++ js/user-administration.js | 239 +++ js/user.js | 132 ++ js/vacations-overview.js | 318 +++ login.php | 120 ++ logout.php | 17 + pngs/icons8-island-32.png | Bin 0 -> 756 bytes redirect.php | 34 + style-admin.css | 42 + style-colors.css | 36 + style-defaults.css | 165 ++ style-login.css | 9 + style-user.css | 20 + style-useradmin.css | 35 + style-visitor.css | 11 + style.css | 1043 +++++++++ useradmin.php | 118 + 243 files changed, 22246 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 303fa6b..fe7667b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # dienstplancreator -Dienstplan erstellen +dienstplan erstellen diff --git a/admin.php b/admin.php new file mode 100644 index 0000000..7555f8c --- /dev/null +++ b/admin.php @@ -0,0 +1,169 @@ +<!DOCTYPE html> +<?php + +session_start(); + +require './api/config/db_inc.php'; +require './api/objects/account_class.php'; + +$account = new Account(); + +if (!$account->sessionLogin()) { + if (!$account->isAuthenticated()) { + header('Location: login.php'); + die(); + } +} + +if ($_SESSION["user_role"] !== "superadmin" ) { + header('Location: /'); + die(); +} + +?> +<html> + <head> + <link rel="stylesheet" href="style-colors.css"> + <link rel="stylesheet" href="style-defaults.css"> + <link rel="stylesheet" href="style-admin.css"> + <script src="js/database/institutions.js" defer></script> + <script src="js/database/account.js" defer></script> + <script src="js/administration.js" defer></script> +<script> +Date.prototype.getWeek = function(){ + var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate())); + var dayNum = d.getUTCDay() || 7; + d.setUTCDate(d.getUTCDate() + 4 - dayNum); + var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1)); + return Math.ceil((((d - yearStart) / 86400000) + 1)/7) +} + let DATE = new Date(); + let DATE_YEAR = new Date().getFullYear().toString(); + let DATE_WEEK = new Date().getWeek().toString(); + DATE_WEEK.length === 1 && (DATE_WEEK = "0"+DATE_WEEK) + let DATE_YEAR_WEEK = `${DATE_YEAR}-${DATE_WEEK}` +</script> + </head> + <body id="Administration" onload="renderInstitutions(); renderUsers()"> + <button id="Logout-button" onClick="logout()">Logout</button> + <h1>Administration</h1> + <div class="container"> + <div class="container-institutions"> + <h2>Einrichtungen</h2> + <div id="Institutions"></div> + </div> + <div class="container-users"> + <h2>Benutzer</h2> + <div class="role-hints"> + <div>Benutzer:</div><div>Kann Schichtpläne einsehen.</div> + <div>Einrichtungs-Administrator:</div><div>Kann Schichtpläne erstellen und bearbeiten.<br>Kann Benutzer und Einrichtungs-Administratoren hinzufügen.</div> + <div>Super-Administrator:</div><div>Kann Einrichtungen hinzufügen</br>Kann Einrichtungs-Administratoren und Super-Administratoren hinzufügen</div> + </div> + <div id="Users"></div> + </div> + </div> + <div class="Popup Popup-add-new"> + <div class="Popup-container"> + <div class="container"> + <h2 class="title">Einrichtung hinzufügen</h2> + <div class="container-input"> + <label>Name</label> + <input class="name"> + </div> + <div class="container-buttons"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="cofirm" onClick="addNewInstitution()">Hinzufügen</button> + </div> + </div> + </div> + </div> + <div class="Popup Popup-add-new-user"> + <div class="Popup-container"> + <h2 class="title">Benutzer hinzufügen</h2> + <div class="container"> + <label>Name: </label><input class="name"> + <label>Passwort: </label><input class="password" type="password"> + <label>Passwort wiederholung: </label><input class="password-confirm"type="password"> + <label class="label-institution">Einrichtung: </label> + <label class="label-select-institution chevron-select chevron-down"> + <select class="select-institution"> </select> + </label> + <label>Rolle: </label> + <label class="chevron-select chevron-down"> + <select class="select-role" onchange="changeSelectRole(this.value)"> + <option value="admin" selected="selected">Einrichtungs-Administrator</option> + <option value="superadmin">Super-Administrator</option> + </select> + </label> + <div class="container-buttons"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="cofirm" onClick="addNewUser()">Hinzufügen</button> + </div> + <p class="hint"></p> + </div> + </div> + </div> + <div class="Popup Popup-request-remove-institution"> + <div class="Popup-container"> + <div class="container-title"> + <h2 class="title">Einrichtung </h2> + <h2 class="name"></h2> + <h2 class="title"> löschen</h2> + </div> + <div class="container"> + <div class="container-password"><label>Passwort: </label><input class="password" type="password"></div> + <p class="hint"></p> + <div class="container-buttons"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="confirm">Löschen</button> + </div> + </div> + </div> + </div> + <div class="Popup Popup-remove-user"> + <div class="Popup-container"> + <div class="container-title"> + <h2 class="title">Benutzer </h2> + <h2 class="name"></h2> + <h2 class="title"> löschen</h2> + </div> + <div class="container"> + <div class="container-password"><label>Passwort: </label><input class="password" type="password"></div> + <p class="hint"></p> + <div class="container-buttons"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="confirm" onClick="removeUser()">Löschen</button> + </div> + </div> + </div> + </div> + <div class="Popup Popup-edit-user"> + <div class="Popup-container"> + <div class="container-title"> + <h2 class="title">Benuter </h2> + <h2 class="name"></h2> + <h2 class="title"> bearbeiten</h2> + </div> + <div class="container"> + <div class="container-name"> + <h3>Name ändern</h3> + <input class="name"/> + <div class="container-buttons"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="confirm" onClick="changeName()">Ändern</button> + </div> + </div> + <p class="hint hint-name"></p> + <div class="container-password"> + <h3>Neues Passwort</h3> + <label>Passwort: </label><input class="password_1" type="password"> + <label>Passwort wiederholung: </label><input class="password_2" type="password"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="confirm" onClick="changePassword()">Ändern</button> + </div> + <p class="hint hint-password"></p> + </div> + </div> + </div> + </body> +</html> diff --git a/api/account/addUser.php b/api/account/addUser.php new file mode 100644 index 0000000..6b1dc5a --- /dev/null +++ b/api/account/addUser.php @@ -0,0 +1,29 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['user_role'] !== 'superadmin' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/account_class.php'; + +$account = new Account(); + +$data = json_decode(file_get_contents("php://input")); + + +try { + $newId = $account->addAccount($data->name, $data->password, $data->role, $data->data_id, "false"); +} +catch (Exception $e) { + $newId = $e->getMessage(); +} +echo json_encode($newId); +?> diff --git a/api/account/addUserDefaultData.php b/api/account/addUserDefaultData.php new file mode 100644 index 0000000..1531096 --- /dev/null +++ b/api/account/addUserDefaultData.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['user_role'] !== 'admin' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/account_class.php'; + +$account = new Account(); + +$data = json_decode(file_get_contents("php://input")); +$role = $data->role; +$connected = $data->connected; +$data_id = $_SESSION["data_id"]; + +$check = FALSE; +if ($role === "admin") {$check = TRUE;} +else if (($role === "user") && ($connected != "false")){$check = TRUE;} +if (!$check) {return;} + +try { + $newId = $account->addAccount($data->name, $data->password, $role, $data_id, $connected); +} +catch (Exception $e) { + $newId = $e->getMessage(); +} +echo json_encode($newId); +?> diff --git a/api/account/getAll.php b/api/account/getAll.php new file mode 100644 index 0000000..2c482d1 --- /dev/null +++ b/api/account/getAll.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/account_class.php'; + +$users = new Account(); +echo json_encode($users->getAll()); +?> diff --git a/api/account/getAllDefaultData.php b/api/account/getAllDefaultData.php new file mode 100644 index 0000000..0088aee --- /dev/null +++ b/api/account/getAllDefaultData.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/account_class.php'; + +$users = new Account(); +echo json_encode($users->getAllDefaultData($_SESSION["data_id"])); +?> diff --git a/api/account/removeUser.php b/api/account/removeUser.php new file mode 100644 index 0000000..480c2e4 --- /dev/null +++ b/api/account/removeUser.php @@ -0,0 +1,23 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/account_class.php'; + +$user = new Account(); +$data = json_decode(file_get_contents("php://input")); +if ($_SESSION["user_role"] === "superadmin") { + $data_id = $data->data_id; +} else if ($_SESSION["user_role"] === "admin") { + $data_id = $_SESSION["data_id"]; +} else {return;} + +echo json_encode($user->deleteAccount($data->user_id, $data_id, $data->password)); +?> diff --git a/api/account/updateName.php b/api/account/updateName.php new file mode 100644 index 0000000..b28123f --- /dev/null +++ b/api/account/updateName.php @@ -0,0 +1,28 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if (($_SESSION['user_role'] === 'superadmin') || ($_SESSION['user_role'] === 'admin')) { + require '../config/db_inc.php'; + require '../objects/account_class.php'; + + $account = new Account(); + + $data = json_decode(file_get_contents("php://input")); + + + $data_id = $_SESSION["data_id"]; + try { + $newName = $account->updateName($data_id, $data->id, $data->name ); + } catch (Exception $e) { + $newName = $e->getMessage(); + } + echo json_encode($newName); +} +?> diff --git a/api/account/updatePassword.php b/api/account/updatePassword.php new file mode 100644 index 0000000..1a275bd --- /dev/null +++ b/api/account/updatePassword.php @@ -0,0 +1,26 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if (($_SESSION['user_role'] === 'superadmin') || ($_SESSION['user_role'] === 'admin')) { + require '../config/db_inc.php'; + require '../objects/account_class.php'; + + $account = new Account(); + + $data = json_decode(file_get_contents("php://input")); + $data_id = $_SESSION["data_id"]; + try { + $newName = $account->updatePassword($data_id, $data->id, $data->password ); + } catch (Exception $e) { + $newName = $e->getMessage(); + } + echo json_encode($newName); +} +?> diff --git a/api/closingtime_persons/add.php b/api/closingtime_persons/add.php new file mode 100644 index 0000000..5ebce99 --- /dev/null +++ b/api/closingtime_persons/add.php @@ -0,0 +1,31 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/closingtime_person_class.php'; + +$closingtime_person = new Closingtime_person(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$closingtime_id = $data->closingtime_id ; +$person_id = $data->person_id; + +try { + $cid = $closingtime_person->add($data_id, $closingtime_id, $person_id); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +echo json_encode($cid) +?> diff --git a/api/closingtime_persons/get.php b/api/closingtime_persons/get.php new file mode 100644 index 0000000..2a581e7 --- /dev/null +++ b/api/closingtime_persons/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/closingtime_person_class.php'; + +$closingtime_person = new Closingtime_person(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($closingtime_person->get($_SESSION["data_id"], $data->closingtime_id)); +?> diff --git a/api/closingtime_persons/getWherePerson.php b/api/closingtime_persons/getWherePerson.php new file mode 100644 index 0000000..051264f --- /dev/null +++ b/api/closingtime_persons/getWherePerson.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/closingtime_person_class.php'; + +$closingtime_person = new Closingtime_person(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($closingtime_person->getWherePerson($_SESSION["data_id"], $data->person_id)); +?> diff --git a/api/closingtime_persons/remove.php b/api/closingtime_persons/remove.php new file mode 100644 index 0000000..59e8bb8 --- /dev/null +++ b/api/closingtime_persons/remove.php @@ -0,0 +1,20 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/closingtime_person_class.php'; + +$closingtime_person = new Closingtime_person(); +$data = json_decode(file_get_contents("php://input")); + +$closingtime_person->remove($_SESSION["data_id"], $data->closingtime_id, $data->person_id); +?> diff --git a/api/closingtime_persons/removeAll.php b/api/closingtime_persons/removeAll.php new file mode 100644 index 0000000..44889da --- /dev/null +++ b/api/closingtime_persons/removeAll.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/closingtime_person_class.php'; + +$closingtime_person = new Closingtime_person(); +$data = json_decode(file_get_contents("php://input")); + +$closingtime_person->removeAll($_SESSION["data_id"], $data->closingtime_id); +echo json_encode($data->closingtime_id) +?> diff --git a/api/closingtimes/add.php b/api/closingtimes/add.php new file mode 100644 index 0000000..2334f65 --- /dev/null +++ b/api/closingtimes/add.php @@ -0,0 +1,35 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/closingtime_class.php'; + +$closingtime = new Closingtime(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$name = $data->name; +$start = $data->start; +$end = $data->end; +$lawful = $data->lawful; +$persons = $data->persons; + +$cid; +try { + $cid = $closingtime->add($data_id, $name, $start, $end, $lawful, $persons); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($cid); +?> diff --git a/api/closingtimes/get.php b/api/closingtimes/get.php new file mode 100644 index 0000000..d930043 --- /dev/null +++ b/api/closingtimes/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/closingtime_class.php'; + +$closingtime = new Closingtime(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($closingtime->get($_SESSION["data_id"], $data->id)); +?> diff --git a/api/closingtimes/getAll.php b/api/closingtimes/getAll.php new file mode 100644 index 0000000..d0690d6 --- /dev/null +++ b/api/closingtimes/getAll.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/closingtime_class.php'; + +$closingtime = new Closingtime(); +echo json_encode($closingtime->getAll($_SESSION["data_id"])); +?> diff --git a/api/closingtimes/getLawful.php b/api/closingtimes/getLawful.php new file mode 100644 index 0000000..2e00343 --- /dev/null +++ b/api/closingtimes/getLawful.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/closingtime_class.php'; + +$closingtime = new Closingtime(); +echo json_encode($closingtime->getLawful($_SESSION["data_id"])); +?> diff --git a/api/closingtimes/remove.php b/api/closingtimes/remove.php new file mode 100644 index 0000000..6047507 --- /dev/null +++ b/api/closingtimes/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION["administration"] === 'visitor') {return;} + +require '../config/db_inc.php'; +require '../objects/closingtime_class.php'; + +$closingtime = new Closingtime(); +$data = json_decode(file_get_contents("php://input")); + +$closingtime->remove($_SESSION["data_id"], $data->id); +echo json_encode($data->id) +?> diff --git a/api/closingtimes/update.php b/api/closingtimes/update.php new file mode 100644 index 0000000..857ddb2 --- /dev/null +++ b/api/closingtimes/update.php @@ -0,0 +1,35 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION["administration"] === 'visitor') {return;} + +require '../config/db_inc.php'; +require '../objects/closingtime_class.php'; + +$closingtime = new Closingtime(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$name = $data->name; +$start = $data->start; +$end = $data->end; +$lawful = $data->lawful; + + +try { + $closingtime->update($data_id, $id, $name, $start, $end, $lawful); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +?> diff --git a/api/config/db_inc.php b/api/config/db_inc.php new file mode 100644 index 0000000..639c49b --- /dev/null +++ b/api/config/db_inc.php @@ -0,0 +1,51 @@ +<?php + +/* + * This example script can be downloaded from Alex Web Develop "PHP Login and Authentication Tutorial": + * + * https://alexwebdevelop.com/user-authentication/ + * + * You are free to use and share this script as you like. + * If you share it, please leave this disclaimer inside. + * + * Subscribe to my free newsletter and get my exclusive PHP tips and learning advice: + * + * https://alexwebdevelop.com/ + * +*/ + + +/* Host name of the MySQL server */ +$host = 'localhost'; + +/* MySQL account username */ +$user = ''; + +/* MySQL account password */ +$passwd = ''; + +/* The schema you want to use */ +$schema = 'datadienstplandb'; + +/* The PDO object */ +$pdo = NULL; + +/* Connection string, or "data source name" */ +$dsn = 'mysql:host=' . $host . ';dbname=' . $schema; + +/* Connection inside a try/catch block */ +try +{ + /* PDO object creation */ + $pdo = new PDO($dsn, $user, $passwd); + + /* Enable exceptions on errors */ + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +} +catch (PDOException $e) +{ + /* If there is an error an exception is thrown */ + echo 'Database connection failed<br>'; + print_r($e); + die(); +} diff --git a/api/departments/add.php b/api/departments/add.php new file mode 100644 index 0000000..588a9ad --- /dev/null +++ b/api/departments/add.php @@ -0,0 +1,30 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/department_class.php'; + +$department = new Department(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$name = $data->name; + +try { + $res = $department->add($data_id, $name); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +echo json_encode($res); +?> diff --git a/api/departments/get.php b/api/departments/get.php new file mode 100644 index 0000000..a44fc6f --- /dev/null +++ b/api/departments/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/department_class.php'; + +$department = new Department(); +$data_id = $department->get($_SESSION["data_id"]); +echo json_encode($data_id); +?> diff --git a/api/departments/remove.php b/api/departments/remove.php new file mode 100644 index 0000000..cc2b816 --- /dev/null +++ b/api/departments/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/department_class.php'; + +$department = new Department(); +$data = json_decode(file_get_contents("php://input")); + +$res = $department->remove($_SESSION["data_id"], $data->id); +echo json_encode($res); +?> diff --git a/api/departments/update.php b/api/departments/update.php new file mode 100644 index 0000000..f153918 --- /dev/null +++ b/api/departments/update.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/department_class.php'; + +$department = new Department(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$name = $data->name; + + +try { + $res = $department->update($data_id, $id, $name); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +echo json_encode($res); +?> diff --git a/api/institution/add.php b/api/institution/add.php new file mode 100644 index 0000000..48ea27a --- /dev/null +++ b/api/institution/add.php @@ -0,0 +1,27 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + + +require '../config/db_inc.php'; +require '../objects/institution_class.php'; + +if ($_SESSION["user_role"] !== "superadmin") { return; } +$institution = new Institution(); + +$data = json_decode(file_get_contents("php://input")); + +try { + $institution->add($data->name, $data->yearweek); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($data->name) +?> diff --git a/api/institution/addClean.php b/api/institution/addClean.php new file mode 100644 index 0000000..339d1d4 --- /dev/null +++ b/api/institution/addClean.php @@ -0,0 +1,25 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/institution_class.php'; + +if ($_SESSION["user_role"] !== "superadmin") { return; } +$institution = new Institution(); + +$data = json_decode(file_get_contents("php://input")); + +try { + $institution->addClean($data->name, $data->yearweek); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/institution/get.php b/api/institution/get.php new file mode 100644 index 0000000..6480785 --- /dev/null +++ b/api/institution/get.php @@ -0,0 +1,19 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION["user_role"] !== "superadmin") { return; } + +require '../config/db_inc.php'; +require '../objects/institution_class.php'; + +$institution = new Institution(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($institution->get($data->id)); +?> diff --git a/api/institution/getAll.php b/api/institution/getAll.php new file mode 100644 index 0000000..d0a13f4 --- /dev/null +++ b/api/institution/getAll.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/institution_class.php'; + +$institution = new Institution(); +echo json_encode($institution->getAll()); +?> diff --git a/api/institution/remove.php b/api/institution/remove.php new file mode 100644 index 0000000..69bc32f --- /dev/null +++ b/api/institution/remove.php @@ -0,0 +1,19 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION["user_role"] !== "superadmin") { return; } +require '../config/db_inc.php'; +require '../objects/institution_class.php'; + +$institution = new Institution(); +$data = json_decode(file_get_contents("php://input")); + +echo json_encode($institution->remove($data->data_id, $data->password)); +?> diff --git a/api/institution/switch.php b/api/institution/switch.php new file mode 100644 index 0000000..040f4fe --- /dev/null +++ b/api/institution/switch.php @@ -0,0 +1,19 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION["user_role"] !== "superadmin") { return; } + +require '../config/db_inc.php'; +require '../objects/institution_class.php'; + +$institution = new Institution(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($institution->switchInstitution($data->id)); +?> diff --git a/api/institution/switchAs.php b/api/institution/switchAs.php new file mode 100644 index 0000000..3e8bbef --- /dev/null +++ b/api/institution/switchAs.php @@ -0,0 +1,19 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION["user_role"] !== "superadmin") { return; } + +require '../config/db_inc.php'; +require '../objects/institution_class.php'; + +$institution = new Institution(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($institution->switchAsInstitution($data->id, $data->as)); +?> diff --git a/api/login.php b/api/login.php new file mode 100644 index 0000000..18775a2 --- /dev/null +++ b/api/login.php @@ -0,0 +1,35 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require 'config/db_inc.php'; +require 'objects/account_class.php'; +require 'objects/settings_class.php'; + +$account = new Account(); + +$data = json_decode(file_get_contents("php://input")); + +$name = $data->name; +$password = $data->password; +$data_id = $data->data_id; +try { + $login = $account->login($name, $password, $data_id); +} catch (Exception $e) { + echo json_encode($e->getMessage()); + die(); +} + +if ($login) { + echo json_encode("success"); + //header("Location: "); +} else { + echo json_encode('mismatch'); +} +?> diff --git a/api/logout.php b/api/logout.php new file mode 100644 index 0000000..5da20cf --- /dev/null +++ b/api/logout.php @@ -0,0 +1,16 @@ +<?php +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require 'config/db_inc.php'; +require 'objects/account_class.php'; + +$account = new Account(); +$account->logout(); +header('Location: ../login.php'); +?> diff --git a/api/objects/.department_class.php.swp b/api/objects/.department_class.php.swp new file mode 100644 index 0000000..f45a5ff Binary files /dev/null and b/api/objects/.department_class.php.swp differ diff --git a/api/objects/account_class.php b/api/objects/account_class.php new file mode 100644 index 0000000..3e761cd --- /dev/null +++ b/api/objects/account_class.php @@ -0,0 +1,531 @@ +<?php + +/* + * This class file can be downloaded from Alex Web Develop "PHP Login and Authentication Tutorial": + * + * https://alexwebdevelop.com/user-authentication/ + * + * You are free to use and share this script as you like. + * If you want to share it, please leave this disclaimer inside. + * + * Subscribe to my free newsletter and get my exclusive PHP tips and learning advice: + * + * https://alexwebdevelop.com/ + * +*/ + + +class Account { + private $id; + private $name; + private $role; + private $data_id; + /* TRUE if the user is authenticated, FALSE otherwise */ + private $authenticated; + + public function __construct() + { + $this->id = NULL; + $this->name = NULL; + $this->role = NULL; + $this->data_id = NULL; + $this->authenticated = FALSE; + } + + public function __destruct() { } + + public function getId(): ?int { + return $this->id; + } + + public function getName(): ?string { + return $this->name; + } + + public function getRole(): ?string { + return $this->role; + } + + public function getDataId(): ?string { + return $this->data_id; + } + public function isAuthenticated(): bool { + return $this->authenticated; + } + + public function addAccount(string $name, string $passwd, string $role, $data_id, $connected): int { + global $pdo; + + $name = trim($name); + $passwd = trim($passwd); + $role = trim($role); + $data_id = trim($data_id); + $connected = trim($connected); + + if ($role === "superadmin") { + $data_id = NULL; + } + + if (!$this->isNameValid($name)) { + throw new Exception('Der Benutzername muss aus mindestens 4 Buchstaben bestehen.'); + } + + if (!$this->isPasswdValid($passwd)) { + throw new Exception('Das Passwort muss aus indestens 8 Buchstaben/ Zeichen bestehen.'); + } + + if (!is_null($this->getIdFromName($name, $data_id))) { + throw new Exception('Der Benutzername ist bereits vergeben.'); + } + + $query; + $value; + if ($connected === "false") { + $query = 'INSERT INTO datadienstplandb.users (username, password, role, data_id) VALUES (:name, :passwd, :role, :data_id)'; + $hash = password_hash($passwd, PASSWORD_DEFAULT); + $values = array(':name' => $name, ':passwd' => $hash, ':role' => $role, 'data_id' => $data_id); + } else { + $query = 'INSERT INTO datadienstplandb.users (username, password, role, data_id, connected_person) VALUES (:name, :passwd, :role, :data_id, :connected)'; + $hash = password_hash($passwd, PASSWORD_DEFAULT); + $values = array(':name' => $name, ':passwd' => $hash, ':role' => $role, ':data_id' => $data_id, ':connected' => $connected ); + } + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + + return $pdo->lastInsertId(); + } + + public function deleteAccount(int $id, int $data_id, string $passwd) { + global $pdo; + $passwd = trim($passwd); + $query = 'SELECT * FROM datadienstplandb.users WHERE (id = :user_id)'; + $values = array(':user_id' => $_SESSION["user_id"]); + + try { + $res_u = $pdo->prepare($query); + $res_u->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + $row_u = $res_u->fetch(PDO::FETCH_ASSOC); + if (is_array($row_u)) { + if (!password_verify($passwd, $row_u['password'])) { + return 'Dein Passwort ist ungültig.'; + } + } + + if (!$this->isIdValid($id)) { + throw new Exception('Invalid account ID'); + } + + $query = 'DELETE FROM datadienstplandb.users WHERE (id = :id)'; + $values = array(':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + + $query = 'DELETE FROM datadienstplandb.user_sessions WHERE (user_id = :id)'; + $values = array(':id' => $id); + + try { + $res_s = $pdo->prepare($query); + $res_s->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + return (int) $id; + } + + public function editAccount(int $id, string $name, string $passwd, bool $enabled, int $data_id) { + global $pdo; + + $name = trim($name); + $passwd = trim($passwd); + + if (!$this->isIdValid($id)) { + throw new Exception('Invalid account ID'); + } + + if (!$this->isNameValid($name)) { + throw new Exception('Der Benutzername muss aus mindestens 4 Buchstaben bestehen.'); + } + + if (!$this->isPasswdValid($passwd)) { + throw new Exception('Das Passwort muss aus indestens 8 Buchstaben/ Zeichen bestehen.'); + } + + $idFromName = $this->getIdFromName($name, $data_id); + + if (!is_null($idFromName) && ($idFromName != $id)) { + throw new Exception('Der Benutzername wirdbereits genutzt.'); + } + + $query = 'UPDATE datadienstplandb.users SET username = :name, password = :passwd, enabled = :enabled WHERE id = :id'; + $hash = password_hash($passwd, PASSWORD_DEFAULT); + $intEnabled = $enabled ? 1 : 0; + $values = array(':name' => $name, ':passwd' => $hash, ':enabled' => $intEnabled, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + } + + /* Login with username and password */ + public function login(string $name, string $passwd, $data_id): bool { + global $pdo; + + $name = trim($name); + $passwd = trim($passwd); + + if (!$this->isNameValid($name)) { + return FALSE; + } + + if (!$this->isPasswdValid($passwd)) { + return FALSE; + } + + $query; + $values = array(); + if ($data_id === "superadmin") { + $query = 'SELECT * FROM datadienstplandb.users WHERE (username = :name) AND (enabled = 1) AND data_id IS NULL'; + $values = array(':name' => $name); + } else { + $query = 'SELECT * FROM datadienstplandb.users WHERE (username = :name) AND (enabled = 1) AND data_id = :data_id'; + $values = array(':name' => $name, ':data_id' => $data_id); + } + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + + $row = $res->fetch(PDO::FETCH_ASSOC); + + if (is_array($row)) { + if (password_verify($passwd, $row['password'])) { + /* Authentication succeeded. Set the class properties (id and name) */ + $this->id = intval($row['id'], 10); + $this->name = $name; + $this->role = $row['role']; + $this->authenticated = TRUE; + $this->data_id = $row['data_id']; + /* Register the current Sessions on the database */ + $this->registerLoginSession(); + + $_SESSION["data_id"] = $row['data_id']; + $_SESSION["user_id"] = $row['id']; + $_SESSION["user_role"] = $row['role']; + if ($row['role'] === "admin") { + $_SESSION["administration"] = 'editor'; + } else if ($row['role'] === "user") { + $_SESSION["connected_person"] = $row['connected_person']; + $_SESSION["administration"] = 'visitor'; + } else { + $_SESSION["administration"] = 'visitor'; + } + $this->closeOtherSessions(); + return TRUE; + } + } + + return FALSE; + } + + /* A sanitization check for the account username */ + public function isNameValid(string $name): bool { + $valid = TRUE; + $len = mb_strlen($name); + + if ($len < 4) { + $valid = FALSE; + } + + return $valid; + } + + /* A sanitization check for the account password */ + public function isPasswdValid(string $passwd): bool { + $valid = TRUE; + $len = mb_strlen($passwd); + if ($len < 8) { + $valid = FALSE; + } + + return $valid; + } + + /* A sanitization check for the account ID */ + public function isIdValid(int $id): bool { + $valid = TRUE; + if (($id < 1) || ($id > 1000000)) { + $valid = FALSE; + } + + return $valid; + } + + /* Login using Sessions */ + public function sessionLogin(): bool { + global $pdo; + + /* Check that the Session has been started */ + if (session_status() == PHP_SESSION_ACTIVE) { + $query = + 'SELECT * FROM datadienstplandb.user_sessions, datadienstplandb.users WHERE (user_sessions.session_id = :sid) ' . + 'AND (user_sessions.login_time >= (NOW() - INTERVAL 7 DAY)) AND (user_sessions.user_id = users.id) ' . + 'AND (users.enabled = 1)'; + $values = array(':sid' => session_id()); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + + $row = $res->fetch(PDO::FETCH_ASSOC); + + if (is_array($row)) { + /* Authentication succeeded. Set the class properties (id and name) and return TRUE*/ + $this->id = intval($row['user_id'], 10); + $this->name = $row['username']; + $this->authenticated = TRUE; + $_SESSION["data_id"] = $row['data_id']; + $_SESSION["user_id"] = $row['id']; + $_SESSION["user_role"] = $row['role']; + if ($row['role'] === "admin") { + $_SESSION["administration"] = 'editor'; + } else if ($row['role'] === "user") { + $_SESSION["connected_person"] = $row['connected_person']; + $_SESSION["administration"] = 'visitor'; + } else { + $_SESSION["administration"] = 'visitor'; + } + + return TRUE; + } + } + + return FALSE; + } + + /* Logout the current user */ + public function logout() { + global $pdo; + + /* If there is no logged in user, do nothing */ + /*if (is_null($this->id)) + { + return; + }*/ + + /* Reset the account-related properties */ + $this->id = NULL; + $this->name = NULL; + $this->authenticated = FALSE; + + /* If there is an open Session, remove it from the user_sessions table */ + if (session_status() == PHP_SESSION_ACTIVE) { + $query = 'DELETE FROM datadienstplandb.user_sessions WHERE (user_id = :user_id)'; + $values = array(':user_id' => $_SESSION["user_id"]); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + echo json_encode(array("message" => "Logout sucess.")); + } + } + + /* Close all account Sessions except for the current one (aka: "logout from other devices") */ + public function closeOtherSessions() { + global $pdo; + + /* If there is no logged in user, do nothing */ + if (is_null($this->id)) { + return; + } + + /* Check that a Session has been started */ + if (session_status() == PHP_SESSION_ACTIVE) { + $query = 'DELETE FROM datadienstplandb.user_sessions WHERE session_id != :sid AND user_id = :id'; + $values = array(':sid' => session_id(), ':id' => $this->id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + } + } + + /* Returns the account id having $name as name, or NULL if it's not found */ + public function getIdFromName(string $name, $data_id): ?int { + global $pdo; + if (!$this->isNameValid($name)) { + throw new Exception('Der Benutzername muss aus mindestens 4 Buchstaben bestehen.'); + } + + $id = NULL; + + $query = 'SELECT id FROM datadienstplandb.users WHERE username = :name AND data_id = :data_id'; + $values = array(':name' => $name, ':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + + $row = $res->fetch(PDO::FETCH_ASSOC); + + if (is_array($row)) { + $id = intval($row['id'], 10); + } + + return $id; + } + public function getAll() { + global $pdo; + $query = "SELECT * FROM datadienstplandb.users"; + $values = array(); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + $users=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + $users_item=array( + "id" => (int)$row["id"], + "name" => (string)$row["username"], + "role" => (string)$row["role"], + "data_id" => (int)$row["data_id"], + "enabled" => (int)$row["enabled"], + "created_at" => (string)$row["created_at"] + ); + array_push($users, $users_item); + } + return $users; + } + public function getAllDefaultData(int $data_id) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.users WHERE data_id = :data_id AND role != "superadmin"'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + $users=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + $connected = $row["connected_person"]; + if (is_numeric($connected)) { + $connected = (int)$connected; + } + $users_item=array( + "id" => (int)$row["id"], + "name" => (string)$row["username"], + "role" => (string)$row["role"], + "enabled" => (int)$row["enabled"], + "created_at" => (string)$row["created_at"], + "connected_person" => $connected + ); + array_push($users, $users_item); + } + return $users; + } + public function updatePassword(int $data_id, int $id, string $password ) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $passwd = trim($password); + + if (!$this->isPasswdValid($passwd)) { + throw new Exception('Das Passwort muss aus indestens 8 Buchstaben/ Zeichen bestehen.'); + } + + $query = 'UPDATE datadienstplandb.users SET password = :passwd WHERE id = :id'; + $hash = password_hash($passwd, PASSWORD_DEFAULT); + $intEnabled = $enabled ? 1 : 0; + $values = array(':passwd' => $hash, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + return (int)$id; + } + public function updateName(int $data_id, int $id, string $name ) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + + if (!$this->isNameValid($name)) { + throw new Exception('Der Benutzername muss aus mindestens 4 Buchstaben bestehen.'); + } + $idFromName = $this->getIdFromName($name, $data_id); + + if (!is_null($idFromName) && ($idFromName != $id)) { + throw new Exception('Der Benutzername wirdbereits genutzt.'); + } + + $query = 'UPDATE datadienstplandb.users SET username = :name WHERE id = :id'; + $values = array(':name' => $name, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + return $name; + } + + + /* Private class methods */ + + /* Saves the current Session ID with the account ID */ + private function registerLoginSession() { + global $pdo; + + /* Check that a Session has been started */ + if (session_status() == PHP_SESSION_ACTIVE) { + $query = 'REPLACE INTO datadienstplandb.user_sessions (session_id, user_id, login_time) VALUES (:sid, :accountId, NOW())'; + $values = array(':sid' => session_id(), ':accountId' => $this->id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error account_class.php'); + } + } + } +} diff --git a/api/objects/closingtime_class.php b/api/objects/closingtime_class.php new file mode 100644 index 0000000..ba0e66c --- /dev/null +++ b/api/objects/closingtime_class.php @@ -0,0 +1,202 @@ +<?php + +require_once 'closingtime_person_class.php'; + +class Closingtime +{ + private $data_id; + private $id; + private $name; + private $start; + private $end; + private $lawful; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->name = NULL; + $this->start = NULL; + $this->end = NULL; + $this->lawful = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $name, string $start, string $end, int $lawful, array $persons): array { + global $pdo; + $data_id = trim($data_id); + $name = trim($name); + $start = trim($start); + $end = trim($end); + $lawful = trim($lawful); + + $query = 'INSERT INTO datadienstplandb.closingtimes (data_id, name, start, end, lawful) VALUES (:data_id, :name, :start, :end, :lawful)'; + + $values = array(':data_id' => $data_id, ':name' => $name, ':start' => $start, ':end' => $end, ':lawful' => $lawful); + + try { + $res = $pdo->prepare($query); $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_class.php'); + } + $id = $pdo->lastInsertId(); + foreach ($persons as $pid) { + $cp = new Closingtime_person(); + $cp->add($data_id, $id, $pid); + } + + return array( + 'id' => $id, + 'name' => $name, + 'start' => $start, + 'end' => $end, + 'lawful' => $lawful, + 'persons' => $persons + ); + } + public function get(int $data_id, int $id) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $query = 'SELECT * FROM datadienstplandb.closingtimes WHERE data_id = :data_id AND id = :id'; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error closingtime_class.php'); + } + + $row = $res->fetch(PDO::FETCH_ASSOC); + extract($row); + $cp = new Closingtime_person(); + $closingtime_person = $cp->get($data_id, $id); + $persons=array(); + foreach ($closingtime_person as $key=>$value) { + array_push($persons, $value["person_id"]); + } + return array( + "id" => (int)$id, + "name" => $name, + "start" => $start, + "end" => $end, + "lawful" => (int)$lawful, + "persons" => $persons + ); + } + public function getAll(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.closingtimes WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error closingtime_class.php'); + } + + $closingtimes=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $cp = new Closingtime_person(); + $closingtime_person = $cp->get($data_id, $id); + $persons=array(); + foreach ($closingtime_person as $key=>$value) { + array_push($persons, $value["person_id"]); + } + $closingtimes_item=array( + "id" => (int)$id, + "name" => $name, + "start" => $start, + "end" => $end, + "lawful" => (int)$lawful, + "persons" => $persons + ); + array_push($closingtimes, $closingtimes_item); + } + return $closingtimes; + } + public function getLawful(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.closingtimes WHERE data_id = :data_id AND lawful = 1'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error closingtime_class.php'); + } + + $closingtimes=array(); + $closingtimes["closingtimes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $closingtimes_item=array( + "id" => (int)$id, + "name" => $name, + "start" => $start, + "end" => $end, + "lawful" => $lawful + ); + array_push($closingtimes["closingtimes"], $closingtimes_item); + } + return $closingtimes; + } + public function update(int $data_id, int $id, string $name, string $start, string $end, int $lawful) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + $start = trim($start); + $end = trim($end); + $lawful = trim($lawful); + $query = "UPDATE datadienstplandb.closingtimes SET name = :name, start = :start, end = :end, lawful = :lawful WHERE data_id = :data_id AND id = :id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':name' => $name, ':start' => $start, ':end' => $end, ':lawful' => $lawful); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_class.php'); + } + } + public function remove(int $data_id, int $id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $query = "DELETE FROM datadienstplandb.closingtimes WHERE (data_id = :data_id) AND (id = :id)"; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_class.php'); + } + $cp = new Closingtime_person(); + $cp->removeAll($data_id, $id); + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.closingtimes WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_class.php'); + } + } +} diff --git a/api/objects/closingtime_person_class.php b/api/objects/closingtime_person_class.php new file mode 100644 index 0000000..d05b465 --- /dev/null +++ b/api/objects/closingtime_person_class.php @@ -0,0 +1,182 @@ +<?php + +require_once 'person_hours_class.php'; +require_once 'closingtime_class.php'; + +class Closingtime_person +{ + private $data_id; + private $id; + private $closingtime_id; + private $person_id ; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->closingtime_id = NULL; + $this->person_id = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $closingtime_id, string $person_id): int { + global $pdo; + $data_id = trim($data_id); + $closingtime_id = trim($closingtime_id); + $person_id = trim($person_id); + + $query = 'INSERT INTO datadienstplandb.closingtime_persons (data_id, closingtime_id, person_id) VALUES (:data_id, :closingtime_id, :person_id)'; + + $values = array(':data_id' => $data_id, ':closingtime_id' => $closingtime_id, ':person_id' => $person_id); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + /* If there is a PDO exception, throw a standard exception */ + throw new Exception('Database query error closingtime_person_class.php'); + } + + + + $closingtime = new Closingtime(); + $cl = $closingtime->get($data_id, $closingtime_id); + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $cl["start"], $cl["end"], "should"); + + return $pdo->lastInsertId(); + } + public function get(int $data_id, int $closingtime_id) { + global $pdo; + $data_id = trim($data_id); + $closingtime_id = trim($closingtime_id); + $query = "SELECT * FROM datadienstplandb.closingtime_persons WHERE (data_id = :data_id) AND closingtime_id = :closingtime_id"; + $values = array(':data_id' => $data_id, ':closingtime_id' => $closingtime_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_person_class.php'); + } + $persons=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $persons_item=array( + "id" => (int)$id, + "closingtime_id" => (int)$closingtime_id, + "person_id" => (int)$person_id + ); + array_push($persons, $persons_item); + } + return $persons; + } + public function getWherePerson(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = "SELECT * FROM datadienstplandb.closingtime_persons WHERE data_id = :data_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_person_class.php'); + } + $closingtimes=array(); + $closingtimes["closingtimes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $persons_item=array( + "id" => (int)$id, + "closingtime_id" => (int)$closingtime_id, + "person_id" => (int)$person_id + ); + array_push($closingtimes["closingtimes"], $persons_item); + } + return $closingtimes; + } + public function remove(int $data_id, int $closingtime_id, int $person_id) { + global $pdo; + + $data_id = trim($data_id); + $closingtime_id = trim($closingtime_id); + $person_id = trim($person_id); + + $cl = new Closingtime(); + $closingtime = $cl->get($data_id, $closingtime_id); + + $query = "DELETE FROM datadienstplandb.closingtime_persons WHERE (data_id = :data_id) AND closingtime_id = :closingtime_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':closingtime_id' => $closingtime_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_person_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $closingtime["start"], $closingtime["end"], "should"); + } + public function removeAllWherePerson(int $data_id, int $person_id) { + global $pdo; + + $data_id = trim($data_id); + $person_id = trim($person_id); + + $query = "DELETE FROM datadienstplandb.closingtime_persons WHERE data_id = :data_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_person_class.php'); + } + } + public function removeAll(int $data_id, int $closingtime_id) { + global $pdo; + + $data_id = trim($data_id); + $closingtime_id = trim($closingtime_id); + + $closingtime = new Closingtime(); + $closingtime->get($data_id, $closingtime_id); + + $query = "DELETE FROM datadienstplandb.closingtime_persons WHERE (data_id = :data_id) AND closingtime_id = :closingtime_id"; + $values = array(':data_id' => $data_id, ':closingtime_id' => $closingtime_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_person_class.php'); + } + + $persons = $this->get($data_id, $closingtime_id); + foreach($persons["persons"] as $key=> $value) { + $person_id = $value["person_id"]; + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $closingtime["start"], $closingtime["end"], "should"); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.closingtime_persons WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error closingtime_person_class.php'); + } + } +} diff --git a/api/objects/department_class.php b/api/objects/department_class.php new file mode 100644 index 0000000..3729906 --- /dev/null +++ b/api/objects/department_class.php @@ -0,0 +1,125 @@ +<?php + +require_once 'person_change_class.php'; +require_once 'person_class.php'; + +class Department +{ + private $data_id; + private $id; + private $name; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->name = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $name): int { + global $pdo; + $data_id = trim($data_id); + $name = trim($name); + + $query = 'INSERT INTO datadienstplandb.departments (data_id, name) VALUES (:data_id, :name)'; + $values = array(':data_id' => $data_id, ':name' => $name); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error department_class.php'); + } + + return $pdo->lastInsertId(); + } + public function get(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.departments WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error department_class.php'); + } + + $departments=array(); + $departments["departments"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $departments_item=array( + "id" => (int)$id, + "name" => $name, + ); + array_push($departments["departments"], $departments_item); + } + return $departments; + } + public function update(int $data_id, int $id, string $name) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + $query = "UPDATE datadienstplandb.departments SET name = :name WHERE data_id = :data_id AND id = :id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':name' => $name); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error department_class.php'); + } + return $id; + } + public function remove(int $data_id, int $id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $query = "DELETE FROM datadienstplandb.departments WHERE (data_id = :data_id) AND (id = :id)"; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error department_class.php'); + } + $query = 'SELECT * FROM departments WHERE data_id = :data_id AND name = ""'; + $values = array(':data_id' => $data_id); + + try { + $res_n = $pdo->prepare($query); + $res_n->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error department_class.php'); + } + $dep_new = $res_n->fetch(PDO::FETCH_ASSOC); + $new_id = $dep_new["id"]; + $persons = new Person(); + $persons->updateWhereDepartment($data_id, $id, $new_id); + $persons_c = new Person_change(); + $persons_c->updateWhereDepartment($data_id, $id, $new_id); + + return $id; + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.departments WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error department_class.php'); + } + } +} diff --git a/api/objects/institution_class.php b/api/objects/institution_class.php new file mode 100644 index 0000000..178a77f --- /dev/null +++ b/api/objects/institution_class.php @@ -0,0 +1,255 @@ +<?php + +require_once 'closingtime_person_class.php'; +require_once 'department_class.php'; +require_once 'person_class.php'; +require_once 'person_vacation_class.php'; +require_once 'person_illnes_class.php'; +require_once 'roster_changes_class.php'; +require_once 'roster_class.php'; +require_once 'roster_editable_cell_right_class.php'; +require_once 'roster_editable_row_bottom_class.php'; +require_once 'roster_editable_row_top_class.php'; +require_once 'roster_person_info_class.php'; +require_once 'settings_class.php'; +require_once 'settings_labels_class.php'; +require_once 'shift_labels_class.php'; + +class Institution { + private $data_id; + private $name; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->name = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function addClean(string $name, string $yearweek): int { + global $pdo; + $name = trim($name); + $yearweek = trim($yearweek); + $query = 'INSERT INTO datadienstplandb.institutions (name) VALUES (:name)'; + $values = array('name' => $name); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + return $pdo->lastInsertId(); + } + public function add(string $name, string $yearweek): int { + global $pdo; + $name = trim($name); + $yearweek = trim($yearweek); + $query = 'INSERT INTO datadienstplandb.institutions (name) VALUES (:name)'; + $values = array('name' => $name); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + $data_id = $pdo->lastInsertId(); + // add settings + //($data_id, $database_version, $default_overtime, $default_edit_cell_right, $default_row_top, $default_row_bottom, $sort_days, $sort_week, $printmode, $zoom_web, $zoom_print_h, $zoom_print_v) + $settings = new Settings(); + $settings->addSettings($data_id, 2.35, 1, 0, 0, 0, "n-d", "n-d", 0, 100, 100, 100); + // add settings_labels + //add(int $data_id, int $id, string $name, string $cut) + $settings_l = new Settings_labels; + $settings_l->add($data_id, 0, "mpA", "MPA"); + $settings_l->add($data_id, 1, "Krank", "Krank"); + $settings_l->add($data_id, 2, "Weiterbildung", "W"); + $settings_l->add($data_id, 3, "Urlaub", "Urlaub"); + // add shift_labels + $shift_labels = new Shift_labels(); + $shift_labels->add($data_id, "Frei", "Frei"); + $shift_labels->add($data_id, "Schule", "S"); + // add roster + //($data_id, $yearweek, $time_step, $break_60, $break_90, $days) + $roster = new Roster(); + $roster->update($data_id, $yearweek, 0.25, 0.5, 0.25, "Montag,Dienstag,Mittwoch,Donnerstag,Freitag"); + // add roster_change + $roster_c = new Roster_changes(); + $roster_c->update($data_id, $yearweek, 0, 7, 17, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + $roster_c->update($data_id, $yearweek, 1, 7, 17, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + $roster_c->update($data_id, $yearweek, 2, 7, 17, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + $roster_c->update($data_id, $yearweek, 3, 7, 17, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + $roster_c->update($data_id, $yearweek, 4, 7, 17, "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + // add departments + $department = new Department(); + $department->add($data_id, ""); + $department->add($data_id, "Elementar"); + $department->add($data_id, "Kleinkind"); + + + return $data_id; + } + public function get(int $id) { + global $pdo; + $data_id = trim($data_id); + $name = trim($name); + $query = 'SELECT :name FROM datadienstplandb.institutions WHERE id = :id'; + $values = array(':data_id' => $data_id, ':name' => $name); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + + $institution = $res->fetch(PDO::FETCH_ASSOC); + return $institution["name"]; + } + public function getAll() { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.institutions'; + $values=array(); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + + $institutions=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $institutions_item=array( + "id" => (int)$row["id"], + "name" => (string)$row["name"] + ); + array_push($institutions, $institutions_item); + } + return $institutions; + } + public function switchInstitution(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $user_id = $_SESSION["user_id"]; + $_SESSION["data_id"] = $data_id; + $query = 'UPDATE datadienstplandb.users SET data_id = :data_id WHERE id = :user_id'; + $values = array(':data_id' => $data_id, ':user_id' => $user_id); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + return TRUE; + } + public function switchAsInstitution(int $data_id, string $as) { + $_SESSION["administration"] = $as; + $this->switchInstitution($data_id); + return TRUE; + } + public function removeInstitution(int $data_id) { + global $pdo; + + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.institutions WHERE id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + } + public function remove(int $data_id, string $password) { + global $pdo; + // check pass + $password = trim($password); + $query = 'SELECT * FROM datadienstplandb.users WHERE (id = :user_id)'; + $values = array(':user_id' => $_SESSION["user_id"]); + + try { + $res_u = $pdo->prepare($query); + $res_u->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + $row_u = $res_u->fetch(PDO::FETCH_ASSOC); + if (is_array($row_u)) { + if (!password_verify($password, $row_u['password'])) { + return FALSE; + } + } + $query = "SELECT * FROM datadienstplandb.users WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res_a = $pdo->prepare($query); + $res_a->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + while ($row = $res_a->fetch(PDO::FETCH_ASSOC)) { + if ($row["role"] !== "superadmin") { + $query = "DELETE FROM datadienstplandb.users WHERE id = :user_id"; + $values = array(':user_id' => $row["id"]); + try { + $res_r = $pdo->prepare($query); + $res_r->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + $query = "DELETE FROM datadienstplandb.user_sessions WHERE user_id = :user_id"; + $values = array(':user_id' => $row["id"]); + try { + $res_s = $pdo->prepare($query); + $res_s->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error institution_class.php'); + } + } + } + + $data_id = trim($data_id); + $settings = new Settings(); + $settings->removeWhereDataId($data_id); + $settings_l = new Settings_labels(); + $settings_l->removeWhereDataId($data_id); + $roster = new Roster(); + $roster->removeWhereDataId($data_id); + $closingtime = new Closingtime(); + $closingtime->removeWhereDataId($data_id); + $closingtime_p = new Closingtime_person(); + $closingtime_p->removeWhereDataId($data_id); + $department = new Department(); + $department->removeWhereDataId($data_id); + $person = new Person(); + $person->removeWhereDataId($data_id); + $person_b = new Person_betterment(); + $person_b->removeWhereDataId($data_id); + $person_c = new Person_change(); + $person_c->removeWhereDataId($data_id); + $person_v = new Person_vacation(); + $person_v->removeWhereDataId($data_id); + $person_h = new Person_hours(); + $person_h->removeWhereDataId($data_id); + $roster_c = new Roster_changes(); + $roster_c->removeWhereDataId($data_id); + $roster = new Roster(); + $roster->removeWhereDataId($data_id); + $roster_ecr = new Roster_editable_cell_right(); + $roster_ecr->removeWhereDataId($data_id); + $roster_pi = new Roster_person_info(); + $roster_pi->removeWhereDataId($data_id); + $roster_pi = new Roster_person_info(); + $roster_pi->removeWhereDataId($data_id); + $shift = new Shift(); + $shift->removeWhereDataId($data_id); + $shift_l = new Shift_labels(); + $shift_l->removeWhereDataId($data_id); + $this->removeInstitution($data_id); + return TRUE; + } +} diff --git a/api/objects/person_active_class.php b/api/objects/person_active_class.php new file mode 100644 index 0000000..e3e949b --- /dev/null +++ b/api/objects/person_active_class.php @@ -0,0 +1,365 @@ +<?php +require_once 'person_change_class.php'; +require_once 'shift_class.php'; +require_once 'person_betterment_class.php'; +require_once 'person_overtime_manual_class.php'; +require_once 'person_illnes_class.php'; +require_once 'person_vacation_class.php'; +require_once 'settings_labels_class.php'; +require_once 'person_hours_class.php'; + +class Person_active +{ + private $data_id; + private $id; + private $name; + private $activated; + private $department; + private $hours; + private $mpa; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->name = NULL; + $this->activated = NULL; + $this->department = NULL; + $this->hours = NULL; + $this->mpa = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function getActive(int $data_id, string $yearweek, int $person_id, bool $get_removed, bool $just_name) { + global $pdo; + $data_id = trim($data_id); + $yearweek_is = $yearweek; + $query = 'SELECT * FROM datadienstplandb.persons WHERE data_id = :data_id AND id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_active_class.php'); + } + $row = $res->fetch(PDO::FETCH_ASSOC); + extract($row); + if (($activated > $yearweek_is) && (!$just_name)) {return;} + $hours_def = $hours; + // get removed + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = 999 AND yearweek <= :yearweek AND change_key = "r" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $r = $res_c->fetch(PDO::FETCH_ASSOC); + if ((isset($r["value"])) && (!$get_removed)) { + if ($r["value"] <= $yearweek_is) { + unset($r); + return; + } + } else if ((!isset($r["value"])) && ($get_removed)) { + unset($r); + return; + } else if ((isset($r["value"])) && ($get_removed)) { + if ($r["value"] > $yearweek_is) { + unset($r); + return; + } + } + + // get name + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = 999 AND yearweek <= :yearweek AND change_key = "n" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $n = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($n["value"])) { + $name = $n["value"]; + unset($n); + } + + if ($just_name) { + return array( + "id" => (int)$person_id, + "name" => (string)$name + ); + } + + // get others + $shift = new Shift(); + $shifts = $shift->getWhereYearweekPerson($data_id, $yearweek_is, $person_id); + $person_betterment = new Person_betterment(); + $betterments = $person_betterment->get($data_id, $person_id); + $person_overtime_manual = new Person_overtime_manual(); + $overtimes_manual = $person_overtime_manual->get($data_id, $person_id); + $person_illnes = new Person_illnes(); + $illnesses = $person_illnes->get($data_id, $person_id); + $person_vacation = new Person_vacation(); + $vacations = $person_vacation->get($data_id, $person_id); + $settings_labels = new Settings_labels(); + $labels = $settings_labels->get($data_id); + $labels = $labels["labels"]; + // set changes + $sa = [false, false, false, false, false]; + $sf = [false, false, false, false, false]; + $sl = [false, false, false, false, false]; + $mpa_def = explode(',', $mpa); + $mpa_def = array_map('floatval', $mpa_def); + $freedays_this_week=array(); + + $query = 'SELECT days FROM datadienstplandb.rosters WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is); + try { + $res_r = $pdo->prepare($query); + $res_r->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $days_de = $res_r->fetch(PDO::FETCH_ASSOC); + $days_def = explode(',', $days_de["days"]); + for ($day_id=0; $day_id < count($days_def); $day_id++) { + // get mpa + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = :day_id AND yearweek <= :yearweek AND change_key = "m" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':day_id' => $day_id, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $m = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($m["value"])) { $mpa_def[$day_id] = (float)$m["value"]; unset($m);}; + // + // get sa + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = :day_id AND yearweek <= :yearweek AND change_key = "sa" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':day_id' => $day_id, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $a = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($a["value"])) { + if (is_numeric($a["value"])) { + $sa[$day_id] = (float)$a["value"]; + } else { + $sa[$day_id] = filter_var($a["value"], FILTER_VALIDATE_BOOLEAN); + } + unset($a); + }; + // get sf + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = :day_id AND yearweek <= :yearweek AND change_key = "sf" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':day_id' => $day_id, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $f = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($f["value"])) { $sf[$day_id] = filter_var($f["value"], FILTER_VALIDATE_BOOLEAN); unset($f);}; + // get sl + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = :day_id AND yearweek <= :yearweek AND change_key = "sl" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':day_id' => $day_id, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $l = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($l["value"])) { + if (is_numeric($l["value"])) { + $sl[$day_id] = (float)$l["value"]; + } else { + $sl[$day_id] = filter_var($l["value"], FILTER_VALIDATE_BOOLEAN); + } + unset($l); + } + array_push($freedays_this_week, false); + $dt = new DateTime; + $check_date = $dt->setISODate(substr($yearweek_is, 0,4), substr($yearweek_is, 5, 7)); + $check_date = date_format($check_date,"Y-m-d"); + $check_date = date("Y-m-d", strtotime($check_date. "+${day_id} days")); + // get FREEDAYS vacations + if ($freedays_this_week[$day_id] === false) { + $v_keys = array_column($labels, 'id'); + $v_index = array_search('3', $v_keys); + foreach($vacations["person_vacations"] as $key=>$value) { + if (($check_date >= $value['start']) && ($check_date <= $value['end'])) { + if (isset($value["name"])) { + $freedays_this_week[$day_id] = $value["name"]; + } else { + $freedays_this_week[$day_id] = $labels[$v_index]["cut"]; + } + break; + } + } + } + // get FREEDAYS illness + if ($freedays_this_week[$day_id] === false) { + $i_keys = array_column($labels, 'id'); + $i_index = array_search('1', $i_keys); + foreach($illnesses["person_illnes"] as $key=>$value) { + if (($check_date >= $value['start']) && ($check_date <= $value['end'])) { + if ($yearweek_is === $yearweek_is) {$freedays_this_week[$day_id] = $labels[$i_index]["cut"];} + break; + } + } + } + // get FREEDAYS betterment + if ($freedays_this_week[$day_id] === false) { + $b_keys = array_column($labels, 'id'); + $b_index = array_search('2', $b_keys); + foreach($betterments["person_betterments"] as $key=>$value) { + if (($check_date >= $value['start']) && ($check_date <= $value['end'])) { + if ($yearweek_is === $yearweek_is) {$freedays_this_week[$day_id] = $labels[$b_index]["cut"];} + } + } + } + } + + // get hours + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = 999 AND yearweek <= :yearweek AND change_key = "h" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $h = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($h["value"])) { + $hours_def = (float)$h["value"]; + unset($h); + } + // get department + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = 999 AND yearweek <= :yearweek AND change_key = "d" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_is, ':person_id' => $person_id); + try { + $res_c = $pdo->prepare($query); + $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_active_class.php'); } + $d = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($d["value"])) { + $department = (float)$d["value"]; + unset($d); + } + + + $pers_h = new Person_hours; + $hours_week = $pers_h->getHoursWhereYearweek($data_id, $yearweek_is, $person_id); + $hours_total = $pers_h->getHoursTotalWhereYearweek($data_id, $yearweek_is, $person_id); + + $persons_item=array( + "id" => (int)$person_id, + "name" => (string)$name, + "activated" => (string)$activated, + "department" => (int)$department, + "hours" => (float)$hours_def, + "mpa" => $mpa_def, + "sa" => $sa, + "sf" => $sf, + "sl" => $sl, + "hours_week_is" => $hours_week["hours_is"], + "hours_week_should" => $hours_week["hours_should"], + "hours_is" => $hours_total["hours_is"], + "hours_should" => $hours_total["hours_should"], + "overtime" => (float)sprintf ("%.2f", $hours_total["hours_is"]-$hours_total["hours_should"]), + "overtimes_manual" => $overtimes_manual["person_overtimes_manual"], + "shifts" => $shifts["shifts"], + "betterments" => $betterments["person_betterments"], + "illnesses" => $illnesses["person_illnes"], + "vacations" => $vacations["person_vacations"], + "freedays" => $freedays_this_week + ); + + + return $persons_item; + } + public function getAllActive(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $yearweek_is = $yearweek; + $query = 'SELECT * FROM datadienstplandb.persons WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_active_class.php'); + } + + $persons=array(); + $persons["persons"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_id = $id; + $persons_item=$this->getActive($data_id, $yearweek_is, $person_id, FALSE, FALSE); + if (!empty($persons_item)) { + array_push($persons["persons"], $persons_item); + } + } + return $persons; + } + public function getAllActiveIdAndName(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.persons WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_active_class.php'); + } + + $persons=array(); + $persons=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_id = $id; + $persons_item=$this->getActive($data_id, $yearweek, $person_id, FALSE, TRUE); + if (!empty($persons_item)) { + array_push($persons, $persons_item); + } + } + return $persons; + } + public function getRemoved(int $data_id, string $yearweek, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $person = $this->getActive($data_id, $yearweek, $person_id, TRUE, FALSE); + return $person; + } + public function getAllRemoved(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $yearweek_is = $yearweek; + $query = 'SELECT * FROM datadienstplandb.persons WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_active_class.php'); + } + + $persons=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_id = $id; + $persons_item=$this->getActive($data_id, $yearweek_is, $person_id, TRUE, FALSE); + if (!empty($persons_item)) { + array_push($persons, $persons_item); + } + } + return $persons; + } +} diff --git a/api/objects/person_betterment_class.php b/api/objects/person_betterment_class.php new file mode 100644 index 0000000..94ee88e --- /dev/null +++ b/api/objects/person_betterment_class.php @@ -0,0 +1,161 @@ +<?php + +require_once 'person_hours_class.php'; + +class Person_betterment +{ + private $data_id; + private $id; + private $person_id; + private $start; + private $end; + private $hours; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->person_id = NULL; + $this->start = NULL; + $this->end = NULL; + $this->hours = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, int $person_id, string $start, string $end, float $hours): int { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + $hours = trim($hours); + + $query = 'INSERT INTO datadienstplandb.person_betterments (data_id, person_id, start, end, hours) VALUES (:data_id, :person_id, :start, :end, :hours)'; + + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':start' => $start, ':end' => $end, ':hours' => $hours); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error person_betterment_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $start, $end, "is"); + + return $pdo->lastInsertId(); + } + public function getWhereId(int $data_id, int $id) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $query = 'SELECT * FROM datadienstplandb.person_betterments WHERE data_id = :data_id AND id = :id'; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_betterment_class.php'); + } + + $row = $res->fetch(PDO::FETCH_ASSOC); + extract($row); + return array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "start" => $start, + "end" => $end, + "hours" => (float)$hours + ); + } + public function get(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.person_betterments WHERE data_id = :data_id AND person_id = :person_id ORDER BY start DESC'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_betterment_class.php'); + } + + $person_betterments=array(); + $person_betterments["person_betterments"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_betterments_item=array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "start" => $start, + "end" => $end, + "hours" => (float)$hours + ); + array_push($person_betterments["person_betterments"], $person_betterments_item); + } + return $person_betterments; + } + public function getWhereDate(int $data_id, int $person_id, string $date) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $date = trim($date); + $query = 'SELECT * FROM datadienstplandb.person_betterments WHERE data_id = :data_id AND person_id = :person_id AND start <= :date AND end >= :date'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':date' => $date); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_betterment_class.php'); + } + $person_betterment = $res->fetch(PDO::FETCH_ASSOC); + return $person_betterment; + } + public function remove(int $data_id, int $id, int $person_id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + + $betterment = $this->getWhereId($data_id, $id); + + $query = "DELETE FROM datadienstplandb.person_betterments WHERE data_id = :data_id AND id = :id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_betterment_class.php'); + } + + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $betterment["start"], $betterment["end"], "is"); + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_betterments WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_betterment_class.php'); + } + } +} diff --git a/api/objects/person_change_class.php b/api/objects/person_change_class.php new file mode 100644 index 0000000..9080077 --- /dev/null +++ b/api/objects/person_change_class.php @@ -0,0 +1,437 @@ +<?php + +require_once 'person_hours_class.php'; + +class Person_change { + private $data_id; + private $id; + private $person_id; + private $yearweek; + private $day_id; + private $change_key; + private $value; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->person_id = NULL; + $this->yearweek = NULL; + $this->day_id = NULL; + $this->change_key = NULL; + $this->value = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, int $person_id, string $yearweek, $day_id, string $change_key, string $value): int { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $change_key = trim($change_key); + $value = trim($value); + + $query = 'INSERT INTO datadienstplandb.person_changes (data_id, person_id, yearweek, day_id, change_key, value) VALUES (:data_id, :person_id, :yearweek, :day_id, :change_key, :value)'; + + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "should"); + } else if ($change_key === "m") { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + + return $pdo->lastInsertId(); + } + public function get(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + + $person_changes=array(); + $person_changes["person_changes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_changes_item=array( + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "day_id" => (int)$day_id, + "change_key" => $change_key, + "value" => $value + ); + array_push($person_changes["person_changes"], $person_changes_item); + } + return $person_changes; + } + public function getWhereKey(int $data_id, int $person_id, string $change_key) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $change_key = trim($change_key); + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND person_id = :person_id AND change_key = :change_key ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':change_key' => $change_key); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + + $person_changes=array(); + $person_changes["person_changes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_changes_item=array( + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "day_id" => (int)$day_id, + "change_key" => $change_key, + "value" => $value + ); + array_push($person_changes["person_changes"], $person_changes_item); + } + return $person_changes; + } + public function getWhereKeyValue(int $data_id, string $change_key, string $value) { + global $pdo; + $data_id = trim($data_id); + $change_key = trim($change_key); + $value = trim($value); + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND change_key = :change_key AND value = :value ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + + $person_changes=array(); + $person_changes["person_changes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_changes_item=array( + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "day_id" => (int)$day_id, + "change_key" => $change_key, + "value" => $value + ); + array_push($person_changes["person_changes"], $person_changes_item); + } + return $person_changes; + } + public function getWhereYearweekKey(int $data_id, int $person_id, string $yearweek, string $change_key) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $change_key = trim($change_key); + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek AND change_key = :change_key ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':change_key' => $change_key); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + + $person_changes=array(); + $person_changes["person_changes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_changes_item=array( + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "day_id" => $day_id, + "change_key" => $change_key, + "value" => $value + ); + array_push($person_changes["person_changes"], $person_changes_item); + } + return $person_changes; + } + public function getWhereYearweekDayKey(int $data_id, int $person_id, string $yearweek, int $day_id, string $change_key) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $change_key = trim($change_key); + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek AND day_id = :day_id AND change_key = :change_key ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':change_key' => $change_key); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + + $person_changes=array(); + $person_changes["person_changes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_changes_item=array( + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "day_id" => (int)$day_id, + "change_key" => $change_key, + "value" => $value + ); + array_push($person_changes["person_changes"], $person_changes_item); + } + return $person_changes; + } + + + public function updateWhereKey(int $data_id, int $person_id, string $change_key, string $value) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $change_key = trim($change_key); + $value = trim($value); + $query = 'UPDATE datadienstplandb.person_changes SET value = :value WHERE data_id = :data_id AND person_id = :person_id AND change_key = :change_key'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateAllWherePerson($data_id, $person_id, "should"); + } else if ($change_key === "m") { + $set_hours->updateAllWherePerson($data_id, $person_id, "is"); + } + } + public function updateWhereYearweekKey(int $data_id, int $person_id, string $yearweek, string $change_key, string $value) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $change_key = trim($change_key); + $value = trim($value); + $query = 'UPDATE datadienstplandb.person_changes SET value = :value WHERE data_id = :data_id AND person_id = :person_id AND yearweek = : yearweek AND change_key = :change_key'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, 'yearweek' => $yearweek, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "should"); + } else if ($change_key === "m") { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + } + public function updateWhereDayKey(int $data_id, int $person_id, int $day_id, string $change_key, string $value) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $day_id = trim($day_id); + $change_key = trim($change_key); + $value = trim($value); + $query = 'UPDATE datadienstplandb.person_changes SET value = :value WHERE data_id = :data_id AND person_id = :person_id AND day_id = :day_id AND change_key = :change_key'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':day_id' => $day_id, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateAllWherePerson($data_id, $person_id, "should"); + } else if ($change_key === "m") { + $set_hours->updateAllWherePerson($data_id, $person_id, "is"); + } + } + public function updateWhereYearweekDayKey(int $data_id, int $person_id, string $yearweek, int $day_id, string $change_key, string $value) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $change_key = trim($change_key); + $value = trim($value); + $query = 'INSERT INTO datadienstplandb.person_changes (data_id, person_id, yearweek, day_id, change_key, value) VALUES (:data_id, :person_id, :yearweek, :day_id, :change_key, :value) ON DUPLICATE KEY UPDATE value = :value'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, 'yearweek' => $yearweek, ':day_id' => $day_id, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "should"); + } else if ($change_key === "m") { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + } + public function updateWhereYearweekGeKey(int $data_id, int $person_id, string $yearweek, string $change_key, string $value) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $change_key = trim($change_key); + $value = trim($value); + $query = 'UPDATE datadienstplandb.person_changes SET value = :value WHERE data_id = :data_id AND person_id = :person_id AND yearweek >= : yearweek AND change_key = :change_key'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, 'yearweek' => $yearweek, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateWhereGe($data_id, $person_id, $yearweek, "should"); + } else if ($change_key === "m") { + $set_hours->updateWhereGe($data_id, $person_id, $yearweek, "is"); + } + } + public function updateWhereYearweekGeDayKey(int $data_id, int $person_id, string $yearweek, int $day_id, string $change_key, string $value) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $change_key = trim($change_key); + $value = trim($value); + $query = 'UPDATE datadienstplandb.person_changes SET value = :value WHERE data_id = :data_id AND person_id = :person_id AND yearweek >= :yearweek AND day_id = :day_id AND change_key = :change_key'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':change_key' => $change_key, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateWhereGe($data_id, $person_id, $yearweek, "should"); + } else if ($change_key === "m") { + $set_hours->updateWhereGe($data_id, $person_id, $yearweek, "is"); + } + } + public function updateWhereDepartment(int $data_id, int $dep_id, int $new_id) { + global $pdo; + $data_id = trim($data_id); + $dep_id = trim($dep_id); + $new_id = trim($new_id); + $query = 'UPDATE datadienstplandb.person_changes SET value = :new_id WHERE data_id = :data_id AND change_key = "d" AND value = :dep_id'; + $values = array(':data_id' => $data_id, ':new_id' => $new_id, ':dep_id' => $dep_id); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + } + + + public function removeWhereKey(int $data_id, int $person_id, string $change_key) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + $change_key = trim($change_key); + $query = "DELETE FROM datadienstplandb.person_changes WHERE data_id = :data_id AND person_id = :person_id AND change_key = :change_key"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':change_key' => $change_key); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + } + public function removeWherePerson(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = "DELETE FROM datadienstplandb.person_changes WHERE data_id = :data_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + } + + public function removeWhereYearweekDayKey(int $data_id, int $person_id, string $yearweek, int $day_id, string $change_key) { + global $pdo; + + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $change_key = trim($change_key); + $query = "DELETE FROM datadienstplandb.person_changes WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek AND day_id = :day_id AND change_key = :change_key"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':change_key' => $change_key); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + $set_hours = new Person_hours(); + if (($change_key === "h") || ($change_key === "sf")) { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "should"); + } else if ($change_key === "m") { + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_changes WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_change_class.php'); + } + } +} diff --git a/api/objects/person_class.php b/api/objects/person_class.php new file mode 100644 index 0000000..b96ddf6 --- /dev/null +++ b/api/objects/person_class.php @@ -0,0 +1,223 @@ +<?php +require_once 'person_change_class.php'; +require_once 'shift_class.php'; +require_once 'person_hours_class.php'; +require_once 'person_betterment_class.php'; +require_once 'person_overtime_manual_class.php'; +require_once 'roster_class.php'; +require_once 'closingtime_person_class.php'; + +class Person +{ + private $data_id; + private $id; + private $name; + private $activated; + private $department; + private $hours; + private $mpa; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->name = NULL; + $this->activated = NULL; + $this->department = NULL; + $this->hours = NULL; + $this->mpa = NULL; + } + + /* Destructor */ + public function __destruct() { } + + + public function add(int $data_id, string $name, string $activated, int $department, float $hours, string $mpa): int { + global $pdo; + $data_id = trim($data_id); + $name = trim($name); + $activated = trim($activated); + $department = trim($department); + $hours = trim($hours); + $mpa = trim($mpa); + $query = 'INSERT INTO datadienstplandb.persons (data_id, name, activated, department, hours, mpa) VALUES (:data_id, :name, :activated, :department, :hours, :mpa)'; + + $values = array(':data_id' => $data_id, ':name' => $name, ':activated' => $activated, ':department' => $department, ':hours' => $hours, ':mpa' => $mpa,); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + + $id = $pdo->lastInsertId(); + $yearweeks_c = new Roster(); + $yearweeks = $yearweeks_c->getYearweeks($data_id); + $person_hours = new Person_hours(); + foreach ($yearweeks as &$yw) { + if ($yw["yearweek"] >= $activated) { + $person_hours->setHoursWhereYearweek($data_id, $yw["yearweek"], $id); + } + } + return $id; + } + public function get(int $data_id, int $id) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $query = 'SELECT * FROM datadienstplandb.persons WHERE data_id = :data_id AND id = :id'; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + + $person = $res->fetch(PDO::FETCH_ASSOC); + extract($person); + return array( + "id" => (int)$id, + "name" => (string)$name, + "activated" => (string)$activated, + "department" => (int)$department, + "hours" => (float)$hours, + "mpa" => (string)$mpa + ); + } + + public function getAll(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.persons WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + + $persons=array(); + $persons["persons"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $persons_item=array( + "id" => (int)$id, + "name" => (string)$name, + "activated" => (string)$activated, + "department" => (int)$department, + "hours" => (float)$hours, + "mpa" => (string)$mpa + ); + array_push($persons["persons"], $persons_item); + } + return $persons; + } + + public function update(int $data_id, int $id, string $name, string $activated, int $department, float $hours, string $mpa) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + $activated = trim($activated); + $department = trim($department); + $hours = trim($hours); + $mpa = trim($mpa); + + $query = 'UPDATE datadienstplandb.persons SET (data_id, name, activated, department, hours, mpa) VALUES (:data_id, :name, :activated, :department, :hours, :mpa) WHERE id = :id AND data_id = :data_id'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':name' => $name, ':activated' => $activated, ':department' => $department, ':hours ' => $hours , ':mpa' => $mpa,); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + } + public function updateWhereDepartment(int $data_id, int $dep_id, int $new_id) { + global $pdo; + $data_id = trim($data_id); + $dep_id = trim($dep_id); + $new_id = trim($new_id); + + $query = 'UPDATE datadienstplandb.persons SET department = :new_id WHERE data_id = :data_id AND department = :dep_id'; + $values = array(':data_id' => $data_id, ':dep_id' => $dep_id, ':new_id' => $new_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + } + public function updateWhere(int $data_id, int $id, string $name, $value) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + if ($name === "mpa") {$value = implode(",", $value);}; + $value = trim($value); + $query = "UPDATE datadienstplandb.persons SET `".$name."` = :value WHERE data_id = :data_id AND id = :id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + if ($name === "activated") { + $yearweeks_c = new Roster(); + $yearweeks = $yearweeks_c->getYearweeks($data_id); + $person_hours = new Person_hours(); + foreach ($yearweeks as &$yw) { + if ($yw["yearweek"] >= $value) { + $person_hours->setHoursWhereYearweek($data_id, $yw["yearweek"], $id); + } + } + $person_hours->removeWhereYwLt($data_id, $id, $value); + } + + return $id; + } + public function remove(int $data_id, int $id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $query = "DELETE FROM datadienstplandb.persons WHERE (data_id = :data_id) AND (id = :id)"; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + $person_c = new Person_change(); + $person_c->removeWherePerson($data_id, $id); + $closingtime_p = new Closingtime_person(); + $closingtime_p->removeAllWherePerson($data_id, $id); + $person_h = new Person_hours(); + $person_h->removeWherePerson($data_id, $id); + return $id; + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.persons WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_class.php'); + } + } +} diff --git a/api/objects/person_hours_class.php b/api/objects/person_hours_class.php new file mode 100644 index 0000000..7af863b --- /dev/null +++ b/api/objects/person_hours_class.php @@ -0,0 +1,487 @@ +<?php + +class Person_hours +{ + private $data_id; + private $person_id; + private $yearweek; + private $hours_should; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->person_id = NULL; + $this->yearweek = NULL; + $this->hours_should = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function checkFreeDay(int $data_id, string $yearweek_for, int $person_id, int $day_id) { + global $pdo; + $is_free = FALSE; + $is_noworkingday = FALSE; + $dt = new DateTime; + $check_date = $dt->setISODate(substr($yearweek_for, 0,4), substr($yearweek_for, 5, 7)); + $check_date = date_format($check_date,"Y-m-d"); + $check_date = date("Y-m-d", strtotime($check_date. "+${day_id} days")); + // check FREE + //check vacations + if ($is_free === FALSE) { + $query = 'SELECT id FROM datadienstplandb.person_vacations WHERE data_id = :data_id AND person_id = :person_id AND start <= :check_date AND end >= :check_date;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':check_date' => $check_date); + try { $res_v = $pdo->prepare($query); $res_v->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $v = $res_v->fetch(PDO::FETCH_ASSOC); + if (isset($v["id"])) { + $is_free = TRUE; + } + unset($v); + } + //check illnes + if ($is_free === FALSE) { + $query = 'SELECT id FROM datadienstplandb.person_illnes WHERE data_id = :data_id AND person_id = :person_id AND start <= :check_date AND end >= :check_date;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':check_date' => $check_date); + try { $res_i = $pdo->prepare($query); $res_i->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $i = $res_i->fetch(PDO::FETCH_ASSOC); + if (isset($i["id"])) { + $is_free = TRUE; + } + unset($i); + } + //check closingtime + if ($is_free === FALSE){ + $query = 'SELECT * FROM datadienstplandb.closingtimes WHERE data_id = :data_id AND start <= :check_date AND end >= :check_date;'; + $values = array(':data_id' => $data_id, ':check_date' => $check_date); + try { $res_cl = $pdo->prepare($query); $res_cl->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $c = $res_cl->fetch(PDO::FETCH_ASSOC); + if (isset($c["id"])) { + if ((int)$c["lawful"] === 1) { + $is_free = TRUE; + } else { + $query = 'SELECT id FROM datadienstplandb.closingtime_persons WHERE data_id = :data_id AND closingtime_id = :closingtime_id AND person_id = :person_id;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':closingtime_id' => $c["id"]); + try { $res_cp = $pdo->prepare($query); $res_cp->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $cp = $res_cp->fetch(PDO::FETCH_ASSOC); + if (isset($cp["id"])) { + $is_free = TRUE; + } + unset($cp); + } + } + unset($c); + } + return $is_free; + } + public function calculateHoursShould(int $data_id, string $yearweek_for, int $person_id) { + // get hours should be + global $pdo; + $hours_should = 0; + // get hours + $hours_week; + $query = 'SELECT * FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = 999 AND yearweek <= :yearweek AND change_key = "h" AND person_id = :person_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_for, ':person_id' => $person_id); + try { $res_c = $pdo->prepare($query); $res_c->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $h = $res_c->fetch(PDO::FETCH_ASSOC); + if (isset($h["value"])) { + $hours_week = (float)$h["value"]; + unset($h); + } else { + $query = 'SELECT hours FROM datadienstplandb.persons WHERE data_id = :data_id AND id = :person_id;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + try { $res_p = $pdo->prepare($query); $res_p->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); }; + $hours_week = $res_p->fetch(PDO::FETCH_ASSOC); + $hours_week = (float)$hours_week["hours"]; + } + + $query = 'SELECT * FROM datadienstplandb.rosters WHERE data_id = :data_id AND yearweek = :yearweek;'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_for); + try { + $res_y = $pdo->prepare($query); + $res_y->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $row_yearweek = $res_y->fetch(PDO::FETCH_ASSOC); + $days_for = explode(',', $row_yearweek['days']); + // get FREE + $freedays_days = 0; + $noworkingday_days = 0; + + for ($day_id=0; $day_id < count($days_for); $day_id++) { + $is_free = FALSE; + $is_noworkingday = FALSE; + // check FREE + //check label + + $query = 'SELECT value FROM datadienstplandb.person_changes WHERE data_id = :data_id AND day_id = :day_id AND yearweek <= :yearweek_for AND change_key = "sf" AND person_id = :person_id ORDER BY yearweek DESC;'; + $values = array(':data_id' => $data_id, ':yearweek_for' => $yearweek_for, ':day_id' => $day_id, ':person_id' => $person_id); + try { $res_l = $pdo->prepare($query); $res_l->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $l = $res_l->fetch(PDO::FETCH_ASSOC); + if ((isset($l["value"])) && ($l["value"] === "true")) { + $is_noworkingday = TRUE; + $noworkingday_days = $noworkingday_days+1; + } + if ($is_noworkingday === FALSE) { + $is_free = $this->checkFreeDay($data_id, $yearweek_for, $person_id, $day_id); + }; + if ($is_free === TRUE) { + $freedays_days = $freedays_days+1; + } + } + $freedays_hours = ($hours_week/(count($days_for)-$noworkingday_days))*$freedays_days; + + $hours_should = $hours_should+$hours_week-$freedays_hours; + $hours_should = round($hours_should,2); + return $hours_should; + } + public function calculateHoursIs(int $data_id, string $yearweek_for, int $person_id) { + global $pdo; + // get hours is + $hours_is = 0; + $query = 'SELECT SUM(end-start-breaks) FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek AND person_id = :person_id;'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_for, ':person_id' => $person_id); + try { $res_is = $pdo->prepare($query); $res_is->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours_is = $res_is->fetch(PDO::FETCH_ASSOC); + $hours_is = $hours_is["SUM(end-start-breaks)"]; + + + // get mpa_all + + // get overtime_manual + $query = 'SELECT SUM(overtime) FROM datadienstplandb.person_overtimes_manual WHERE data_id = :data_id AND yearweek = :yearweek AND person_id = :person_id;'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_for, ':person_id' => $person_id); + try { + $res_o = $pdo->prepare($query); + $res_o->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $overtime_m = $res_o->fetch(PDO::FETCH_ASSOC); + if (!empty($overtime_m)) { + $hours_is = $hours_is+$overtime_m["SUM(overtime)"]; + } + + $query = 'SELECT * FROM datadienstplandb.rosters WHERE data_id = :data_id AND yearweek = :yearweek;'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_for); + try { + $res_y = $pdo->prepare($query); + $res_y->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $row_yearweek = $res_y->fetch(PDO::FETCH_ASSOC); + $days_for = explode(',', $row_yearweek['days']); + + $query = 'SELECT mpa FROM datadienstplandb.persons WHERE data_id = :data_id AND id = :person_id;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + try { $res_person = $pdo->prepare($query); $res_person->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); }; + $mpa = $res_person->fetch(PDO::FETCH_ASSOC); + $mpa = explode(',', $mpa["mpa"]); + for ($day_id=0; $day_id < count($days_for); $day_id++) { + $dt = new DateTime; + $check_date = $dt->setISODate(substr($yearweek_for, 0,4), substr($yearweek_for, 5, 7)); + $check_date = date_format($check_date,"Y-m-d"); + $check_date = date("Y-m-d", strtotime($check_date. "+${day_id} days")); + //get betterments + $query = 'SELECT hours FROM datadienstplandb.person_betterments WHERE data_id = :data_id AND person_id = :person_id AND start <= :check_date AND end >= :check_date;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':check_date' => $check_date); + try { $res_b = $pdo->prepare($query); $res_b->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $b = $res_b->fetch(PDO::FETCH_ASSOC); + if (isset($b["hours"])) { + $hours_is = $hours_is+$b["hours"]; + } + $is_free = $this->checkFreeDay($data_id, $yearweek_for, $person_id, $day_id); + if ($is_free) {continue;} + // get mpa_day + $query='SELECT value FROM datadienstplandb.person_changes WHERE data_id = :data_id AND person_id = :person_id AND change_key = "m" AND day_id = :day_id AND yearweek <= :yearweek ORDER BY yearweek DESC;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek_for, ':day_id' => $day_id); + try { $res_m = $pdo->prepare($query); $res_m->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $m = $res_m->fetch(PDO::FETCH_ASSOC); + if (isset($m["value"])) { + $hours_is = $hours_is+(float)$m["value"]; + } else { + $hours_is = $hours_is+(float)$mpa[$day_id]; + } + } + $hours_is = round($hours_is, 2); + return $hours_is; + } + public function getHoursTotalWhereYearweek(int $data_id, string $yearweek_for, int $person_id) { + global $pdo; + $query = 'SELECT SUM(hours_is), SUM(hours_should), yearweek FROM datadienstplandb.person_hours WHERE data_id = :data_id AND yearweek <= :yearweek AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek_for); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours=array(); + $row = $res_h->fetch(PDO::FETCH_ASSOC); + return array( + "person_id" => (int)$person_id, + "hours_is" => (float)$row["SUM(hours_is)"], + "hours_should" => (float)$row["SUM(hours_should)"] + ); + } + public function getHoursAll(int $data_id, int $person_id) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.person_hours WHERE data_id = :data_id AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours=array(); + while ($row = $res_h->fetch(PDO::FETCH_ASSOC)) { + $item = array( + "yearweek" => (string)$row["yearweek"], + "person_id" => (int)$row["person_id"], + "hours_is" => (float)$row["hours_is"], + "hours_should" => (float)$row["hours_should"] + ); + array_push($hours, $item); + } + return $hours; + } + public function getHoursWhereYearweek(int $data_id, string $yearweek_for, int $person_id) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.person_hours WHERE data_id = :data_id AND yearweek = :yearweek AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek_for); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $h = $res_h->fetch(PDO::FETCH_ASSOC); + if (!isset($h["hours_is"])) { + $h = $this->setHoursWhereYearweek($data_id, $yearweek_for, $person_id); + } + if (!isset($h["hours_is"])) { + return FALSE; + } + return array( + "yearweek" => (string)$h["yearweek"], + "person_id" => (int)$h["person_id"], + "hours_is" => (float)$h["hours_is"], + "hours_should" => (float)$h["hours_should"] + ); + } + public function getHoursWhereYearweekGeLe(int $data_id, string $yearweek_start, string $yearweek_end, int $person_id) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.person_hours WHERE data_id = :data_id AND yearweek >= :yearweek_start AND yearweek <= :yearweek_end AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek_start' => $yearweek_start, ':yearweek_end' => $yearweek_end); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours=array(); + while ($row = $res_h->fetch(PDO::FETCH_ASSOC)) { + $hours_item = array( + "yearweek" => (string)$row["yearweek"], + "person_id" => (int)$row["person_id"], + "hours_is" => (float)$row["hours_is"], + "hours_should" => (float)$row["hours_should"] + ); + array_push($hours, $hours_item); + } + return $hours; + } + public function getHoursWhereYearweekGe(int $data_id, string $yearweek_for, int $person_id) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.person_hours WHERE data_id = :data_id AND yearweek >= :yearweek AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek_for); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours=array(); + while ($row = $res_h->fetch(PDO::FETCH_ASSOC)) { + $hours_item = array( + "yearweek" => (string)$row["yearweek"], + "person_id" => (int)$row["person_id"], + "hours_is" => (float)$row["hours_is"], + "hours_should" => (float)$row["hours_should"] + ); + array_push($hours, $hours_item); + } + return $hours; + } + public function getHoursWhereYearweekLt(int $data_id, string $yearweek_for, int $person_id) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.person_hours WHERE data_id = :data_id AND yearweek < :yearweek AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek_for); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours=array(); + while ($row = $res_h->fetch(PDO::FETCH_ASSOC)) { + $hours_item = array( + "yearweek" => (string)$row["yearweek"], + "person_id" => (int)$row["person_id"], + "hours_is" => (float)$row["hours_is"], + "hours_should" => (float)$row["hours_should"] + ); + array_push($hours, $hours_item); + } + return $hours; + } + public function getHoursWhereYearweekLe(int $data_id, string $yearweek_for, int $person_id) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.person_hours WHERE data_id = :data_id AND yearweek <= :yearweek AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek_for); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours=array(); + while ($row = $res_h->fetch(PDO::FETCH_ASSOC)) { + $hours_item = array( + "yearweek" => (string)$row["yearweek"], + "person_id" => (int)$row["person_id"], + "hours_is" => (float)$row["hours_is"], + "hours_should" => (float)$row["hours_should"] + ); + array_push($hours, $hours_item); + } + return $hours; + } + public function getHoursAllPersonsWhereYearweek(int $data_id, string $yearweek_for) { + global $pdo; + $query = 'SELECT * FROM datadienstplandb.person_hours WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek_for); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $hours=array(); + while ($row = $res_h->fetch(PDO::FETCH_ASSOC)) { + $hours_item = array( + "yearweek" => (string)$row["yearweek"], + "person_id" => (int)$row["person_id"], + "hours_is" => (float)$row["hours_is"], + "hours_should" => (float)$row["hours_should"] + ); + array_push($hours, $hours_item); + } + return $hours; + } + public function setHoursWhereYearweek(int $data_id, string $yearweek_for, int $person_id) { + global $pdo; + $hours_should = $this->calculateHoursShould($data_id, $yearweek_for, $person_id); + $hours_is = $this->calculateHoursIs($data_id, $yearweek_for, $person_id); + + + $query = 'SELECT activated FROM datadienstplandb.persons WHERE data_id = :data_id AND id = :person_id;'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + try { $res_p = $pdo->prepare($query); $res_p->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + $a = $res_p->fetch(PDO::FETCH_ASSOC); + $test = $a["activated"]; + if ($a["activated"] > $yearweek_for) {return;} + + + $query = 'INSERT INTO datadienstplandb.person_hours (data_id, yearweek, person_id, hours_is, hours_should) VALUES (:data_id, :yearweek, :person_id, :hours_is, :hours_should) ON DUPLICATE KEY UPDATE hours_is = :hours_is, hours_should = :hours_should'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek_for, ':hours_is' => $hours_is, ':hours_should' => $hours_should); + try { $res_h = $pdo->prepare($query); $res_h->execute($values); } catch (PDOException $e) { throw new Exception('Database query error person_hours_class.php'); } + return array( + "yearweek" => (string)$yearweek_for, + "person_id" => (int)$person_id, + "hours_is" => (float)$hours_is, + "hours_should" => (float)$hours_should + ); + } + + public function updateWhere(int $data_id, int $person_id, string $yearweek, string $is_should) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $is_should = trim($is_should); + $yearweek = trim($yearweek); + + $query; + $values; + if ($is_should === "is") { + $value = $this->calculateHoursIs($data_id, $yearweek, $person_id); + $query = "UPDATE datadienstplandb.person_hours SET hours_is = :value WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':value' => $value); + } else if ($is_should === "should") { + $value = $this->calculateHoursShould($data_id, $yearweek, $person_id); + $query = "UPDATE datadienstplandb.person_hours SET hours_should = :value WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':value' => $value); + } else if ($is_should === "both") { + $value_1 = $this->calculateHoursIs($data_id, $yearweek, $person_id); + $value_2 = $this->calculateHoursShould($data_id, $yearweek, $person_id); + $query = "UPDATE datadienstplandb.person_hours SET hours_is = :value_1, hours_should = :value_2 WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':value_1' => $value_1, ':value_2' => $value_2); + } + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_hours_class.php'); + } + } + public function updateWhereGe(int $data_id, int $person_id, string $yearweek, string $is_should) { + $set_hours = $this->getHoursWhereYearweekGe($data_id, $yearweek, $person_id); + foreach($set_hours as $key=>$value) { + $this->updateWhere($data_id, $person_id, $value['yearweek'], $is_should); + } + } + public function updateWhereLt(int $data_id, int $person_id, string $yearweek, string $is_should) { + $set_hours = $this->getHoursWhereYearweekLt($data_id, $yearweek, $person_id); + foreach($set_hours as $key=>$value) { + $this->updateWhere($data_id, $person_id, $value['yearweek'], $is_should); + } + } + public function updateWhereBetweenDate(int $data_id, int $person_id, $start, $end, string $is_should) { + $data_id = trim($data_id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + $is_should = trim($is_should); + + $dt = new DateTime($start); + $week = $dt->format("W"); + if (strlen($week) === 1) {$week = "0$week";} + $year = substr($start, 0,4); + $yearweek_start = "$year-$week"; + + $dt = new DateTime($end); + $week = $dt->format("W"); + if (strlen($week) === 1) {$week = "0$week";} + $year = substr($end, 0,4); + $yearweek_end = "$year-$week"; + + $set_hours = $this->getHoursWhereYearweekGeLe($data_id, $yearweek_start, $yearweek_end, $person_id); + foreach($set_hours as $key=>$value) { + $yearweek_for = $value['yearweek']; + if (($yearweek_for >= $yearweek_start) && ($yearweek_for <= $yearweek_end)) { + $this->updateWhere($data_id, $person_id, $yearweek_for, $is_should); + } + } + } + public function updateAllWherePerson(int $data_id, int $person_id, string $is_should) { + $all = $this->getHoursAll($data_id, $person_id); + foreach($all as $key=>$value) { + $this->updateWhere($data_id, $person_id, $value["yearweek"], $is_should); + } + } + public function updateAllPersonsWhere(int $data_id, string $yearweek, string $is_should) { + $set_hours = $this->getHoursAllPersonsWhereYearweek($data_id, $yearweek); + foreach($set_hours as $key=>$value) { + $this->updateWhere($data_id, $value["person_id"], $yearweek, $is_should); + } + } + public function removeWhereYwLt(int $data_id, int $person_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_hours WHERE data_id = :data_id AND person_id = :person_id AND yearweek < :yearweek"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_hours_class.php'); + } + } + public function removeWherePerson(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_hours WHERE data_id = :data_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_hours_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_hours WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_hours_class.php'); + } + } +} diff --git a/api/objects/person_illnes_class.php b/api/objects/person_illnes_class.php new file mode 100644 index 0000000..543c931 --- /dev/null +++ b/api/objects/person_illnes_class.php @@ -0,0 +1,163 @@ +<?php + +require_once 'person_hours_class.php'; + +class Person_illnes +{ + private $data_id; + private $id; + private $person_id; + private $start; + private $end; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->person_id = NULL; + $this->start = NULL; + $this->end = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, int $person_id, string $start, string $end): int { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + + $query = 'INSERT INTO datadienstplandb.person_illnes (data_id, person_id, start, end) VALUES (:data_id, :person_id, :start, :end)'; + + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':start' => $start, ':end' => $end); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error person_illnes_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $start, $end, "should"); + + return $pdo->lastInsertId(); + } + public function get(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.person_illnes WHERE data_id = :data_id AND person_id = :person_id ORDER BY start DESC'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_illnes_class.php'); + } + + $person_illnes=array(); + $person_illnes["person_illnes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_illnes_item=array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "start" => $start, + "end" => $end + ); + array_push($person_illnes["person_illnes"], $person_illnes_item); + } + return $person_illnes; + } + public function getWhereId(int $data_id, int $id) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $query = 'SELECT * FROM datadienstplandb.person_illnes WHERE data_id = :data_id AND id = :id'; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_illnes_class.php'); + } + + $row = $res->fetch(PDO::FETCH_ASSOC); + extract($row); + return array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "start" => $start, + "end" => $end + ); + } + public function update(int $data_id, int $id, int $person_id, string $start, string $end): int { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + + $query = 'UPDATE datadienstplandb.person_illnes SET start = :start, end = :end WHERE data_id = :data_id AND id = :id AND person_id = :person_id'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':person_id' => $person_id, ':start' => $start, ':end' => $end); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error person_illnes_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $start, $end, "should"); + + return $id; + } + public function remove(int $data_id, int $id, int $person_id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + $illnes = $this->getWhereId($data_id, $id); + $query = "DELETE FROM datadienstplandb.person_illnes WHERE data_id = :data_id AND id = :id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_illnes_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $illnes["start"], $illnes["end"], "should"); + return $id; + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_illnes WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_illnes_class.php'); + } + } +} diff --git a/api/objects/person_overtime_class.php b/api/objects/person_overtime_class.php new file mode 100644 index 0000000..c5b3fd0 --- /dev/null +++ b/api/objects/person_overtime_class.php @@ -0,0 +1,155 @@ +<?php + +class Person_overtime +{ + private $data_id; + private $id; + private $person_id; + private $yearweek; + private $overtime; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->person_id = NULL; + $this->yearweek = NULL; + $this->overtime = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, int $person_id, string $yearweek, float $overtime): int { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $overtime = trim($overtime); + + $query = 'INSERT INTO datadienstplandb.person_overtimes (data_id, person_id, yearweek, overtime) VALUES (:data_id, :person_id, :yearweek, :overtime)'; + + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':overtime' => $overtime); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error person_overtime_class.php'); + } + + return $pdo->lastInsertId(); + } + public function getWhereYearweek(int $data_id, int $person_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.person_overtimes WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_overtime_class.php'); + } + + $person_overtimes=array(); + $person_overtimes["person_overtimes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_overtime_item=array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "overtime" => (float)$overtime + ); + array_push($person_overtimes["person_overtimes"], $person_overtime_item); + } + return $person_overtimes; + } + public function getWhereYearweekLe(int $data_id, int $person_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.person_overtimes WHERE data_id = :data_id AND person_id = :person_id AND yearweek <= :yearweek'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_overtime_class.php'); + } + + $person_overtimes=array(); + $person_overtimes["person_overtimes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_overtime_item=array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "overtime" => (float)$overtime + ); + array_push($person_overtimes["person_overtimes"], $person_overtime_item); + } + return $person_overtimes; + } + public function update(int $data_id, int $person_id, string $yearweek, float $overtime) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $overtime = trim($overtime); + $query = 'INSERT INTO datadienstplandb.person_overtimes (data_id, yearweek, person_id, overtime) VALUES (:data_id, :yearweek, :person_id, :overtime) ON DUPLICATE KEY UPDATE overtime = :overtime'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':overtime' => $overtime, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_overtime_class.php'); + } + } + + public function remove(int $data_id, int $id, int $person_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.person_overtimes WHERE data_id = :data_id AND id = :id AND person_id = :person_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':id' => $id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_overtime_class.php'); + } + } + public function removeWhereYearweekLt(int $data_id, int $id, int $person_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.person_overtimes WHERE data_id = :data_id AND id = :id AND person_id = :person_id AND yearweek < :yearweek"; + $values = array(':data_id' => $data_id, ':id' => $id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_overtime_class.php'); + } + } +} diff --git a/api/objects/person_overtime_manual_class.php b/api/objects/person_overtime_manual_class.php new file mode 100644 index 0000000..120df7e --- /dev/null +++ b/api/objects/person_overtime_manual_class.php @@ -0,0 +1,197 @@ +<?php + +require_once 'person_hours_class.php'; + +class Person_overtime_manual +{ + private $data_id; + private $person_id; + private $yearweek; + private $overtime; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->person_id = NULL; + $this->yearweek = NULL; + $this->overtime = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, int $person_id, string $yearweek, float $overtime): int { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $overtime = trim($overtime); + + $query = 'INSERT INTO datadienstplandb.person_overtimes_manual (data_id, person_id, yearweek, overtime) VALUES (:data_id, :person_id, :yearweek, :overtime)'; + + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek, ':overtime' => $overtime); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + + return $pdo->lastInsertId(); + } + public function get(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.person_overtimes_manual WHERE data_id = :data_id AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + + $person_overtimes_manual=array(); + $person_overtimes_manual["person_overtimes_manual"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_overtime_item=array( + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "overtime" => (float)$overtime + ); + array_push($person_overtimes_manual["person_overtimes_manual"], $person_overtime_item); + } + return $person_overtimes_manual; + } + public function getWhereYearweek(int $data_id, int $person_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.person_overtimes_manual WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + + $person_overtimes_manual=array(); + $person_overtimes_manual["person_overtimes_manual"]=array(); + $row = $res->fetch(PDO::FETCH_ASSOC); + return (float)$row["overtime"]; + } + public function getWhereYearweekLe(int $data_id, int $person_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.person_overtimes_manual WHERE data_id = :data_id AND person_id = :person_id AND yearweek <= :yearweek'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + + $person_overtimes_manual=array(); + $person_overtimes_manual["person_overtimes_manual"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_overtime_item=array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "yearweek" => $yearweek, + "overtime" => (float)$overtime + ); + array_push($person_overtimes_manual["person_overtimes_manual"], $person_overtime_item); + } + return $person_overtimes_manual; + } + public function updateWhereYearweek(int $data_id, int $person_id, string $yearweek, float $overtime) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $overtime = trim($overtime); + $query = "INSERT INTO datadienstplandb.person_overtimes_manual (data_id, person_id, yearweek, overtime) VALUES (:data_id, :person_id, :yearweek, :overtime) ON DUPLICATE KEY UPDATE overtime = :overtime"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':overtime' => $overtime, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + + public function remove(int $data_id, int $person_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.person_overtimes_manual WHERE data_id = :data_id AND person_id = :person_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + public function removeWhereYearweekLt(int $data_id, int $person_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $person_id = trim($person_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.person_overtimes_manual WHERE data_id = :data_id AND person_id = :person_id AND yearweek < :yearweek"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhereLt($data_id, $person_id, $yearweek, "is"); + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_overtimes_manual WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_overtime_manual_class.php'); + } + } +} diff --git a/api/objects/person_vacation_class.php b/api/objects/person_vacation_class.php new file mode 100644 index 0000000..75af677 --- /dev/null +++ b/api/objects/person_vacation_class.php @@ -0,0 +1,186 @@ +<?php + +require_once 'closingtime_class.php'; +require_once 'person_hours_class.php'; + +class Person_vacation +{ + private $data_id; + private $id; + private $person_id; + private $start; + private $end; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->person_id = NULL; + $this->start = NULL; + $this->end = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, int $person_id, string $start, string $end): int { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + + $query = 'INSERT INTO datadienstplandb.person_vacations (data_id, person_id, start, end) VALUES (:data_id, :person_id, :start, :end)'; + + $values = array(':data_id' => $data_id, ':person_id' => $person_id, ':start' => $start, ':end' => $end); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error person_vacation_class.php'); + } + + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $start, $end, "should"); + + return $pdo->lastInsertId(); + } + public function getWhereId(int $data_id, int $id) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $query = 'SELECT * FROM datadienstplandb.person_vacations WHERE data_id = :data_id AND id = :id'; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_vacation_class.php'); + } + + return array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "start" => $start, + "end" => $end + ); + } + + public function update(int $data_id, int $person_id, int $id, string $start, string $end): int { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + + $query = 'UPDATE datadienstplandb.person_vacations SET start = :start, end = :end WHERE data_id = :data_id AND id = :id AND person_id = :person_id'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':person_id' => $person_id, ':start' => $start, ':end' => $end); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_vacation_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $start, $end, "should"); + + return $pdo->lastInsertId(); + } + + public function get(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.person_vacations WHERE data_id = :data_id AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error person_vacation_class.php'); + } + + $person_vacations=array(); + $person_vacations["person_vacations"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $person_vacations_item=array( + "id" => (int)$id, + "person_id" => (int)$person_id, + "start" => $start, + "end" => $end + ); + array_push($person_vacations["person_vacations"], $person_vacations_item); + } + + $query = "SELECT * FROM datadienstplandb.closingtime_persons WHERE data_id = :data_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_vacation_class.php'); + } + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $closingtime_get = new Closingtime(); + $closingtime = $closingtime_get->get($data_id, $closingtime_id); + $closingtime_item=array( + "closingtime_id" => (int)$closingtime_id, + "name" => $closingtime["name"], + "start" => $closingtime["start"], + "end" => $closingtime["end"], + "lawful" => (int)$closingtime["lawful"] + ); + array_push($person_vacations["person_vacations"], $closingtime_item); + } + + return $person_vacations; + } + public function remove(int $data_id, int $id, int $person_id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $person_id = trim($person_id); + $vacation = $this->getWhereId($data_id, $id); + $query = "DELETE FROM datadienstplandb.person_vacations WHERE data_id = :data_id AND id = :id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_vacation_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateWhereBetweenDate($data_id, $person_id, $vacation["start"], $vacation["end"], "should"); + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.person_vacations WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error person_vacation_class.php'); + } + } +} diff --git a/api/objects/roster_active_class.php b/api/objects/roster_active_class.php new file mode 100644 index 0000000..4c13393 --- /dev/null +++ b/api/objects/roster_active_class.php @@ -0,0 +1,39 @@ +<?php + +require_once 'roster_class.php'; +require_once 'roster_changes_class.php'; + +class Roster_active { + public function get(int $data_id, string $yearweek) { + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $roster = new Roster(); + $row = $roster->get($data_id, $yearweek); + $days = $row["days"]; + $time_step = (float)$row["time_step"]; + $roster_array=array(); + for ($day_id=0; $day_id < count($days); $day_id++) { + $roster_changes = new Roster_changes(); + $row_c = $roster_changes->getWhereYearweekLeDay($data_id, $yearweek, $day_id); + $start = $row_c["start"]; + $end = $row_c["end"]; + $amount = $row_c["amount"]; + + $time_array=array(); + for ($time_id=0; $time_id < count($amount); $time_id++) { + $time_item=array( + "t" => $start+($time_step*$time_id), + "a" => $amount[$time_id] + ); + array_push($time_array, $time_item); + } + + $roster_item=array( + "n" => $days[$day_id], + "d" => $time_array + ); + array_push($roster_array, $roster_item); + } + return $roster_array; + } +} diff --git a/api/objects/roster_changes_class.php b/api/objects/roster_changes_class.php new file mode 100644 index 0000000..ac6c2a4 --- /dev/null +++ b/api/objects/roster_changes_class.php @@ -0,0 +1,144 @@ +<?php + +class Roster_changes +{ + private $data_id; + private $yearweek; + private $day_id; + private $start; + private $end; + private $amount; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->yearweek = NULL; + $this->day_id = NULL; + $this->start = NULL; + $this->end = NULL; + $this->amount = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function getWhereYearweek(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_changes WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_changes_class.php'); + } + $roster_changes=array(); + $roster_changes["roster_changes"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $amount = explode(',', $amount); + $amount = array_map('floatval', $amount); + $roster_changes_item=array( + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "start" => (float)$start, + "end" => (float)$end, + "amount" => $amount + ); + array_push($roster_changes["roster_changes"], $roster_changes_item); + } + return $roster_changes; + } + public function getWhereYearweekDay(int $data_id, string $yearweek, int $day_id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $query = 'SELECT * FROM datadienstplandb.roster_changes WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_changes_class.php'); + } + return $res->fetch(PDO::FETCH_ASSOC); + } + public function getWhereYearweekLeDay(int $data_id, string $yearweek, int $day_id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $query = 'SELECT * FROM datadienstplandb.roster_changes WHERE data_id = :data_id AND yearweek <= :yearweek AND day_id = :day_id ORDER BY yearweek DESC'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_changes_class.php'); + } + $row = $res->fetch(PDO::FETCH_ASSOC); + extract($row); + return array( + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "start" => (float)$start, + "end" => (float)$end, + "amount" => explode(',', $amount) + ); + } + public function update(int $data_id, string $yearweek, int $day_id, float $start, float $end, string $amount) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $start = trim($start); + $end = trim($end); + $amount = trim($amount); + $query = 'INSERT INTO datadienstplandb.roster_changes (data_id, yearweek, day_id, start, end, amount) VALUES (:data_id, :yearweek, :day_id, :start, :end, :amount) ON DUPLICATE KEY UPDATE start = :start, end = :end, amount = :amount'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':start' => $start, ':end' => $end, ':amount' => $amount); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_changes_class.php'); + } + } + public function remove(int $data_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.roster_changes WHERE data_id = :data_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_changes_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.roster_changes WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_changes_class.php'); + } + } +} diff --git a/api/objects/roster_class.php b/api/objects/roster_class.php new file mode 100644 index 0000000..f1b89ff --- /dev/null +++ b/api/objects/roster_class.php @@ -0,0 +1,115 @@ +<?php + +class Roster +{ + private $data_id; + private $id; + private $yearweek; + private $time_step; + private $break_60; + private $break_90; + private $days; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->yearweek = NULL; + $this->time_step = NULL; + $this->break_60 = NULL; + $this->break_90 = NULL; + $this->days = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function update(int $data_id, string $yearweek, float $time_step, float $break_60, float $break_90, string $days) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $time_step = trim($time_step); + $break_60 = trim($break_60); + $break_90 = trim($break_90); + $days = trim($days); + + $query = 'INSERT INTO datadienstplandb.rosters (data_id, yearweek, time_step, break_60, break_90, days) VALUES (:data_id, :yearweek, :time_step, :break_60, :break_90, :days) ON DUPLICATE KEY UPDATE time_step = :time_step, break_60 = :break_60, break_90 = :break_90, days = :days'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':time_step' => $time_step, ':break_60' => $break_60, ':break_90' => $break_90, ':days' => $days); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_class.php'); + } + + return $yearweek; + } + public function get(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.rosters WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_class.php'); + } + $row = $res->fetch(PDO::FETCH_ASSOC); + extract($row); + return array( + "yearweek" => $row["yearweek"], + "time_step" => (float)$row["time_step"], + "break_60" => (float)$row["break_60"], + "break_90" => (float)$row["break_90"], + "days" => explode(',', $row["days"]) + ); + } + public function getYearweeks(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT yearweek FROM datadienstplandb.rosters WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_class.php'); + } + return $res->fetchAll(PDO::FETCH_ASSOC); + } + public function remove(int $data_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.rosters WHERE data_id = :data_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.rosters WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_class.php'); + } + } +} diff --git a/api/objects/roster_editable_cell_right_class.php b/api/objects/roster_editable_cell_right_class.php new file mode 100644 index 0000000..781a81d --- /dev/null +++ b/api/objects/roster_editable_cell_right_class.php @@ -0,0 +1,132 @@ +<?php + +class Roster_editable_cell_right +{ + private $data_id; + private $id; + private $yearweek; + private $text; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->yearweek = NULL; + $this->text = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $id, string $yearweek, string $text): int { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $yearweek = trim($yearweek); + $text = trim($text); + + $query = 'INSERT INTO datadienstplandb.roster_editable_cell_right (data_id, id, yearweek, text) VALUES (:data_id, :id, :yearweek, :text)'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':yearweek' => $yearweek, ':text' => $text); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error roster_editable_cell_right_class.php'); + } + + return $pdo->lastInsertId(); + } + public function get(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_editable_cell_right WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_editable_cell_right_class.php'); + } + + $roster_editable_cell_right=array(); + $roster_editable_cell_right["roster_editable_cell_right"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $roster_editable_cell_right_item=array( + "id" => $id, + "yearweek" => $yearweek, + "text" => $text + ); + array_push($roster_editable_cell_right["roster_editable_cell_right"], $roster_editable_cell_right_item); + } + return $roster_editable_cell_right; + } + public function getWhereId(int $data_id, $yearweek, $id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_editable_cell_right WHERE data_id = :data_id AND yearweek = :yearweek AND id = :id'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_editable_cell_right_class.php'); + } + return $res->fetch(PDO::FETCH_ASSOC); + } + public function update(int $data_id, string $yearweek, string $id, string $text) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $id = trim($id); + $text = trim($text); + $query = 'INSERT INTO datadienstplandb.roster_editable_cell_right (data_id, yearweek, id, text) VALUES (:data_id, :yearweek, :id, :text) ON DUPLICATE KEY UPDATE text = :text'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':id' => $id, ':text' => $text); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_cell_right_class.php'); + } + } + public function remove(int $data_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.roster_editable_cell_right WHERE data_id = :data_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_cell_right_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.roster_editable_cell_right WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_cell_right_class.php'); + } + } +} diff --git a/api/objects/roster_editable_row_bottom_class.php b/api/objects/roster_editable_row_bottom_class.php new file mode 100644 index 0000000..15cd518 --- /dev/null +++ b/api/objects/roster_editable_row_bottom_class.php @@ -0,0 +1,133 @@ +<?php + +class Roster_editable_row_bottom +{ + private $data_id; + private $id; + private $yearweek; + private $text; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->yearweek = NULL; + $this->text = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $id, string $yearweek, string $text): int { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $yearweek = trim($yearweek); + $text = trim($text); + + $query = 'INSERT INTO datadienstplandb.roster_editable_row_bottom (data_id, id, yearweek, text) VALUES (:data_id, :id, :yearweek, :text)'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':yearweek' => $yearweek, ':text' => $text); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error roster_editable_row_bottom_class.php'); + } + + return $pdo->lastInsertId(); + } + public function get(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_editable_row_bottom WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_bottom_class.php'); + } + + $roster_editable_row_bottom=array(); + $roster_editable_row_bottom["roster_editable_row_bottom"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $roster_editable_row_bottom_item=array( + "id" => $id, + "yearweek" => $yearweek, + "text" => $text + ); + array_push($roster_editable_row_bottom["roster_editable_row_bottom"], $roster_editable_row_bottom_item); + } + return $roster_editable_row_bottom; + } + public function getWhereId(int $data_id, $yearweek, $id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_editable_row_bottom WHERE data_id = :data_id AND yearweek = :yearweek AND id = :id'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_bottom_class.php'); + } + return $res->fetch(PDO::FETCH_ASSOC); + } + public function update(int $data_id, string $yearweek, string $id, string $text) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $id = trim($id); + $text = trim($text); + + $query = 'INSERT INTO datadienstplandb.roster_editable_row_bottom (data_id, yearweek, id, text) VALUES (:data_id, :yearweek, :id, :text) ON DUPLICATE KEY UPDATE text = :text'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':id' => $id, ':text' => $text); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_bottom_class.php'); + } + } + public function remove(int $data_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.roster_editable_row_bottom WHERE data_id = :data_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_bottom_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.roster_editable_row_bottom WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_bottom_class.php'); + } + } +} diff --git a/api/objects/roster_editable_row_top_class.php b/api/objects/roster_editable_row_top_class.php new file mode 100644 index 0000000..a4638a5 --- /dev/null +++ b/api/objects/roster_editable_row_top_class.php @@ -0,0 +1,133 @@ +<?php + +class Roster_editable_row_top +{ + private $data_id; + private $id; + private $yearweek; + private $text; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->yearweek = NULL; + $this->text = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $id, string $yearweek, string $text): int { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $yearweek = trim($yearweek); + $text = trim($text); + + $query = 'INSERT INTO datadienstplandb.roster_editable_row_top (data_id, id, yearweek, text) VALUES (:data_id, :id, :yearweek, :text)'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':yearweek' => $yearweek, ':text' => $text); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error roster_editable_row_top_class.php'); + } + + return $pdo->lastInsertId(); + } + public function get(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_editable_row_top WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_top_class.php'); + } + + $roster_editable_row_top=array(); + $roster_editable_row_top["roster_editable_row_top"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $roster_editable_row_top_item=array( + "id" => $id, + "yearweek" => $yearweek, + "text" => $text + ); + array_push($roster_editable_row_top["roster_editable_row_top"], $roster_editable_row_top_item); + } + return $roster_editable_row_top; + } + public function getWhereId(int $data_id, $yearweek, $id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_editable_row_top WHERE data_id = :data_id AND yearweek = :yearweek AND id = :id'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_top_class.php'); + } + return $res->fetch(PDO::FETCH_ASSOC); + } + public function update(int $data_id, string $yearweek, string $id, string $text) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $id = trim($id); + $text = trim($text); + + $query = 'INSERT INTO datadienstplandb.roster_editable_row_top (data_id, yearweek, id, text) VALUES (:data_id, :yearweek, :id, :text) ON DUPLICATE KEY UPDATE text = :text'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':id' => $id, ':text' => $text); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_top_class.php'); + } + } + public function remove(int $data_id, string $yearweek) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = "DELETE FROM datadienstplandb.roster_editable_row_top WHERE data_id = :data_id AND yearweek = :yearweek"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_top_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.roster_editable_row_top WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_editable_row_top_class.php'); + } + } +} diff --git a/api/objects/roster_person_info_class.php b/api/objects/roster_person_info_class.php new file mode 100644 index 0000000..92b6069 --- /dev/null +++ b/api/objects/roster_person_info_class.php @@ -0,0 +1,141 @@ +<?php + +class Roster_person_info +{ + private $data_id; + private $id; + private $yearweek; + private $day_id; + private $text; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->yearweek = NULL; + $this->day_id = NULL; + $this->text = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $id, string $yearweek, int $day_id, string $text): int { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $text = trim($text); + + $query = 'INSERT INTO datadienstplandb.roster_person_info (data_id, id, yearweek, day_id, text) VALUES (:data_id, :id, :yearweek, :day_id, :text)'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':text' => $text); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error roster_person_info_class.php'); + } + + return $pdo->lastInsertId(); + } + public function getAll(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.roster_person_info WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_person_info_class.php'); + } + $infos=array(); + $infos["infos"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $infos_item=array( + "id" => (string)$id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "text" => (string)$text + ); + array_push($infos["infos"], $infos_item); + } + return $infos; + } + public function get(int $data_id, string $id, string $yearweek, int $day_id) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $query = 'SELECT * FROM datadienstplandb.roster_person_info WHERE data_id = :data_id AND id = :id AND yearweek = :yearweek AND day_id = :day_id'; + $values = array(':data_id' => $data_id, ':id' => $id, ':yearweek' => $yearweek, ':day_id' => $day_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error roster_person_info_class.php'); + } + + return $res->fetch(PDO::FETCH_ASSOC); + } + public function update(int $data_id, string $id, string $yearweek, int $day_id, string $text) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $text = trim($text); + $query = 'INSERT INTO datadienstplandb.roster_person_info (data_id, id, yearweek, day_id, text) VALUES (:data_id, :id, :yearweek, :day_id, :text) ON DUPLICATE KEY UPDATE text = :text'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':text' => $text); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_person_info_class.php'); + } + } + public function remove(int $data_id, string $id, string $yearweek, int $day_id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $query = "DELETE FROM datadienstplandb.roster_person_info WHERE data_id = :data_id AND id = :id AND yearweek = :yearweek AND day_id = :day_id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':yearweek' => $yearweek, ':day_id' => $day_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_person_info_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.roster_person_info WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error roster_person_info_class.php'); + } + } +} diff --git a/api/objects/settings_class.php b/api/objects/settings_class.php new file mode 100644 index 0000000..fc9ddbf --- /dev/null +++ b/api/objects/settings_class.php @@ -0,0 +1,162 @@ +<?php +class Settings { + private $data_id; + private $database_version; + private $default_overtime; + private $default_edit_cell_right; + private $default_row_top; + private $default_row_bottom; + private $sort_days; + private $sort_week; + private $printmode; + private $zoom_web; + private $zoom_print_h; + private $zoom_print_v; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->database_version = NULL; + $this->default_overtime = NULL; + $this->default_edit_cell_right = NULL; + $this->default_row_top = NULL; + $this->default_row_bottom = NULL; + $this->sort_days = NULL; + $this->sort_week = NULL; + $this->printmode = NULL; + $this->zoom_web = NULL; + $this->zoom_print_h = NULL; + $this->zoom_print_v = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function addSettings(int $data_id, string $database_version, int $default_overtime, int $default_edit_cell_right, int $default_row_top, int $default_row_bottom, string $sort_days, string $sort_week, int $printmode, int $zoom_web, int $zoom_print_h, int $zoom_print_v): int { + global $pdo; + $data_id = trim($data_id); + $database_version = trim($database_version); + $default_overtime = trim($default_overtime); + $default_edit_cell_right = trim($default_edit_cell_right); + $default_row_top = trim($default_row_top); + $default_row_bottom = trim($default_row_bottom); + $sort_days = trim($sort_days); + $sort_week = trim($sort_week); + $printmode = trim($printmode); + $zoom_web = trim($zoom_web); + $zoom_print_h = trim($zoom_print_h); + $zoom_print_v = trim($zoom_print_v); + + + $query = 'INSERT INTO datadienstplandb.settings (data_id, database_version, default_overtime, default_edit_cell_right, default_row_top, default_row_bottom, sort_days, sort_week, printmode, zoom_web, zoom_print_h, zoom_print_v) VALUES (:data_id, :database_version, :default_overtime, :default_edit_cell_right, :default_row_top, :default_row_bottom, :sort_days, :sort_week, :printmode, :zoom_web, :zoom_print_h, :zoom_print_v)'; + + $values = array('data_id' => $data_id, 'database_version' => $database_version, 'default_overtime' => $default_overtime, 'default_edit_cell_right' => $default_edit_cell_right, 'default_row_top' => $default_row_top, 'default_row_bottom' => $default_row_bottom, 'sort_days' => $sort_days, 'sort_week' => $sort_week, 'printmode' => $printmode, 'zoom_web' => $zoom_web, 'zoom_print_h' => $zoom_print_h, 'zoom_print_v' => $zoom_print_v); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + /* If there is a PDO exception, throw a standard exception */ + throw new Exception('Database query error settings_class.php'); + } + + return $pdo->lastInsertId(); + } + public function getWhereName(int $data_id, string $name) { + global $pdo; + $data_id = trim($data_id); + $name = trim($name); + $query = 'SELECT * FROM datadienstplandb.settings WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error settings_class.php'); + } + + $settings = $res->fetch(PDO::FETCH_ASSOC); + $value; + if ($name === "database_version") { $value = (float)$settings["database_version"]; } + else if ($name === "default_edit_cell_right") { $value = (int)$settings["default_edit_cell_right"]; } + else if ($name === "default_overtime") { $value = (int)$settings["default_overtime"]; } + else if ($name === "default_row_bottom") { $value = (int)$settings["default_row_bottom"]; } + else if ($name === "default_row_top") { $value = (int)$settings["default_row_top"]; } + else if ($name === "printmode") { $value = (int)$settings["printmode"]; } + else if ($name === "sort_days") { $value = explode(',', $settings["sort_days"]); } + else if ($name === "sort_week") { $value = explode(',', $settings["sort_week"]); } + else if ($name === "zoom_print_h") { $value = (float)$settings["zoom_print_h"]; } + else if ($name === "zoom_print_v") { $value = (float)$settings["zoom_print_v"]; } + else if ($name === "zoom_web") { $value = (float)$settings["zoom_web"]; }; + return $value; + } + public function getAll(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.settings WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error settings_class.php'); + } + + $settings = $res->fetch(PDO::FETCH_ASSOC); + $query = 'SELECT name FROM datadienstplandb.institutions WHERE id = :data_id'; + $values = array(':data_id' => $data_id); + try { + $res_i = $pdo->prepare($query); + $res_i->execute($values); + } catch (PDOException $e) { throw new Exception('Database query error settings_class.php'); } + + $institution = $res_i->fetch(PDO::FETCH_ASSOC); + return array( + "database_version" => (int)$settings["database_version"], + "default_edit_cell_right" => (int)$settings["default_edit_cell_right"], + "default_overtime" => (int)$settings["default_overtime"], + "default_row_bottom" => (int)$settings["default_row_bottom"], + "default_row_top" => (int)$settings["default_row_top"], + "institution" => (string)$institution["name"], + "printmode" => (int)$settings["printmode"], + "sort_days" => explode(',', $settings["sort_days"]), + "sort_week" => explode(',', $settings["sort_week"]), + "zoom_print_h" => (float)$settings["zoom_print_h"], + "zoom_print_v" => (float)$settings["zoom_print_v"], + "zoom_web" => (float)$settings["zoom_web"] + ); + } + public function updateSettingsWhere(int $data_id, string $name, $value) { + global $pdo; + $data_id = trim($data_id); + $name = trim($name); + $value = trim($value); + $query = "UPDATE datadienstplandb.settings SET `".$name."` = :value WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id, ':value' => $value); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error settings_class.php'); + } + return explode(',', $value); + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.settings WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error settings_class.php'); + } + } +} diff --git a/api/objects/settings_labels_class.php b/api/objects/settings_labels_class.php new file mode 100644 index 0000000..06bb61a --- /dev/null +++ b/api/objects/settings_labels_class.php @@ -0,0 +1,101 @@ +<?php + +class Settings_labels +{ + private $data_id; + private $id; + private $name; + private $cut; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->name = NULL; + $this->cut = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, int $id, string $name, string $cut): int { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + $cut = trim($cut); + + $query = 'INSERT INTO datadienstplandb.settings_labels (data_id, id, name, cut) VALUES (:data_id, :id, :name, :cut)'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':name' => $name, ':cut' => $cut); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + /* If there is a PDO exception, throw a standard exception */ + throw new Exception('Database query error settings_labels_class.php'); + } + + return $pdo->lastInsertId(); + } + public function get(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.settings_labels WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error settings_labels_class.php'); + } + + $labels=array(); + $labels["labels"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $labels_item=array( + "id" => (int)$id, + "name" => $name, + "cut" => $cut + ); + array_push($labels["labels"], $labels_item); + } + return $labels; + } + public function update(int $data_id, int $id, string $name, string $cut) + { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + $cut = trim($cut); + $query = "UPDATE datadienstplandb.settings_labels SET name = :name, cut = :cut WHERE data_id = :data_id AND id = :id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':name' => $name, ':cut' => $cut); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error settings_labels_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.settings_labels WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error settings_labels_class.php'); + } + } +} diff --git a/api/objects/shift_class.php b/api/objects/shift_class.php new file mode 100644 index 0000000..4b43d8c --- /dev/null +++ b/api/objects/shift_class.php @@ -0,0 +1,529 @@ +<?php + +require_once 'person_hours_class.php'; + +class Shift +{ + private $data_id; + private $id; + private $yearweek; + private $day_id; + private $person_id; + private $start; + private $end; + private $break; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->yearweek = NULL; + $this->day_id = NULL; + $this->person_id = NULL; + $this->start = NULL; + $this->end = NULL; + $this->break = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function getShiftBreaks($data_id, $yearweek, $start, $end) { + global $pdo; + $query = "SELECT break_60, break_90 FROM datadienstplandb.rosters WHERE data_id = :data_id AND yearweek = :yearweek;"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $breaks = $res->fetch(PDO::FETCH_ASSOC); + $break = 0; + if ($end-$start > 9) { + $break = $breaks["break_60"]+$breaks["break_90"]; + } elseif ($end-$start > 6) { + $break = $breaks["break_60"]; + } + return $break; + } + public function add(int $data_id, string $yearweek, int $day_id, int $person_id, float $start, float $end) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + $break = $this->getShiftBreaks($data_id, $yearweek, $start, $end); + $break = (float)trim($break); + + $query = 'INSERT INTO datadienstplandb.shifts (data_id, yearweek, day_id, person_id, start, end, breaks) VALUES (:data_id, :yearweek, :day_id, :person_id, :start, :end, :break)'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id, ':start' => $start, ':end' => $end, ':break' => $break); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $shift_id = $pdo->lastInsertId(); + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + return array( + "id" => (int)$shift_id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "person_id" => (int)$person_id, + "start" => (float)$start, + "end" => (float)$end, + "breaks" => (float)$break + ); + } + public function getWhereId(int $data_id, int $id) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $query = 'SELECT * FROM datadienstplandb.shifts WHERE data_id = :data_id AND id = :id'; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $row = $res->fetch(PDO::FETCH_ASSOC); + extract($row); + return array( + "id" => (int)$id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "person_id" => (int)$person_id, + "start" => (float)$start, + "end" => (float)$end, + "hours" => (float)$end-(float)$start-(float)$breaks, + "breaks" => (float)$breaks + ); + } + public function getWherePerson(int $data_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.shifts WHERE data_id = :data_id AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $shifts=array(); + $shifts["shifts"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $shifts_item=array( + "id" => (int)$id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "person_id" => (int)$person_id, + "start" => (float)$start, + "end" => (float)$end, + "hours" => (float)$end-(float)$start-(float)$breaks, + "breaks" => (float)$breaks + ); + array_push($shifts["shifts"], $shifts_item); + } + return $shifts; + } + public function getWhereYearweek(int $data_id, string $yearweek) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $query = 'SELECT * FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $shifts=array(); + $shifts["shifts"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $shifts_item=array( + "id" => (int)$id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "person_id" => (int)$person_id, + "start" => (float)$start, + "end" => (float)$end, + "hours" => (float)$end-(float)$start-(float)$breaks, + "breaks" => (float)$breaks + ); + array_push($shifts["shifts"], $shifts_item); + } + return $shifts; + } + public function getWhereYearweekPerson(int $data_id, string $yearweek, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $shifts=array(); + $shifts["shifts"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $shifts_item=array( + "id" => (int)$id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "person_id" => (int)$person_id, + "start" => (float)$start, + "end" => (float)$end, + "hours" => (float)$end-(float)$start-(float)$breaks, + "breaks" => (float)$breaks + ); + array_push($shifts["shifts"], $shifts_item); + } + return $shifts; + } + public function getWhereYearweekDay(int $data_id, string $yearweek, int $day_id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $query = 'SELECT * FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $shifts=array(); + $shifts["shifts"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $shifts_item=array( + "id" => (int)$id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "person_id" => (int)$person_id, + "start" => (float)$start, + "end" => (float)$end, + "hours" => (float)$end-(float)$start-(float)$breaks, + "breaks" => (float)$breaks + ); + array_push($shifts["shifts"], $shifts_item); + } + return $shifts; + } + public function getWhereYearweekDayPerson(int $data_id, string $yearweek, int $day_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $person_id = trim($person_id); + $query = 'SELECT * FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id AND person_id = :person_id'; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $shifts=array(); + $shifts["shifts"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $shifts_item=array( + "id" => (int)$id, + "yearweek" => (string)$yearweek, + "day_id" => (int)$day_id, + "person_id" => (int)$person_id, + "start" => (float)$start, + "end" => (float)$end, + "hours" => (float)$end-(float)$start-(float)$breaks, + "breaks" => (float)$breaks + ); + array_push($shifts["shifts"], $shifts_item); + } + return $shifts; + } + + public function updateWhereId(int $data_id, int $id, float $start, float $end) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $start = trim($start); + $end = trim($end); + $shift = $this->getWhereId($data_id, $id); + $break = $this->getShiftBreaks($data_id, $shift["yearweek"], $start, $end); + $query = 'UPDATE datadienstplandb.shifts SET start = :start, end = :end , breaks = :break WHERE data_id = :data_id AND id = :id'; + + $values = array(':data_id' => $data_id, ':id' => $id, ':start' => $start, ':end' => $end, ':break' => $break); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $shift["person_id"], $shift["yearweek"], "is"); + return array( + "id" => (int)$id, + "day_id" => (int)$shift["day_id"], + "person_id" => (int)$shift["person_id"], + "start" => (float)$start, + "end" => (float)$end, + "breaks" => (float)$break + ); + } + public function updateStartWhereYearweekDayPersonStart(int $data_id, string $yearweek, int $day_id, int $person_id, float $start, float $end, float $value) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + $value = trim($value); + $break = $this->getShiftBreaks($data_id, $yearweek, $start, $end); + $query = 'UPDATE datadienstplandb.shifts SET start = :value, breaks = :break WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id AND person_id = :person_id AND start = :start'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id, ':start' => $start, ':value' => $value, ':break' => $break); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + public function updateStartWhereYearweekStartLt(int $data_id, string $yearweek, float $start, float $end, float $value) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $start = trim($start); + $end = trim($end); + $value = trim($value); + $break = $this->getShiftBreaks($data_id, $yearweek, $start, $end); + $query = 'UPDATE datadienstplandb.shifts SET start = :value, breaks = :break WHERE data_id = :data_id AND yearweek = :yearweek AND start < :start'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id, ':start' => $start, ':value' => $value, ':break' => $break); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateAllPersonsWhere($data_id, $yearweek, "is"); + } + public function updateEndWhereYearweekDayPersonStart(int $data_id, string $yearweek, int $day_id, int $person_id, float $start, float $end, float $value) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $person_id = trim($person_id); + $start = trim($start); + $end = trim($end); + $value = trim($value); + $break = $this->getShiftBreaks($data_id, $yearweek, $start, $end); + $query = 'UPDATE datadienstplandb.shifts SET end = :value, breaks = :break WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id AND person_id = :person_id AND start = :start'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id, ':start' => $start, ':value' => $value, ':break' => $break); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + } + public function updateEndWhereYearweekEndGt(int $data_id, string $yearweek, float $start, float $end, float $value) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $start = trim($start); + $end = trim($end); + $value = trim($value); + $break = $this->getShiftBreaks($data_id, $yearweek, $start, $end); + $query = 'UPDATE datadienstplandb.shifts SET end = :value, breaks = :break WHERE data_id = :data_id AND yearweek = :yearweek AND end > :end'; + + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id, ':end' => $end, ':value' => $value, ':break' => $break); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + + $set_hours = new Person_hours(); + $set_hours->updateAllPersonsWhere($data_id, $yearweek, "is"); + } + public function removeWhereId(int $data_id, int $id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $shift = $this->getWhereId($data_id, $id); + $query = "DELETE FROM datadienstplandb.shifts WHERE data_id = :data_id AND id = :id"; + $values = array(':data_id' => $data_id, ':id' => $id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $shift["person_id"], $shift["yearweek"], "is"); + return $id; + } + public function removeWhereDayPerson(int $data_id, int $day_id, int $person_id) { + global $pdo; + + $data_id = trim($data_id); + $day_id = trim($day_id); + $person_id = trim($person_id); + $query = "DELETE FROM datadienstplandb.shifts WHERE data_id = :data_id AND day_id = :day_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':day_id' => $day_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateAllWherePerson($data_id, $person_id, "is"); + return $person_id; + } + public function removeWhereYearweekDayPerson(int $data_id, string $yearweek, int $day_id, int $person_id) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $person_id = trim($person_id); + $query = "DELETE FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + return $person_id; + } + public function removeWhereYearweekGeDayPerson(int $data_id, string $yearweek, int $day_id, int $person_id) { + global $pdo; + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $person_id = trim($person_id); + $query = "DELETE FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek >= :yearweek AND day_id = :day_id AND person_id = :person_id"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhereGe($data_id, $person_id, $yearweek, "is"); + return $person_id; + } + public function removeWhereYearweekDayPersonStart(int $data_id, string $yearweek, int $day_id, int $person_id, float $start) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $person_id = trim($person_id); + $start = trim($start); + $query = "DELETE FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id AND person_id = :person_id AND start = :start"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id, ':person_id' => $person_id, ':start' => $start); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateWhere($data_id, $person_id, $yearweek, "is"); + return $person_id; + } + public function removeWhereYearweekDay(int $data_id, string $yearweek, int $day_id) { + global $pdo; + + $data_id = trim($data_id); + $yearweek = trim($yearweek); + $day_id = trim($day_id); + $query = "DELETE FROM datadienstplandb.shifts WHERE data_id = :data_id AND yearweek = :yearweek AND day_id = :day_id"; + $values = array(':data_id' => $data_id, ':yearweek' => $yearweek, ':day_id' => $day_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + $set_hours = new Person_hours(); + $set_hours->updateAllPersonsWhere($data_id, $yearweek, "is"); + return $day_id; + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.shifts WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_class.php'); + } + } +} diff --git a/api/objects/shift_labels_class.php b/api/objects/shift_labels_class.php new file mode 100644 index 0000000..87a08cb --- /dev/null +++ b/api/objects/shift_labels_class.php @@ -0,0 +1,116 @@ +<?php + +class Shift_labels +{ + private $data_id; + private $id; + private $name; + private $cut; + /* Constructor */ + public function __construct() { + $this->data_id = NULL; + $this->id = NULL; + $this->name = NULL; + $this->cut = NULL; + } + + /* Destructor */ + public function __destruct() { } + + public function add(int $data_id, string $name, string $cut): int { + global $pdo; + $data_id = trim($data_id); + $name = trim($name); + $cut = trim($cut); + + $query = 'INSERT INTO datadienstplandb.shift_labels (data_id, name, cut) VALUES (:data_id, :name, :cut)'; + + $values = array(':data_id' => $data_id, ':name' => $name, ':cut' => $cut); + + try + { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) + { + throw new Exception('Database query error shift_labels_class.php'); + } + + return $pdo->lastInsertId(); + } + public function get(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.shift_labels WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error shift_labels_class.php'); + } + + $shift_labels=array(); + $shift_labels["shift_labels"]=array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + extract($row); + $shift_labels_item=array( + "id" => (int)$id, + "name" => $name, + "cut" => $cut + ); + array_push($shift_labels["shift_labels"], $shift_labels_item); + } + return $shift_labels; + } + public function update(int $data_id, int $id, string $name, string $cut) { + global $pdo; + $data_id = trim($data_id); + $id = trim($id); + $name = trim($name); + $cut = trim($cut); + $query = "UPDATE datadienstplandb.shift_labels SET name = :name, cut = :cut WHERE data_id = :data_id AND id = :id"; + $values = array(':data_id' => $data_id, ':id' => $id, ':name' => $name, ':cut' => $cut); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_labels_class.php'); + } + } + public function remove(int $data_id, int $id) { + global $pdo; + + $data_id = trim($data_id); + $id = trim($id); + $query = "DELETE FROM datadienstplandb.shift_labels WHERE (data_id = :data_id) AND (id = :id)"; + $values = array(':data_id' => $data_id, ':id' => $id); + + if ($id === 1) { + return FALSE; + } + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_labels_class.php'); + } + } + public function removeWhereDataId(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = "DELETE FROM datadienstplandb.shift_labels WHERE data_id = :data_id"; + $values = array(':data_id' => $data_id); + + try { + $res = $pdo->prepare($query); + $res->execute($values); + } catch (PDOException $e) { + throw new Exception('Database query error shift_labels_class.php'); + } + } +} diff --git a/api/objects/test_class.php b/api/objects/test_class.php new file mode 100644 index 0000000..f175d7e --- /dev/null +++ b/api/objects/test_class.php @@ -0,0 +1,19 @@ +<?php + +class Test { + public function getAll(int $data_id) { + global $pdo; + $data_id = trim($data_id); + $query = 'SELECT * FROM datadienstplandb.settings WHERE data_id = :data_id'; + $values = array(':data_id' => $data_id); + try { + $res = $pdo->prepare($query); + $res->execute($values); + } + catch (PDOException $e) { + throw new Exception('Database query error test_class.php'); + } + + return $res->fetch(PDO::FETCH_ASSOC); + } +} diff --git a/api/person_betterments/add.php b/api/person_betterments/add.php new file mode 100644 index 0000000..214d051 --- /dev/null +++ b/api/person_betterments/add.php @@ -0,0 +1,35 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_betterment_class.php'; + +$person_betterment = new Person_betterment(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; +$hours = $data->hours; + + +try { + $person_betterment->add($data_id, $person_id, $start, $end, $hours); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} + +echo json_encode($person_id); +?> diff --git a/api/person_betterments/get.php b/api/person_betterments/get.php new file mode 100644 index 0000000..a2ff88b --- /dev/null +++ b/api/person_betterments/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_betterment_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_betterment = new Person_betterment(); +echo json_encode($person_betterment->get($_SESSION["data_id"], $data->person_id)); +?> diff --git a/api/person_betterments/getWhereDate.php b/api/person_betterments/getWhereDate.php new file mode 100644 index 0000000..0fa784f --- /dev/null +++ b/api/person_betterments/getWhereDate.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_betterment_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_betterment = new Person_betterment(); +echo json_encode($person_betterment->getWhereDate($_SESSION["data_id"], $data->person_id, $data->date)); +?> diff --git a/api/person_betterments/remove.php b/api/person_betterments/remove.php new file mode 100644 index 0000000..7d76c69 --- /dev/null +++ b/api/person_betterments/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_betterment_class.php'; + +$person_betterment = new Person_betterment(); +$data = json_decode(file_get_contents("php://input")); + +$person_betterment->remove($_SESSION["data_id"], $data->id, $data->person_id); +echo json_encode($person_id); +?> diff --git a/api/person_changes/add.php b/api/person_changes/add.php new file mode 100644 index 0000000..19e2732 --- /dev/null +++ b/api/person_changes/add.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$change_key = $data->change_key; +$value = $data->value; + +try { + $person_change->add($data_id, $person_id, $yearweek, $day_id, $change_key, $value); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($person_id) +?> diff --git a/api/person_changes/get.php b/api/person_changes/get.php new file mode 100644 index 0000000..fbf2c95 --- /dev/null +++ b/api/person_changes/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_change = new Person_change(); +echo json_encode($person_change->get($_SESSION["data_id"])); +?> diff --git a/api/person_changes/getWhereKey.php b/api/person_changes/getWhereKey.php new file mode 100644 index 0000000..e448373 --- /dev/null +++ b/api/person_changes/getWhereKey.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_change = new Person_change(); +echo json_encode($person_change->getWhereKey($_SESSION["data_id"], $data->person_id, $data->change_key)); +?> diff --git a/api/person_changes/getWhereKeyValue.php b/api/person_changes/getWhereKeyValue.php new file mode 100644 index 0000000..6259509 --- /dev/null +++ b/api/person_changes/getWhereKeyValue.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_change = new Person_change(); +echo json_encode($person_change->getWhereKeyValue($_SESSION["data_id"], $data->change_key, $data->value)); +?> diff --git a/api/person_changes/getWhereYearweekDayKey.php b/api/person_changes/getWhereYearweekDayKey.php new file mode 100644 index 0000000..b17de75 --- /dev/null +++ b/api/person_changes/getWhereYearweekDayKey.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_change = new Person_change(); +echo json_encode($person_change->getWhereYearweekDayKey($_SESSION["data_id"], $data->person_id, $data->yearweek, $data->day_id, $data->change_key)); +?> diff --git a/api/person_changes/getWhereYearweekKey.php b/api/person_changes/getWhereYearweekKey.php new file mode 100644 index 0000000..277726c --- /dev/null +++ b/api/person_changes/getWhereYearweekKey.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_change = new Person_change(); +echo json_encode($person_change->getWhereYearweekKey($_SESSION["data_id"], $data->person_id, $data->yearweek, $data->change_key)); +?> diff --git a/api/person_changes/remove.php b/api/person_changes/remove.php new file mode 100644 index 0000000..648824e --- /dev/null +++ b/api/person_changes/remove.php @@ -0,0 +1,20 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); +$data = json_decode(file_get_contents("php://input")); + +$person_change->remove($_SESSION["data_id"], $data->person_id); +?> diff --git a/api/person_changes/removeWhereKey.php b/api/person_changes/removeWhereKey.php new file mode 100644 index 0000000..e8873ad --- /dev/null +++ b/api/person_changes/removeWhereKey.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); +$data = json_decode(file_get_contents("php://input")); + +$person_change->removeWhereKey($_SESSION["data_id"], $data->person_id, $data->change_key); +echo json_encode($data->person_id) +?> diff --git a/api/person_changes/removeWhereYearweekDayKey.php b/api/person_changes/removeWhereYearweekDayKey.php new file mode 100644 index 0000000..82a6736 --- /dev/null +++ b/api/person_changes/removeWhereYearweekDayKey.php @@ -0,0 +1,20 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); +$data = json_decode(file_get_contents("php://input")); + +$person_change->removeWhereYearweekDayKey($_SESSION["data_id"], $data->person_id, $data->yearweek, $data->day_id, $data->change_key); +?> diff --git a/api/person_changes/updateWhereDayKey.php b/api/person_changes/updateWhereDayKey.php new file mode 100644 index 0000000..14b9076 --- /dev/null +++ b/api/person_changes/updateWhereDayKey.php @@ -0,0 +1,38 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$day_id = $data->day_id; +$change_key = $data->change_key; +$value = $data->value; + + +try { + $person_change ->updateWhereDayKey($data_id, $person_id, $day_id, $change_key, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +echo json_encode($person_id); + +?> diff --git a/api/person_changes/updateWhereKey.php b/api/person_changes/updateWhereKey.php new file mode 100644 index 0000000..667335e --- /dev/null +++ b/api/person_changes/updateWhereKey.php @@ -0,0 +1,37 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$change_key = $data->change_key; +$value = $data->value; + + +try { + $person_change ->updateWhereKey($data_id, $person_id, $change_key, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +echo json_encode($person_id); +?> diff --git a/api/person_changes/updateWhereYearweekDayKey.php b/api/person_changes/updateWhereYearweekDayKey.php new file mode 100644 index 0000000..b9e52f1 --- /dev/null +++ b/api/person_changes/updateWhereYearweekDayKey.php @@ -0,0 +1,40 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$change_key = $data->change_key; +$value = $data->value; + + +try { + $person_change ->updateWhereYearweekDayKey($data_id, $person_id, $yearweek, $day_id, $change_key, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +echo json_encode($person_id); +?> diff --git a/api/person_changes/updateWhereYearweekGeDayKey.php b/api/person_changes/updateWhereYearweekGeDayKey.php new file mode 100644 index 0000000..73ca9d1 --- /dev/null +++ b/api/person_changes/updateWhereYearweekGeDayKey.php @@ -0,0 +1,39 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$change_key = $data->change_key; +$value = $data->value; + + +try { + $person_change ->updateWhereYearweekGeDayKey($data_id, $person_id, $yearweek, $day_id, $change_key, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +echo json_encode($person_id); +?> diff --git a/api/person_changes/updateWhereYearweekGeKey.php b/api/person_changes/updateWhereYearweekGeKey.php new file mode 100644 index 0000000..79ab161 --- /dev/null +++ b/api/person_changes/updateWhereYearweekGeKey.php @@ -0,0 +1,39 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$change_key = $data->change_key; +$value = $data->value; + + +try { + $person_change ->updateWhereYearweekGeKey($data_id, $person_id, $yearweek, $change_key, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +echo json_encode($person_id); +?> diff --git a/api/person_changes/updateWhereYearweekKey.php b/api/person_changes/updateWhereYearweekKey.php new file mode 100644 index 0000000..fc4218f --- /dev/null +++ b/api/person_changes/updateWhereYearweekKey.php @@ -0,0 +1,38 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +if ($_SESSION['administration'] === 'visitor' ) {return;} + +require '../config/db_inc.php'; +require '../objects/person_change_class.php'; + +$person_change = new Person_change(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$change_key = $data->change_key; +$value = $data->value; + + +try { + $person_change ->updateWhereYearweekKey($data_id, $person_id, $yearweek, $change_key, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +echo json_encode($person_id); +?> diff --git a/api/person_hours/getAll.php b/api/person_hours/getAll.php new file mode 100644 index 0000000..00ad172 --- /dev/null +++ b/api/person_hours/getAll.php @@ -0,0 +1,30 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_hours_class.php'; + +$hours = new Person_hours(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; + + +$person_id; +try { + $yws = $hours->getHoursAll($data_id, $person_id); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($yws); +?> diff --git a/api/person_hours/update.php b/api/person_hours/update.php new file mode 100644 index 0000000..ab235a1 --- /dev/null +++ b/api/person_hours/update.php @@ -0,0 +1,37 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_hours_class.php'; + +$hours = new Person_hours(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$person_id = $data->person_id; + + +$person_id; +try { + $person_id = $hours->setHoursWhereYearweek($data_id, $yearweek, $person_id); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($person_id); +?> diff --git a/api/person_illnes/add.php b/api/person_illnes/add.php new file mode 100644 index 0000000..05f6166 --- /dev/null +++ b/api/person_illnes/add.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_illnes_class.php'; + +$person_illnes = new Person_illnes(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; + + +try { + $res = $person_illnes->add($data_id, $person_id, $start, $end); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($res); +?> diff --git a/api/person_illnes/get.php b/api/person_illnes/get.php new file mode 100644 index 0000000..924981f --- /dev/null +++ b/api/person_illnes/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_illnes_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_illnes = new Person_illnes(); +echo json_encode($person_illnes->get($_SESSION["data_id"], $data->person_id)); +?> diff --git a/api/person_illnes/remove.php b/api/person_illnes/remove.php new file mode 100644 index 0000000..4ce0868 --- /dev/null +++ b/api/person_illnes/remove.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_illnes_class.php'; + +$person_illnes = new Person_illnes(); +$data = json_decode(file_get_contents("php://input")); + +$person_illnes->remove($_SESSION["data_id"], $data->id, $data->person_id); +echo json_encode($data->id); +?> diff --git a/api/person_illnes/update.php b/api/person_illnes/update.php new file mode 100644 index 0000000..5fe5c0c --- /dev/null +++ b/api/person_illnes/update.php @@ -0,0 +1,35 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_illnes_class.php'; + +$person_illnes = new Person_illnes(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; + + +try { + $person_illnes->update($data_id, $id, $person_id, $start, $end); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($id); +?> diff --git a/api/person_overtimes/add.php b/api/person_overtimes/add.php new file mode 100644 index 0000000..90b468b --- /dev/null +++ b/api/person_overtimes/add.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_class.php'; + +$person_overtime = new Person_overtime(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$overtime = $data->overtime; + + +try { + $person_overtime->add($data_id, $person_id, $yearweek, $overtime); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/person_overtimes/getWhereYearweek.php b/api/person_overtimes/getWhereYearweek.php new file mode 100644 index 0000000..3298d08 --- /dev/null +++ b/api/person_overtimes/getWhereYearweek.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_overtime_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_overtime = new Person_overtime(); +echo json_encode($person_overtime->getWhereYearweek($_SESSION["data_id"], $data->person_id, $data->yearweek)); +?> diff --git a/api/person_overtimes/getWhereYearweekLe.php b/api/person_overtimes/getWhereYearweekLe.php new file mode 100644 index 0000000..45589f0 --- /dev/null +++ b/api/person_overtimes/getWhereYearweekLe.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_overtime_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_overtime = new Person_overtime(); +echo json_encode($person_overtime->getWhereYearweekLe($_SESSION["data_id"], $data->person_id, $data->yearweek)); +?> diff --git a/api/person_overtimes/remove.php b/api/person_overtimes/remove.php new file mode 100644 index 0000000..5e84acd --- /dev/null +++ b/api/person_overtimes/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_class.php'; + +$person_overtime = new Person_overtime(); +$data = json_decode(file_get_contents("php://input")); + +$person_overtime->remove($_SESSION["data_id"], $data->person_id, $data->yearweek); +?> diff --git a/api/person_overtimes/removeWhereYearweekLt.php b/api/person_overtimes/removeWhereYearweekLt.php new file mode 100644 index 0000000..5e84acd --- /dev/null +++ b/api/person_overtimes/removeWhereYearweekLt.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_class.php'; + +$person_overtime = new Person_overtime(); +$data = json_decode(file_get_contents("php://input")); + +$person_overtime->remove($_SESSION["data_id"], $data->person_id, $data->yearweek); +?> diff --git a/api/person_overtimes/update.php b/api/person_overtimes/update.php new file mode 100644 index 0000000..c2a7d24 --- /dev/null +++ b/api/person_overtimes/update.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_class.php'; + +$person_overtime = new Person_overtime(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$overtime = $data->overtime; + + +try { + $person_overtime->update($data_id, $person_id, $yearweek, $overtime); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/person_overtimes_manual/add.php b/api/person_overtimes_manual/add.php new file mode 100644 index 0000000..260b156 --- /dev/null +++ b/api/person_overtimes_manual/add.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_manual_class.php'; + +$person_overtime_manual = new Person_overtime_manual(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$overtime = $data->overtime; + + +try { + $person_overtime_manual->add($data_id, $person_id, $yearweek, $overtime); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/person_overtimes_manual/get.php b/api/person_overtimes_manual/get.php new file mode 100644 index 0000000..9bf38f0 --- /dev/null +++ b/api/person_overtimes_manual/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_overtime_manual_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_overtime_manual = new Person_overtime_manual(); +echo json_encode($person_overtime_manual->get($_SESSION["data_id"], $data->person_id)); +?> diff --git a/api/person_overtimes_manual/getWhereYearweek.php b/api/person_overtimes_manual/getWhereYearweek.php new file mode 100644 index 0000000..f156e7e --- /dev/null +++ b/api/person_overtimes_manual/getWhereYearweek.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_overtime_manual_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_overtime_manual = new Person_overtime_manual(); +echo json_encode($person_overtime_manual->getWhereYearweek($_SESSION["data_id"], $data->person_id, $data->yearweek)); +?> diff --git a/api/person_overtimes_manual/getWhereYearweekLe.php b/api/person_overtimes_manual/getWhereYearweekLe.php new file mode 100644 index 0000000..e842439 --- /dev/null +++ b/api/person_overtimes_manual/getWhereYearweekLe.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_overtime_manual_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_overtime_manual = new Person_overtime_manual(); +echo json_encode($person_overtime_manual->getWhereYearweekLe($_SESSION["data_id"], $data->person_id, $data->yearweek)); +?> diff --git a/api/person_overtimes_manual/remove.php b/api/person_overtimes_manual/remove.php new file mode 100644 index 0000000..e7af15a --- /dev/null +++ b/api/person_overtimes_manual/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_manual_class.php'; + +$person_overtime_manual = new Person_overtime_manual(); +$data = json_decode(file_get_contents("php://input")); + +$person_overtime_manual->remove($_SESSION["data_id"], $data->person_id, $data->yearweek); +?> diff --git a/api/person_overtimes_manual/removeWhereYearweekLt.php b/api/person_overtimes_manual/removeWhereYearweekLt.php new file mode 100644 index 0000000..e7af15a --- /dev/null +++ b/api/person_overtimes_manual/removeWhereYearweekLt.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_manual_class.php'; + +$person_overtime_manual = new Person_overtime_manual(); +$data = json_decode(file_get_contents("php://input")); + +$person_overtime_manual->remove($_SESSION["data_id"], $data->person_id, $data->yearweek); +?> diff --git a/api/person_overtimes_manual/update.php b/api/person_overtimes_manual/update.php new file mode 100644 index 0000000..7b0fbeb --- /dev/null +++ b/api/person_overtimes_manual/update.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_overtime_manual_class.php'; + +$person_overtime_manual = new Person_overtime_manual(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$yearweek = $data->yearweek; +$overtime = $data->overtime; + + +try { + $person_overtime_manual->updateWhereYearweek($data_id, $person_id, $yearweek, $overtime); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +echo json_encode($data->person_id) +?> diff --git a/api/person_vacations/add.php b/api/person_vacations/add.php new file mode 100644 index 0000000..70e8263 --- /dev/null +++ b/api/person_vacations/add.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_vacation_class.php'; + +$person_vacation = new Person_vacation(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; + + +try { + $id = $person_vacation->add($data_id, $person_id, $start, $end); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($id) +?> diff --git a/api/person_vacations/get.php b/api/person_vacations/get.php new file mode 100644 index 0000000..1c547d2 --- /dev/null +++ b/api/person_vacations/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_vacation_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$person_vacation = new Person_vacation(); +echo json_encode($person_vacation->get($_SESSION["data_id"], $data->person_id)); +?> diff --git a/api/person_vacations/remove.php b/api/person_vacations/remove.php new file mode 100644 index 0000000..17f3040 --- /dev/null +++ b/api/person_vacations/remove.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_vacation_class.php'; + +$person_vacation = new Person_vacation(); +$data = json_decode(file_get_contents("php://input")); + +$person_vacation->remove($_SESSION["data_id"], $data->id, $data->person_id); +echo json_encode($data->id) +?> diff --git a/api/person_vacations/update.php b/api/person_vacations/update.php new file mode 100644 index 0000000..7696d9b --- /dev/null +++ b/api/person_vacations/update.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_vacation_class.php'; + +$person_vacation = new Person_vacation(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$person_id = $data->person_id; +$id = $data->id; +$start = $data->start; +$end = $data->end; + + +try { + $person_vacation->update($data_id, $person_id, $id, $start, $end); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} + +echo json_encode($id); +?> diff --git a/api/persons/add.php b/api/persons/add.php new file mode 100644 index 0000000..5a0096f --- /dev/null +++ b/api/persons/add.php @@ -0,0 +1,37 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_class.php'; + +$person = new Person(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$name = $data->name; +$activated = $data->activated; +$department = $data->department; +$hours = $data->hours; +$mpa = $data->mpa; + + +$person_id; +try { + $person_id = $person->add($data_id, $name, $activated, $department, $hours, $mpa); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($person_id); +?> diff --git a/api/persons/get.php b/api/persons/get.php new file mode 100644 index 0000000..b02fc88 --- /dev/null +++ b/api/persons/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_class.php'; + +$person = new Person(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($person->get($_SESSION["data_id"], $data->id)); +?> diff --git a/api/persons/getAll.php b/api/persons/getAll.php new file mode 100644 index 0000000..ee750c1 --- /dev/null +++ b/api/persons/getAll.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_class.php'; + +$person = new Person(); +echo json_encode($person->getAll($_SESSION["data_id"])); +?> diff --git a/api/persons/remove.php b/api/persons/remove.php new file mode 100644 index 0000000..6b3fa41 --- /dev/null +++ b/api/persons/remove.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_class.php'; + +$person = new Person(); +$data = json_decode(file_get_contents("php://input")); + +$res = $person->remove($_SESSION["data_id"], $data->id); +echo json_encode($res); +?> diff --git a/api/persons/update.php b/api/persons/update.php new file mode 100644 index 0000000..7816850 --- /dev/null +++ b/api/persons/update.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_class.php'; + + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$name = $data->name; +$activated = $data->activated; +$department = $data->department; +$hours = $data->hours; +$mpa = $data->mpa; + + + +try { + $res = $person->update($data_id, $name, $activated, $department, $hours, $mpa); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($res); +?> diff --git a/api/persons/updateWhere.php b/api/persons/updateWhere.php new file mode 100644 index 0000000..6c19c15 --- /dev/null +++ b/api/persons/updateWhere.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/person_class.php'; + +$person = new Person(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$name = $data->name; +$value = $data->value; + +try { + $res = $person->updateWhere($data_id, $id, $name, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +echo json_encode($res); +?> diff --git a/api/persons_active/getActive.php b/api/persons_active/getActive.php new file mode 100644 index 0000000..c2ed1d4 --- /dev/null +++ b/api/persons_active/getActive.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_active_class.php'; + +$person = new Person_active(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($person->getActive($_SESSION["data_id"], $data->yearweek, $data->person_id, FALSE, FALSE)); +?> diff --git a/api/persons_active/getAllActive.php b/api/persons_active/getAllActive.php new file mode 100644 index 0000000..f28b008 --- /dev/null +++ b/api/persons_active/getAllActive.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_active_class.php'; + +$person = new Person_active(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($person->getAllActive($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/persons_active/getAllActiveIdAndName.php b/api/persons_active/getAllActiveIdAndName.php new file mode 100644 index 0000000..002d7af --- /dev/null +++ b/api/persons_active/getAllActiveIdAndName.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_active_class.php'; + +$person = new Person_active(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($person->getAllActiveIdAndName($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/persons_active/getAllRemoved.php b/api/persons_active/getAllRemoved.php new file mode 100644 index 0000000..5682cef --- /dev/null +++ b/api/persons_active/getAllRemoved.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_active_class.php'; + +$person = new Person_active(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($person->getAllRemoved($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/persons_active/getRemoved.php b/api/persons_active/getRemoved.php new file mode 100644 index 0000000..055f424 --- /dev/null +++ b/api/persons_active/getRemoved.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_active_class.php'; + +$person = new Person_active(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($person->getRemoved($_SESSION["data_id"], $data->yearweek, $data->person_id)); +?> diff --git a/api/persons_active/getUserActive.php b/api/persons_active/getUserActive.php new file mode 100644 index 0000000..c9b2f66 --- /dev/null +++ b/api/persons_active/getUserActive.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/person_active_class.php'; + +$person = new Person_active(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($person->getActive($_SESSION["data_id"], $data->yearweek, $_SESSION["connected_person"], FALSE, FALSE)); +?> diff --git a/api/roster/get.php b/api/roster/get.php new file mode 100644 index 0000000..adefc75 --- /dev/null +++ b/api/roster/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster = new Roster(); +echo json_encode($roster->get($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/roster/getYearweeks.php b/api/roster/getYearweeks.php new file mode 100644 index 0000000..4153102 --- /dev/null +++ b/api/roster/getYearweeks.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_class.php'; + +$roster = new Roster(); +echo json_encode($roster->getYearweeks($_SESSION["data_id"])); +?> diff --git a/api/roster/remove.php b/api/roster/remove.php new file mode 100644 index 0000000..bd1812a --- /dev/null +++ b/api/roster/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_class.php'; + +$roster = new Roster(); +$data = json_decode(file_get_contents("php://input")); + +$roster->remove($_SESSION["data_id"], $data->yearweek); +?> diff --git a/api/roster/update.php b/api/roster/update.php new file mode 100644 index 0000000..73ffc12 --- /dev/null +++ b/api/roster/update.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_class.php'; + +$roster = new Roster(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$time_step = $data->time_step; +$break_60 = $data->break_60; +$break_90 = $data->break_90; +$days = $data->days; + + +try { + $roster_id = $roster->update($data_id, $yearweek, $time_step, $break_60, $break_90, $days); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($roster_id); +?> diff --git a/api/roster/updateWhere.php b/api/roster/updateWhere.php new file mode 100644 index 0000000..72fd117 --- /dev/null +++ b/api/roster/updateWhere.php @@ -0,0 +1,31 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_class.php'; + +$roster = new Roster(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$name = $data->name; +$value = $data->value; + +try { + $roster->updateSettingsWhere($data_id, $name, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/roster_active/get.php b/api/roster_active/get.php new file mode 100644 index 0000000..91be55d --- /dev/null +++ b/api/roster_active/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_active_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster_active = new Roster_active(); +echo json_encode($roster_active->get($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/roster_changes/getWhereYearweek.php b/api/roster_changes/getWhereYearweek.php new file mode 100644 index 0000000..2d3b66f --- /dev/null +++ b/api/roster_changes/getWhereYearweek.php @@ -0,0 +1,23 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_changes_class.php'; + +$roster_changes = new Roster_changes(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; + + +echo json_encode($roster_changes->getWhereYearweek($data_id, $yearweek)); +?> diff --git a/api/roster_changes/getWhereYearweekDay.php b/api/roster_changes/getWhereYearweekDay.php new file mode 100644 index 0000000..a896937 --- /dev/null +++ b/api/roster_changes/getWhereYearweekDay.php @@ -0,0 +1,24 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_changes_class.php'; + +$roster_changes = new Roster_changes(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; + + +echo json_encode($roster_changes->getWhereYearweekDay($data_id, $yearweek, $day_id)); +?> diff --git a/api/roster_changes/getWhereYearweekLeDay.php b/api/roster_changes/getWhereYearweekLeDay.php new file mode 100644 index 0000000..055e554 --- /dev/null +++ b/api/roster_changes/getWhereYearweekLeDay.php @@ -0,0 +1,24 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_changes_class.php'; + +$roster_changes = new Roster_changes(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; + + +echo json_encode($roster_changes->getWhereYearweekLeDay($data_id, $yearweek, $day_id)); +?> diff --git a/api/roster_changes/remove.php b/api/roster_changes/remove.php new file mode 100644 index 0000000..b6ee9a9 --- /dev/null +++ b/api/roster_changes/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_changes_class.php'; + +$roster_changes = new Roster_changes(); +$data = json_decode(file_get_contents("php://input")); + +$roster_changes->remove($_SESSION["data_id"], $data->yearweek); +?> diff --git a/api/roster_changes/update.php b/api/roster_changes/update.php new file mode 100644 index 0000000..526ca09 --- /dev/null +++ b/api/roster_changes/update.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_changes_class.php'; + +$roster_changes = new Roster_changes(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$start = $data->start; +$end = $data->end; +$amount = $data->amount; + + +try { + $roster_changes->update($data_id, $yearweek, $day_id, $start, $end, $amount); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($year_week) +?> diff --git a/api/roster_editable_cell_right/add.php b/api/roster_editable_cell_right/add.php new file mode 100644 index 0000000..785e1e1 --- /dev/null +++ b/api/roster_editable_cell_right/add.php @@ -0,0 +1,32 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_cell_right_class.php'; + +$roster_editable_cell_right = new Roster_editable_cell_right(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$id = $data->id; +$text = $data->text; + +try { + $roster_editable_cell_right->add($data_id, $id, $yearweek, $text); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/roster_editable_cell_right/get.php b/api/roster_editable_cell_right/get.php new file mode 100644 index 0000000..ce6d993 --- /dev/null +++ b/api/roster_editable_cell_right/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_editable_cell_right_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster_editable_cell_right = new Roster_editable_cell_right(); +echo json_encode($roster_editable_cell_right->get($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/roster_editable_cell_right/getWhereId.php b/api/roster_editable_cell_right/getWhereId.php new file mode 100644 index 0000000..7e0ee4e --- /dev/null +++ b/api/roster_editable_cell_right/getWhereId.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_editable_cell_right_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster_editable_cell_right = new Roster_editable_cell_right(); +echo json_encode($roster_editable_cell_right->getWhereId($_SESSION["data_id"], $data->yearweek, $data->id)); +?> diff --git a/api/roster_editable_cell_right/remove.php b/api/roster_editable_cell_right/remove.php new file mode 100644 index 0000000..aa8086e --- /dev/null +++ b/api/roster_editable_cell_right/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_cell_right_class.php'; + +$roster_editable_cell_right = new Roster_editable_cell_right(); +$data = json_decode(file_get_contents("php://input")); + +$roster_editable_cell_right->remove($_SESSION["data_id"], $data->yearweek); +?> diff --git a/api/roster_editable_cell_right/update.php b/api/roster_editable_cell_right/update.php new file mode 100644 index 0000000..83f3d60 --- /dev/null +++ b/api/roster_editable_cell_right/update.php @@ -0,0 +1,32 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_cell_right_class.php'; + +$roster_editable_cell_right = new Roster_editable_cell_right(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$id = $data->id; +$text = $data->text; + +try { + $roster_editable_cell_right->update($data_id, $yearweek, $id, $text); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/roster_editable_row_bottom/add.php b/api/roster_editable_row_bottom/add.php new file mode 100644 index 0000000..c49a33b --- /dev/null +++ b/api/roster_editable_row_bottom/add.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_bottom_class.php'; + +$roster_editable_row_bottom = new Roster_editable_row_bottom(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$id = $data->id; +$text = $data->text; + + +try { + $roster_editable_row_bottom->add($data_id, $id, $yearweek, $text); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/roster_editable_row_bottom/get.php b/api/roster_editable_row_bottom/get.php new file mode 100644 index 0000000..e5ce62a --- /dev/null +++ b/api/roster_editable_row_bottom/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_bottom_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster_editable_row_bottom = new Roster_editable_row_bottom(); +echo json_encode($roster_editable_row_bottom->get($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/roster_editable_row_bottom/getWhereId.php b/api/roster_editable_row_bottom/getWhereId.php new file mode 100644 index 0000000..9c90d1c --- /dev/null +++ b/api/roster_editable_row_bottom/getWhereId.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_bottom_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster_editable_row_bottom = new Roster_editable_row_bottom(); +echo json_encode($roster_editable_row_bottom->getWhereId($_SESSION["data_id"], $data->yearweek, $data->id)); +?> diff --git a/api/roster_editable_row_bottom/remove.php b/api/roster_editable_row_bottom/remove.php new file mode 100644 index 0000000..225fc2d --- /dev/null +++ b/api/roster_editable_row_bottom/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_bottom_class.php'; + +$roster_editable_row_bottom = new Roster_editable_row_bottom(); +$data = json_decode(file_get_contents("php://input")); + +$roster_editable_row_bottom->remove($_SESSION["data_id"], $data->yearweek); +?> diff --git a/api/roster_editable_row_bottom/update.php b/api/roster_editable_row_bottom/update.php new file mode 100644 index 0000000..ce3bc32 --- /dev/null +++ b/api/roster_editable_row_bottom/update.php @@ -0,0 +1,32 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_bottom_class.php'; + +$roster_editable_row_bottom = new Roster_editable_row_bottom(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$id = $data->id; +$text = $data->text; + +try { + $roster_editable_row_bottom->update($data_id, $yearweek, $id, $text); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/roster_editable_row_top/add.php b/api/roster_editable_row_top/add.php new file mode 100644 index 0000000..ae9d7c2 --- /dev/null +++ b/api/roster_editable_row_top/add.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_top_class.php'; + +$roster_editable_row_top = new Roster_editable_row_top(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$id = $data->id; +$text = $data->text; + + +try { + $roster_editable_row_top->add($data_id, $id, $yearweek, $text); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/roster_editable_row_top/get.php b/api/roster_editable_row_top/get.php new file mode 100644 index 0000000..f5a13ac --- /dev/null +++ b/api/roster_editable_row_top/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_top_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster_editable_row_top = new Roster_editable_row_top(); +echo json_encode($roster_editable_row_top->get($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/roster_editable_row_top/getWhereId.php b/api/roster_editable_row_top/getWhereId.php new file mode 100644 index 0000000..712cc97 --- /dev/null +++ b/api/roster_editable_row_top/getWhereId.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_top_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$roster_editable_row_top = new Roster_editable_row_top(); +echo json_encode($roster_editable_row_top->getWhereId($_SESSION["data_id"], $data->yearweek, $data->id)); +?> diff --git a/api/roster_editable_row_top/remove.php b/api/roster_editable_row_top/remove.php new file mode 100644 index 0000000..101ae0c --- /dev/null +++ b/api/roster_editable_row_top/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_top_class.php'; + +$roster_editable_row_top = new Roster_editable_row_top(); +$data = json_decode(file_get_contents("php://input")); + +$roster_editable_row_top->remove($_SESSION["data_id"], $data->yearweek); +?> diff --git a/api/roster_editable_row_top/update.php b/api/roster_editable_row_top/update.php new file mode 100644 index 0000000..b92aad8 --- /dev/null +++ b/api/roster_editable_row_top/update.php @@ -0,0 +1,32 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_editable_row_top_class.php'; + +$roster_editable_row_top = new Roster_editable_row_top(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$id = $data->id; +$text = $data->text; + +try { + $roster_editable_row_top->update($data_id, $yearweek, $id, $text); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/roster_person_info/.remove.php.swp b/api/roster_person_info/.remove.php.swp new file mode 100644 index 0000000..2947c01 Binary files /dev/null and b/api/roster_person_info/.remove.php.swp differ diff --git a/api/roster_person_info/add.php b/api/roster_person_info/add.php new file mode 100644 index 0000000..7e63c4a --- /dev/null +++ b/api/roster_person_info/add.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_person_info_class.php'; + +$roster_person_info = new Roster_person_info(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$text = $data->text; + + +try { + $roster_person_info->add($data_id, $id, $yearweek, $day_id, $text); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/roster_person_info/get.php b/api/roster_person_info/get.php new file mode 100644 index 0000000..04b8c9e --- /dev/null +++ b/api/roster_person_info/get.php @@ -0,0 +1,25 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_person_info_class.php'; + +$roster_person_info = new Roster_person_info(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$yearweek = $data->yearweek; +$day_id = $data->day_id; + + +echo json_encode($roster_person_info->get($data_id, $id, $yearweek, $day_id)); +?> diff --git a/api/roster_person_info/getAll.php b/api/roster_person_info/getAll.php new file mode 100644 index 0000000..61b806e --- /dev/null +++ b/api/roster_person_info/getAll.php @@ -0,0 +1,23 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/roster_person_info_class.php'; + +$roster_person_info = new Roster_person_info(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; + + +echo json_encode($roster_person_info->getAll($data_id, $yearweek)); +?> diff --git a/api/roster_person_info/remove.php b/api/roster_person_info/remove.php new file mode 100644 index 0000000..11ff4b9 --- /dev/null +++ b/api/roster_person_info/remove.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_person_info_class.php'; + +$roster_person_info = new Roster_person_info(); +$data = json_decode(file_get_contents("php://input")); + +$roster_person_info->remove($_SESSION["data_id"], $data->id, $data->yearweek, $data->day_id); +echo json_encode($data->id) +?> diff --git a/api/roster_person_info/update.php b/api/roster_person_info/update.php new file mode 100644 index 0000000..fe903e8 --- /dev/null +++ b/api/roster_person_info/update.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/roster_person_info_class.php'; + +$roster_person_info = new Roster_person_info(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$text = $data->text; + + +try { + $roster_person_info->update($data_id, $id, $yearweek, $day_id, $text); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/settings/add.php b/api/settings/add.php new file mode 100644 index 0000000..f15c014 --- /dev/null +++ b/api/settings/add.php @@ -0,0 +1,41 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/settings_class.php'; + +$settings = new Settings(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$database_version = $data->database_version; +$default_overtime = $data->default_overtime; +$default_edit_cell_right = $data->default_edit_cell_right; +$default_row_top = $data->default_row_top; +$default_row_bottom = $data->default_row_bottom; +$sort_days = $data->sort_days; +$sort_week = $data->sort_week; +$printmode = $data->printmode; +$zoom_web = $data->zoom_web; +$zoom_print_h = $data->zoom_print_h; +$zoom_print_v = $data->zoom_print_v; + + +try { + $newId = $settings->addSettings($data_id, $database_version, $default_overtime, $default_edit_cell_right, $default_row_top, $default_row_bottom, $sort_days, $sort_week, $printmode, $zoom_web, $zoom_print_h, $zoom_print_v); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/settings/get.php b/api/settings/get.php new file mode 100644 index 0000000..ac12472 --- /dev/null +++ b/api/settings/get.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +require '../config/db_inc.php'; +require '../objects/settings_class.php'; + +session_start(); + +$data = json_decode(file_get_contents("php://input")); + +$name = $data->name; + + +$settings = new Settings(); +$data = json_decode(file_get_contents("php://input")); +echo json_encode($settings->getWhereName($_SESSION["data_id"], $data->name)); +?> diff --git a/api/settings/getAll.php b/api/settings/getAll.php new file mode 100644 index 0000000..8b93441 --- /dev/null +++ b/api/settings/getAll.php @@ -0,0 +1,18 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +require '../config/db_inc.php'; +require '../objects/settings_class.php'; + +session_start(); + +$data_id = $_SESSION["data_id"]; +$settings = new Settings(); + +echo json_encode($settings->getAll($data_id)); +?> diff --git a/api/settings/update.php b/api/settings/update.php new file mode 100644 index 0000000..9794b8b --- /dev/null +++ b/api/settings/update.php @@ -0,0 +1,32 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/settings_class.php'; + +$settings = new Settings(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$name = $data->name; +$value = $data->value; + +try { + $set = $settings->updateSettingsWhere($data_id, $name, $value); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +echo json_encode($set); +?> diff --git a/api/settings_labels/add.php b/api/settings_labels/add.php new file mode 100644 index 0000000..782c417 --- /dev/null +++ b/api/settings_labels/add.php @@ -0,0 +1,32 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/settings_labels_class.php'; + +$settings_labels = new Settings_labels(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$name = $data->name; +$cut = $data->cut; + +try { + $settings_labels->add($data_id, $id, $name, $cut); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/settings_labels/get.php b/api/settings_labels/get.php new file mode 100644 index 0000000..ba8ca73 --- /dev/null +++ b/api/settings_labels/get.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/settings_labels_class.php'; + +$settings_labels = new Settings_labels(); +$labels = $settings_labels->get($_SESSION["data_id"]); +echo json_encode($labels) +?> diff --git a/api/settings_labels/update.php b/api/settings_labels/update.php new file mode 100644 index 0000000..17960ce --- /dev/null +++ b/api/settings_labels/update.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/settings_labels_class.php'; + +$settings_labels = new Settings_labels(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$name = $data->name; +$cut = $data->cut; + + +try { + $settings_labels->update($data_id, $id, $name, $cut); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} +?> diff --git a/api/shift_labels/add.php b/api/shift_labels/add.php new file mode 100644 index 0000000..5143bf5 --- /dev/null +++ b/api/shift_labels/add.php @@ -0,0 +1,33 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_labels_class.php'; + +$shift_labels = new Shift_labels(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$name = $data->name; +$cut = $data->cut; + +$sid; +try { + $sid = $shift_labels->add($data_id, $name, $cut); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($sid); +?> diff --git a/api/shift_labels/get.php b/api/shift_labels/get.php new file mode 100644 index 0000000..72c79ac --- /dev/null +++ b/api/shift_labels/get.php @@ -0,0 +1,16 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/shift_labels_class.php'; + +$shift_labels = new Shift_labels(); +echo json_encode($shift_labels->get($_SESSION["data_id"])); +?> diff --git a/api/shift_labels/remove.php b/api/shift_labels/remove.php new file mode 100644 index 0000000..ed5ef02 --- /dev/null +++ b/api/shift_labels/remove.php @@ -0,0 +1,21 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_labels_class.php'; + +$shift_labels = new Shift_labels(); +$data = json_decode(file_get_contents("php://input")); + +$shift_labels->remove($_SESSION["data_id"], $data->id); +?> diff --git a/api/shift_labels/update.php b/api/shift_labels/update.php new file mode 100644 index 0000000..1c3cce6 --- /dev/null +++ b/api/shift_labels/update.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_labels_class.php'; + +$shift_labels = new Shift_labels(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$name = $data->name; +$cut = $data->cut; + + +try { + $shift_labels->update($data_id, $id, $name, $cut); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +?> diff --git a/api/shifts/add.php b/api/shifts/add.php new file mode 100644 index 0000000..65e9a59 --- /dev/null +++ b/api/shifts/add.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; + +$shift_id; +try { + $shift_id = $shifts->add($data_id, $yearweek, $day_id, $person_id, $start, $end); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($shift_id); +?> diff --git a/api/shifts/getWherePerson.php b/api/shifts/getWherePerson.php new file mode 100644 index 0000000..619821e --- /dev/null +++ b/api/shifts/getWherePerson.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$shifts = new Shift(); +echo json_encode($shifts->getWherePerson($_SESSION["data_id"], $data->person_id)); +?> diff --git a/api/shifts/getWhereYearweek.php b/api/shifts/getWhereYearweek.php new file mode 100644 index 0000000..d605adb --- /dev/null +++ b/api/shifts/getWhereYearweek.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$shifts = new Shift(); +echo json_encode($shifts->getWhereYearweek($_SESSION["data_id"], $data->yearweek)); +?> diff --git a/api/shifts/getWhereYearweekDay.php b/api/shifts/getWhereYearweekDay.php new file mode 100644 index 0000000..581eeb0 --- /dev/null +++ b/api/shifts/getWhereYearweekDay.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$shifts = new Shift(); +echo json_encode($shifts->getWhereYearweekDay($_SESSION["data_id"], $data->yearweek, $data->day_id)); +?> diff --git a/api/shifts/getWhereYearweekDayPerson.php b/api/shifts/getWhereYearweekDayPerson.php new file mode 100644 index 0000000..184d5f8 --- /dev/null +++ b/api/shifts/getWhereYearweekDayPerson.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$shifts = new Shift(); +echo json_encode($shifts->getWhereYearweekDayPerson($_SESSION["data_id"], $data->yearweek, $data->day_id, $data->person_id)); +?> diff --git a/api/shifts/getWhereYearweekPerson.php b/api/shifts/getWhereYearweekPerson.php new file mode 100644 index 0000000..86a6940 --- /dev/null +++ b/api/shifts/getWhereYearweekPerson.php @@ -0,0 +1,17 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$data = json_decode(file_get_contents("php://input")); +$shifts = new Shift(); +echo json_encode($shifts->getWhereYearweekPerson($_SESSION["data_id"], $data->yearweek, $data->person_id)); +?> diff --git a/api/shifts/removeWhereDayPerson.php b/api/shifts/removeWhereDayPerson.php new file mode 100644 index 0000000..79742a4 --- /dev/null +++ b/api/shifts/removeWhereDayPerson.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); +$data = json_decode(file_get_contents("php://input")); + +$ret = $shifts->removeWhereDayPerson($_SESSION["data_id"], $data->day_id, $data->person_id); +echo json_encode($ret); +?> diff --git a/api/shifts/removeWhereId.php b/api/shifts/removeWhereId.php new file mode 100644 index 0000000..3c85d55 --- /dev/null +++ b/api/shifts/removeWhereId.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); +$data = json_decode(file_get_contents("php://input")); + +$ret = $shifts->removeWhereId($_SESSION["data_id"], $data->id); +echo json_encode($ret); +?> diff --git a/api/shifts/removeWhereYearweekDay.php b/api/shifts/removeWhereYearweekDay.php new file mode 100644 index 0000000..aea1cea --- /dev/null +++ b/api/shifts/removeWhereYearweekDay.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); +$data = json_decode(file_get_contents("php://input")); + +$ret = $shifts->removeWhereYearweekDay($_SESSION["data_id"], $data->yearweek, $data->day_id); +echo json_encode($ret); +?> diff --git a/api/shifts/removeWhereYearweekDayPerson.php b/api/shifts/removeWhereYearweekDayPerson.php new file mode 100644 index 0000000..127e5c5 --- /dev/null +++ b/api/shifts/removeWhereYearweekDayPerson.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); +$data = json_decode(file_get_contents("php://input")); + +$ret = $shifts->removeWhereYearweekDayPerson($_SESSION["data_id"], $data->yearweek, $data->day_id, $data->person_id); +echo json_encode($ret); +?> diff --git a/api/shifts/removeWhereYearweekDayPersonStart.php b/api/shifts/removeWhereYearweekDayPersonStart.php new file mode 100644 index 0000000..315bf56 --- /dev/null +++ b/api/shifts/removeWhereYearweekDayPersonStart.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); +$data = json_decode(file_get_contents("php://input")); + +$ret = $shifts->removeWhereYearweekDayPersonStart($_SESSION["data_id"], $data->yearweek, $data->day_id, $data->person_id, $data->start); +echo json_encode($ret); +?> diff --git a/api/shifts/removeWhereYearweekGeDayPerson.php b/api/shifts/removeWhereYearweekGeDayPerson.php new file mode 100644 index 0000000..ca441c8 --- /dev/null +++ b/api/shifts/removeWhereYearweekGeDayPerson.php @@ -0,0 +1,22 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); +$data = json_decode(file_get_contents("php://input")); + +$ret = $shifts->removeWhereYearweekGeDayPerson($_SESSION["data_id"], $data->yearweek, $data->day_id, $data->person_id); +echo json_encode($ret); +?> diff --git a/api/shifts/test.php b/api/shifts/test.php new file mode 100644 index 0000000..9814914 --- /dev/null +++ b/api/shifts/test.php @@ -0,0 +1,30 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->yearweek; +$start = $data->start; +$end = $data->end; + + +try { + $shifts->testI($data_id, $id, $start, $end); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/shifts/updateEndWhereYearweekDayPersonStart.php b/api/shifts/updateEndWhereYearweekDayPersonStart.php new file mode 100644 index 0000000..167cf95 --- /dev/null +++ b/api/shifts/updateEndWhereYearweekDayPersonStart.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; +$value = $data->value; + + +try { + $shifts->updateEndWhereYearweekDayPersonStart($data_id, $yearweek, $day_id, $person_id, $start, $end, $value); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/shifts/updateEndWhereYearweekEndGt.php b/api/shifts/updateEndWhereYearweekEndGt.php new file mode 100644 index 0000000..ccba48c --- /dev/null +++ b/api/shifts/updateEndWhereYearweekEndGt.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; +$value = $data->value; + + +try { + $shifts->updateEndWhereYearweekEndGt($data_id, $yearweek, $day_id, $person_id, $start, $end, $value); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/shifts/updateStartWhereYearweekDayPersonStart.php b/api/shifts/updateStartWhereYearweekDayPersonStart.php new file mode 100644 index 0000000..1fad86f --- /dev/null +++ b/api/shifts/updateStartWhereYearweekDayPersonStart.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; +$value = $data->value; + + +try { + $shifts->updateStartWhereYearweekDayPersonStart($data_id, $yearweek, $day_id, $person_id, $start, $end, $value); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/shifts/updateStartWhereYearweekStartLt.php b/api/shifts/updateStartWhereYearweekStartLt.php new file mode 100644 index 0000000..6676fa3 --- /dev/null +++ b/api/shifts/updateStartWhereYearweekStartLt.php @@ -0,0 +1,36 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$yearweek = $data->yearweek; +$day_id = $data->day_id; +$person_id = $data->person_id; +$start = $data->start; +$end = $data->end; +$value = $data->value; + + +try { + $shifts->updateStartWhereYearweekStartLt($data_id, $yearweek, $day_id, $person_id, $start, $end, $value); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +?> diff --git a/api/shifts/updateWhereId.php b/api/shifts/updateWhereId.php new file mode 100644 index 0000000..5162abd --- /dev/null +++ b/api/shifts/updateWhereId.php @@ -0,0 +1,34 @@ +<?php +// required headers +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +if ($_SESSION['administration'] === 'visitor' ) {return;} + + +require '../config/db_inc.php'; +require '../objects/shift_class.php'; + +$shifts = new Shift(); + +$data = json_decode(file_get_contents("php://input")); + +$data_id = $_SESSION["data_id"]; +$id = $data->id; +$start = $data->start; +$end = $data->end; + + +try { + $shift_id = $shifts->updateWhereId($data_id, $id, $start, $end); +} catch (Exception $e) { + error_log($e->getMessage()); + die(); +} +echo json_encode($shift_id); +?> diff --git a/createDataDienstplanDB.sh b/createDataDienstplanDB.sh new file mode 100644 index 0000000..822730b --- /dev/null +++ b/createDataDienstplanDB.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +createdb='DROP DATABASE datadienstplandb; CREATE DATABASE datadienstplandb;' +use='USE datadienstplandb;' +create_a='CREATE TABLE shifts ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + yearweek VARCHAR(255), + day_id INT, + person_id INT, + start FLOAT, + end FLOAT, + breaks FLOAT +); CREATE TABLE person_overtimes_manual ( + data_id INT(10) UNSIGNED NOT NULL, + person_id INT, + yearweek VARCHAR(255), + overtime FLOAT, + PRIMARY KEY (person_id, data_id, yearweek) +); CREATE TABLE person_hours ( + data_id INT(10) UNSIGNED NOT NULL, + person_id INT, + yearweek VARCHAR(255), + hours_is FLOAT, + hours_should FLOAT, + PRIMARY KEY (data_id, person_id, yearweek) +); CREATE TABLE roster_person_info ( + data_id int(10) UNSIGNED NOT NULL, + id VARCHAR(255), + yearweek VARCHAR(255), + day_id INT, + text VARCHAR(255), + PRIMARY KEY (data_id, id, yearweek, day_id) +); CREATE TABLE roster_editable_cell_right ( + id VARCHAR(255), + data_id int(10), + yearweek VARCHAR(255), + text VARCHAR(255), + PRIMARY KEY (id, data_id, yearweek) +); CREATE TABLE roster_editable_row_bottom ( + id VARCHAR(255), + data_id int(10), + yearweek VARCHAR(255), + text VARCHAR(255), + PRIMARY KEY (id, data_id, yearweek) +); CREATE TABLE roster_editable_row_top ( + id VARCHAR(255), + data_id int(10), + yearweek VARCHAR(255), + text VARCHAR(255), + PRIMARY KEY (id, data_id, yearweek) +);' +create_b='CREATE TABLE roster_changes ( + data_id int(10) UNSIGNED NOT NULL, + yearweek VARCHAR(255), + day_id INT, + start FLOAT, + end FLOAT, + amount VARCHAR(255), + PRIMARY KEY (data_id, yearweek, day_id) +);' +create_c='CREATE TABLE rosters ( + data_id int(10) UNSIGNED NOT NULL, + yearweek VARCHAR(255), + time_step FLOAT, + break_60 FLOAT, + break_90 FLOAT, + days VARCHAR(255), + PRIMARY KEY (data_id, yearweek) +); CREATE TABLE departments ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + name VARCHAR(255) +); CREATE TABLE person_changes ( + data_id int(10) UNSIGNED NOT NULL, + person_id INT, + yearweek VARCHAR(255), + day_id INT, + change_key VARCHAR(255), + value VARCHAR(255), + PRIMARY KEY (data_id, yearweek, day_id, person_id, change_key) +); CREATE TABLE person_betterments ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + person_id INT, + start VARCHAR(255), + end VARCHAR(255), + hours FLOAT +); CREATE TABLE person_vacations ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + person_id INT, + start VARCHAR(255), + end VARCHAR(255) +); CREATE TABLE person_illnes ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + person_id INT, + start VARCHAR(255), + end VARCHAR(255) +); CREATE TABLE persons ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + activated VARCHAR(255), + name VARCHAR(255), + department INT, + hours FLOAT, + mpa VARCHAR(255) +); CREATE TABLE shift_labels ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + name VARCHAR(50), + cut VARCHAR(50) +); CREATE TABLE settings_labels ( + id INT, + data_id int(10) UNSIGNED NOT NULL, + name VARCHAR(50), + cut VARCHAR(50) +); CREATE TABLE settings ( + data_id int(10) UNSIGNED NOT NULL, + database_version VARCHAR(255), + default_overtime tinyint(1), + default_edit_cell_right tinyint(1) UNSIGNED NOT NULL, + default_row_top tinyint(1) UNSIGNED NOT NULL, + default_row_bottom tinyint(1) UNSIGNED NOT NULL, + sort_days VARCHAR(255), + sort_week VARCHAR(255), + printmode tinyint(1) UNSIGNED NOT NULL, + zoom_web INT, + zoom_print_h INT, + zoom_print_v INT +); CREATE TABLE closingtime_persons ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + closingtime_id INT NOT NULL, + person_id INT +); CREATE TABLE closingtimes ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + data_id int(10) UNSIGNED NOT NULL, + name VARCHAR(255), + start VARCHAR(255), + end VARCHAR(255), + lawful tinyint(1) UNSIGNED +); CREATE TABLE institutions ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(255) NOT NULL +); CREATE TABLE users ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(50) NOT NULL, + role VARCHAR(50) NOT NULL, + password VARCHAR(255) NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + enabled tinyint(1) UNSIGNED NOT NULL DEFAULT "1", + data_id int(10), + connected_person int(10) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE user_sessions ( + session_id varchar(255) NOT NULL, + user_id int(10) UNSIGNED NOT NULL, + login_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +);' +mysql -u root -p -e "$createdb $use $create_a $create_b $create_c" diff --git a/dataToDatabase.html b/dataToDatabase.html new file mode 100644 index 0000000..dd35094 --- /dev/null +++ b/dataToDatabase.html @@ -0,0 +1,18 @@ +<html> + <head> + <script src="js/database/settings.js" defer></script> + <script src="js/database/database.js" defer></script> + <script src="js/database/departments.js" defer></script> + <script src="js/database/persons.js" defer></script> + <script src="js/database/person_changes.js" defer></script> + <script src="js/database/roster.js" defer></script> + <script src="js/database/roster-changes.js" defer></script> + <script src="js/database/shifts.js" defer></script> + <script src="js/database/shift-labels.js" defer></script> + <script src="js/database/closingtime.js" defer></script> + <script src="js/database/data-to-database.js" defer></script> + </head> + <body> + <button onClick="dataToDatabase(DATA)">CLICKME</button> + </body> +</html> diff --git a/dienstplan-example b/dienstplan-example new file mode 100644 index 0000000..809326a --- /dev/null +++ b/dienstplan-example @@ -0,0 +1 @@ +{"DATA":{"v":2.35,"d":[{"id":0,"v":""},{"id":1,"v":"Elementar"},{"id":2,"v":"Kleinkind"}],"m":0,"p":[{"id":1,"a":"2023-03","n":"Jacqueline","h":39.4,"d":1,"m":[0,0,0,0,0],"i":[],"v":[["2023-04-03","2023-04-06"],["2023-05-19","2023-05-19"],["2023-06-05","2023-06-09"],["2023-07-24","2023-08-04"],["2023-09-11","2023-09-15"],["2023-10-02","2023-10-02"],["2023-12-27","2023-12-29"],["2023-05-26","2023-05-26"]],"b":[["2023-03-09","2023-03-10",8]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":2,"a":"2023-03","n":"Nelli","h":39.4,"d":1,"m":[0,0,0,0,0],"i":[],"v":[],"b":[["2023-03-09","2023-03-10",7.5]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":3,"a":"2023-03","n":"Robin","h":39.4,"d":1,"m":[0,0,0,0,0],"i":[["2023-02-06","2023-02-10"]],"v":[["2023-02-27","2023-02-27"]],"b":[["2023-02-16","2023-02-16",8],["2023-03-09","2023-03-10",8]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":4,"a":"2023-03","n":"Jasmin","h":39.4,"d":1,"m":[0,0,1,0,0],"i":[["2023-02-06","2023-02-10"]],"v":[],"b":[["2023-03-09","2023-03-10",8]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":5,"a":"2023-03","n":"Marcus","h":35,"d":1,"m":[0,0,0,0,0],"i":[],"v":[["2023-03-13","2023-03-14"]],"b":[["2023-02-17","2023-02-17",7],["2023-03-09","2023-03-10",7]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":6,"a":"2023-03","n":"Kemi","h":35,"d":1,"m":[0,0,0,0,0],"i":[],"v":[["2023-03-02","2023-03-03"]],"b":[["2023-03-09","2023-03-10",7]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":7,"a":"2023-03","n":"Christian","h":30,"d":1,"m":[0,0,0,0,0],"i":[],"v":[],"b":[["2023-03-09","2023-03-10",7]],"o":[["2023-6",4]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":8,"a":"2023-03","n":"Nicole","h":25,"d":1,"m":[0,0,0,0,0],"i":[["2023-03-02","2023-03-02"]],"v":[],"b":[["2023-03-09","2023-03-10",7]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":9,"a":"2023-03","n":"Mandy","h":24,"d":2,"m":[0,0,0,0,0],"i":[],"v":[["2023-01-30","2023-01-31"]],"b":[["2023-03-10","2023-03-10",8]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":true},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":1},{"d":4,"v":false}]},{"id":10,"a":"2023-03","n":"Doreen","h":35,"d":2,"m":[0,0,0,0,0],"i":[],"v":[["2023-03-06","2023-03-07"],["2023-03-17","2023-03-17"],["2023-03-20","2023-03-21"]],"b":[["2023-02-13","2023-02-13",7],["2023-03-09","2023-03-10",7]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":12,"a":"2023-03","n":"Luise","h":24,"d":1,"m":[0,0,0,0,0],"i":[["2023-02-06","2023-02-10"]],"v":[["2023-03-07","2023-03-07"]],"b":[["2023-03-09","2023-03-09",8]],"sf":[{"d":0,"v":true},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":true}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":1},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":1}]},{"id":13,"a":"2023-06","n":"Lilia","h":30,"d":1,"m":[0,0,0,0,0],"i":[],"v":[["2023-02-07","2023-02-07"]],"b":[["2023-03-09","2023-03-10",7]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":14,"a":"2023-06","n":"Antje","h":30,"d":1,"m":[0,0,0,0,0],"i":[],"v":[["2023-03-06","2023-03-07"]],"b":[["2023-03-09","2023-03-10",7]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]},{"id":15,"a":"2023-10","n":"Anika","h":39.5,"d":1,"m":[0,0,0,0,0],"i":[],"v":[["2023-05-19","2023-05-19"]],"b":[["2023-03-09","2023-03-10",8]],"sf":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sa":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}],"sl":[{"d":0,"v":false},{"d":1,"v":false},{"d":2,"v":false},{"d":3,"v":false},{"d":4,"v":false}]}],"a":[{"d":"2023-05","t":0.25,"s":[[{"s":8,"e":16.25,"p":1},{"s":8.25,"e":16.25,"p":2},{"s":7.75,"e":15.75,"p":3},{"s":6.75,"e":15,"p":4},{"s":8,"e":15.25,"p":5},{"s":8,"e":15.25,"p":6},{"s":9,"e":14.75,"p":7},{"s":9,"e":13.75,"p":8},{"s":8,"e":15.25,"p":10}],[{"s":7.75,"e":15.75,"p":12},{"s":8,"e":16.25,"p":1},{"s":8.25,"e":16.25,"p":2},{"s":6.75,"e":14.25,"p":4},{"s":8.5,"e":15.25,"p":5},{"s":8,"e":15.25,"p":6},{"s":9,"e":14.75,"p":7},{"s":9,"e":13.75,"p":8},{"s":8,"e":15.25,"p":10},{"s":7.75,"e":15.75,"p":3}],[{"s":9.25,"e":16.75,"p":1},{"s":7.75,"e":16.75,"p":12},{"s":6.75,"e":16.75,"p":4},{"s":8.5,"e":16.75,"p":5},{"s":8,"e":15.25,"p":6},{"s":9,"e":14.75,"p":7},{"s":9,"e":13.75,"p":8},{"s":8,"e":15.25,"p":10},{"s":8,"e":16.75,"p":2},{"s":8,"e":16.75,"p":3}],[{"s":7.75,"e":15.5,"p":12},{"s":8,"e":16.25,"p":1},{"s":8.25,"e":16.25,"p":2},{"s":6.75,"e":14.25,"p":4},{"s":8.5,"e":15.25,"p":5},{"s":8,"e":15.25,"p":6},{"s":9,"e":14.75,"p":7},{"s":9,"e":13.75,"p":8},{"s":8,"e":15.25,"p":10},{"s":7.75,"e":15.75,"p":3}],[{"s":8,"e":16.25,"p":9},{"s":8.25,"e":16.25,"p":2},{"s":6.75,"e":14.25,"p":4},{"s":8,"e":15.25,"p":5},{"s":8,"e":15.25,"p":6},{"s":9,"e":14.75,"p":7},{"s":9,"e":13.75,"p":8},{"s":8,"e":15.25,"p":10},{"s":7.75,"e":15.75,"p":3},{"s":7.75,"e":16.25,"p":1}]],"b":[0.5,0],"o":[[1,0.1],[2,0.1],[3,0.1],[4,0.1],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[12,0]],"i":[],"ecr":[{"k":"1","v":" "},{"k":"2","v":""},{"k":"3","v":""},{"k":"4","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"7","v":""},{"k":"8","v":""},{"k":"9","v":" "},{"k":"10","v":""},{"k":"11","v":""},{"k":"12","v":""},{"k":"i","v":""}],"ert":[{"k":"0","v":" "},{"k":"1","v":" Umzug "},{"k":"2","v":"<br>"},{"k":"3","v":"Ele KT 16:00- 17:00 <br><br>"},{"k":"4","v":" "},{"k":"5","v":" "}]},{"d":"2023-06","t":0.25,"s":[[{"s":8,"e":16.25,"p":9},{"s":8.5,"e":15.75,"p":6},{"s":8.25,"e":15,"p":10},{"s":8.25,"e":14.25,"p":7},{"s":9,"e":13.5,"p":13},{"s":6.75,"e":15.5,"p":1},{"p":2,"s":8.75,"e":14.75},{"p":2,"s":15.25,"e":15.75},{"s":7.75,"e":12.5,"p":8},{"s":8,"e":15.25,"p":5},{"s":8.5,"e":14.25,"p":14}],[{"s":8,"e":15.75,"p":9},{"s":8.5,"e":14.25,"p":7},{"s":7,"e":16.25,"p":2},{"s":7,"e":14.25,"p":1},{"s":8.5,"e":15.75,"p":6},{"s":8.25,"e":15.25,"p":10},{"s":8.5,"e":12.75,"p":8},{"s":8.5,"e":15.25,"p":5},{"s":8.5,"e":14.25,"p":14}],[{"s":6.75,"e":16.75,"p":1},{"s":8.25,"e":16.75,"p":13},{"s":8,"e":16.75,"p":10},{"s":8.5,"e":16.75,"p":5},{"s":9,"e":16.75,"p":6},{"s":8.5,"e":16.75,"p":2},{"s":11,"e":16.75,"p":7},{"p":8,"s":9,"e":11.75},{"p":8,"s":15,"e":16.75},{"s":8.5,"e":16.75,"p":14}],[{"s":6.75,"e":14.25,"p":1},{"s":8,"e":15.25,"p":10},{"s":8.5,"e":15.75,"p":6},{"s":9,"e":14.75,"p":7},{"s":8.25,"e":14.75,"p":13},{"s":8.75,"e":16.25,"p":2},{"s":8.5,"e":15.25,"p":5},{"s":9,"e":13.75,"p":8},{"s":8.5,"e":14.25,"p":14}],[{"s":6.75,"e":14,"p":1},{"s":9,"e":13.5,"p":13},{"s":8.5,"e":15.25,"p":6},{"s":8,"e":15.75,"p":9},{"s":8.75,"e":16.25,"p":2},{"s":8.25,"e":14.75,"p":10},{"s":8,"e":12.75,"p":8},{"s":8,"e":13.25,"p":7},{"s":8,"e":15.25,"p":5},{"s":8.5,"e":14.25,"p":14}]],"b":[0.5,0],"o":[[1,0.1],[2,0],[3,0],[4,0],[5,0],[6,0],[7,3.25],[8,-0.5],[9,-1],[10,0],[12,0],[13,0],[14,0]],"i":[{"p":4,"d":2,"t":"KiSchu AG 13:30 Uhr"}],"ecr":[{"k":"9","v":". "},{"k":"13","v":""},{"k":"10","v":""},{"k":"12","v":""},{"k":"8","v":""},{"k":"7","v":""},{"k":"14","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"2","v":""},{"k":"1","v":""},{"k":"3","v":""},{"k":"4","v":""},{"k":"i","v":""}],"ert":[{"k":"0","v":""},{"k":"1","v":""},{"k":"2","v":"MIA Luise + Marcus <br>12:00 - 13:00 Uhr "},{"k":"3","v":"Fallb. 15:00 - 16:00 <br>DB 16:00 - 17:00 "},{"k":"4","v":""},{"k":"5","v":"MIA Mandy Doreen <br>12:30 - 13:30 Uhr"}]},{"d":"2023-07","t":0.25,"s":[[{"s":8.5,"e":14.25,"p":14},{"s":9,"e":14.75,"p":7},{"s":8,"e":16.25,"p":9},{"s":9,"e":13.75,"p":8},{"s":8.5,"e":15.75,"p":5},{"s":6.75,"e":14,"p":2},{"s":8.5,"e":16,"p":6},{"s":9,"e":14.75,"p":13},{"s":8.25,"e":16.25,"p":1},{"s":7.75,"e":15.75,"p":4},{"s":8,"e":16,"p":3}],[{"s":8.5,"e":14.25,"p":14},{"s":9,"e":14.75,"p":7},{"s":8,"e":16.25,"p":9},{"s":6.75,"e":14,"p":2},{"s":8,"e":14.25,"p":10},{"s":9,"e":13.75,"p":8},{"s":8.25,"e":16.25,"p":1},{"s":8,"e":16,"p":12},{"s":8,"e":16,"p":3},{"s":8.5,"e":15.25,"p":5},{"s":8,"e":14.75,"p":6},{"s":7.75,"e":16,"p":4},{"s":9,"e":14.75,"p":13}],[{"s":8.5,"e":16.75,"p":14},{"s":9,"e":14.75,"p":7},{"s":6.75,"e":16.75,"p":2},{"s":8,"e":15.75,"p":10},{"s":9,"e":14.75,"p":13},{"s":9,"e":11.75,"p":8},{"s":15,"e":16.75,"p":8},{"s":8.25,"e":16.75,"p":1},{"s":8,"e":16.75,"p":12},{"s":8,"e":16.75,"p":3},{"s":7.75,"e":16.75,"p":4},{"s":8.5,"e":16.75,"p":5},{"s":8,"e":16,"p":6}],[{"s":8.5,"e":14.25,"p":14},{"s":9.5,"e":15.75,"p":6},{"s":9,"e":14.75,"p":7},{"s":8,"e":14.75,"p":10},{"s":9,"e":14.75,"p":13},{"s":8,"e":16,"p":12},{"s":9,"e":13.75,"p":8},{"s":8.5,"e":15.25,"p":5},{"s":6.75,"e":15,"p":1},{"s":7.75,"e":16.25,"p":4},{"p":2,"s":8.75,"e":16.25}],[{"s":8.5,"e":14.25,"p":14},{"s":9,"e":14.75,"p":7},{"s":8,"e":16.25,"p":9},{"s":6.75,"e":14,"p":2},{"s":9,"e":14.75,"p":13},{"s":8,"e":14.75,"p":10},{"s":8.25,"e":16.25,"p":1},{"s":8,"e":15.75,"p":3},{"s":8.5,"e":16.25,"p":6},{"s":8.75,"e":15.75,"p":4},{"s":9,"e":13.75,"p":8}]],"b":[0.5,0],"o":[[14,0],[1,0.1],[2,0],[3,0.1],[4,0.1],[5,0],[6,0],[7,0],[8,0],[9,0],[10,-1.5],[12,0],[13,0]],"i":[{"p":10,"d":0,"t":"Kolloguium"},{"p":3,"d":3,"t":"Erste Hilfe Kurs"},{"p":5,"d":4,"t":"ASITA Weiherkette"},{"p":2,"d":3,"t":"Gespräch Ben 15:30"}],"ecr":[{"k":"i","v":"MPA "},{"k":"9","v":" "},{"k":"13","v":""},{"k":"10","v":""},{"k":"12","v":""},{"k":"8","v":""},{"k":"7","v":""},{"k":"14","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"2","v":""},{"k":"1","v":""},{"k":"3","v":""},{"k":"4","v":""}],"ert":[{"k":"0","v":""},{"k":"1","v":""},{"k":"2","v":""},{"k":"3","v":"Fallberatung 15:00 Uhr<br>Dienstberatung ELE 16:00 Uhr"},{"k":"4","v":"Robin Erste Hilfe Kurs"},{"k":"5","v":"Marcus Asita"}]},{"d":"2023-08","t":0.25,"s":[[{"s":8,"e":13.75,"p":13},{"s":8.5,"e":14.25,"p":14},{"s":9,"e":14.75,"p":7},{"s":8,"e":15.75,"p":9},{"s":9,"e":13.75,"p":8},{"s":8.5,"e":15.75,"p":5},{"s":8.5,"e":15.75,"p":2},{"s":6.75,"e":14.25,"p":4},{"s":8.25,"e":16.25,"p":3},{"s":7.5,"e":16.25,"p":1},{"s":8,"e":15.75,"p":6},{"s":9,"e":14.75,"p":10}],[{"s":8.5,"e":13.25,"p":8},{"s":8.5,"e":14.25,"p":14},{"s":9,"e":14.75,"p":7},{"s":7,"e":14.25,"p":10},{"s":7,"e":15.5,"p":2},{"s":7,"e":15.25,"p":1},{"s":8.5,"e":15.75,"p":5},{"s":7.75,"e":15.75,"p":12},{"s":8,"e":15.75,"p":9},{"s":8.5,"e":16.25,"p":6},{"s":8,"e":16.25,"p":3},{"s":6.75,"e":14.25,"p":4},{"s":9,"e":14.75,"p":13}],[{"s":6.75,"e":16.75,"p":14},{"s":11,"e":16.75,"p":7},{"s":8.5,"e":16.75,"p":6},{"s":9,"e":16.75,"p":13},{"s":8,"e":16.75,"p":10},{"s":8.5,"e":16.75,"p":2},{"s":9,"e":11.75,"p":8},{"s":15,"e":16.75,"p":8},{"s":8.5,"e":16.75,"p":12},{"s":9,"e":16.25,"p":5},{"s":8.25,"e":16.75,"p":3},{"s":6.75,"e":16.75,"p":4},{"s":7.5,"e":16.75,"p":1}],[{"s":8.5,"e":14,"p":8},{"s":9,"e":14.75,"p":7},{"s":8,"e":14.75,"p":10},{"s":9,"e":14,"p":13},{"s":7.75,"e":16.25,"p":12},{"s":8.25,"e":16.25,"p":3},{"s":7.5,"e":15.5,"p":1},{"s":8,"e":14.75,"p":6},{"s":6.75,"e":14,"p":4},{"s":8.5,"e":15.75,"p":2},{"s":6.75,"e":12.5,"p":14},{"p":5,"s":9,"e":14.25},{"p":5,"s":15,"e":16.25}],[{"s":6.75,"e":10.75,"p":14},{"s":9,"e":14,"p":8},{"s":7.5,"e":14.75,"p":1},{"s":9,"e":14,"p":13},{"s":9,"e":14.75,"p":7},{"s":8.5,"e":15.75,"p":5},{"s":8,"e":13.75,"p":10},{"s":8.25,"e":16.25,"p":3},{"s":8,"e":13.75,"p":6},{"s":6.75,"e":14.25,"p":4},{"s":8,"e":16.25,"p":9},{"s":8.5,"e":15.75,"p":2}]],"b":[0.5,0],"o":[[1,0.85],[2,-0.75],[3,0.1],[4,0.1],[5,0],[6,0.5],[7,0],[8,1],[9,-1],[10,-1],[12,0],[13,0],[14,0]],"ecr":[{"k":"i","v":""},{"k":"9","v":""},{"k":"13","v":""},{"k":"10","v":""},{"k":"12","v":""},{"k":"8","v":""},{"k":"7","v":""},{"k":"14","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"2","v":""},{"k":"1","v":""},{"k":"3","v":""},{"k":"4","v":""}]},{"d":"2023-09","t":0.25,"s":[[{"s":6.75,"e":12.5,"p":14},{"s":8.5,"e":15.5,"p":5},{"s":9,"e":13.75,"p":8},{"s":9,"e":14.75,"p":7},{"s":8.5,"e":16.25,"p":1},{"s":9,"e":15.75,"p":6},{"s":7.5,"e":15.5,"p":4},{"s":8,"e":16,"p":2},{"s":8,"e":14.25,"p":10},{"s":8,"e":16.25,"p":9},{"s":10,"e":14.75,"p":13}],[{"s":7.75,"e":15.75,"p":12},{"s":8.5,"e":15.5,"p":5},{"s":9,"e":13.75,"p":8},{"s":9,"e":14.75,"p":7},{"s":8.5,"e":16.25,"p":1},{"s":9,"e":15.75,"p":6},{"s":8,"e":15.75,"p":2},{"s":8,"e":15.25,"p":9},{"s":9,"e":14.75,"p":13},{"s":8,"e":13.75,"p":10},{"s":7.5,"e":15.25,"p":4},{"s":6.75,"e":12.5,"p":14},{"s":8.5,"e":16.25,"p":3}],[{"p":14,"s":6.75,"e":13},{"p":14,"s":15,"e":16.75},{"s":8.5,"e":16.75,"p":1},{"s":8.5,"e":16.75,"p":6},{"s":7.75,"e":16.75,"p":12},{"p":5,"s":8,"e":15.25},{"p":5,"s":16,"e":16.75},{"s":7.5,"e":16.75,"p":4},{"p":8,"s":9,"e":11.75},{"p":8,"s":15,"e":16.75},{"s":11,"e":16.75,"p":7},{"s":8,"e":16.75,"p":10},{"s":8,"e":16.75,"p":2},{"s":8.5,"e":16.75,"p":13},{"s":8,"e":16.75,"p":3}],[{"s":7,"e":16.25,"p":1},{"s":7,"e":14.75,"p":2},{"s":7,"e":14.75,"p":10},{"s":7.75,"e":15.5,"p":12},{"s":8.5,"e":15.5,"p":5},{"s":9,"e":14.75,"p":7},{"s":8,"e":16.25,"p":3},{"s":9,"e":14.75,"p":13},{"s":7.5,"e":15.25,"p":4},{"s":6.75,"e":12.5,"p":14}],[{"s":8.5,"e":16.25,"p":1},{"s":7,"e":14,"p":5},{"s":9,"e":14.75,"p":7},{"s":8.5,"e":14.25,"p":10},{"s":7.5,"e":15.5,"p":4},{"s":10,"e":14.75,"p":13},{"s":6.75,"e":12.5,"p":14},{"s":8,"e":15.5,"p":2},{"s":8.5,"e":12.75,"p":8},{"s":8,"e":15.25,"p":9},{"s":8.5,"e":16.25,"p":3}]],"b":[0.5,0],"o":[[1,0.1],[2,0.5],[3,-0.02],[4,0.1],[5,0],[6,0],[7,0],[8,-0.5],[9,-2],[10,-1],[12,0],[13,0],[14,0]],"i":[{"p":5,"d":2,"t":"außer Haus Asita Abenteuerwelt"},{"p":5,"d":4,"t":"Außer Haus Asita Teterower "},{"p":2,"d":3,"t":"Unterstützung KK \n08:00 - 09:00"},{"p":2,"d":2,"t":"Unterstützung KK\n08:00 - 09:00 Uhr"}],"ecr":[{"k":"i","v":"MPA "},{"k":"9","v":""},{"k":"13","v":"W"},{"k":"10","v":""},{"k":"12","v":""},{"k":"8","v":""},{"k":"7","v":""},{"k":"14","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"2","v":""},{"k":"1","v":""},{"k":"3","v":""},{"k":"4","v":""}],"ert":[{"k":"0","v":""},{"k":"1","v":""},{"k":"2","v":""},{"k":"3","v":"15:00 - 16:00 Fallberatung<br>16:00 - 17:00 KT<br>"},{"k":"4","v":""},{"k":"5","v":"Füchse Bibo 09:30 Uhr "}]},{"d":"2023-10","t":0.25,"s":[[{"s":6.75,"e":14.75,"p":1},{"s":7.5,"e":15.5,"p":15},{"s":9,"e":14.75,"p":7},{"s":9,"e":13.25,"p":8},{"s":8.5,"e":14.25,"p":13},{"s":8.5,"e":15.75,"p":6},{"s":8,"e":16,"p":4},{"s":8.25,"e":16.25,"p":2},{"s":8.25,"e":16.25,"p":3},{"s":8,"e":16.25,"p":9},{"p":5,"s":8.5,"e":13.25},{"p":5,"s":14,"e":16.25}],[{"s":6.75,"e":14.75,"p":1},{"s":8.5,"e":14.25,"p":13},{"s":8.25,"e":16.25,"p":3},{"s":9,"e":13.25,"p":8},{"s":8.25,"e":16.25,"p":2},{"s":8.5,"e":15.25,"p":5},{"s":8,"e":15.25,"p":9},{"s":8.5,"e":15.75,"p":6},{"s":8,"e":16,"p":4},{"s":9,"e":14.75,"p":7},{"s":7.5,"e":15.5,"p":15}],[],[],[]],"b":[0.5,0],"o":[[1,-0.02],[2,0.1],[3,-0.02],[4,-0.02],[5,0],[6,0],[7,2],[8,3],[9,-1],[10,0],[12,0],[13,2],[14,1.2],[15,-0.02]],"i":[{"p":8,"d":4,"t":"Asita 13:00 - 16:00 Uhr "},{"p":9,"d":4,"t":"Asita 13:00 - 16:00 Uhr"},{"p":6,"d":4,"t":"Asita 13:00 - 16:00 Uhr"},{"p":5,"d":4,"t":"Asita 13:00- 16:00 Uhr"},{"p":14,"d":4,"t":"Asita 13:00 - 16:00 Uhr"},{"p":5,"d":0,"t":"ab 14:00 Uhr außer Haus Gesundheitszirkel"},{"p":3,"d":1,"t":"EG ab 15:30 Uhr"},{"p":2,"d":1,"t":"08:30 Uhr Gespräch Dr. Reinhold"},{"p":9,"d":2,"t":"Schule / Feiertag"},{"p":4,"d":1,"t":"08:00 - 08:30 Uhr Unterstützung KK"},{"p":4,"d":0,"t":"08:00 Uhr - 08:30 Uhr Unterstüzung KK"}],"ecr":[{"k":"i","v":" <br><br><br> "},{"k":"9","v":""},{"k":"13","v":""},{"k":"10","v":""},{"k":"12","v":""},{"k":"8","v":""},{"k":"7","v":""},{"k":"14","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"2","v":""},{"k":"1","v":""},{"k":"3","v":""},{"k":"4","v":""},{"k":"15","v":""}],"ert":[{"k":"0","v":""},{"k":"1","v":""},{"k":"2","v":""},{"k":"3","v":""},{"k":"4","v":"Fobi im Haus<br>08:00 - 15:00 Uhr"},{"k":"5","v":"Fobi im Haus<br>09:00 - 16:00 Uhr"}]},{"d":"2023-11","t":0.25,"s":[[{"s":8,"e":15.75,"p":3},{"s":9,"e":13.75,"p":8},{"s":6.75,"e":14.25,"p":2},{"s":8,"e":16,"p":9},{"s":8.5,"e":15.75,"p":6},{"s":8,"e":16.25,"p":1},{"s":8.5,"e":14.25,"p":14},{"s":8,"e":14.25,"p":10},{"s":7.5,"e":15,"p":4},{"s":8.25,"e":16.25,"p":15},{"s":9,"e":14.75,"p":7},{"s":9.5,"e":14.75,"p":13}],[{"s":8.25,"e":15.75,"p":1},{"s":9,"e":13.75,"p":8},{"s":6.75,"e":14,"p":2},{"s":8,"e":16,"p":9},{"s":8.5,"e":15.75,"p":6},{"s":8,"e":16,"p":15},{"s":8.5,"e":14.25,"p":14},{"s":8,"e":13.75,"p":10},{"s":10,"e":14.75,"p":13},{"s":7.5,"e":15,"p":4},{"s":8,"e":16.25,"p":3},{"s":9,"e":14.75,"p":7},{"s":8,"e":16.25,"p":12}],[{"p":8,"s":9,"e":11.75},{"p":8,"s":15,"e":16.75},{"s":6.75,"e":16.75,"p":2},{"s":8.5,"e":16.75,"p":14},{"s":8,"e":16.75,"p":10},{"s":8.5,"e":16.75,"p":5},{"s":8,"e":16.75,"p":1},{"s":9,"e":16.75,"p":13},{"s":8.5,"e":15.75,"p":6},{"s":8,"e":16.75,"p":15},{"s":7.5,"e":16.75,"p":4},{"s":8,"e":16.75,"p":3},{"s":7.5,"e":16.75,"p":12},{"p":7,"s":9,"e":12.75},{"p":7,"s":15,"e":16.75},{"s":16,"e":16.75,"p":9}],[{"s":7,"e":16.25,"p":1},{"s":7,"e":14,"p":2},{"s":7,"e":14.75,"p":10},{"s":9,"e":14.75,"p":13},{"s":8.5,"e":15.75,"p":6},{"s":9,"e":13.75,"p":8},{"s":8.5,"e":15.25,"p":5},{"s":8.5,"e":14.25,"p":14},{"s":6.75,"e":14.75,"p":4},{"s":8.25,"e":16.25,"p":3},{"s":8,"e":16,"p":15},{"s":7.5,"e":14.75,"p":12},{"s":9,"e":14.75,"p":7}],[{"s":8.5,"e":14.25,"p":14},{"s":8.5,"e":15.75,"p":6},{"s":9,"e":14.75,"p":13},{"s":8.25,"e":15.25,"p":1},{"s":8.5,"e":15.25,"p":5},{"s":6.75,"e":14.25,"p":2},{"s":9,"e":13.75,"p":8},{"s":8.25,"e":16.25,"p":3},{"s":8,"e":15.75,"p":9},{"s":7.5,"e":15,"p":4},{"s":8.25,"e":16.25,"p":15},{"s":9,"e":14.75,"p":7}]],"b":[0.5,0],"o":[[1,0.1],[2,0],[3,0.1],[4,0.1],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[12,0],[13,0],[14,0],[15,0.1]],"i":[{"p":12,"d":2,"t":"MIA 12:00 Uhr - 13:00 Uhr"},{"p":5,"d":2,"t":"08:45 Uhr Eingewöhnung\nMIA 12:00 Uhr - 13:00 Uhr"},{"p":2,"d":1,"t":"EG 09:00 - 10:00 Uhr "},{"p":1,"d":2,"t":"Unterstützung KK 08:00 Uhr - 09:00 Uhr/ Übergänge"},{"p":1,"d":3,"t":"08:00 Uhr - 09:00 Uhr/ Übergänge"},{"p":1,"d":4,"t":"08:00 Uhr - 09:00 Uhr/ Übergänge"},{"p":9,"d":1,"t":"MIA 13:00 Uhr - 14:00 Uhr"},{"p":5,"d":3,"t":"08:45 Uhr Eingewöhnung"},{"p":5,"d":4,"t":"08:45 Uhr Eingewöhnung"}],"ecr":[{"k":"i","v":"<br><br>MPA"},{"k":"9","v":""},{"k":"13","v":""},{"k":"10","v":""},{"k":"12","v":""},{"k":"8","v":""},{"k":"7","v":""},{"k":"14","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"2","v":""},{"k":"1","v":""},{"k":"3","v":""},{"k":"4","v":""},{"k":"15","v":""}],"ert":[{"k":"0","v":""},{"k":"1","v":""},{"k":"2","v":""},{"k":"3","v":"15:00 Uhr - 16:00 Uhr Fallberatung<br>16:00 Uhr - 17:00 Uhr DB"},{"k":"4","v":"Inte 07:00 - 08:00 Uhr"},{"k":"5","v":""}]},{"d":"2023-12","t":0.25,"s":[[{"s":6.75,"e":14.25,"p":1},{"s":9,"e":13.75,"p":8},{"s":7.5,"e":15.5,"p":15},{"s":9,"e":14.75,"p":7},{"s":8,"e":16.25,"p":4},{"s":8.5,"e":15.5,"p":6},{"s":8,"e":15.75,"p":2},{"s":9,"e":14.75,"p":13},{"s":8.5,"e":15.5,"p":5},{"s":8,"e":15.25,"p":9},{"s":8,"e":16.25,"p":3},{"s":8,"e":13.75,"p":14}],[{"s":9,"e":13.75,"p":8},{"s":9,"e":14.75,"p":7},{"s":7.5,"e":15.25,"p":15},{"s":6.75,"e":14.5,"p":1},{"s":8.5,"e":16.25,"p":3},{"s":8,"e":15.75,"p":2},{"s":8.5,"e":15.5,"p":5},{"s":8,"e":16,"p":12},{"s":9,"e":15.5,"p":13},{"s":8,"e":13.75,"p":14},{"s":8,"e":16,"p":4},{"s":8.5,"e":15.5,"p":6},{"s":8,"e":15.25,"p":9}],[{"p":8,"s":9,"e":11.75},{"p":8,"s":15,"e":16.75},{"s":8.5,"e":16.75,"p":14},{"s":8.5,"e":16.75,"p":6},{"s":8.5,"e":16.75,"p":5},{"p":7,"s":9,"e":12.75},{"p":7,"s":15,"e":16.75},{"s":7.5,"e":16.75,"p":15},{"s":6.75,"e":16.75,"p":1},{"s":8,"e":16.75,"p":2},{"s":8,"e":16.75,"p":10},{"s":9,"e":14.75,"p":13},{"s":8,"e":16.75,"p":3},{"s":8,"e":16.75,"p":4},{"s":11,"e":16.75,"p":12},{"s":14,"e":16.75,"p":9}],[{"s":9,"e":13.75,"p":8},{"s":9,"e":14.75,"p":7},{"s":7.5,"e":15.25,"p":15},{"s":6.75,"e":14.5,"p":1},{"s":8,"e":16.25,"p":3},{"s":8,"e":13.75,"p":14},{"s":8,"e":15.75,"p":4},{"s":8,"e":16.25,"p":2},{"s":8,"e":15,"p":5},{"s":8.5,"e":15.5,"p":6},{"s":9,"e":15.25,"p":13},{"s":8,"e":14.5,"p":10},{"p":12,"s":8,"e":16.25}],[{"s":9,"e":13.75,"p":8},{"s":7.5,"e":15.5,"p":15},{"s":9,"e":14.75,"p":7},{"s":8.5,"e":15.5,"p":6},{"s":8.5,"e":15.5,"p":5},{"s":6.75,"e":14.5,"p":1},{"s":8.5,"e":16.25,"p":3},{"s":8,"e":16.25,"p":2},{"s":8,"e":15.25,"p":9},{"s":8,"e":13.75,"p":14},{"s":8,"e":14.5,"p":10},{"s":9,"e":14.75,"p":13},{"s":8,"e":16,"p":4}]],"b":[0.5,0],"o":[[1,0.1],[2,0.1],[3,0.1],[4,1.1],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[12,-2.25],[13,0.25],[14,2],[15,0]],"i":[{"p":1,"d":0,"t":"Termin ab 14:30 Uhr"},{"p":12,"d":1,"t":"MIA 12:00 - 13:00 Uhr"},{"p":2,"d":0,"t":"08:00 Uhr - 09:00 Uhr Unterstützung KK"},{"p":2,"d":2,"t":"Unterstützung 08:00 . 09:00 Uhr KK / Übergänge"},{"p":9,"d":4,"t":"MIA 12:00 - 13:00 Uhr"},{"p":9,"d":2,"t":"MIA Treffen 14:00 - 17:00 Uhr außer Haus"},{"p":12,"d":2,"t":"MIA Treffen 13:00 - 17:00 Uhr außer Haus "},{"p":2,"d":3,"t":"Unterstützung 08:00 . 09:00 Uhr KK / Übergänge"}],"ecr":[{"k":"i","v":""},{"k":"9","v":""},{"k":"10","v":""},{"k":"12","v":""},{"k":"8","v":""},{"k":"7","v":""},{"k":"13","v":""},{"k":"14","v":""},{"k":"5","v":""},{"k":"6","v":""},{"k":"1","v":""},{"k":"2","v":""},{"k":"3","v":""},{"k":"4","v":""},{"k":"15","v":""}],"ert":[{"k":"0","v":""},{"k":"1","v":""},{"k":"2","v":""},{"k":"3","v":"15:00 - 16:00 Uhr Fallberatung<br>16:00 - 17:00 Uhr KT"},{"k":"4","v":""},{"k":"5","v":""}]}],"z":"50","n":[{"t":"mpA","a":"MPA","id":0},{"t":"Krank","a":"Krank","id":1},{"t":"Weiterbildung","a":"w","id":2},{"t":"Urlaub","a":"Urlaub","id":3}],"x":[{"t":"Frauentag","s":"2023-03-08","e":"2023-03-08","p":[1,2,3,4,5,6,7,8,10,12,13,14,15],"x":false,"id":0}],"l":[{"n":"Frei","c":"Frei","id":0},{"n":"Schule","c":"S","id":1}],"rc":[{"k":3,"s":6.75,"e":16.75,"a":[0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0,0],"d":"2023-12"},{"k":0,"s":6.75,"e":16.25,"a":[0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12],"d":"2023-05"},{"k":1,"s":6.75,"e":16.25,"a":[0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12],"d":"2023-05"},{"k":2,"s":6.75,"e":16.75,"a":[0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12],"d":"2023-05"},{"k":3,"s":6.75,"e":16.25,"a":[0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12],"d":"2023-05"},{"k":4,"s":6.75,"e":16.25,"a":[0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12],"d":"2023-05"}],"sd":["n-u"],"sw":["d-u","h-d"],"zh":85,"zv":70,"so":false,"secr":true,"sert":false,"serb":false,"pc":[{"p":4,"d":"2023-10","t":2,"k":"m","v":1},{"p":4,"d":"2023-09","t":2,"k":"m","v":0},{"p":4,"d":"2023-08","t":2,"k":"m","v":1},{"p":4,"d":"2023-07","t":2,"k":"m","v":0},{"p":4,"d":"2023-06","t":2,"k":"m","v":1},{"p":4,"d":"2023-05","t":2,"k":"m","v":0},{"p":9,"d":"2023-13","t":2,"k":"sl","v":1},{"p":9,"d":"2023-13","t":3,"k":"sl","v":1},{"p":9,"d":"2023-13","t":2,"k":"sf","v":true},{"p":9,"d":"2023-13","t":3,"k":"sf","v":true},{"p":9,"d":"2023-11","t":2,"k":"sl","v":false},{"p":9,"d":"2023-11","t":3,"k":"sl","v":1},{"p":9,"d":"2023-11","t":2,"k":"sf","v":false},{"p":9,"d":"2023-11","t":3,"k":"sf","v":true},{"p":9,"d":"2023-03","t":2,"k":"sl","v":1},{"p":9,"d":"2023-03","t":3,"k":"sl","v":1},{"p":9,"d":"2023-03","t":2,"k":"sf","v":true},{"p":9,"d":"2023-03","t":3,"k":"sf","v":true},{"p":12,"d":"2023-03","t":0,"k":"sl","v":1},{"p":12,"d":"2023-03","t":4,"k":"sl","v":1},{"p":12,"d":"2023-03","t":0,"k":"sf","v":true},{"p":12,"d":"2023-03","t":4,"k":"sf","v":true},{"p":13,"d":"2023-06","t":0,"k":"sa","v":false},{"p":13,"d":"2023-06","t":1,"k":"sa","v":false},{"p":13,"d":"2023-06","t":2,"k":"sa","v":false},{"p":13,"d":"2023-06","t":3,"k":"sa","v":false},{"p":13,"d":"2023-06","t":4,"k":"sa","v":false},{"p":13,"d":"2023-06","t":0,"k":"sl","v":false},{"p":13,"d":"2023-06","t":1,"k":"sl","v":false},{"p":13,"d":"2023-06","t":2,"k":"sl","v":false},{"p":13,"d":"2023-06","t":3,"k":"sl","v":false},{"p":13,"d":"2023-06","t":4,"k":"sl","v":false},{"p":13,"d":"2023-06","t":0,"k":"sf","v":false},{"p":13,"d":"2023-06","t":1,"k":"sf","v":false},{"p":13,"d":"2023-06","t":2,"k":"sf","v":false},{"p":13,"d":"2023-06","t":3,"k":"sf","v":false},{"p":13,"d":"2023-06","t":4,"k":"sf","v":false},{"p":14,"d":"2023-06","t":0,"k":"sa","v":false},{"p":14,"d":"2023-06","t":1,"k":"sa","v":false},{"p":14,"d":"2023-06","t":2,"k":"sa","v":false},{"p":14,"d":"2023-06","t":3,"k":"sa","v":false},{"p":14,"d":"2023-06","t":4,"k":"sa","v":false},{"p":14,"d":"2023-06","t":0,"k":"sl","v":false},{"p":14,"d":"2023-06","t":1,"k":"sl","v":false},{"p":14,"d":"2023-06","t":2,"k":"sl","v":false},{"p":14,"d":"2023-06","t":3,"k":"sl","v":false},{"p":14,"d":"2023-06","t":4,"k":"sl","v":false},{"p":14,"d":"2023-06","t":0,"k":"sf","v":false},{"p":14,"d":"2023-06","t":1,"k":"sf","v":false},{"p":14,"d":"2023-06","t":2,"k":"sf","v":false},{"p":14,"d":"2023-06","t":3,"k":"sf","v":false},{"p":14,"d":"2023-06","t":4,"k":"sf","v":false},{"p":15,"d":"2023-10","t":0,"k":"sa","v":false},{"p":15,"d":"2023-10","t":1,"k":"sa","v":false},{"p":15,"d":"2023-10","t":2,"k":"sa","v":false},{"p":15,"d":"2023-10","t":3,"k":"sa","v":false},{"p":15,"d":"2023-10","t":4,"k":"sa","v":false},{"p":15,"d":"2023-10","t":0,"k":"sf","v":false},{"p":15,"d":"2023-10","t":1,"k":"sf","v":false},{"p":15,"d":"2023-10","t":2,"k":"sf","v":false},{"p":15,"d":"2023-10","t":3,"k":"sf","v":false},{"p":15,"d":"2023-10","t":4,"k":"sf","v":false},{"p":15,"d":"2023-10","t":0,"k":"sl","v":false},{"p":15,"d":"2023-10","t":1,"k":"sl","v":false},{"p":15,"d":"2023-10","t":2,"k":"sl","v":false},{"p":15,"d":"2023-10","t":3,"k":"sl","v":false},{"p":15,"d":"2023-10","t":4,"k":"sl","v":false}]}} diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/fix b/fix new file mode 100644 index 0000000..8ef0093 --- /dev/null +++ b/fix @@ -0,0 +1,3 @@ +person_illnes => person.i +person_vacations => person.v +person_betterments => person.b diff --git a/fontawesome/LICENSE.txt b/fontawesome/LICENSE.txt new file mode 100644 index 0000000..39e18e3 --- /dev/null +++ b/fontawesome/LICENSE.txt @@ -0,0 +1,165 @@ +Fonticons, Inc. (https://fontawesome.com) + +-------------------------------------------------------------------------------- + +Font Awesome Free License + +Font Awesome Free is free, open source, and GPL friendly. You can use it for +commercial projects, open source projects, or really almost whatever you want. +Full Font Awesome Free license: https://fontawesome.com/license/free. + +-------------------------------------------------------------------------------- + +# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) + +The Font Awesome Free download is licensed under a Creative Commons +Attribution 4.0 International License and applies to all icons packaged +as SVG and JS file types. + +-------------------------------------------------------------------------------- + +# Fonts: SIL OFL 1.1 License + +In the Font Awesome Free download, the SIL OFL license applies to all icons +packaged as web and desktop font files. + +Copyright (c) 2023 Fonticons, Inc. (https://fontawesome.com) +with Reserved Font Name: "Font Awesome". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE +Version 1.1 - 26 February 2007 + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting — in part or in whole — any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +-------------------------------------------------------------------------------- + +# Code: MIT License (https://opensource.org/licenses/MIT) + +In the Font Awesome Free download, the MIT license applies to all non-font and +non-icon files. + +Copyright 2023 Fonticons, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +# Attribution + +Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font +Awesome Free files already contain embedded comments with sufficient +attribution, so you shouldn't need to do anything additional when using these +files normally. + +We've kept attribution comments terse, so we ask that you do not actively work +to remove them from files, especially code. They're a great way for folks to +learn about Font Awesome. + +-------------------------------------------------------------------------------- + +# Brand Icons + +All brand icons are trademarks of their respective owners. The use of these +trademarks does not indicate endorsement of the trademark holder by Font +Awesome, nor vice versa. **Please do not use brand logos for any purpose except +to represent the company, product, or service to which they refer.** diff --git a/fontawesome/bundle/regular/calendar.svg b/fontawesome/bundle/regular/calendar.svg new file mode 100644 index 0000000..e89cb59 --- /dev/null +++ b/fontawesome/bundle/regular/calendar.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M152 24c0-13.3-10.7-24-24-24s-24 10.7-24 24V64H64C28.7 64 0 92.7 0 128v16 48V448c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V192 144 128c0-35.3-28.7-64-64-64H344V24c0-13.3-10.7-24-24-24s-24 10.7-24 24V64H152V24zM48 192H400V448c0 8.8-7.2 16-16 16H64c-8.8 0-16-7.2-16-16V192z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/arrow-right.svg b/fontawesome/bundle/solid/arrow-right.svg new file mode 100644 index 0000000..a74e604 --- /dev/null +++ b/fontawesome/bundle/solid/arrow-right.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M438.6 278.6c12.5-12.5 12.5-32.8 0-45.3l-160-160c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L338.8 224 32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l306.7 0L233.4 393.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l160-160z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/calendar.svg b/fontawesome/bundle/solid/calendar.svg new file mode 100644 index 0000000..6907e96 --- /dev/null +++ b/fontawesome/bundle/solid/calendar.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M96 32V64H48C21.5 64 0 85.5 0 112v48H448V112c0-26.5-21.5-48-48-48H352V32c0-17.7-14.3-32-32-32s-32 14.3-32 32V64H160V32c0-17.7-14.3-32-32-32S96 14.3 96 32zM448 192H0V464c0 26.5 21.5 48 48 48H400c26.5 0 48-21.5 48-48V192z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/chevron-left.svg b/fontawesome/bundle/solid/chevron-left.svg new file mode 100644 index 0000000..ef8e7f9 --- /dev/null +++ b/fontawesome/bundle/solid/chevron-left.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/chevron-right.svg b/fontawesome/bundle/solid/chevron-right.svg new file mode 100644 index 0000000..00bd8e4 --- /dev/null +++ b/fontawesome/bundle/solid/chevron-right.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/gear.svg b/fontawesome/bundle/solid/gear.svg new file mode 100644 index 0000000..319bcfe --- /dev/null +++ b/fontawesome/bundle/solid/gear.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/question.svg b/fontawesome/bundle/solid/question.svg new file mode 100644 index 0000000..47d1752 --- /dev/null +++ b/fontawesome/bundle/solid/question.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M80 160c0-35.3 28.7-64 64-64h32c35.3 0 64 28.7 64 64v3.6c0 21.8-11.1 42.1-29.4 53.8l-42.2 27.1c-25.2 16.2-40.4 44.1-40.4 74V320c0 17.7 14.3 32 32 32s32-14.3 32-32v-1.4c0-8.2 4.2-15.8 11-20.2l42.2-27.1c36.6-23.6 58.8-64.1 58.8-107.7V160c0-70.7-57.3-128-128-128H144C73.3 32 16 89.3 16 160c0 17.7 14.3 32 32 32s32-14.3 32-32zm80 320a40 40 0 1 0 0-80 40 40 0 1 0 0 80z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/right-from-bracket.svg b/fontawesome/bundle/solid/right-from-bracket.svg new file mode 100644 index 0000000..7d07202 --- /dev/null +++ b/fontawesome/bundle/solid/right-from-bracket.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M377.9 105.9L500.7 228.7c7.2 7.2 11.3 17.1 11.3 27.3s-4.1 20.1-11.3 27.3L377.9 406.1c-6.4 6.4-15 9.9-24 9.9c-18.7 0-33.9-15.2-33.9-33.9l0-62.1-128 0c-17.7 0-32-14.3-32-32l0-64c0-17.7 14.3-32 32-32l128 0 0-62.1c0-18.7 15.2-33.9 33.9-33.9c9 0 17.6 3.6 24 9.9zM160 96L96 96c-17.7 0-32 14.3-32 32l0 256c0 17.7 14.3 32 32 32l64 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-64 0c-53 0-96-43-96-96L0 128C0 75 43 32 96 32l64 0c17.7 0 32 14.3 32 32s-14.3 32-32 32z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/user-gear.svg b/fontawesome/bundle/solid/user-gear.svg new file mode 100644 index 0000000..ca1afa4 --- /dev/null +++ b/fontawesome/bundle/solid/user-gear.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M224 0a128 128 0 1 1 0 256A128 128 0 1 1 224 0zM178.3 304h91.4c11.8 0 23.4 1.2 34.5 3.3c-2.1 18.5 7.4 35.6 21.8 44.8c-16.6 10.6-26.7 31.6-20 53.3c4 12.9 9.4 25.5 16.4 37.6s15.2 23.1 24.4 33c15.7 16.9 39.6 18.4 57.2 8.7v.9c0 9.2 2.7 18.5 7.9 26.3H29.7C13.3 512 0 498.7 0 482.3C0 383.8 79.8 304 178.3 304zM436 218.2c0-7 4.5-13.3 11.3-14.8c10.5-2.4 21.5-3.7 32.7-3.7s22.2 1.3 32.7 3.7c6.8 1.5 11.3 7.8 11.3 14.8v30.6c7.9 3.4 15.4 7.7 22.3 12.8l24.9-14.3c6.1-3.5 13.7-2.7 18.5 2.4c7.6 8.1 14.3 17.2 20.1 27.2s10.3 20.4 13.5 31c2.1 6.7-1.1 13.7-7.2 17.2l-25 14.4c.4 4 .7 8.1 .7 12.3s-.2 8.2-.7 12.3l25 14.4c6.1 3.5 9.2 10.5 7.2 17.2c-3.3 10.6-7.8 21-13.5 31s-12.5 19.1-20.1 27.2c-4.8 5.1-12.5 5.9-18.5 2.4l-24.9-14.3c-6.9 5.1-14.3 9.4-22.3 12.8l0 30.6c0 7-4.5 13.3-11.3 14.8c-10.5 2.4-21.5 3.7-32.7 3.7s-22.2-1.3-32.7-3.7c-6.8-1.5-11.3-7.8-11.3-14.8V454.8c-8-3.4-15.6-7.7-22.5-12.9l-24.7 14.3c-6.1 3.5-13.7 2.7-18.5-2.4c-7.6-8.1-14.3-17.2-20.1-27.2s-10.3-20.4-13.5-31c-2.1-6.7 1.1-13.7 7.2-17.2l24.8-14.3c-.4-4.1-.7-8.2-.7-12.4s.2-8.3 .7-12.4L343.8 325c-6.1-3.5-9.2-10.5-7.2-17.2c3.3-10.6 7.7-21 13.5-31s12.5-19.1 20.1-27.2c4.8-5.1 12.4-5.9 18.5-2.4l24.8 14.3c6.9-5.1 14.5-9.4 22.5-12.9V218.2zm92.1 133.5a48.1 48.1 0 1 0 -96.1 0 48.1 48.1 0 1 0 96.1 0z"/></svg> \ No newline at end of file diff --git a/fontawesome/bundle/solid/user.svg b/fontawesome/bundle/solid/user.svg new file mode 100644 index 0000000..c04f5bc --- /dev/null +++ b/fontawesome/bundle/solid/user.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z"/></svg> \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..a037f93 --- /dev/null +++ b/index.php @@ -0,0 +1,637 @@ +<!DOCTYPE html> +<?php + +session_start(); + +require './api/config/db_inc.php'; +require './api/objects/account_class.php'; + +$account = new Account(); +$login = FALSE; + +// 1. Insert a new account (execute twice to test the "already existing" account error) +/* +try { + $newId = $account->addAccount('test', 'test123123', 'admin', '1', "false"); +} catch (Exception $e) +{ + echo $e->getMessage(); + die(); +} + +echo 'The new account ID is ' . $newId; +*/ + +if (!$account->sessionLogin()) { + if (!$account->isAuthenticated()) { + header('Location: login.php'); + die(); + } +} + +if ($_SESSION['user_role'] === "superadmin") { + header('Location: admin.php'); + die(); +} +?> +<html lang=de-DE> + <head> + <meta charset="utf-8"> + <title>Dienstplan</title> + <link rel="stylesheet" href="style-colors.css"> + <link rel="stylesheet" href="style-defaults.css"> + <link rel="stylesheet" href="style.css"> +<?php if ($_SESSION["user_role"] !== "admin") { ?> + <link rel="stylesheet" href="style-visitor.css"> +<?php } ?> +<?php if ($_SESSION["user_role"] === "user") { ?> + <link rel="stylesheet" href="style-user.css"> + <script src="js/user.js" defer></script> +<?php } ?> + <script src="js/settings.js" defer></script> + <script src="js/database/database.js" defer></script> + <script src="js/database/settings.js" defer></script> + <script src="js/database/departments.js" defer></script> + <script src="js/database/persons.js" defer></script> + <script src="js/database/person_changes.js" defer></script> + <script src="js/database/roster.js" defer></script> + <script src="js/database/roster-changes.js" defer></script> + <script src="js/database/shifts.js" defer></script> + <script src="js/database/shift-labels.js" defer></script> + <script src="js/database/closingtime.js" defer></script> + <script src="js/database/data-to-database.js" defer></script> + <script src="js/scroll.js" defer></script> + <script src="js/popup.js" defer></script> + <script src="js/startpage.js" defer></script> + <script src="js/person.js" defer></script> + <script src="js/roster.js" defer></script> + <script src="js/roster-person-menu.js" defer></script> + <script src="js/closing-time.js" defer></script> + <script src="js/vacations-overview.js" defer></script> + <script src="js/copy-person-shifts.js" defer></script> + <script src="js/shortcuts.js" defer></script> + <script src="js/get-lawful-vacations.js" defer></script> + <script src="js/console.js" defer></script> +<script> + let DATA = {sd: [], sw: []} +let DISABLE_WINDOW_RELOAD = true +/*REPLACE +window.addEventListener('beforeunload', (event) => { +// Cancel the event as stated by the standard. +if (DISABLE_WINDOW_RELOAD) return +event.preventDefault(); +// Chrome requires returnValue to be set. +event.returnValue = ''; +}); + +REPLACE*/ + + +if (typeof structuredClone !== "function") { + structuredClone = (obj) => { + if(typeof obj !== 'object' || obj === null) { + return obj; + } + + if(obj instanceof Date) { + return new Date(obj.getTime()); + } + + if(obj instanceof Array) { + return obj.reduce((arr, item, i) => { + arr[i] = structuredClone(item); + return arr; + }, []); + } + + if(obj instanceof Object) { + return Object.keys(obj).reduce((newObj, key) => { + newObj[key] = structuredClone(obj[key]); + return newObj; + }, {}) + } + } +} + +let colors_red_orange_green = [ "#ff4949", "#ff7a4c", "#ffaa4f", "#fbc966", "#c0c666", "#8ec678", "#6fba5c" ] + +let CLOSINGTIMES + +let CONSOLE = false +let CONSOLE_INPUT = [] +let CONSOLE_OPTIONS = [] + +const DAYS = [ "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag" ] + +let EDITABLE_TABLES = [] +let EDITABLE_ROW = false +let EDITABLE_ROWS_TOP +let EDITABLE_ROW_BOTTOM = false +let EDITABLE_ROWS_BOTTOM +let EDITABLE_CELL = false +let EDITABLE_CELLS_RIGHT +let DISPLAY_OVERTIME = false +let EDITABLE_TD_0 = "" +DAYS.forEach((day, day_id) => { let id = day_id+1; eval("EDITABLE_TD_"+id+" = ''")}) + +let DEPARTMENTS = [ {id: 1, v: ""}, {id: 2, v: "Elementar"}, {id: 3, v:"Kleinkind"}] +let DEPARTMENT_COLORS = [ "#ffffff", "#ecf5ff", "#f9f9ee", "#ecfffb", "#ecfff0", "#ffeeec", "#ffecfc", "#ecedff", "#ecfbff"] + +NOWEEKEDIT = false + +let SHIFT_LABELS = [{i: 0, n: "Frei", c: "Frei"}, {i: 1, n: "Schule", c: "S"}] + +let SETTINGS_LABELS + +let PRINT_ZOOM = [100, 78] + +let DATA_LAST_CREATED = -1 + +let INVIEW = "" +let ROSTERS = [] +let ROSTERS_YEARWEEK +let ROSTER_TABLES +let ROSTER_TABLE_WEEK +let ROSTER_PERSON_INFOS +let ROSTER_PERSON_INFOS_FROM +let ROSTER_PERSON_INFOS_TO +let LOADED_TABLES +let LOADINGS = [] + +let HOURS_DEFAULT = 39.5 + + +let PERSONS_ALL +let PERSONS_DEFAULT = [] +let PERSONS = [] +let PERSONS_ROSTER = [] +let PERSONS_WEEK = [] +let PERSONS_TABLE_TO = [] +let PERSONS_TABLE_FROM = [] +let PERSON_NEW_ID + +let TIMES = [] +let DAYBREAK_1 = 0.5 +let DAYBREAK_2 = 0.25 + +let VERSIONS = [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.21, 2.1, 2.2, 2.21, 2.22, 2.23, 2.24, 2.25, 2.26, 2.27, 2.28, 2.29, 2.3 ,2.31, 2.32, 2.33, 2.34, 2.35] +let VERSION_DEFAULT = VERSIONS[VERSIONS.length-1] +let VERSION + +let ROSTER_DEFAULT = [] +let ROSTER = [] +let ROSTER_TABLE_FROM = [] +let ROSTER_TABLE_TO = [] +let ACTIVE_ROSTERS_MAPPED = [] + +Date.prototype.getWeek = function(){ + var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate())); + var dayNum = d.getUTCDay() || 7; + d.setUTCDate(d.getUTCDate() + 4 - dayNum); + var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1)); + return Math.ceil((((d - yearStart) / 86400000) + 1)/7) +}; + + +let DATE = new Date() +let DATE_YEAR = DATE.getFullYear(); +let DATE_WEEK = DATE.getWeek(); +let DATE_YEAR_WEEK = DATE_YEAR+"-"+DATE_WEEK +let DATE_YEAR_WEEK_OLD +let DATE_YEAR_WEEK_NEWEST +let DATE_YEAR_WEEK_AFTER +let DATE_YEAR_WEEK_OLDEST +let DATE_YEAR_WEEK_BEFORE +let DATE_YEAR_WEEK_BEFORE_WEEK +let DATE_YEAR_WEEK_TABLE_TO +let DATE_YEAR_WEEK_TABLE_FROM +let DATE_START + +let PRINT_MODES = ["Hochformat", "Querformat"] + + +// a: activeSince(2022-49), n: name h: hours, d: department, f: freedays, m: mpa, i: ill, v: vacations, c: changes [{ d: "2022-49", k: "n", v: "nameBefore49"], sl: [schicht_labels per day], sf: [freedays], sa: [average]] +const PERSONS_DEFAULT_LAYOUT = { activated: DATE_YEAR_WEEK, name: "", hours: HOURS_DEFAULT, department: 0, mpa: []} +DAYS.forEach(d => {PERSONS_DEFAULT_LAYOUT.mpa.push(0)}) + + +</script> + </head> +<?php if ($_SESSION["user_role"] === "admin") { ?> + <body class="noscroll" onload="startRoster()"> +<?php } else if ($_SESSION["user_role"] === "user") { ?> + <body class="noscroll" onload="startVisitor().then(() => renderUserDetails())"> +<?php } else { ?> + <body class="noscroll" onload="startVisitor()"> +<?php } if ($_SESSION["user_role"] === "superadmin") { ?> + <button id="Superadmin-back-button" onClick='window.location="/admin.php"'>Zurück</button> +<?php } ?> + + <div class="main-container" onscroll="checkHideSettingsMenu()"> + + <div id="Settings" class="page"> +<?php if ($_SESSION["user_role"] === "admin") { ?> + <div id="Menu-settings" class="active"> + <h3>Dienstplan</h3> + <button class="toggle-menu d-none" onClick="toggleSettingsMenu()"> + <img class="icon left" src="/fontawesome/bundle/solid/chevron-left.svg"/> + <img class="icon right" src="/fontawesome/bundle/solid/chevron-right.svg"/> + </button> + <button class="Menu-Person-container" onClick="renderPerson()"> + <img class="icon" src="/fontawesome/bundle/solid/user.svg"/> + </button> + <div class="Menu-Closingtimes Menu-Vacations-overview dropdown"> + <img class="icon" style="height: 18px;" src="/pngs/icons8-island-32.png"/> + <div class="d-none"> + <button class="closingtime" onClick="openClosingTime()">Schließzeiten</button> + <button class="vacation" onClick="openVacationsOverview()">Urlaubsübersicht</button> + </div> + </div> + <button class="Menu-Settings-default" onClick="renderSettings()"> + <img class="icon" src="/fontawesome/bundle/solid/gear.svg"/> + </button> + <button onCLick="visiteAdministration()"> + <img class="icon" src="/fontawesome/bundle/solid/user-gear.svg"/> + </button> + <button class="Menu-Help" onClick="renderHelp()"> + <img class="icon" style="font-weight: bold;"src="/fontawesome/bundle/solid/question.svg"/> + </button> + <button id="Logout-button" onClick="logout()"> + <img class="icon" src="/fontawesome/bundle/solid/right-from-bracket.svg"/> + </button> + </div> + <div id="Settings-container"> + <div id="Person-container" class="settings-box active d-none"> + <h2>Personen</h2> + <div id="Person-list-buttons"> + <button onClick="setSelectRenderPerson(this, 'active')" title="Alle in dieser woche aktiven Personen anzeigen" class="person-active active">Aktiv</button> + <button onClick="setSelectRenderPerson(this, 'all')" title="Alle aktiven Personen anzeigen" class="person-all">Alle</button> + <button onClick="setSelectRenderPerson(this, 'removed')" title="Alle gelöschten Personen anzeigen" class="person-removed">Gelöscht</button> + </div> + <table id="Person"> + <thead> + <tr> + <th>Name</th> + <th>Stunden</th> + <th>Bereich</th> + <th id="Person-table-freedays">Frei</th> + <th id="Person-table-labels">Labels</th> + <th id="Person-table-mpa" title="mittelbar pädagogische Arbeit">mpA</th> + <th id="Person-table-illnes">Krank</th> + <th id="Person-table-betterment" class="td-overflow"><div>Weiterbildung</div></th> + <th id="Person-table-vacation">Urlaub</th> + <th id="Person-table-overtime" title="Überstunden bis einschließlich dieser Woche">Überstunden</th> + </tr> + </thead> + <tbody><tr><td>Mitarbeiter hinzufügen</td></tr></tbody> + </table> + <button onClick='addPerson()' class="button-add-person button-whitegreen">Hinzufügen</button> + <div id="Week-select" class="settings-box"> + <input type="date" name="date" id="Roster-week-input" onChange="changeDate(this.value)" required> + <button onClick="changeDate('prev')">vorherige Woche</button> + <button onClick="changeDate(new Date())">diese Woche</button> + <button onClick="changeDate('next')">nächste Woche</button> + <label id="Week-select-overview" class="chevron-select chevron-down"></label> + </div> + </div> + <div id="Vacations-overview" class="settings-box d-none"></div> + <div id="Closingtimes" class="settings-box d-none"></div> + <div id="Settings-default" class="settings-box active d-none"> + <h2>Einstellungen</h2> + <div class="container"> + <div class="container-buttons"> + <button id="Settings-weekly-button" class="active" onClick="changeSettingsView(this, 'weekly')">Wöchentlich</button> + <button id="Settings-global-button" onClick="changeSettingsView(this, 'global')">Allgemein</button> + </div> + <div id="Settings-weekly"> + <div class="timesteps-container settings-item"></div> + <div class="daybreaks-container settings-item"></div> + <div class="timestart-container settings-item"></div> + <div class="timeend-container settings-item"></div> + <div class="specialstart-container settings-item"></div> + <div id="Settings-day-time-change"></div> + </div> + <div id="Settings-global" class="d-none"></div> + </div> + </div> + </div> + +<?php } ?> + </div> +<?php if ($_SESSION["user_role"] === "admin") { ?> + <div id="Roster-days-container" class="page"> + <div id="Sort-roster-by" class="settings-box"> + <div class="sort-box"> + <button id="Sort-roster-by-name" class="sort-roster-by sort" name="n" onClick="sortRosterBy('days', this)">Name</button> + <button id="Sort-roster-by-department" class="sort-roster-by sort" name="d" onClick="sortRosterBy('days', this)">Bereich</button> + <button id="Sort-roster-by-hours" class="sort-roster-by sort" name="h" onClick="sortRosterBy('days', this)">Stunden</button> + </div> + </div> + </div> +<?php } ?> +<?php if ($_SESSION["user_role"] === "user") { ?> +<div id="User-details" class="page"> + <h2 class="main-title">Dienstplan</h2> +</div> +<?php } ?> + <div id="Roster-container-week" class="page"> +<?php if ($_SESSION["user_role"] === "admin") { ?> + <div id="Roster-week-view-settings"> + <button id="Roster-week-view-settings-toggle-button" class="button-orange" onClick='this.parentNode.classList.toggle("active"); this.classList.toggle("active");'>Einstellungen Wochenübersicht</button> + <div class="settings"> + <div class="row"> + <div id="Roster-week-display-overtime"> + <button onClick="rosterWeekDisplayOvertime(this)">Überstunden anzeigen</button> + </div> + <div id="Roster-week-print-mode"> + <label>Druckausrichtung: </label> + <button onClick="changePrintMode(this)" title="Druckeinstellung für die Ausrichtung.
Die Ausrichtung muss ebenfalls in den Druckeinstellungen, welche sich nach drücken auf 'Drucken' öffnen, geändert werden">Hochformat</button> + </div> + <div id="Roster-week-print-zoom"> + <label>Druckvergrößerung: </label> + <div> + <button title="verkleinern" onClick="setPrintZoomLevelValue(-1)">-</button> + <input type="range" min="40" max="120"> + <button title="vergrößern" onClick="setPrintZoomLevelValue(+1)">+</button> + <div class="zoom-value"></div> + </div> + </div> + </div> + <div class="row"> + <div id="Roster-week-add-editable-row"> + <button onClick="rosterWeekAddEditableRow(this)" class="row-top" title="Die Standarteinstellung kann in den Einstellungen -> Allgemein, eingestellt werden.">Bearbeitbare Zeile einfügen - oben</button> + <button onClick="rosterWeekAddEditableRowBottom(this)" class="row-bottom" title="Die Standarteinstellung kann in den Einstellungen -> Allgemein, eingestellt werden.">Bearbeitbare Zeile einfügen - unten</button> + </div> + <div id="Roster-week-add-editable-cell"> + <button onClick="rosterWeekAddEditableCell(this)" title="Die Standarteinstellung kann in den Einstellungen -> Allgemein, eingestellt werden.">Bearbeitbare Spalte einfügen</button> + </div> + <button id="Roster-week-week-info" onClick="toggleSetWeekInfo(this)">Wocheninformation</button> + </div> + <div class="row"> + <div id="Set-week-info-container" class="d-none"> + <textarea rows="10" cols="50" onchange="setWeekInfo(this.value)"></textarea> + </div> + </div> + </div> + </div> + <div id="Roster-week-buttons-edit-sort"> + <button id="Table-week-editable-button" onClick="this.classList.toggle('active'); toggleTableWeekEditeable('Roster-week-table')" title="Hiermit kannst du in der Tabelle die Zeiten ändern.">Schichten bearbeiten</button> + <div id="Sort-week-by"> + <div class="sort-box"> + <button id="Sort-week-by-name" class="sort-week-by sort" name="n" onClick="sortRosterBy('week', this)">Name</button> + <button id="Sort-week-by-department" class="sort-week-by sort" name="d" onClick="sortRosterBy('week', this)">Bereich</button> + <button id="Sort-week-by-hours" class="sort-week-by sort" name="h" onClick="sortRosterBy('week', this)">Stunden</button> + </div> + </div> + </div> +<?php } ?> + + <div id="Roster-week-container"></div> + <div class="Footer"> + <a title="Impressum" href="https://www.christianimmanuel.de">Impressum</a> + <a title="Datenschutz" href="https://www.christianimmanuel.de">Datenschutz</a> + </div> + </div> + </div> + <div id="Menu"> + <div id="Menu-item-week"> + <button id="Menu-week" onClick='document.getElementById("Roster-week-container")?.scrollIntoView(); closePopup()'>Woche</button> + <label id="Menu-week-select" class="chevron-select chevron-down"></label> +<?php if ($_SESSION["user_role"] === "admin") { ?> + <button id="Roster-copy-person-from"> + <img class="icon" src="/fontawesome/bundle/solid/calendar.svg"/> + <img class="icon" src="/fontawesome/bundle/solid/arrow-right.svg"/> + <img class="icon" src="/fontawesome/bundle/regular/calendar.svg"/> + </button> +<?php } ?> + </div> +<?php if ($_SESSION["user_role"] === "admin") { ?> + <div class="menu-item-days-container"> + <button class="chevron-left" title="letze Woche" onClick="changeDate('prev')"></button> + <div id="Menu-item-days"></div> + <button class="chevron-right" title="nächste Woche" onClick="changeDate('next')"></button> + </div> + <input id="Zoom-roster" title="Dienstplan Tagesübersichten zoomen" type="range" min="50" max="100" value="100" oninput="changeZoomLevel(this.value)"> +<?php } else { ?> + <div id="Week-select" class="settings-box"> + <button onClick="changeDate('prev')">vorherige Woche</button> + <button onClick="changeDate(new Date())">diese Woche</button> + <button onClick="changeDate('next')">nächste Woche</button> + </div> + <button id="Logout-button" onClick="logout()"><img class="icon" src="/fontawesome/bundle/solid/right-from-bracket.svg"/></button> +<?php } ?> + </div> + <div id="Edit-person"> + <div id="Edit-person-container"> + <div class="remove"><button class="button-remove">löschen</button></div> + <div class="person-container edit-box"> + <div class="container"> + <div class="select-assign-container"></div> + <div class="name"><label class="title">Name:</label><input/></div> + <div class="hours"><label class="title">Stunden:</label><input type="number" min="0" max="168" step="0.5"/></div> + <div class="department"><label class="title">Bereich:</label></div> + </div> + <div class="activation" title="Einstellungs KW"><label class="title">Aktiviert:</label><div class="input-container"></div></div> + </div> + <div id="Edit-person-shift-settings" class="edit-box"> + <label class="title">Schichteinstellung</label><div class="select-assign-container"></div><div class="container"></div> + </div> + <div id="Edit-person-mpa" class="edit-box"> + <label class="title">MPA:</label><div class="select-assign-container"></div><div class="container"></div> + </div> + <div id="Edit-person-illnesses" class="edit-person-table-container edit-box"> + <label class="title">Krank:</label><div class="container"></div><div class="container-add"></div> + </div> + <div id="Edit-person-betterments" class="edit-person-table-container edit-box"> + <label class="title">Weiterbildung:</label><div class="container"></div><div class="container-add"></div> + </div> + <div id="Settings-vacations" class="edit-person-table-container edit-box"> + <label class="title">Urlaub:</label><div class="container"></div><div class="container-add"></div> + </div> + <div id="Edit-person-overtime" class="edit-box"> + <label class="title">Überstunden:</label><div class="container-add"></div><div class="container"></div> + </div> + <button class="button-save edit-close">Fertig</button> + </div> + </div> + <div id="Popup"><div id="Popup-container"></div></div> + <div id="Loading-screen" class="d-none"><div>.</div><div>.</div><div>.</div></div> + <div id="Console" class="d-none font-number"> + <div id="Console-help"></div> + <div id="Console-input" ></div> + </div> + <script> + +logout = () => { + fetch("/api/logout.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then(() => {window.location = "login.php"}) +} + +let BLOCK_MENU_DAYS = document.getElementById("Menu-item-days") +renderMenuWeeks = () => { + DAYS.forEach((day, day_id) =>{ + let block_menu_week_button = document.createElement("button") + block_menu_week_button.setAttribute("onClick", 'document.getElementById("Roster-'+day_id+'")?.scrollIntoView(); closePopup()') + block_menu_week_button.innerHTML = day + BLOCK_MENU_DAYS.appendChild(block_menu_week_button) + }) +} + +exportRoster = () => { + window.setTimeout(() => { + let data = { DATA } + let filename = "Dienstplan_"+DATE_YEAR_WEEK_NEWEST+".json" + let blob = new Blob([JSON.stringify(data)], {type: "application/json;charset=utf-8"}) + let url = URL.createObjectURL(blob); + let elem = document.createElement("a"); + elem.href = url; + elem.download = filename; + document.body.appendChild(elem); + elem.click(); + document.body.removeChild(elem); + }, 100) +} + +setRosterFromFile = (e) => { + showLoading(); window.setTimeout(() => { + ALL = JSON.parse(e.target.result).DATA + if (typeof ALL === "undefined") {ALL = JSON.parse(e.target.result)} + startRoster(ALL) + hideLoading() + },1) +} +importRoster = (ev) => { + DISABLE_WINDOW_RELOAD = false + let reader = new FileReader() + reader.onload = setRosterFromFile + let content = reader.readAsText(ev.target.files[0]) +} + +printTable = (table, year_week) => { + if (EDITABLE_TABLES.indexOf("Roster-week-table") > -1) { + document.getElementById("Table-week-editable-button").classList.remove("active") + toggleTableWeekEditeable('Roster-week-table') + } +let style = "#Roster-week-container> button {display: none;}" + +"body {font-family: Arial, Helvetica, sans-serif; margin: auto; width: 200mm; }" + +".font-number { font-family: Arial, Helvetica, monospace}" + +".v-bottom { vertical-align: bottom !important; }" + +"#Print-container { margin: 40px 40px 20px; }" + +"* { box-sizing: border-box; -moz-box-sizing: border-box; }" + +"#Roster-week-container { transform-origin: top left;}" + +"table { border-collapse: collapse;}" + +"table, th, td { border: 1px solid; }" + +"tbody td {vertical-align: top;}" + +"p {margin: 0; padding: 6px;}" + +".tr-empty td {height: 5px !important;}" + +"#Roster-week-container .tr-editable td, #Roster-week-container .tr-editable th { font-weight: normal; padding: 8px 6px; white-space: pre; vertical-align: top; }" + +"#Roster-week-container .Roster-week-td.free { vertical-align: middle;}" + +"#Roster-week-container .Roster-week-td.free p { margin: auto; font-size: 19px; }" + +"#Roster-week-container .Roster-week-td.free p.time { max-width: 100px; overflow: hidden; }" + +".Roster-week-td { height: 0; vertical-align: top;}" + +".Roster-week-td:first-child { vertical-align: middle;}" + +".Roster-week-td .container { display: grid; font-family: Arial, Helvetica, monospace; min-width: max-content; grid-template-areas: 'time time time' 'break mpa duration'; grid-template-columns: 1fr auto 1fr; gap: 0; white-space: pre; }" + +".Roster-week-td .container p {padding: 0 4px;}" + +".Roster-week-td .time { margin-top: 6px; grid-area: time; text-align: center; }" + +".Roster-week-td .time >div { display: flex; }" + +".Roster-week-td .time p { margin-bottom: 3px; margin-top: 0; }" + +".Roster-week-td .duration { justify-content: flex-end; grid-area: duration;}" + +".Roster-week-td .mpa { grid-area: mpa; margin-top: 2px; text-align: center; font-size: 12px; padding: 0 2px 0 4px;}" + +".Roster-week-td .label { grid-area: label; text-align: center; font-size: 19px; margin: auto; display: flex; padding: 0 4px 0 2px; }" + +".Roster-week-td .info { max-width: fit-content; font-size: 12px; white-space: break-spaces;}" + +".Roster-week-td .info >div { margin: 0 4px 4px;}" + +".break {text-align: right; }" + +".td-name { display: grid; gap: 6px 0; grid-template-areas: 'name overtime' 'hours breaks'; margin-top: 4px; }" + +".td-name p:first-child { grid-area: name; padding-bottom: 3px;}" + +".td-name p:nth-child(2) { font-size: 10px; grid-area: overtime; text-align: right; }" + +".td-name p:nth-child(3) { font-size: 14px; grid-area: hours; padding-right: 0; }" + +".td-name p:nth-child(4) { font-size: 14px; grid-area: breaks; text-align: right; }" + +".td-name p { margin: 0; padding: 2px 8px 6px; }" + +".duration, .break {display: flex; align-items: flex-end; margin: 7px 0 5px; }" + +".td-editable-cell {border-left: 4px double black; font-weight: normal; padding: 5px 3px; min-width: 60px; vertical-align: top; white-space: pre; text-align: left; }" + +"#Roster-week-info { max-width: fit-content; white-space: break-spaces; margin-top: 40px; }" +let zoom +if (SETTINGS.printmode === 1) { + zoom = SETTINGS.zoom_print_v + if (navigator.userAgent.search("Firefox") === -1) { + style = style+` @media print{@page {size: landscape} } body {zoom: ${zoom}%;}` + + "td { padding: 4px 13px !important;}" + } else { + style = style+` @media print{@page {size: landscape} }` + + `#Roster-week-container {transform: scale(${zoom*0.01})}` + + "td { padding: 4px 13px !important;}" + } +} else if (SETTINGS.printmode === 0) { + zoom = SETTINGS.zoom_print_h + if (navigator.userAgent.search("Firefox") === -1) { + style = style+ `body {zoom: ${zoom}%;}` + } else { + style = style+ `#Roster-week-container {transform: scale(${zoom*0.01})}` + } +} + +let divContents = document.getElementById(table).innerHTML; +let a = window.open('', '', 'height=500, width=500'); +a.document.write('<html>'); +a.document.write('<head>'); +a.document.write(`<title>Dienstplan_${year_week}</title>`); + +a.document.write('<style>'+style+'</style>'); +a.document.write('</head>'); +a.document.write('<body style="background: white;" >'); +a.document.write('<div id="Print-container">'); +a.document.write('<div id="Roster-week-container">'); +a.document.write(divContents); +if (SETTINGS.printmode === 0) { + let zoom_string = '<script>let zoom = `${((document.body.offsetWidth-84)/document.getElementById("Roster-week-table").offsetWidth)*100}`; zoom = `${(('+zoom+'*zoom)/100)}`; if (navigator.userAgent.search("Firefox") === -1) { document.getElementById("Roster-week-container").style.zoom = `${zoom}%`; } else {document.getElementById("Roster-week-table").style = `transform: scale(${zoom*0.01}); transform-origin: inherit`;console.log(zoom)} </'+'script>'; + a.document.write(zoom_string); +} +a.document.write('</div>'); +a.document.write('</div>'); +a.document.write('</body></html>'); +a.document.close(); +a.print(); +} + +hhMMToTime = (time) => { + let time_string = time.toString() +if (time_string.length === 4) {time_string = `0${time_string}`} + if(time_string.indexOf(":15") >= 0) { + time_string = time_string.replace(":15", ".25") + } else if(time_string.indexOf(":30") >= 0) { + time_string = time_string.replace(":30", ".5") + } else if(time_string.indexOf(":45") >= 0) { + time_string = time_string.replace(":45", ".75") + } else { + time_string = time_string.replace(":00", "") + } +console.log(time_string) + return parseFloat(time_string) +} +timeToHHMM = (time) => { + let time_string = time.toString() + if(time_string.indexOf(".25") >= 0) { + return time_string.replace(".25", ":15") + } else if(time_string.indexOf(".5") >= 0) { + return time_string.replace(".5", ":30") + } else if(time_string.indexOf(".75") >= 0) { + return time_string.replace(".75", ":45") + } else { + return time_string+":00" + } +} +timeToFullHHMM = (time) => { + let text = timeToHHMM(time) + if (text.length === 4) {return `0${text}`} + else {return text} +} + + + </script> + + </body> +</html> diff --git a/js/.copy-person-shifts.js.swp b/js/.copy-person-shifts.js.swp new file mode 100644 index 0000000..4b64474 Binary files /dev/null and b/js/.copy-person-shifts.js.swp differ diff --git a/js/.person.js.swp b/js/.person.js.swp new file mode 100644 index 0000000..858714e Binary files /dev/null and b/js/.person.js.swp differ diff --git a/js/.roster.js.swp b/js/.roster.js.swp new file mode 100644 index 0000000..6fde039 Binary files /dev/null and b/js/.roster.js.swp differ diff --git a/js/administration.js b/js/administration.js new file mode 100644 index 0000000..6f7b391 --- /dev/null +++ b/js/administration.js @@ -0,0 +1,296 @@ + +logout = () => { + fetch("/api/logout.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then(() => {window.location = "login.php"}) +} +closePopup = () => { + let block = document.querySelector(".Popup-request-remove-institution") + block.classList.remove("active") + block.querySelector(".password").value = "" + document.querySelector(".Popup-request-remove-institution .hint").innerHTML = "" +} +addNewInstitution = () => { + let block_name = document.querySelector(".Popup-add-new .name") + let name = block_name.value + if (name.length === 0) {return} + dbAdd_institution(name, DATE_YEAR_WEEK).then(() => { + block_name.value = "" + renderInstitutions() + document.querySelector(".Popup-add-new").classList.remove("active") + }) +} +removeInstitution = async (id) => { + let check = await dbRemove_institution(id, document.querySelector(".Popup-request-remove-institution .password").value) + if (check) { + closePopup() + renderInstitutions() + renderUsers() + } else { + document.querySelector(".Popup-request-remove-institution .hint").innerHTML = "Passwort stimmt nicht überein." + } +} +requestRemoveInstitution = (id, name) => { + let block = document.querySelector(".Popup-request-remove-institution") + block.classList.add("active") + let block_name = block.querySelector(".name") + block_name.innerHTML = name + let password = block.querySelector(".password").value + let block_confirm = block.querySelector(".confirm") + block_confirm.setAttribute("onClick", `removeInstitution(${id})`) +} +visiteInstitution = async (data_id, as) => { + dbSwitchAs_institution(data_id, as).then(() => {window.location = "/";}) +} +renderInstitutions = async () => { + let institutions = await dbGet_institutions() + let block = document.querySelector("#Institutions") + block.innerHTML = "" + institutions.forEach(institution => { + let block_name = document.createElement("div") + block_name.classList.add("name") + block_name.innerHTML = institution.name + block.appendChild(block_name) + /* + let block_visite_container = document.createElement("div") + block_visite_container.classList.add("container-visite") + let block_visite = document.createElement("button") + block_visite.innerHTML = "Anschauen" + block_visite.setAttribute("onClick", `visiteInstitution(${institution.id}, "visitor")`) + block_visite_container.appendChild(block_visite) + let block_edit = document.createElement("button") + block_edit.innerHTML = "Bearbeiten" + block_edit.setAttribute("onClick", `visiteInstitution(${institution.id}, "editor")`) + block_visite_container.appendChild(block_edit) + block.appendChild(block_visite_container) + */ + let block_remove_container = document.createElement("div") + block_remove_container.classList.add("container-remove") + let block_remove = document.createElement("button") + block_remove.setAttribute("onClick", `requestRemoveInstitution(${institution.id}, "${institution.name}")`) + block_remove.innerHTML = "Löschen" + block_remove_container.appendChild(block_remove) + block.appendChild(block_remove_container) + }) + let block_add = document.createElement("button") + block_add.setAttribute("onClick", `document.querySelector(".Popup-add-new").classList.add("active")`) + block_add.setAttribute("id", "Institution-add-button") + block_add.innerHTML = "Hinzufügen" + block.appendChild(block_add) +} +changeSelectRole = (role) => { + if (role === "superadmin") { + document.querySelector(".Popup-container .label-institution").classList.add("d-none") + document.querySelector(".Popup-container .label-select-institution").classList.add("d-none") + } else { + document.querySelector(".Popup-container .label-institution").classList.remove("d-none") + document.querySelector(".Popup-container .label-select-institution").classList.remove("d-none") + } +} +addNewUser = () => { + let block = document.querySelector(".Popup-add-new-user") + let block_hint = block.querySelector(".hint") + let name = block.querySelector(".name").value + let password = block.querySelector(".password").value + let password_1 = block.querySelector(".password-confirm").value + let institution = parseFloat(block.querySelector(".select-institution").value) + let role = block.querySelector(".select-role").value + if (password !== password_1) { + block_hint.innerHTML = "Passwörter stimmen nicht überein." + return + } + if (password.length < 8) { + block_hint.innerHTML = "Das passwort sollte mindestens 8 stellen haben." + return + } + addU = async () => { + let response = await fetch("/api/account/addUser.php", { + method: "POST", + body: JSON.stringify({name: name, password: password, role: role, data_id: institution}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let user_id = await response.json() + if (isNaN(user_id)) { + block_hint.innerHTML = user_id + } else { + renderUsers() + closeAddUser() + } + } + addU() +} +closeAddUser = () => { + let block = document.querySelector(".Popup-add-new-user") + block.querySelector(".hint").innerHTML = "" + block.querySelector(".name").value = "" + block.querySelector(".password").value = "" + block.querySelector(".password-confirm").value = "" + block.classList.remove("active") +} +renderAddUser = async () => { + let block = document.querySelector(".Popup-add-new-user") + let block_select_institutions = block.querySelector(".select-institution") + block_select_institutions.innerHTML = "" + let institutions = await dbGet_institutions() + institutions.forEach((institution, iid) => { + let block_option = document.createElement("option") + block_option.innerHTML = institution.name + block_option.value = institution.id + if (iid === 0) { + block_option.setAttribute("selected", "selected") + } + block_select_institutions.appendChild(block_option) + }) + + document.querySelector(".Popup-add-new-user").classList.add("active") +} +changePassword = () => { + let block = document.querySelector(".Popup-edit-user") + let user_id = parseFloat(block.getAttribute("user_id")) + let pw_1 = block.querySelector(".password_1").value + let pw_2 = block.querySelector(".password_2").value + if (pw_1 !== pw_2) { + block.querySelector(".hint-password").innerHTML = "Die Passwörter stimmen nicht überein." + return + } + fetch("/api/account/updatePassword.php", { + method: "POST", + body: JSON.stringify({id: user_id, password: pw_1}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then((response) => response.json()).then(data => { + if (data === user_id) { + window.location = "/admin.php" + } else { + block.querySelector(".hint-password").innerHTML = data + } + }) + +} +changeName = () => { + let block = document.querySelector(".Popup-edit-user") + let user_id = parseFloat(block.getAttribute("user_id")) + let user_name = block.querySelector(".container-name .name").value + fetch("/api/account/updateName.php", { + method: "POST", + body: JSON.stringify({id: user_id, name: user_name}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then((response) => response.json()).then(data => { + if (data === user_name) { + window.location = "/admin.php" + } else { + block.querySelector(".hint-name").innerHTML = data + } + }) + +} +renderEditUser = (user_id, user_name) => { + let block = document.querySelector(".Popup-edit-user") + let block_title_name = block.querySelector("h2.name") + block_title_name.innerHTML = user_name + block.classList.add("active") + block.setAttribute("user_id", user_id) + block.querySelector("input.name").value = user_name +} +removeUser = (user_id, data_id) => { + let block = document.querySelector(".Popup-remove-user") + let password = block.querySelector(".password").value + fetch("/api/account/removeUser.php", { + method: "POST", + body: JSON.stringify({user_id: user_id, data_id: data_id, password: password}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then((response) => response.json()).then(data => { + if (data === user_id) { + window.location = "/admin.php" + } else { + block.querySelector(".hint").innerHTML = data + } + }) +} +renderRemoveUser = (user_id, user_name, data_id) => { + let block = document.querySelector(".Popup-remove-user") + block.setAttribute("user_id", user_id) + block.classList.add("active") + let block_name = block.querySelector(".name") + block_name.innerHTML = user_name + let block_confirm = block.querySelector(".confirm") + block_confirm.setAttribute("onClick", `removeUser(${user_id}, ${data_id})`) +} +renderUsers = async () => { + let ROLES = [{c: "user", n: "Benutzer"}, {c: "admin", n: "Einrichtungs-Administrator"}, {c: "superadmin", n: "Super-Administrator"}] + let users = await dbGet_users() + let institutions = await dbGet_institutions() + let block = document.querySelector("#Users") + block.innerHTML = "" + let block_name_title = document.createElement("div") + block_name_title.innerHTML = "Name" + block_name_title.classList.add("title") + block.appendChild(block_name_title) + let block_role_title = document.createElement("div") + block_role_title.innerHTML = "Rolle" + block_role_title.classList.add("title") + block.appendChild(block_role_title) + let block_institution_title = document.createElement("div") + block_institution_title.innerHTML = "Einrichtung" + block_institution_title.classList.add("title") + block.appendChild(block_institution_title) + let block_created_title = document.createElement("div") + block_created_title.innerHTML = "Erstellt" + block_created_title.classList.add("title") + block.appendChild(block_created_title) + let block_edit_title = document.createElement("div") + block_edit_title.classList.add("title") + block.appendChild(block_edit_title) + let block_remove_title = document.createElement("div") + block_remove_title.classList.add("title") + block.appendChild(block_remove_title) + for (let u=0; u<users.length; u++) { + let user = users[u] + if (user.role === "user") { continue } + let block_name = document.createElement("div") + block_name.innerHTML = user.name + block.appendChild(block_name) + let block_role = document.createElement("div") + block_role.innerHTML = ROLES.find(r => r.c === user.role).n + block.appendChild(block_role) + let block_institution = document.createElement("div") + block_institution.innerHTML = user.role === "superadmin" ? "" : institutions?.find(i => i.id === user.data_id)?.name + block.appendChild(block_institution) + let block_created = document.createElement("div") + block_created.innerHTML = `${user.created_at.substring(8, 10)}.${user.created_at.substring(5, 7)}.${user.created_at.substring(0, 4)}` + block.appendChild(block_created) + let block_edit = document.createElement("button") + block_edit.innerHTML = "Bearbeiten" + block_edit.setAttribute("onClick", `renderEditUser(${user.id}, "${user.name}")`) + block.appendChild(block_edit) + let block_remove = document.createElement("button") + block_remove.innerHTML = "Löschen" + block_remove.setAttribute("onClick", `renderRemoveUser(${user.id}, "${user.name}", ${user.data_id})`) + block.appendChild(block_remove) + } + let block_add = document.createElement("button") + block_add.setAttribute("onClick", `renderAddUser()`) + block_add.setAttribute("id", "Users-add-button") + block_add.innerHTML = "Hinzufügen" + block.appendChild(block_add) + +} + +closePopup = () => { + let popups = document.querySelectorAll(".Popup.active") + for (let i=0; i<popups.length; i++) { + popups[i].classList.remove("active") + } + let clear_inputs = document.querySelectorAll(".Popup input") + for (i=0; i<clear_inputs.length; i++) { + clear_inputs[i].value = "" + } +} diff --git a/js/closing-time.js b/js/closing-time.js new file mode 100755 index 0000000..fb77440 --- /dev/null +++ b/js/closing-time.js @@ -0,0 +1,346 @@ +SET_CLOSING_DATE_CHANGED = false + + +closeClosingTime = () => { + document.getElementById("Settings-toggle-closingtime").classList.remove("active") + closePopup() + setPerson().then(() => getActiveRoster()) +} +rerenderClosingtimes = () => { + showLoading("rerenderClosingtimes") + return dbGet_closingtimes().then(cl => { + CLOSINGTIMES = cl + renderClosingTimesTable() + renderBlockButtonAddClosingTime() + hideLoading("rerenderClosingtimes") + return + }) +} +removeClosingTime = (year, id) => { + showLoading("removeClosingTime") + dbRemove_closingtime(id).then(() => { + setPerson().then(() => { + getActiveRoster().then(() => { + openClosingTime() + hideLoading("removeClosingTime") + }) + }) + }) +} +saveClosingTime = () => { + SET_CLOSING_DATE_CHANGED = false + let block = document.getElementById("Set-closing-time") + let title = block.querySelector(".title").value + let start = block.querySelector(".start").value + let end = block.querySelector(".end").value + let is_public_holiday = block.querySelector(".button-public-holiday").classList.contains("active") + addClosingTime(title, start, end, is_public_holiday) + renderBlockButtonAddClosingTime() +} +addClosingTime = (title, start, end, is_public_holiday) => { + showLoading("addClosingTime") + let start_year = new Date(start).getFullYear() + start_year = start_year.toString() + + let person_ids = [] + if (is_public_holiday) { + if (ROSTERS_YEARWEEK.indexOf(getDateToRosterDate(new Date(start))[0]) > -1) { + dbGet_persons_active_where_yearweek(getDateToRosterDate(new Date(start))[0]).then(persons => { + persons.forEach(p => {removePersonShiftsBetweenDate(p.id, start, end)}) + person_ids = persons.map(p => p.id) + dbAdd_closingtime(title, start, end, person_ids, is_public_holiday).then(() => {rerenderClosingtimes(); hideLoading("addClosingTime")}) + }) + } else { + person_ids = PERSONS.map(p => p.id) + dbAdd_closingtime(title, start, end, person_ids, is_public_holiday).then(() => {rerenderClosingtimes(); hideLoading("addClosingTime")}) + } + } else { + dbAdd_closingtime(title, start, end, person_ids, is_public_holiday).then(() => {rerenderClosingtimes(); hideLoading("addClosingTime")}) + } +} +changeClosingTimeBlockDate = (value, dir) => { + if (SET_CLOSING_DATE_CHANGED) return + SET_CLOSING_DATE_CHANGED = true + if (dir === "start") { + let end = document.querySelector("#Set-closing-time .end").value + if (value > end) { + //let date_end = new Date(value) + //date_end = new Date((date_end.getTime() + 7 * 24 * 60 * 60 * 1000) - date_end.getTimezoneOffset() * 60000).toISOString().slice(0,10); + document.querySelector("#Set-closing-time .end").value = value + } + } else if (dir === "end") { + let start = document.querySelector("#Set-closing-time .start").value + if (value < start) { + //let date_start = new Date(value) + //date_start = new Date((date_start.getTime() - 7 * 24 * 60 * 60 * 1000) - date_start.getTimezoneOffset() * 60000).toISOString().slice(0,10); + document.querySelector("#Set-closing-time .start").value = value + } + } + +} +createAddClosingTime = () => { + SET_CLOSING_DATE_CHANGED = false + let date_start = new Date(getDateOfISOWeek(DATE_YEAR_WEEK)) + date_start = new Date(date_start.getTime() - date_start.getTimezoneOffset() * 60000).toISOString().slice(0,10); + let date_end = new Date(getDateOfISOWeek(DATE_YEAR_WEEK)) + date_end = new Date((date_end.getTime() + 7 * 24 * 60 * 60 * 1000) - date_end.getTimezoneOffset() * 60000).toISOString().slice(0,10); + + let block_container = document.createElement("div") + block_container.setAttribute("id", "Set-closing-time") + + let block_title = document.createElement("input") + block_title.classList.add("title") + block_title.setAttribute("title", "Bezeichnung") + block_title.setAttribute("placeholder", "Bezeichnung") + block_container.appendChild(block_title) + + let block_start = document.createElement("input") + block_start.setAttribute("type", "date") + block_start.setAttribute("onchange", "changeClosingTimeBlockDate(this.value, 'start')") + block_start.setAttribute("title", "Start Datum") + block_start.classList.add("start") + block_start.value = date_start + block_container.appendChild(block_start) + + let block_end = document.createElement("input") + block_end.setAttribute("type", "date") + block_end.setAttribute("onchange", "changeClosingTimeBlockDate(this.value, 'end')") + block_end.setAttribute("title", "End Datum") + block_end.classList.add("end") + block_end.value = date_end + block_container.appendChild(block_end) + + let block_public_holiday = document.createElement("button") + block_public_holiday.innerHTML = "Feiertag" + block_public_holiday.classList.add("button-public-holiday") + block_public_holiday.setAttribute("onclick", "this.classList.toggle('active')") + block_public_holiday.setAttribute("title", "Die freien Tage werden nich als Urlaub angerechnet.\nAlle nehmen teil.") + block_container.appendChild(block_public_holiday) + + let block_add = document.createElement("button") + block_add.innerHTML = "Speichern" + block_add.setAttribute("onclick", "saveClosingTime()") + block_add.classList.add("button-whitegreen") + block_add.setAttribute("title", "Speichern") + block_container.appendChild(block_add) + return block_container +} + +renderClosingTimesTable = () => { + let block_closingtimes = document.querySelector("#Add-closingtimes-closingtimes") + if (!block_closingtimes) return + block_closingtimes.innerHTML = "" + block_closingtimes.appendChild(createBlockClosingTimes()) +} +togglePersonClosingTime = async (button, person_id, year, date_id) => { + showLoading("togglePersonClosingTime") + year = year.toString() + let closingtime = CLOSINGTIMES.find(c => c.id === date_id) + + let person_all = await dbGet_persons_active_where_yearweek(getDateToRosterDate(new Date(closingtime.start))[0]) + + callback = () => { + let cid = CLOSINGTIMES.map(c => c.id).indexOf(date_id) + dbGet_closingtime(date_id).then(closingtime => { + CLOSINGTIMES[cid] = closingtime + let block_person = document.querySelector(`#Add-closingtimes-closingtimes .td-person-${year}-${date_id}`) + block_person.innerHTML = "" + block_person.appendChild(renderCheckPersonClosingTime(year, date_id)) + hideLoading("togglePersonClosingTime") + if (getDateToRosterDate(new Date(closingtime.start))[0] <= DATE_YEAR_WEEK && getDateToRosterDate(new Date(closingtime.end))[0] >= DATE_YEAR_WEEK) { + setPerson().then(() => { + loadRosterTable() + loadRosterTableWeek() + }) + } + }) + } + if (person_id === "all" ) { + if (closingtime.persons.length === person_all.length) { + dbRemove_closingtime_all_persons(closingtime.id).then(() => callback()) + } else { + for (let pa=0; pa<person_all.length; pa++) { + let person = person_all[pa] + if (closingtime.persons.indexOf(person.id) === -1) { + removePersonShiftsBetweenDate(person.id, closingtime.start, closingtime.end, true) + dbAdd_closingtime_person(closingtime.id, person.id).then(() => { + if (pa === person_all.length-1) {callback()} + }) + } else { + if (pa === person_all.length-1) {callback()} + } + } + } + } else if (closingtime.persons.indexOf(person_id) > -1) { + dbRemove_closingtime_person(closingtime.id, person_id).then(() => callback()) + } else { + removePersonShiftsBetweenDate(person_id, closingtime.start, closingtime.end, true) + dbAdd_closingtime_person(closingtime.id, person_id).then(() => callback()) + } + +} +renderCheckPersonClosingTime = (year, date_id) => { + year = year.toString() + let closingtime = CLOSINGTIMES.find(c => c.id === date_id) + let block_container = document.createElement("div") + let block_person_select_all_container = document.createElement("div") + block_person_select_all_container.classList.add("all") + let block_person_select_all = document.createElement("button") + block_person_select_all.innerHTML = "Alle" + block_person_select_all.setAttribute("onclick", `togglePersonClosingTime(this, "all", ${year}, ${date_id})`) + if (closingtime.persons.length === PERSONS.length) { + block_person_select_all.classList.add("active") + } + block_person_select_all_container.appendChild(block_person_select_all) + block_container.appendChild(block_person_select_all_container) + + let block_person_select_single_container = document.createElement("div") + block_person_select_single_container.classList.add("container") + //let person_all = dbGet_persons_active_where_yearweek(getDateToRosterDate(new Date(closingtime.start))[0]) + let person_all = PERSONS + person_all.forEach(person => { + let block_button = document.createElement("button") + block_button.innerHTML = person.name + block_button.setAttribute("onclick", `window.setTimeout(() => {togglePersonClosingTime(this, ${person.id}, ${year}, ${date_id})}, 50)`) + if (closingtime.persons.indexOf(person.id) > -1) { + block_button.classList.add("active") + } + block_person_select_single_container.appendChild(block_button) + }) + block_container.appendChild(block_person_select_single_container) + return block_container +} +createBlockClosingTimes = () => { + let block_table = document.createElement("table") + + let block_thead = document.createElement("thead") + let block_thead_tr = document.createElement("tr") + let block_th_year = document.createElement("th") + block_th_year.innerHTML = "Jahr" + block_thead_tr.appendChild(block_th_year) + let block_th_date = document.createElement("th") + block_th_date.innerHTML = "Datum" + block_thead_tr.appendChild(block_th_date) + let block_th_name = document.createElement("th") + block_th_name.innerHTML = "Bezeichnung" + block_thead_tr.appendChild(block_th_name) + let block_th_person = document.createElement("th") + block_th_person.innerHTML = "Personen" + block_thead_tr.appendChild(block_th_person) + let block_th_remove = document.createElement("th") + block_thead_tr.appendChild(block_th_remove) + block_thead.appendChild(block_thead_tr) + + block_table.appendChild(block_thead) + + let block_tbody = document.createElement("tbody") + + let year_before + + CLOSINGTIMES.sort((a,b) => b.start.localeCompare(a.start)).forEach(date => { + let date_id = date.id + let year = date.start.substring(0, 4) + let block_tr = document.createElement("tr") + let block_year = document.createElement("td") + block_year.classList.add("font-number") + if ((typeof year_before === "undefined") || (year !== year_before) ) { + year_before = year + block_year.classList.add("year") + block_year.innerHTML = year + } + block_tr.appendChild(block_year) + + let block_date = document.createElement("td") + block_date.classList.add("font-number") + fixDateLength = (d) => {if (d.toString().length === 1) {d = `0${d}`}; return d} + let end_year = new Date(date.end).getFullYear().toString() + checkYear = () => {if (year !== end_year) {return `.${end_year.slice(2,4)}`}; return ""} + let date_start = `${fixDateLength(new Date(date.start).getDate())}.${fixDateLength(new Date(date.start).getMonth()+1)}` + let date_end = `${fixDateLength(new Date(date.end).getDate())}.${fixDateLength(new Date(date.end).getMonth()+1)}${checkYear()}` + if (date_start === date_end) { block_date.innerHTML = date_start } + else { block_date.innerHTML = `${date_start} - ${date_end}` } + + block_tr.appendChild(block_date) + + let block_title = document.createElement("td") + block_title.innerHTML = date.name + block_tr.appendChild(block_title) + + let block_person = document.createElement("td") + block_person.classList.add("td-person", `td-person-${year}-${date_id}`) + if (date.lawful === 1) { + let block_public_holiday = document.createElement("div") + block_public_holiday.innerHTML = "Feiertag" + block_person.appendChild(block_public_holiday) + } else { + block_person.appendChild(renderCheckPersonClosingTime(year, date_id)) + + } + block_tr.appendChild(block_person) + + let block_remove = document.createElement("td") + let block_button_remove = document.createElement("button") + block_button_remove.innerHTML = "löschen" + block_button_remove.classList.add("button-remove") + block_button_remove.setAttribute("title", "löschen") + block_button_remove.setAttribute("onclick", `removeClosingTime(${year}, ${date_id})`) + block_remove.appendChild(block_button_remove) + block_tr.appendChild(block_remove) + block_tbody.appendChild(block_tr) + }) + + block_table.appendChild(block_tbody) + return block_table +} +renderBlockButtonAddClosingTime = () => { + let block_container_add = document.querySelector("#Closingtimes .container-add") + block_container_add.classList.remove("active") + block_container_add.innerHTML = "" + let block_button_add = document.createElement("button") + block_button_add.innerHTML = "Hinzufügen" + block_button_add.setAttribute("title", "speichern") + block_button_add.classList.add("button-whitegreen") + block_button_add.setAttribute("onclick", "renderBlockAddClosingTime()") + block_container_add.appendChild(block_button_add) + + let block_button_add_lawful = document.createElement("button") + block_button_add_lawful.innerHTML = "Feiertage automatisch hinzufügen" + block_button_add_lawful.setAttribute("id", "Lawful-vacations-Automatic-add-request") + block_button_add_lawful.setAttribute("onclick", "addClosingTimeLawfulVacations()") + block_container_add.appendChild(block_button_add_lawful) +} +renderBlockAddClosingTime = () => { + let block_container_add = document.querySelector("#Closingtimes .container-add") + block_container_add.classList.add("active") + block_container_add.innerHTML = "" + let block_cancel = document.createElement("button") + block_cancel.classList.add("button-orange", "button-cancel") + block_cancel.setAttribute("onCLick", "renderBlockButtonAddClosingTime()") + block_cancel.innerHTML = "Abbrechen" + block_container_add.appendChild(block_cancel) + let block_add = createAddClosingTime() + block_container_add.appendChild(block_add) +} +openClosingTime = async () => { + settingsContainerHideAll("Closingtimes") + CLOSINGTIMES = await dbGet_closingtimes() + let popup_container = document.getElementById("Closingtimes") + popup_container.innerHTML = "" + popup_container.classList.add("active", "closingtime") + + let block_header = document.createElement("h2") + block_header.innerHTML = "Schließzeiten" + popup_container.appendChild(block_header) + + let block_container_add = document.createElement("div") + block_container_add.classList.add("container-add") + popup_container.appendChild(block_container_add) + renderBlockButtonAddClosingTime() + + let block_closingtimes = document.createElement("div") + block_closingtimes.setAttribute("id", "Add-closingtimes-closingtimes") + block_closingtimes.appendChild(createBlockClosingTimes()) + popup_container.appendChild(block_closingtimes) + + document.body.classList.add("noscroll") +} diff --git a/js/console.js b/js/console.js new file mode 100644 index 0000000..d6ed77f --- /dev/null +++ b/js/console.js @@ -0,0 +1,162 @@ + +devConsole = () => { + CONSOLE = true + CONSOLE_INPUT = [{type: "", value: "", name: ""}] + CONSOLE_OPTIONS = [] + let block = document.getElementById("Console") + let block_input = block.querySelector("#Console-input") + block.classList.remove("d-none") + document.body.setAttribute("onclick", "closeConsole()") +} +closeConsole = () => { + CONSOLE = false + document.body.removeAttribute('onclick') + document.querySelector("#Console").classList.add("d-none") +} +watchConsole = (ev) => { + console.log(ev.key) + if ((ev.key === "Enter") || (ev.key === "ArrowRight") || (ev.key === "Tab")) checkConsoleOption() + if (ev.key === "ArrowUp") consoleSelectNextOption(1) + if (ev.key === "ArrowDown") consoleSelectNextOption() + if (ev.key !== "Backspace" && ev.key.length > 1) return + else if (ev.key === "Backspace") { + removeConsoleInput() + } else if (ev.key === " ") { + checkForType() + } else { + CONSOLE_INPUT[CONSOLE_INPUT.length-1].name = CONSOLE_INPUT[CONSOLE_INPUT.length-1].name+ev.key + } + renderConsoleInput() + checkForOptions() +} + +removeConsoleInput = () => { + if (CONSOLE_INPUT.length === 0) return + last_word = CONSOLE_INPUT[CONSOLE_INPUT.length-1].name + if (last_word.length === 0) { + CONSOLE_INPUT.splice(CONSOLE_INPUT.length-1, 1) + last_word = CONSOLE_INPUT[CONSOLE_INPUT.length-1].name + last_word = last_word.substring(0, last_word.length-1) + } else { + last_word = last_word.substring(0, last_word.length-1) + } + CONSOLE_INPUT[CONSOLE_INPUT.length-1].name = last_word + CONSOLE_INPUT[CONSOLE_INPUT.length-1].type = "" + CONSOLE_INPUT[CONSOLE_INPUT.length-1].value = "" +} +renderConsoleInput = () => { + let block_input = document.querySelector("#Console-input") + block_input.innerHTML = CONSOLE_INPUT.map(c => `<div class="${c.type}">${c.name} </div>`).join(" ") +} +checkConsoleOption = () => { + checkForAction() + checkForDays() + active_block = document.querySelector('#Console-help div.active') + if (!active_block) { + removeConsoleInput() + renderConsoleInput() + checkForOptions() + return + } + let type = active_block.getAttribute("type") + let value = active_block.getAttribute("value") + let name = active_block.innerHTML + insertConsoleOption(type, value, name) +} +insertConsoleOption = (type, value, name) => { + CONSOLE_INPUT[CONSOLE_INPUT.length - 1].value = value + CONSOLE_INPUT[CONSOLE_INPUT.length - 1].type = type + CONSOLE_INPUT[CONSOLE_INPUT.length - 1].name = name + CONSOLE_INPUT.push({type: "", value: "", name: ""}) + document.getElementById("Console-help").innerHTML = "" + renderConsoleInput() +} +consoleSelectDefaultOption = () => { + let blocks = document.querySelectorAll('#Console-help div') + if (blocks.length > 0) blocks[blocks.length-1].classList.add("active") +} +consoleSelectNextOption = (direction) => { + selected="selected" + let active_option = document.querySelector('#Console-help .active') + if (!active_option) { consoleSelectDefaultOption(); return } + active_option.classList.remove("active") + let next_option = active_option.nextSibling + if (direction === 1) { + next_option = active_option.previousSibling + if (!next_option) { + let options = document.querySelectorAll('#Console-help div') + next_option = options[options.length-1] + } + } else { + next_option = active_option.nextSibling + if (!next_option) { next_option = document.querySelector('#Console-help div') } + } + next_option.classList.add("active") +} +checkForType = () => { + let block_option = document.querySelector("#Console-help .active") + let type + if (!block_option) { + CONSOLE_INPUT.splice(CONSOLE_INPUT[CONSOLE_INPUT.length-1], 1) + } else { + CONSOLE_INPUT[CONSOLE_INPUT.length-1].name = block_option.innerHTML + CONSOLE_INPUT[CONSOLE_INPUT.length-1].value = block_option.getAttribute("value") + CONSOLE_INPUT[CONSOLE_INPUT.length-1].type = block_option.getAttribute("type") + } + CONSOLE_INPUT.push({type: "", value: "", name: ""}) +} +checkForOptions = () => { + CONSOLE_OPTIONS = [] + let block_help = document.querySelector("#Console-help") + + checkForAction() + checkForTypes() + checkForDays() + checkForName() + + block_help.innerHTML = "" + CONSOLE_OPTIONS.sort((a, b) => {return b.name.localeCompare(a.name)}) + CONSOLE_OPTIONS.forEach((o) => { + if (CONSOLE_INPUT.map(c => {return c.name}).indexOf(o.name) > -1 ) return + let block_option = document.createElement("div") + block_option.setAttribute("type", o.type) + block_option.setAttribute("value", o.value) + block_option.innerHTML = o.name + block_help.appendChild(block_option) + }) + consoleSelectDefaultOption() +} +checkForDays = () => { + let last_word = CONSOLE_INPUT[CONSOLE_INPUT.length-1].name + let days = DAYS.filter((d) => d.toLocaleLowerCase().includes(last_word.toLocaleLowerCase())) + DAYS.forEach((d, d_id) => { + if (days.indexOf(d) > -1) { + CONSOLE_OPTIONS.push({type: "day", value: d_id, name: d}) + } + }) +} +checkForTypes = () => { + let last_word = CONSOLE_INPUT[CONSOLE_INPUT.length-1].name + let default_types = ["shift", "person", "vacation", "mpa", "department"] + let types = default_types.filter((d) => d.toLocaleLowerCase().includes(last_word.toLocaleLowerCase())) + let options = "" + types.forEach(t => { + CONSOLE_OPTIONS.push({type: "type", value: t, name: t}) + }) +} +checkForAction = () => { + let last_word = CONSOLE_INPUT[CONSOLE_INPUT.length-1].name + let default_actions = ["add", "remove", "copy"] + let actions = default_actions.filter((d) => d.toLocaleLowerCase().includes(last_word.toLocaleLowerCase())) + + actions.forEach(a => { + CONSOLE_OPTIONS.push({type: "action", value: a, name: a}) + }) +} +checkForName = () => { + let last_word = CONSOLE_INPUT[CONSOLE_INPUT.length-1].name + let person_all = PERSONS.filter((p) => p.n.toUpperCase().includes(last_word.toUpperCase())) + person_all.forEach(p => { + CONSOLE_OPTIONS.push({type: "person", value: p.id, name: p.n}) + }) +} diff --git a/js/copy-person-shifts.js b/js/copy-person-shifts.js new file mode 100755 index 0000000..aacc104 --- /dev/null +++ b/js/copy-person-shifts.js @@ -0,0 +1,668 @@ +transferCopyPersonTable = () => { + showLoading("transferCopyPersonTable") + let transfer_shifts = document.querySelectorAll(`#Roster-week-table-from .Roster-week-td.active`) + if (transfer_shifts.length === 0) { + hideLoading("transferCopyPersonTable") + } + let all_shifts = [] + for (let i=0; i<transfer_shifts.length; i++) { + let block_shift = transfer_shifts[i] + all_shifts.push({person_id: parseFloat(transfer_shifts[i].getAttribute("person_id")), day_id: parseFloat(transfer_shifts[i].getAttribute("day_id"))}) + } + all_shifts = all_shifts.sort((a,b) => b.person_id-a.person_id) + let unique_persons = [...new Set(all_shifts.map(item => item.person_id))] + setS = async (shifts) => { + for (let s=0; s<shifts.length; s++) { + reloadPersonDayData(shifts[s].person_id, shifts[s].day_id, DATE_YEAR_WEEK_TABLE_TO , "Roster-week-table-to") + } + } + setP = (spid) => { + let shifts = all_shifts.filter(d => d.person_id === spid) + return dbGet_person_active(DATE_YEAR_WEEK_TABLE_TO, spid).then(new_person => { + let pid = PERSONS_TABLE_TO.map(p => p.id).indexOf(new_person.id) + PERSONS_TABLE_TO[pid] = new_person + if (DATE_YEAR_WEEK_TABLE_TO === DATE_YEAR_WEEK) { + let pwid = PERSONS_WEEK.map(p => p.id).indexOf(new_person.id) + PERSONS_WEEK[pwid] = new_person + let prid = PERSONS_ROSTER.map(p => p.id).indexOf(new_person.id) + PERSONS_ROSTER[prid] = new_person + let ppid = PERSONS.map(p => p.id).indexOf(new_person.id) + PERSONS[ppid] = new_person + } + setS(shifts) + + }) + } + setAll = async () => { + for (let u=0; u<unique_persons.length; u++) { + setP(unique_persons[u]) + } + hideLoading("transferCopyPersonTable") + } + for (let i=0; i<transfer_shifts.length; i++) { + let block_shift = transfer_shifts[i] + let person_id = parseFloat(block_shift.getAttribute("person_id")) + let person = PERSONS_TABLE_TO.find(p => p.id === person_id) + let day_id = parseFloat(block_shift.getAttribute("day_id")) + let shifts = PERSONS_TABLE_FROM.find(p => p.id === person_id).shifts.filter(s => s.day_id === day_id) + checkIfPersonDayIsFree(person_id, day_id, DATE_YEAR_WEEK_TABLE_TO).then(cfree => { + if (cfree === false) { + removePersonFromShiftDay(person.id, day_id, DATE_YEAR_WEEK_TABLE_TO, true).then(() => { + shifts.forEach((shift, s_d) => { + addShift(DATE_YEAR_WEEK_TABLE_TO, day_id, person_id, shift.start, shift.end, true).then(() => { + if (s_d === shifts.length-1 && i === transfer_shifts.length-1) setAll() + }) + }) + }) + } + }) + } + let change_tds = document.querySelectorAll("#Popup.roster-copy-person-table .Roster-week-table-copy-person td.active") + for (let ic=0; ic<change_tds.length; ic++) { + let change_td = change_tds[ic] + if (change_td.classList.contains("active")) { + change_td.classList.remove("active") + change_td.classList.add("inactive") + change_td.setAttribute("onClick", "") + } + } + let change_ths = document.querySelectorAll("#Popup.roster-copy-person-table .Roster-week-table-copy-person th.active") + for (let ih=0; ih<change_ths.length; ih++) { + let change_th = change_ths[ih] + if (change_th.classList.contains("active")) { + change_th.classList.remove("active") + change_th.classList.add("inactive") + change_th.setAttribute("onClick", "") + } + } +} + +toggleCopyPersonActiveDays = (el) => { + let day_id = el.getAttribute("day_id") + if (day_id === "all") { + let block_buttons = document.querySelectorAll("#Popup.roster-copy-person .item-days button") + if (el.classList.contains("active")) { + for (let i=0; i< block_buttons.length; i++) block_buttons[i].classList.remove("active") + + } else { + for (let i=0; i< block_buttons.length; i++) block_buttons[i].classList.add("active") + } + return + } + if (el.classList.contains("active")) { + document.querySelector("#Popup.roster-copy-person .item-days button.button-all").classList.remove("active") + el.classList.remove("active") + } else { + el.classList.add("active") + } +} +toggleCopyPersonActivePerson = (el) => { + let person_id = el.getAttribute("person_id") + if (person_id === "all") { + let block_buttons = document.querySelectorAll("#Popup.roster-copy-person .item-person button") + if (el.classList.contains("active")) { + for (let i=0; i< block_buttons.length; i++) block_buttons[i].classList.remove("active") + + } else { + for (let i=0; i< block_buttons.length; i++) block_buttons[i].classList.add("active") + } + return + } + if (el.classList.contains("active")) { + document.querySelector("#Popup.roster-copy-person .item-days button.button-all").classList.remove("active") + el.classList.remove("active") + } else { + el.classList.add("active") + } +} +toggleCopyPersonTableToButton = (person_id, day_id, set_active) => { + person_id = parseFloat(person_id) + day_id = parseFloat(day_id) + if (!document.querySelector(`#Roster-week-table-to .Roster-week-td-name-${person_id}-day-${day_id}`)) return + if (!document.querySelector(`#Roster-week-table-from .Roster-week-td-name-${person_id}-day-${day_id}`)) return + let free_from = PERSONS_TABLE_FROM.find(p => p.id === person_id).freedays[day_id] + if (!free_from) {free_from = PERSONS_TABLE_FROM.find(p => p.id === person_id).sf[day_id]} + let free_to = PERSONS_TABLE_TO.find(p => p.id === person_id).freedays[day_id] + if (!free_to) {free_to = PERSONS_TABLE_TO.find(p => p.id === person_id).sf[day_id]} + if ((free_from !== false) || (free_to !== false)) return + if (typeof set_active === "undefined") { + document.querySelector(`#Roster-week-table-to .Roster-week-td-name-${person_id}-day-${day_id}`).classList.toggle("active") + } else if (set_active) { + document.querySelector(`#Roster-week-table-to .Roster-week-td-name-${person_id}-day-${day_id}`).classList.add("active") + } else if (!set_active) { + document.querySelector(`#Roster-week-table-to .Roster-week-td-name-${person_id}-day-${day_id}`).classList.remove("active") + } +} +toggleCopyPersonTableButton = (el, set) => { + el = document.querySelector(`#Popup.roster-copy-person-table #Roster-week-table-from .Roster-week-td-name-${el.getAttribute("person_id")}-day-${el.getAttribute("day_id")}`) + el_to = document.querySelector(`#Popup.roster-copy-person-table #Roster-week-table-to .Roster-week-td-name-${el.getAttribute("person_id")}-day-${el.getAttribute("day_id")}`) + if (!el) return + if (!el_to) return + if (el.classList.contains("free")) return + if (el.classList.contains("inactive")) return + if (el_to.classList.contains("free")) return + if (el_to.classList.contains("inactive")) return + let person_id = parseFloat(el.getAttribute("person_id")) + let day_id = parseFloat(el.getAttribute("day_id")) + + let free_from = PERSONS_TABLE_FROM.find(p => p.id === person_id).freedays[day_id] + if (!free_from) {free_from = PERSONS_TABLE_FROM.find(p => p.id === person_id).sf[day_id]} + let free_to = PERSONS_TABLE_TO.find(p => p.id === person_id).freedays[day_id] + if (!free_to) {free_to = PERSONS_TABLE_TO.find(p => p.id === person_id).sf[day_id]} + if ((free_from !== false) || (free_to !== false)) return + if (EDITABLE_TABLES.indexOf("Roster-week-table-to") > -1 && !el_to.classList.contains("active")) return + + if (typeof set === "undefined") { + el.classList.toggle("active") + } else if (set) { + el.classList.add("active") + } else { + el.classList.remove("active") + } + toggleCopyPersonTableToButton(el.getAttribute("person_id"), el.getAttribute("day_id"), set) + toggleCopyPersonTitleButton(el.getAttribute("person_id"), el.getAttribute("day_id")) +} +toggleCopyPersonTableNameButton = (el) => { + if (EDITABLE_TABLES.indexOf("Roster-week-table-to") > -1 && !el.classList.contains("active")) return + let block_tds = document.querySelectorAll(`#Popup.roster-copy-person-table #Roster-week-table-from .Roster-week-td[person_id="${el.getAttribute("person_id")}"]`) + if (el.classList.contains("active")) { + for (let i=0; i< block_tds.length; i++) { + toggleCopyPersonTableButton(block_tds[i], false) + } + } else { + for (let i=0; i< block_tds.length; i++) { + toggleCopyPersonTableButton(block_tds[i], true) + } + } +} +toggleCopyPersonTableDayNameButton = (el) => { + let block_tds = document.querySelectorAll("#Popup.roster-copy-person-table .Roster-week-table-copy-person .Roster-week-td-name") + let set_active = el.classList.contains("active") + if (EDITABLE_TABLES.indexOf("Roster-week-table-to") > -1 && !set_active) return + + let block_all_active = document.querySelectorAll("#Popup.roster-copy-person-table table.Roster-week-table-copy-person .active") + for (let i=0; i<block_all_active .length; i++) block_all_active[i].classList.remove("active") + if (set_active) { + el.classList.remove("active") + } else { + el.classList.add("active") + let block_ths = document.querySelectorAll("#Popup.roster-copy-person-table #Roster-week-table-from .Roster-week-th") + for (let i=0; i<block_ths .length; i++) toggleCopyPersonTableDayButton(block_ths[i]) + + } +} +toggleCopyPersonTableDayButton = (el) => { + if (EDITABLE_TABLES.indexOf("Roster-week-table-to") > -1 && !el.classList.contains("active")) return + let block_tds = document.querySelectorAll(`#Popup.roster-copy-person-table #Roster-week-table-from .Roster-week-td[day_id="${el.getAttribute("day_id")}"]`) + if (el.classList.contains("active")) { + for (let i=0; i< block_tds.length; i++) { + toggleCopyPersonTableButton(block_tds[i], false) + } + } else { + for (let i=0; i< block_tds.length; i++) { + toggleCopyPersonTableButton(block_tds[i], true) + } + } +} + + +toggleCopyPersonTitleButton = (person_id, day_id) => { + toggleName = () => { + if (person_id !== null) { + let block_from_person = document.querySelector(`#Roster-week-table-from .Roster-week-tr-${person_id} .Roster-week-td-name`) + let block_to_person = document.querySelector(`#Roster-week-table-to .Roster-week-tr-${person_id} .Roster-week-td-name`) + if (!block_from_person) return + if (!block_to_person) return + let blocks_from_tds_person = document.querySelectorAll(`#Roster-week-table-from tbody .Roster-week-tr-${person_id} .Roster-week-td:not(.free):not(.inactive)`) + let set_active = true + for (let i=0; i<blocks_from_tds_person.length; i++) { + let td_from = blocks_from_tds_person[i] + if (!td_from.classList.contains("active")) { + let day_id = td_from.getAttribute("day_id") + let person_id = td_from.getAttribute("person_id") + let block_to = document.querySelector(`#Roster-week-table-to .Roster-week-td[day_id="${day_id}"][person_id="${person_id}"]:not(.free):not(.inactive)`) + if ((block_to) && (!block_to.classList.contains("active"))) { + set_active = false + break + } + } + } + if (set_active) { + block_from_person.classList.add("active") + block_to_person.classList.add("active") + } else { + block_from_person.classList.remove("active") + block_to_person.classList.remove("active") + } + } + } + toggleDay = () => { + if (day_id !== null) { + let block_from_days = document.querySelector(`#Roster-week-table-from .Roster-week-th[day_id="${day_id}"]`) + let block_to_days = document.querySelector(`#Roster-week-table-to .Roster-week-th[day_id="${day_id}"]`) + let blocks_from_tds_days = document.querySelectorAll(`#Roster-week-table-from .Roster-week-td[day_id="${day_id}"]:not(.free):not(.inactive)`) + set_active = true + for (let i=0; i<blocks_from_tds_days.length; i++) { + let td = blocks_from_tds_days[i] + if (!td.classList.contains("active")) { + let day_id = td.getAttribute("day_id") + let person_id = td.getAttribute("person_id") + let block_to = document.querySelector(`#Roster-week-table-to .Roster-week-td[day_id="${day_id}"][person_id="${person_id}"]:not(.free):not(.inactive)`) + if ((block_to) && (!block_to.classList.contains("active"))) { + set_active = false + break + } + } + } + if (set_active) { + block_from_days.classList.add("active") + block_to_days.classList.add("active") + } else { + block_from_days.classList.remove("active") + block_to_days.classList.remove("active") + } + } + } + toggleName() + toggleDay() +} + +reloadCopyPersonSelects = (year_week_from, year_week_to) => { + let block_select_from = document.querySelector(".roster-copy-person-table .item-table-from .select-roster") + let block_select_to = document.querySelector(".roster-copy-person-table .item-table-to .select-roster") + if (typeof year_week_from === "undefined") { year_week_from = block_select_from.value } + if (typeof year_week_to === "undefined") { year_week_to = block_select_to.value } + + let options_from = [] + let options_to = [] + + loadOption = (block_select, rosters, year_week) => { + block_select.innerHTML = "" + rosters.forEach((r, r_id) => { + let block_roster_option = document.createElement("option") + if (year_week === r) {block_roster_option.defaultSelected = true} + block_roster_option.innerHTML = r + block_roster_option.setAttribute("value", r) + block_select.appendChild(block_roster_option) + }) + } + let rosters_from = [...ROSTERS_YEARWEEK] + loadOption(block_select_from, rosters_from, year_week_from) + let rosters_to = [...ROSTERS_YEARWEEK] + rosters_to = [ getYearWeekNewestAfterWeek(), getYearWeekNewestAfter(), ...rosters_to ] + loadOption(block_select_to, rosters_to, year_week_to) +} +reloadCopyPersonWeekData = async (year_week, table_id) => { + showLoading("reloadCopyPersonWeekData") + let el = document.querySelector(`#${table_id}`) + let block = el.parentNode + let block_tds_inactive = el.querySelectorAll(".inactive") + let shift_check = false + + DATA_LAST_CREATED = undefined + block.removeChild(el) + return createBlockRosterTableWeek(year_week, table_id).then(block_table => { + block_table.classList.add("Roster-week-table-copy-person") + block.appendChild(block_table) + renderCopyPersonPopupTitle() + reloadCopyPersonSelects() + let remove_classes = [...document.querySelectorAll(".Roster-week-table-copy-person td"), ...document.querySelectorAll(".Roster-week-table-copy-person th")] + for (i=0; i<remove_classes.length;i++) { + remove_classes[i].classList.remove("active", "inactive", "hover") + } + hideLoading("reloadCopyPersonWeekData") + return + }) +} +hoverCopyPersonTdOver = (e) => { + hoverCopyPersonTd(e, "over") +} +hoverCopyPersonTdOut = (e) => { + hoverCopyPersonTd(e, "out") +} +hoverCopyPersonTd = (e, in_out) => { + let block_td = e.target.closest("td") + if (block_td === null) {block_td = e.target.closest("th")} + if (block_td === null) {return} + let name + let day_id = block_td.getAttribute("day_id") + let person_id = block_td.getAttribute("person_id") + if (day_id === null) { name = `Roster-week-td-name[person_id="${person_id}"]` } + else if (person_id === null) { name = `Roster-week-th[day_id="${day_id}"]` } + else if (day_id !== null && person_id !== null){ name = `Roster-week-td-name-${person_id}-day-${day_id}` } + else if (block_td.classList.contains("Roster-week-th-name")) {name = "Roster-week-th-name"} + else return + let block_tds = document.querySelectorAll(`#Popup.roster-copy-person-table .Roster-week-table-copy-person .${name}`) + if (in_out === "over") { + for (let i=0; i<block_tds.length; i++) {block_tds[i].classList.add("hover")} + } else if (in_out === "out") { + for (let i=0; i<block_tds.length; i++) {block_tds[i].classList.remove("hover")} + } + +} +loadCopyPersonWeekData = (year_week, table_id) => { + let block_table_from = document.querySelector(`#${table_id}`) + let blocks_set_onclick = block_table_from.querySelectorAll(".Roster-week-td") + for (let i = 0; i<blocks_set_onclick.length; i++ ) { + blocks_set_onclick[i].setAttribute("onClick", "toggleCopyPersonTableButton(this)") + blocks_set_onclick[i].addEventListener('mouseover', hoverCopyPersonTdOver); + blocks_set_onclick[i].addEventListener('mouseout', hoverCopyPersonTdOut); + } + + let blocks_set_onclick_name = block_table_from.querySelectorAll(".Roster-week-td-name") + for (let i = 0; i<blocks_set_onclick_name.length; i++ ) { + blocks_set_onclick_name[i].setAttribute("onClick", "toggleCopyPersonTableNameButton(this)") + blocks_set_onclick_name[i].addEventListener('mouseover', hoverCopyPersonTdOver); + blocks_set_onclick_name[i].addEventListener('mouseout', hoverCopyPersonTdOut); + } + let blocks_set_onclick_ths = block_table_from.querySelectorAll(".Roster-week-th") + for (let i = 0; i<blocks_set_onclick_ths.length; i++ ) { + blocks_set_onclick_ths[i].setAttribute("onClick", "toggleCopyPersonTableDayButton(this)") + blocks_set_onclick_ths[i].addEventListener('mouseover', hoverCopyPersonTdOver); + blocks_set_onclick_ths[i].addEventListener('mouseout', hoverCopyPersonTdOut); + } + let block_set_onclick_th_name = block_table_from.querySelector(".Roster-week-th-name") + block_set_onclick_th_name.setAttribute("onClick", "toggleCopyPersonTableDayNameButton(this)") + block_set_onclick_th_name.addEventListener('mouseover', hoverCopyPersonTdOver); + block_set_onclick_th_name.addEventListener('mouseout', hoverCopyPersonTdOut); +} +changeCopyPersonDate = (from_to, direction) => { + showLoading("changeCopyPersonDate") + let year_week_is = document.querySelector(`#Popup.roster-copy-person-table .item-table-${from_to} .select-roster`).value + let year_week + let year_week_from + let year_week_to + if (from_to === "from") { + let year_weeks_all = [...ROSTERS_YEARWEEK] + if (direction === "prev") { + year_week = year_weeks_all[year_weeks_all.indexOf(year_week_is)+1] + if (typeof year_week === "undefined") {year_week = year_weeks_all[0]} + } else if (direction === "next") { + year_week = year_weeks_all[year_weeks_all.indexOf(year_week_is)-1] + if (typeof year_week === "undefined") {year_week = year_weeks_all[year_weeks_all.length-1]} + } else { + year_week = direction + } + year_week_from = year_week + } else if (from_to === "to") { + if (direction === "prev") { + year_week = getDateToRosterDate(new Date(new Date(getDateOfISOWeek(year_week_is)).getTime() - 7 * 24 * 60 * 60 * 1000))[0] + if (year_week < DATE_YEAR_WEEK_OLDEST) { + hideLoading("changeCopyPersonDate") + return + } + } else if (direction === "next") { + year_week = getDateToRosterDate(new Date(new Date(getDateOfISOWeek(year_week_is)).getTime() + 7 * 24 * 60 * 60 * 1000))[0] + } else { + year_week = direction + } + year_week_to = year_week + } + getCopyPersonValues(year_week_from, year_week_to).then(() => { + reloadCopyPersonWeekData(year_week, `Roster-week-table-${from_to}`).then(() => { + reloadCopyPersonSelects(year_week_from, year_week_to) + renderCopyPersonPopupTitle() + if (from_to === "from") { + loadCopyPersonWeekData(year_week_from, `Roster-week-table-${from_to}`) + } else { + loadCopyPersonWeekData(year_week_to, `Roster-week-table-${from_to}`) + } + hideLoading("changeCopyPersonDate") + }) + }) +} +getCopyPersonValues = async (year_week_from, year_week_to) => { + showLoading("getCopyPersonValues") + getIfTo = () => { + if (typeof year_week_to !== "undefined") { + callback = () => { + DATE_YEAR_WEEK_TABLE_TO = year_week_to + if (DATE_YEAR_WEEK_TABLE_TO === DATE_YEAR_WEEK) { + PERSONS_TABLE_TO = PERSONS_WEEK + ROSTER_PERSON_INFOS_TABLE_TO = ROSTER_PERSON_INFOS + ROSTER_TABLE_TO = ROSTER + hideLoading("getCopyPersonValues") + return + } else if (DATE_YEAR_WEEK_TABLE_TO === DATE_YEAR_WEEK_TABLE_FROM ) { + PERSONS_TABLE_TO = PERSONS_TABLE_TO + ROSTER_PERSON_INFOS_TABLE_TO = ROSTER_PERSON_INFOS_TABLE_FROM + ROSTER_TABLE_TO = ROSTER_TABLE_FROM + hideLoading("getCopyPersonValues") + return + } else { + return getSortedPersonRosterWeek(1, year_week_to).then(pt => { + PERSONS_TABLE_TO = pt + return dbGet_roster_info_where_yearweek(year_week_to).then(rpi => { + ROSTER_PERSON_INFOS_TABLE_TO = rpi + return getDataRosterToRoster(year_week_to).then(rt => { + ROSTER_TABLE_TO = rt + hideLoading("getCopyPersonValues") + return + }) + }) + }) + } + } + if (ROSTERS_YEARWEEK.indexOf(year_week_to) === -1) { + let get_yw + if (ROSTERS_YEARWEEK[0] < year_week_to) { get_yw = ROSTERS_YEARWEEK[0]} + else if (ROSTERS_YEARWEEK[ROSTERS_YEARWEEK.length-1] > year_week_to) { get_yw = ROSTERS_YEARWEEK[ROSTERS_YEARWEEK.length-1]} + else { get_yw = ROSTERS_YEARWEEK.find(y => y < year_week_to)} + return dbGet_roster_where_yearweek(get_yw).then(roster_old => { + setR = (changes) => { + return dbSet_roster(year_week_to, roster_old.time_step, [roster_old.break_60, roster_old.break_90]).then(() => { + callA = () => { + return dbGet_rosters_yearweek().then(year_weeks => { + ROSTERS_YEARWEEK = year_weeks + DATE_YEAR_WEEK_NEWEST = ROSTERS_YEARWEEK[0] + DATE_YEAR_WEEK_OLDEST = ROSTERS_YEARWEEK[ROSTERS_YEARWEEK.length-1] + return callback() + }) + } + if (year_week_to < DATE_YEAR_WEEK_OLDEST) { + changes.forEach((c, ci) => dbSet_roster_change_where_yearweek_and_day(year_week_to, c.day_id, c.start, c.end, c.amount).then(() => { + if (ci === changes.length-1) { return callA() } + })) + } else { + return callA() + } + }) + } + if (year_week_to < DATE_YEAR_WEEK_OLDEST) { + return dbGet_roster_changes_where_yearweek(DATE_YEAR_WEEK_OLDEST).then(changes => { + return setR(changes) + }) + } else { + return setR() + } + }) + } else { + return callback() + } + } else { + hideLoading("getCopyPersonValues") + return + } + } + if (typeof year_week_from !== "undefined") { + DATE_YEAR_WEEK_TABLE_FROM = year_week_from + if (DATE_YEAR_WEEK_TABLE_FROM === DATE_YEAR_WEEK) { + PERSONS_TABLE_FROM = PERSONS_WEEK + ROSTER_PERSON_INFOS_TABLE_FROM = ROSTER_PERSON_INFOS + ROSTER_TABLE_FROM = ROSTER + return getIfTo() + } else if (DATE_YEAR_WEEK_TABLE_FROM === DATE_YEAR_WEEK_TABLE_TO ) { + PERSONS_TABLE_FROM = PERSONS_TABLE_TO + ROSTER_PERSON_INFOS_TABLE_FROM = ROSTER_PERSON_INFOS_TABLE_TO + ROSTER_TABLE_FROM = ROSTER_TABLE_TO + return getIfTo() + } else { + return getSortedPersonRosterWeek(1, year_week_from).then(pf => { + PERSONS_TABLE_FROM = pf + return dbGet_roster_info_where_yearweek(year_week_from).then(rpi => { + ROSTER_PERSON_INFOS_TABLE_FROM = rpi + return getDataRosterToRoster(year_week_from).then(rf => { + ROSTER_TABLE_FROM = rf + return getIfTo() + }) + }) + }) + } + } else { + return getIfTo() + } +} +openCopyPersonTablePopup = async (year_week_from, year_week_to) => { + showLoading("openCopyPersonTablePopup") + if (typeof year_week_to === "undefined") { year_week_to = DATE_YEAR_WEEK} + createB = async () => { + document.body.classList.add("noscroll") + let block = document.getElementById("Popup") + block.onclick = (e) => eventListenerClosePopup(e, "copypersonselect") + block.classList.add("roster-copy-person-table","active") + let block_container = document.getElementById("Popup-container") + + let block_close = document.createElement("button") + block_close.setAttribute("onClick", "closeCopyPersonPopupSelect()") + block_close.classList.add("button-x") + block_container.appendChild(block_close) + + let block_header = document.createElement("h2") + block_header.innerHTML = `Schichten übertragen` + block_container.appendChild(block_header) + let block_box = document.createElement("div") + block_box.classList.add("box") + + let block_box_rosters = document.createElement("div") + addDragToScroll(block_box_rosters) + block_box_rosters.classList.add("item" , "item-table", "item-table-from") + let rosters = [...ROSTERS_YEARWEEK] + let roster_from_id = rosters.indexOf(year_week_to)+1 + if (roster_from_id === rosters.length) {roster_from_id = 0} + let roster_date = structuredClone(rosters[roster_from_id]) + + let block_box_roster_header = document.createElement("div") + block_box_roster_header.classList.add("item-header") + let block_roster_select_label = document.createElement("label") + block_roster_select_label.classList.add("select-roster-label", "chevron-down", "chevron-select") + let block_roster_select = document.createElement("select") + block_roster_select.classList.add("select-roster") + block_roster_select.setAttribute("onchange", `changeCopyPersonDate("from", this.value)`) + rosters.forEach((r, r_id) => { + let block_roster_option = document.createElement("option") + if (roster_date === r) {block_roster_option.defaultSelected = true} + block_roster_option.innerHTML = r + block_roster_option.setAttribute("value", r) + block_roster_select.appendChild(block_roster_option) + }) + block_roster_select_label.appendChild(block_roster_select) + block_box_roster_header.appendChild(block_roster_select_label) + + let block_change_date = document.createElement("div") + block_change_date.classList.add("change-date") + let block_change_prev = document.createElement("button") + block_change_prev.setAttribute("onClick", `changeCopyPersonDate("from", "prev")`) + block_change_prev.setAttribute("title", `Vorherige Woche`) + block_change_prev.classList.add("chevron-left") + let block_change_next = document.createElement("button") + block_change_next.setAttribute("onClick", `changeCopyPersonDate("from", "next")`) + block_change_next.setAttribute("title", `Vorherige Woche`) + block_change_next.classList.add("chevron-right") + block_change_date.appendChild(block_change_prev) + block_change_date.appendChild(block_change_next) + block_box_roster_header.appendChild(block_change_date) + block_box_rosters.appendChild(block_box_roster_header) + + let block_table_from_container = document.createElement("div") + block_table_from_container .classList.add("container") + let block_table_from = await createBlockRosterTableWeek(roster_date, "Roster-week-table-from") + block_table_from.classList.add("Roster-week-table-copy-person") + block_table_from_container.appendChild(block_table_from) + + block_box_rosters.appendChild(block_table_from_container) + block_box.appendChild(block_box_rosters) + + let block_box_roster_to = document.createElement("div") + let block_save = document.createElement("button") + block_save.innerHTML = "Übertragen" + block_save.classList.add("button-save") + block_save.setAttribute("onClick", "transferCopyPersonTable()") + block_box_roster_to .appendChild(block_save) + let block_roster_to_container = document.createElement("div") + block_roster_to_container.classList.add("container") + addDragToScroll(block_roster_to_container ) + let block_box_to_roster_header = document.createElement("div") + block_box_to_roster_header.classList.add("item-header") + + let block_edit_shift_button = document.createElement("button") + block_edit_shift_button.innerHTML = "Tabelle bearbeiten" + block_edit_shift_button.setAttribute("title", "Hiermit kannst du in der Tabelle die Zeiten ändern.") + block_edit_shift_button.classList.add("edit-shift") + block_edit_shift_button.setAttribute("onClick", "this.classList.toggle('active'); toggleTableWeekEditeable('Roster-week-table-to')") + block_box_to_roster_header.appendChild(block_edit_shift_button) + let block_to_change_date = document.createElement("div") + block_to_change_date.classList.add("change-date") + let block_to_change_prev = document.createElement("button") + block_to_change_prev.setAttribute("onClick", `changeCopyPersonDate("to", "prev")`) + block_to_change_prev.setAttribute("title", `Vorherige Woche`) + block_to_change_prev.classList.add("chevron-left") + let block_to_change_next = document.createElement("button") + block_to_change_next.setAttribute("onClick", `changeCopyPersonDate("to", "next")`) + block_to_change_next.setAttribute("title", `Nächste Woche`) + block_to_change_next.classList.add("chevron-right") + block_to_change_date.appendChild(block_to_change_prev) + block_to_change_date.appendChild(block_to_change_next) + block_box_to_roster_header.appendChild(block_to_change_date) + + let rosters_to = [...ROSTERS_YEARWEEK] + rosters_to = [ getYearWeekNewestAfterWeek(), getYearWeekNewestAfter(), ...rosters_to ] + let block_roster_to_select_label = document.createElement("label") + block_roster_to_select_label.classList.add("select-roster-label", "chevron-down", "chevron-select") + let block_roster_to_select = document.createElement("select") + block_roster_to_select.classList.add("select-roster") + block_roster_to_select.setAttribute("onchange", `changeCopyPersonDate("to", this.value)`) + rosters_to.forEach((r, r_id) => { + let block_roster_to_option = document.createElement("option") + if (r === DATE_YEAR_WEEK) {block_roster_to_option.defaultSelected = true} + block_roster_to_option.innerHTML = r + block_roster_to_option.setAttribute("value", r) + block_roster_to_select.appendChild(block_roster_to_option) + }) + block_roster_to_select_label.appendChild(block_roster_to_select) + block_box_to_roster_header.appendChild(block_roster_to_select_label) + block_box_roster_to.appendChild(block_box_to_roster_header) + + block_box_roster_to.classList.add("item", "item-table", "item-table-to") + let block_table_to = await createBlockRosterTableWeek(DATE_YEAR_WEEK, "Roster-week-table-to") + block_table_to.classList.add("Roster-week-table-copy-person") + + block_roster_to_container.appendChild(block_table_to) + block_box_roster_to.appendChild(block_roster_to_container) + block_box.appendChild(block_box_roster_to) + + block_container.appendChild(block_box) + + } + getCopyPersonValues(year_week_from, year_week_to).then(() => { + createB().then(() => { + loadCopyPersonWeekData(year_week_from, "Roster-week-table-from") + loadCopyPersonWeekData(year_week_to, "Roster-week-table-to") + renderCopyPersonPopupTitle() + hideLoading("openCopyPersonTablePopup") + }) + }) +} +closeCopyPersonPopup = () => { + closePopup() +} +closeCopyPersonPopupSelect = () => { + if (EDITABLE_TABLES.indexOf("Roster-week-table-to") > -1) EDITABLE_TABLES.splice(EDITABLE_TABLES.indexOf("Roster-week-table-to")) + let year_week = document.querySelector("#Popup.roster-copy-person-table .item-table-to .select-roster").value + changeDate(getDateOfISOWeek(year_week)) + closePopup() +} +renderCopyPersonPopupTitle = () => { + let from_yw = DATE_YEAR_WEEK_TABLE_FROM + let to_yw = DATE_YEAR_WEEK_TABLE_TO + document.querySelector("#Popup.roster-copy-person-table #Popup-container > h2").innerHTML = `Schichten übertragen von <b>${from_yw}</bold> nach <bold>${to_yw}</bold>` +} diff --git a/js/database/.persons.js.swp b/js/database/.persons.js.swp new file mode 100644 index 0000000..c188906 Binary files /dev/null and b/js/database/.persons.js.swp differ diff --git a/js/database/account-institution-admin.js b/js/database/account-institution-admin.js new file mode 100644 index 0000000..e9f086e --- /dev/null +++ b/js/database/account-institution-admin.js @@ -0,0 +1,9 @@ +dbGet_users = async () => { + let response = await fetch("/api/account/getAllDefaultData.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} diff --git a/js/database/account.js b/js/database/account.js new file mode 100644 index 0000000..bbe308d --- /dev/null +++ b/js/database/account.js @@ -0,0 +1,9 @@ +dbGet_users = async () => { + let response = await fetch("/api/account/getAll.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} diff --git a/js/database/closingtime.js b/js/database/closingtime.js new file mode 100644 index 0000000..ec67f23 --- /dev/null +++ b/js/database/closingtime.js @@ -0,0 +1,135 @@ +dbAdd_closingtime = async (name, start, end, person_ids, lawful) => { + let clos = {name: name, start: start, end: end, lawful: lawful ? 1 : 0, persons: person_ids} + let response = await fetch("/api/closingtimes/add.php", { + method: "POST", + body: JSON.stringify(clos), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() + /*.then(response => {return response.json.then(id => { + if (person_ids.length === 0) {return} + for (let i=0; i<person_ids.length; i++) { + let pid = person_ids[i] + let per = {closingtime_id: id, person_id: pid} + fetch("/api/closingtime_persons/add.php", { + method: "POST", + body: JSON.stringify(per), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }).then(ppid => { + if (person_ids.length-1 === i) { + return ppid + } + }) + } + })})*/ +} +dbGet_closingtime_persons = async (closingtime_id) => { + let data = {closingtime_id: closingtime_id} + let response = await fetch("/api/closingtime_persons/get.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + let persons = await response.json() + return persons.persons +} +dbGet_closingtime_persons_where_person = async (person_id) => { + let response = await fetch("/api/closingtime_persons/getWherePerson.php", { + method: "POST", + body: JSON.stringify({person_id: person_id}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + let closingtimes = await response.json() + return closingtimes +} +dbGet_closingtimes = async () => { + let response = await fetch("/api/closingtimes/getAll.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return response.json() +} +dbGet_closingtime = async (id) => { + let response = await fetch("/api/closingtimes/get.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return response.json() +} +//dbGet_closingtime = (id) => {return CLOSINGTIMES.find(x => x.id === id)} +dbGet_closingtimes_lawful = () => {return CLOSINGTIMES.filter(x => x.lawful === 1)} +/*dbGet_closingtime = async (id) => { + let data = {id: id} + let response = await fetch("/api/closingtimes/get.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + let closingtimes = await response.json() + return closingtimes +}*/ +/*dbGet_closingtimes_lawful = async () => { + let response = await fetch("/api/closingtimes/getLawful.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + let closingtimes = await response.json() + return closingtimes.closingtimes +}*/ +dbGet_closingtime_person_during_date = (person_id, check_date) => {return CLOSINGTIMES.find(x => x.persons.map(p => p.person_id).indexOf(person_id) > -1 && x.start <= check_date && x.end >= check_date)} +dbAdd_closingtime_person = async (c_id, p_id) => { + let data = {closingtime_id: c_id, person_id: p_id} + fetch("/api/closingtime_persons/add.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} +dbRemove_closingtime = async (id) => { + let response = await fetch("/api/closingtimes/remove.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbRemove_closingtime_person = async (closingtime_id, person_id) => { + let data = {closingtime_id: closingtime_id, person_id: person_id} + fetch("/api/closingtime_persons/remove.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} +dbRemove_closingtime_all_persons = async(closingtime_id) => { + let data = {closingtime_id: closingtime_id} + let response = await fetch("/api/closingtime_persons/removeAll.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} diff --git a/js/database/data-to-database.js b/js/database/data-to-database.js new file mode 100644 index 0000000..97b7cdf --- /dev/null +++ b/js/database/data-to-database.js @@ -0,0 +1,117 @@ + +dataToDatabaseCallPeople = async (data) => { + let labels = await dbGet_shift_labels() + let departments = await dbGet_departments() + callP = (p, p_id) => { + // fix closingtime person ids + data.x.forEach(x => { + let xid = x.p.indexOf(p.id) + x.p[xid] = p_id + }) + data.a.forEach(a => { + if (a.d >= p.a) { + dbSet_person_hours(p_id, a.d) + } + let pos = a.o.filter(o => o[0] === p.id) + //pos.forEach(o => dbAdd_person_overtime(p_id, a.d, o[1])) + if (a.i) { + let pis = a.i.filter(i => i.p === p.id) + pis?.forEach(i => dbSet_roster_info_where_yearweek_and_day_and_person(a.d, i.d, p_id, i.t)) + } + a.s.forEach((s, sid) => { + let psds = s.filter(sd => sd.p === p.id) + let breaks + let hours = s.e+a.t-s.a + psds?.forEach(s => dbAdd_shift(a.d, sid, p_id, s.s, s.e+a.t)) + }) + let ecrs = a.ecr?.filter(r => r.k === p.id.toString()) + ecrs?.forEach(d => dbSet_roster_editable_cells_right_where_key(a.d, p_id.toString(), d.v)) + }) + let pcs = data.pc.filter(c => c.p === p.id) + dbAdd_person_change_where_yearweek_and_day_and_person_and_key(p.a, 999, p_id, "n", p.n) + dbAdd_person_change_where_yearweek_and_day_and_person_and_key(p.a, 999, p_id, "d", p.d.toString()) + dbAdd_person_change_where_yearweek_and_day_and_person_and_key(p.a, 999, p_id, "h", p.h) + pcs.forEach(c => { + let c_v + if (c.k === "sl") { + c_v = labels.find(ll => ll.name === DATA.l.find(l => l.id === c.v)?.n)?.id?.toString() || c.v.toString() + } else if (c.k === "d") { + c_v = departments.find(dd => dd.name === DATA.d.find(l => l.id === c.v)?.v)?.id?.toString() || c.v.toString() + } else if (c.k === "n") { + c_v = p.n + } else { + c_v = c.v.toString() + } + dbAdd_person_change_where_yearweek_and_day_and_person_and_key(c.d, typeof c.t === "undefined" ? 999 : c.t, p_id, c.k, c_v) + }) + p.i.forEach(i => dbAdd_person_illnes(p_id, i[0], i[1])) + p.v.forEach(v => dbAdd_person_vacation(p_id, v[0], v[1])) + p.b.forEach(b => dbAdd_person_betterment(p_id, b[0], b[1], b[2])) + if (p.o) p.o.forEach(o => dbAdd_person_overtime_manual(o[0].length === 6 ? (o[0].substring(0,5)+"0"+o[0].substring(5)) : o[0], p_id, o[1])) + + } + for (let i=0; i<data.p.length; i++) { + let p = data.p[i] + p.n = `person_${i+1}` + p.d = departments.find(dd => dd.name === DATA.d.find(l => l.id === p.d)?.v)?.id + dbAdd_person({name: p.n, activated: p.a, department: p.d, hours: p.h, mpa: [...p.m]}).then(p_id => { + p.newid = p_id + DATA.p.find(dp => dp.id === p.id).newid = p_id + callP(p, p_id) + data.x.forEach(x => { + x.p.indexOf(p.id > -1) && + dbAdd_closingtime_person(x.id, p_id) + }) + }) + } +} +dataToDatabase = (data) => { + fetch("/api/institution/addClean.php", { + method: "POST", + body: JSON.stringify({name: "Test_1", yearweek: "2023-05"}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + dbAdd_settings(data.v, data.so, data.secr, data.sert, data.serb, data.sd, data.sw, data.m, data.z, 100, 100) + data.n.forEach(label => dbAdd_settings_label(label.id, label.t, label.a) ) + data.d.sort((a, b) => a.id - b.id).forEach(dep => dbAdd_department(dep.v)) + data.l.forEach(l => dbAdd_shift_label(l.n, l.c)) + data.rc.forEach(c=> dbSet_roster_change_where_yearweek_and_day(c.d, c.k, c.s, c.e, c.a.toString())) + data.a.forEach(a => a.ecr?.forEach(d => {d.k === "i" && dbSet_roster_editable_cells_right_where_key(a.d, d.k, d.v)}) ) + data.a.forEach(a => dbSet_roster(a.d, a.t, a.b) ) + data.a.forEach((a) => a.ert?.forEach(d => dbSet_roster_editable_rows_top_where_key(a.d, d.k, d.v)) ) + data.a.forEach((a) => a.erb?.forEach(d => dbSet_roster_editable_rows_bottom_where_key(a.d, d.k, d.v)) ) + data.x.forEach((x, xi) => { + dbAdd_closingtime(x.t, x.s, x.e, [], x.x).then((cl_id) => { + x.id = cl_id + if (xi === data.x.length-1) { + dataToDatabaseCallPeople(data).then((person_ids) => { + DATA.p.forEach(p => { + data.a.forEach(a => { + if (a.d >= p.a) { + dbSet_person_hours(p.newid, a.d) + } + }) + }) + }) + } + }) + }) +} + +dataResetAllOvertime = () => { + DATA.p.forEach(p => { + DATA.a.forEach(a => { + if (a.d >= p.a) { + dbSet_person_hours(p.newid, a.d) + } + }) + }) +} + +/* +fetch('./dienstplan-example') + .then((response) => response.json()) + .then((json) => {DATA = json.DATA; console.log(DATA)}); + */ diff --git a/js/database/database.js b/js/database/database.js new file mode 100644 index 0000000..20c0da4 --- /dev/null +++ b/js/database/database.js @@ -0,0 +1,44 @@ + +dbCreate_database = () => { DATA = {} } +dbCreate_database_default = () => { + dbCreate_settings_version() + dbSet_settings_version(VERSION_DEFAULT) + + dbCreate_settings_label() + dbAdd_settings_label(0, 'mpA', 'MPA') + dbAdd_settings_label(1, 'Krank', 'Krank') + dbAdd_settings_label(2, 'Weiterbildung', 'W') + dbAdd_settings_label(3, 'Urlaub', 'Urlaub') + dbCreate_shift_label() + dbAdd_shift_label("Frei", "Frei") + dbAdd_shift_label("Schule", "S") + dbCreate_settings_label_text = (id) => { DATA.n[id].t } + + dbCreat_settings_departments() + dbAdd_settings_department("") + dbAdd_settings_department("Elementar") + dbAdd_settings_department("Kleinkind") + + dbCreate_settings_sort_days() + dbAdd_settings_sort_days("n-d") + dbCreate_settings_sort_weeks() + dbAdd_settings_sort_weeks("n-d") + + dbCreate_settings_overtime_default() + dbCreate_settings_edit_cell_default() + dbCreate_settings_edit_row_top_default() + dbCreate_settings_edit_row_bottom_default() + + dbCreate_settings_printmode() + + dbCreate_settings_zoom_print_h() + dbCreate_settings_zoom_print_v() + dbCreate_settings_zoom_web() + + dbCreate_closingtimes() + + dbCreate_persons() + dbCreate_person_changes() + dbCreate_rosters() + dbCreate_roster_changes() +} diff --git a/js/database/departments.js b/js/database/departments.js new file mode 100644 index 0000000..b1651d9 --- /dev/null +++ b/js/database/departments.js @@ -0,0 +1,39 @@ +dbAdd_department = async (name) => { + let response = await fetch("/api/departments/add.php", { + method: "POST", + body: JSON.stringify({name: name}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbGet_departments = async () => { + return await fetch("/api/departments/get.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + .then((response) => {return response.json()}) + .then((data) => { return data.departments}) +} +dbGet_department_where_id = (id) => {return DEPARTMENTS.find(d => d.id === id).name} +dbSet_department = async (id, value) => { + let response = await fetch("/api/departments/update.php", { + method: "POST", + body: JSON.stringify({id: id, name: value}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbRemove_department = async (id) => { + let response = await fetch("/api/departments/remove.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} diff --git a/js/database/institutions.js b/js/database/institutions.js new file mode 100644 index 0000000..66a747c --- /dev/null +++ b/js/database/institutions.js @@ -0,0 +1,53 @@ +dbAdd_institution = async (name, yearweek) => { + let response = await fetch("/api/institution/add.php", { + method: "POST", + body: JSON.stringify({name: name, yearweek: yearweek}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbGet_institution = async (id) => { + let response = await fetch("/api/institution/get.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbGet_institutions = async () => { + let response = await fetch("/api/institution/getAll.php", { + method: "POST", + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSwitch_institution = async (id) => { + let response = await fetch("/api/institution/switch.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSwitchAs_institution = async (id, as) => { + let response = await fetch("/api/institution/switchAs.php", { + method: "POST", + body: JSON.stringify({id: id, as: as}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_institution = async (data_id, password) => { + let response = await fetch("/api/institution/remove.php", { + method: "POST", + body: JSON.stringify({data_id: data_id, password: password}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} diff --git a/js/database/list.sh b/js/database/list.sh new file mode 100644 index 0000000..b40a907 --- /dev/null +++ b/js/database/list.sh @@ -0,0 +1,4 @@ +function="$1" +echo "$function" +[[ "$function" = "" ]] && function="dbGet" +sed -n "s/^${function}_\(.*\) = (\(.*\)) *=> .*$/${function}_\1(\2);/p" ./* | sed "s/ *//g" diff --git a/js/database/person_changes.js b/js/database/person_changes.js new file mode 100644 index 0000000..e79d9f3 --- /dev/null +++ b/js/database/person_changes.js @@ -0,0 +1,126 @@ +dbAdd_person_change_where_yearweek_and_person_and_key = (year_week, id, key, value) => { + fetch("/api/person_changes/add.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, day_id: 999, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} +dbAdd_person_change_where_yearweek_and_day_and_person_and_key = async (year_week, day_id, id, key, value) => { + let response = await fetch("/api/person_changes/add.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, day_id: day_id, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + +dbGet_person_changes = async () => { + let response = await fetch("/api/person_changes/get.php", { + method: "POST", + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let changes = await response.json() + return changes.person_changes +} +dbGet_person_changes_where_key = async (id, key) => { + let response = await fetch("/api/person_changes/getWhereKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, change_key: key}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let changes = await response.json() + return changes.person_changes +} +dbGet_person_changes_where_key_and_value = async (key, value) => { + let response = await fetch("/api/person_changes/getWhereKeyValue.php", { + method: "POST", + body: JSON.stringify({change_key: key, value: value }), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let changes = await response.json() + return changes.person_changes +} +dbGet_person_changes_where_yearweek_and_person_and_key = async (year_week, id, key) => { + let response = await fetch("/api/person_changes/getWhereYearweekKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, change_key: key }), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let changes = await response.json() + return changes.person_changes +} +dbGet_person_change_where_yearweek_and_day_and_person_and_key = async (year_week, day_id, id, key) => { + let response = await fetch("/api/person_changes/getWhereYearweekDayKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, day_id: day_id, change_key: key }), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let changes = await response.json() + return changes.person_changes +} + +dbSet_person_changes_where_person_and_key = async (id, key, value) => { + let response = await fetch("/api/person_changes/updateWhereKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_change_where_yearweek_and_person_and_key = async (year_week, id, key, value) => { + let response = await fetch("/api/person_changes/updateWhereYearweekKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_changes_where_day_and_person_and_key = async (day_id, id, key, value) => { + let response = await fetch("/api/person_changes/updateWhereDayKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, day_id: day_id, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_change_where_yearweek_day_and_person_and_key = async (year_week, day_id, person_id, key, value) => { + let response = await fetch("/api/person_changes/updateWhereYearweekDayKey.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: year_week, day_id: day_id, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_changes_where_yearweek_is_ge_and_person_and_key = async (year_week, id, key, value) => { + let response = await fetch("/api/person_changes/updateWhereYearweekGeKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_changes_where_yearweek_is_ge_and_day_and_person_and_key = async (year_week, day_id, id, key, value) => { + let response = await fetch("/api/person_changes/updateWhereYearweekGeDayKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, day_id: day_id, change_key: key, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + + +dbRemove_person_changes_where_person_and_key = async (id, key) => { + let response = await fetch("/api/person_changes/removeWhereKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, change_key: key}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_person_change_where_yearweek_and_day_and_person_and_key = (year_week, day_id, id, key) => { + fetch("/api/person_changes/removeWhereYearweekDayKey.php", { + method: "POST", + body: JSON.stringify({person_id: id, yearweek: year_week, day_id: day_id, change_key: key}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} diff --git a/js/database/persons.js b/js/database/persons.js new file mode 100644 index 0000000..1a41f2c --- /dev/null +++ b/js/database/persons.js @@ -0,0 +1,272 @@ +// [{}] +dbAdd_person = async (person) => { + let person_is = {name: person.name, activated: person.activated, department: person.department, hours: person.hours, mpa: person.mpa.toString()} + let response = await fetch("/api/persons/add.php", { + method: "POST", + body: JSON.stringify(person_is), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person_id = await response.json() + return person_id +} +dbGet_persons = async () => { + let response = await fetch("/api/persons/getAll.php", { + method: "POST", + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let persons = await response.json() + return persons.persons +} +// [id: int, a: string, n: string, h: decimal, d: int, m: [int], c: [{d: string, k: string, v: [{d: int, v|a|l|f: boolean}]}], b: [str]} +dbGet_person = async (id) => { + let response = await fetch("/api/persons/get.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_where = async (id, name, value) => { + let response = await fetch("/api/persons/updateWhere.php", { + method: "POST", + body: JSON.stringify({id: id, name: name, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_person = async (id) => { + let response = await fetch("/api/persons/remove.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + +dbSet_person_hours = async (person_id, yearweek) => { + let response = await fetch("/api/person_hours/update.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + +dbAdd_person_illnes = async (person_id, start, end) => { + let response = await fetch("/api/person_illnes/add.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, start: start, end: end}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_illnes = async (id, person_id, start, end) => { + let response = await fetch("/api/person_illnes/add.php", { + method: "POST", + body: JSON.stringify({id: id, person_id: person_id, start: start, end: end}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_person_illnesses = async (person_id) => { + /*let response = await fetch("/api/person_illnes/get.php", { + method: "POST", + body: JSON.stringify({person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person_illnes = await response.json() + return person_illnes?.person_illnes */ + return PERSONS.find(p => p.id === person_id).illnesses +} +dbRemove_person_illnes = async (id, person_id) => { + let response = await fetch("/api/person_illnes/remove.php", { + method: "POST", + body: JSON.stringify({id: id, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbAdd_person_vacation = async (person_id, start, end) => { + let response = await fetch("/api/person_vacations/add.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, start: start, end: end}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_person_vacation = async (person_id, id, start, end) => { + let response = await fetch("/api/person_vacations/update.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, id: id, start: start, end: end}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_person_vacations = async (person_id) => { + /*let response = await fetch("/api/person_vacations/get.php", { + method: "POST", + body: JSON.stringify({person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person_vacations = await response.json() + return person_vacations?.person_vacations*/ + return PERSONS.find(p => p.id === person_id).vacations +} +dbRemove_person_vacation = async (id, person_id) => { + let response = await fetch("/api/person_vacations/remove.php", { + method: "POST", + body: JSON.stringify({id: id, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + +dbAdd_person_betterment = async (person_id, start, end, hours) => { + let response = await fetch("/api/person_betterments/add.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, start: start, end: end, hours: hours}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_person_betterments = async (person_id) => { + /*let response = await fetch("/api/person_betterments/get.php", { + method: "POST", + body: JSON.stringify({person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person_betterments = await response.json() + return person_betterments?.person_betterments + */ + return PERSONS.find(p => p.id === person_id).betterments +} +dbGet_person_betterments_where_date = async (person_id, date) => { + /* + let response = await fetch("/api/person_betterments/getWhereDate.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, date: date}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person_betterment = await response.json() + */ + return PERSONS.find(p => p.id === person_id).betterments?.find(b => b.start <= date && b.end >= date) +} +dbRemove_person_betterment = async (id, person_id) => { + let response = await fetch("/api/person_betterments/remove.php", { + method: "POST", + body: JSON.stringify({id: id, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + +dbGet_person_overtimes_yearweeks = async (person_id) => { + let response = await fetch("/api/person_hours/getAll.php", { + method: "POST", + body: JSON.stringify({person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person_overtime = await response.json() + return person_overtime +} + +dbAdd_person_overtime_manual = async (yearweek, person_id, overtime) => { + let response = await fetch("/api/person_overtimes_manual/add.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: yearweek, overtime: overtime ? overtime : 0}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_person_overtime_manual_where_yearweek = async (yearweek, person_id) => { + let response = await fetch("/api/person_overtimes_manual/getWhereYearweek.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_person_overtimes_manual_where_yearweek_le = async (yearweek, person_id) => { + let response = await fetch("/api/person_overtimes_manual/getWhereYearweekLe.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person_overtime = await response.json() + return person_overtime.person_overtimes_manual +} +dbSet_person_overtime_manual_where_yearweek = async (yearweek, person_id, overtime) => { + overtime = overtime ? overtime : 0 + let response = await fetch("/api/person_overtimes_manual/update.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: yearweek, overtime: overtime}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_person_overtime_manual_where_yearweek = async (yearweek, person_id) => { + let response = await fetch("/api/person_overtimes_manual/remove.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_person_overtime_manual_where_yearweek_lt = async (person_id, yearweek) =>{ + let response = await fetch("/api/person_overtimes_manual/removeWhereYearweekLt.php", { + method: "POST", + body: JSON.stringify({person_id: person_id, yearweek: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + + + + +dbGet_persons_active_where_yearweek = async (yearweek) => { + let response = await fetch("/api/persons_active/getAllActive.php", { + method: "POST", + body: JSON.stringify({yearweek: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let persons = await response.json() + return persons.persons +} +dbGet_person_active = async (yearweek, person_id) => { + let response = await fetch("/api/persons_active/getActive.php", { + method: "POST", + body: JSON.stringify({yearweek: yearweek, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let persons = await response.json() + return persons +} +dbSet_person_person_activated = async (person_id, yearweek) => { + let response = await fetch("/api/persons/updateWhere.php", { + method: "POST", + body: JSON.stringify({id: person_id, name: "activated", value: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_person_removed = async (yearweek, person_id) => { + let response = await fetch("/api/persons_active/getRemoved.php", { + method: "POST", + body: JSON.stringify({yearweek: yearweek, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_persons_removed = async (yearweek) => { + let response = await fetch("/api/persons_active/getAllRemoved.php", { + method: "POST", + body: JSON.stringify({yearweek: yearweek}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + + +dbSet_persons_departments_where_id = (department_id, value) => + {PERSONS_ALL.forEach(p => {p.d === department_id && (p.d = value)})} diff --git a/js/database/roster-changes.js b/js/database/roster-changes.js new file mode 100644 index 0000000..199b400 --- /dev/null +++ b/js/database/roster-changes.js @@ -0,0 +1,51 @@ + +dbSet_roster_change_where_yearweek_and_day = async (year_week, day_id, start, end, amount) => { + let response = await fetch("/api/roster_changes/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, start: start, end: end, amount: amount.toString()}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_roster_changes_where_yearweek = async (year_week) => { + let response = await fetch("/api/roster_changes/getWhereYearweek.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let data = await response.json() + let rc = data?.roster_changes + return rc +} +dbGet_roster_change_where_yearweek_and_day = async (year_week, day_id) => { + let response = await fetch("/api/roster_changes/getWhereYearweekDay.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let data = await response.json() + let c = data?.roster_changes + c.start = parseFloat(c.start) + c.end = parseFloat(c.end) + c.amount = parseFloat(c.amount.split(",").map(Number)) + return c +} +dbGet_roster_change_where_yearweek_le_and_day = async (year_week, day_id) => { + let response = await fetch("/api/roster_changes/getWhereYearweekLeDay.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let c = await response.json() + c.start = parseFloat(c.start) + c.end = parseFloat(c.end) + return c +} + +dbRemove_roster_changes_where_yeaweek = (year_week) => { + fetch("/api/roster_changes/remove.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} diff --git a/js/database/roster.js b/js/database/roster.js new file mode 100644 index 0000000..00cde72 --- /dev/null +++ b/js/database/roster.js @@ -0,0 +1,195 @@ + +dbSet_roster = async (year_week, time_step, breaks) => { + let days = DAYS.toString() + let response = await fetch("/api/roster/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, time_step: time_step, break_60: breaks[0], break_90: breaks[1], days: days}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbGet_roster_where_yearweek = async (year_week) => { + let response = await fetch("/api/roster/get.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let rosters = await response.json() + return rosters +} +dbGet_rosters_yearweek = async () => { + let response = await fetch("/api/roster/getYearweeks.php", { + method: "POST", + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let rosters = await response.json() + return rosters.map(r => r.yearweek).sort((a,b) => b.localeCompare(a)) +} + +dbRemove_roster_where_yearweek = (year_week) => { + fetch("/api/roster/remove.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} + +dbGet_roster_active = async (year_week) => { + let response = await fetch("/api/roster_active/get.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let rosters = await response.json() + return rosters +} + +dbGet_roster_editable_cells_right = async (year_week) => { + let response = await fetch("/api/roster_editable_cell_right/get.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let data = await response.json() + return data.roster_editable_cell_right +} +dbGet_roster_editable_cell_right_where_key = (year_week, key) => + {return EDITABLE_CELLS_RIGHT?.find(e => e.id === key.toString())?.text} +dbSet_roster_editable_cells_right_where_key = (year_week, id, text) => { + fetch("/api/roster_editable_cell_right/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, id: id, text: text}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} +dbRemove_roster_editable_cells_right = (year_week) => { + fetch("/api/roster_editable_cell_right/remove.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} + +dbGet_roster_editable_rows_bottom = async (year_week) => { + let response = await fetch("/api/roster_editable_row_bottom/get.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let data = await response.json() + return data.roster_editable_row_bottom +} +dbGet_roster_editable_rows_bottom_where_key = (year_week, key) => + {return EDITABLE_ROWS_BOTTOM?.find(e => e.id === key.toString())?.text} +dbSet_roster_editable_rows_bottom_where_key = (year_week, id, text) => { + fetch("/api/roster_editable_row_bottom/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, id: id, text: text}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} +dbRemove_roster_editable_rows_bottom = (year_week) => { + fetch("/api/roster_editable_row_bottom/remove.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} + +dbGet_roster_editable_rows_top = async (year_week) => { + let response = await fetch("/api/roster_editable_row_top/get.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let data = await response.json() + return data.roster_editable_row_top +} +dbGet_roster_editable_rows_top_where_key = (year_week, key) => + {return EDITABLE_ROWS_TOP?.find(e => e.id === key.toString())?.text} +dbSet_roster_editable_rows_top_where_key = (year_week, id, text) => { + fetch("/api/roster_editable_row_top/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, id: id, text: text}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} +dbRemove_roster_editable_rows_top = (year_week) => { + fetch("/api/roster_editable_row_top/remove.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} + +dbGet_roster_info_where_yearweek = async (year_week) => { + let response = await fetch("/api/roster_person_info/getAll.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let data = await response.json() + return data?.infos +} +dbGet_roster_info_where_yearweek_and_day_and_person = async (year_week, day_id, id) => { + let response = await fetch("/api/roster_person_info/get.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, id: id.toString()}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let data = await response.json() + return data?.text +} +dbSet_roster_info_where_yearweek_and_day_and_person = (year_week, day_id, id, text) => { + fetch("/api/roster_person_info/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, id: id.toString(), text: text}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} +dbRemove_roster_info_where_yearweek_and_day_and_person = async (year_week, day_id, id) => { + console.log(year_week, day_id, id) + let response = await fetch("/api/roster_person_info/remove.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, id: id.toString()}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + +dbSet_roster_shiftbreak_60 = async (year_week, value) => { + let days = DAYS.toString() + let time_step = TIME_STEP + let break_60 = value + let break_90 = DAYBREAK_2 + let response = await fetch("/api/roster/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, time_step: time_step, break_60: break_60, break_90: break_90, days: days}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_roster_shiftbreak_90 = async (year_week, value) => { + let days = DAYS.toString() + let time_step = TIME_STEP + let break_60 = DAYBREAK_1 + let break_90 = value + let response = await fetch("/api/roster/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, time_step: time_step, break_60: break_60, break_90: break_90, days: days}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbSet_roster_timestep = async (year_week, value) => { + let days = DAYS.toString() + let time_step = value + let break_60 = DAYBREAK_1 + let break_90 = DAYBREAK_2 + let response = await fetch("/api/roster/update.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, time_step: time_step, break_60: break_60, break_90: break_90, days: days}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} diff --git a/js/database/settings.js b/js/database/settings.js new file mode 100644 index 0000000..ee31959 --- /dev/null +++ b/js/database/settings.js @@ -0,0 +1,127 @@ +dbAdd_settings = (database_version, default_overtime, default_edit_cell_right, default_row_top, default_row_bottom, sort_days, sort_week, printmode, zoom_web, zoom_print_h, zoom_print_v) => { + let data = { database_version: database_version.toString(), default_overtime: default_overtime ? 1 : 0, default_edit_cell_right: default_edit_cell_right ? 1 : 0, default_row_top: default_row_top ? 1 : 0, default_row_bottom: default_row_bottom ? 1 : 0, sort_days: sort_days.toString(), sort_week: sort_week.toString(), printmode: printmode, zoom_web: parseFloat(zoom_web), zoom_print_h: zoom_print_h, zoom_print_v: zoom_print_v } + fetch("/api/settings/add.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} +dbSet_settings_where = async (name, value) => { + let data = {name: name, value: value} + let response = await fetch("/api/settings/update.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbGet_settings = async () => { + let response = await fetch("/api/settings/getAll.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbGet_settings_where = async (name) => { + let response = await fetch("/api/settings/get.php", { + method: "POST", + body: JSON.stringify({name: name}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} + +dbSet_settings_edit_cell_default = (value) => { dbSet_settings_where("default_edit_cell_right", value) } + +dbSet_settings_edit_row_top_default = (value) => { dbSet_settings_where("default_row_top", value) } + +dbSet_settings_edit_row_bottom_default = (value) => { dbSet_settings_where("default_row_bottom", value) } + +// [{t: string, a: string},..] +dbAdd_settings_label = (id, name, cut) => { + let label = {id: id, name: name, cut: cut} + fetch("/api/settings_labels/add.php", { + method: "POST", + body: JSON.stringify(label), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} +dbGet_settings_labels = async () => { + let data + return await fetch("/api/settings_labels/get.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + .then((response) => {return response.json()}) + .then((data) => { return data.labels}) +} +dbGet_settings_label = (id) => { return SETTINGS_LABELS.find(l => l.id === id)} +dbGet_settings_label_text = (id) => { return dbGet_settings_label(id).name } +dbGet_settings_label_cut = (id) => { return dbGet_settings_label(id).cut } +dbSet_settings_label_text = async (id, text) => { + let l = dbGet_settings_label(id) + let data = {id: l.id, name: text, cut: l.cut} + return await fetch("/api/settings_labels/update.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} +dbSet_settings_label_cut = async (id, cut) => { + let l = dbGet_settings_label(id) + let data = {id: l.id, name: l.name, cut: cut} + return await fetch("/api/settings_labels/update.php", { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} + +// boolean +dbSet_settings_overtime_default = (value) => { dbSet_settings_where("default_overtime", value ? 1 : 0) } +dbGet_settings_overtime_default = async () => { return (await dbGet_settings_where("default_overtime")) === "0" ? false : true } + +// 0 || 1 +dbSet_settings_printmode = (value) => { dbSet_settings_where("printmode", value) } +dbGet_settings_printmode = async () => { return await dbGet_settings_where("printmode") } + +// ["string", "string"] +dbSet_settings_sort_days = async (value) => { return await dbSet_settings_where("sort_days", value.toString())} +dbGet_settings_sort_days = async () => { return (await dbGet_settings_where("sort_days")) } + +// decimal +dbSet_settings_version = (value) => { dbSet_settings_where("database_version", value) } +dbGet_settings_version = () => { dbGet_settings_where("database_version")} + +// ["string", "string"] +dbSet_settings_sort_week = async (value) => {return await dbSet_settings_where("sort_week", value.toString())} +dbGet_settings_sort_week = async () => { return (await dbGet_settings_where("sort_week")) } + +// decimal +dbSet_settings_zoom_web = (value) => { dbSet_settings_where("zoom_web", value) } +dbGet_settings_zoom_web = async () => { return await dbGet_settings_where("zoom_web") } + +// decimal +dbSet_settings_zoom_print_h = (value) => { dbSet_settings_where("zoom_print_h", value) } +dbGet_settings_zoom_print_h = async () => { return await dbGet_settings_where("zoom_print_h") } + +// decimal +dbSet_settings_zoom_print_v = (value) => { dbSet_settings_where("zoom_print_v", value) } +dbGet_settings_zoom_print_v = async () => { return await dbGet_settings_where("zoom_print_v") } diff --git a/js/database/settings.js.orig b/js/database/settings.js.orig new file mode 100644 index 0000000..8781067 --- /dev/null +++ b/js/database/settings.js.orig @@ -0,0 +1,130 @@ +dbCreat_settings_departments = () => { DATA.d = []} +dbAdd_settings = (database_version, default_overtime, default_edit_cell_right, default_row_top, default_row_bottom, sort_days, sort_week, printmode, zoom_web, zoom_print_h, zoom_print_v) => { + settings = { database_version: database_version.toString(), default_overtime: default_overtime ? 1 : 0, default_edit_cell_right: default_edit_cell_right ? 1 : 0, default_row_top: default_row_top ? 1 : 0, default_row_bottom: default_row_bottom ? 1 : 0, sort_days: sort_days.toString(), sort_week: sort_week.toString(), printmode: printmode, zoom_web: parseFloat(zoom_web), zoom_print_h: zoom_print_h, zoom_print_v: zoom_print_v } + console.log("###", settings) + $.ajax({ + url: "/api/settings/add.php", + type: "POST", + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify(settings), + cache: false, + success: (data) => { $('body').load('index.php') }, + error: (data) => {console.log("fail", data)} + }) +} +dbSet_settings_where = (name, value) => { + let data = {name: name, value: value} + $.ajax({ + url: "/api/settings/update.php", + type: "POST", + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify(data), + cache: false, + error: (data) => {console.log("fail", data)} + }); +} +dbGet_settings_where = async (name) => { + let data = {name: name} + let d + return await $.ajax({ + url: "/api/settings/get.php", + type: "POST", + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify(data), + cache: false, + success: (res) => { return res }, + error: (res) => {console.log("fail", res)} + }); +} +dbGet_settings_departments = () => {return DATA.d} +dbGet_settings_department_where_id = (id) => {return DATA.d.find(d => d.id === id).v} +dbAdd_settings_department = (name) => {DATA.d.push({id: dbGet_settings_departments().length > 0 ? 1+Math.max.apply(Math, dbGet_settings_departments().map(l => l.id)) : 0, v: name})} +dbSet_settings_department = (id, value) => {DATA.d.find(d => d.id === id).v = value} +dbRemove_settings_department = (id) => {DATA.d = DATA.d.filter(d => d.id !== id)} + +dbSet_settings_edit_cell_default = (value) => { dbSet_settings_where("default_edit_cell_right", value ? 0 : 1) } +dbGet_settings_edit_cell_default = () => { return dbSet_settings_where("default_edit_cell_right") === 0 ? false : true } + +dbSet_settings_edit_row_top_default = (value) => { dbSet_settings_where("default_row_top", value ? 0 : 1) } +dbGet_settings_edit_row_top_default = async () => { return await dbGet_settings_where("default_row_top") === 0 ? false : true } + +dbSet_settings_edit_row_bottom_default = (value) => { dbSet_settings_where("default_row_bottom", value ? 0 : 1) } +dbGet_settings_edit_row_bottom_default = async () => { return await dbGet_settings_where("default_row_bottom") === 0 ? false : true } + +// [{t: string, a: string},..] +dbAdd_settings_label = (name, cut) => { + let label = {name: name, cut: cut} + $.ajax({ + url: "/api/settings_labels/add.php", + type: "POST", + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify(label), + cache: false, + success: (data) => { $('body').load('index.php') }, + error: (data) => {console.log("fail", data)} + }) +} +dbGet_settings_labels = () => { + return await $.ajax({ + url: "/api/settings_labels/get.php", + type: "POST", + dataType: 'json', + contentType: 'application/json', + cache: false, + success: (res) => { return res }, + error: (res) => {console.log("fail", res)} + }); +} +dbGet_settings_label = (id) => { return SETTINGS_LABELS.find(l => l.id === id)} +dbGet_settings_label_text = (id) => { return dbGet_settings_label(id).t } +dbGet_settings_label_cut = (id) => { return dbGet_settings_label(id).a } +dbSet_settings_label_text = (id, text) => { dbGet_settings_label(id).t = text } +dbSet_settings_label_cut = (id, cut) => { dbGet_settings_label(id).a = cut } + +//[{}] +dbCreate_shift_label = () => {DATA.l = []} +dbGet_shift_labels = () => { return DATA.l } +// {i: int, n: string, c: string} +dbGet_shift_label = (id) => { return dbGet_shift_labels().find(l => l.id === id)} +dbGet_shift_label_text = (id) => { return dbGet_shift_label(id)?.n } +dbset_shift_label_text = (id, value) => { dbGet_shift_label(id).n = value } +dbGet_shift_label_cut = (id) => { return dbGet_shift_label(id)?.c } +dbSet_shift_label_cut = (id, value) => { dbGet_shift_label(id).c = value } +dbAdd_shift_label = (name, cut) => { DATA.l.push({id: dbGet_shift_labels().length > 0 ? 1+Math.max.apply(Math, dbGet_shift_labels().map(l => l.id)) : 0, n: name, c: cut}) } +dbRemove_shift_label = (id) => { DATA.l.splice(id, 1) } + +// boolean +dbSet_settings_overtime_default = (value) => { dbSet_settings_where("default_overtime", value ? 0 : 1) } +dbGet_settings_overtime_default = async () => { return await dbGet_settings_where("default_overtime") === 0 ? false : true } + +// 0 || 1 +dbSet_settings_printmode = (value) => { dbSet_settings_where("printmode", value) } +dbGet_settings_printmode = async () => { return await dbGet_settings_where("printmode") } + +// ["string", "string"] +dbSet_settings_sort_days = (value) => { dbSet_settings_where("sort_days", value.toString())} +dbGet_settings_sort_days = async () => { return (await dbGet_settings_where("sort_days")).split(',') } + +// decimal +dbSet_settings_version = (value) => { dbSet_settings_where("database_version", value) } +dbGet_settings_version = () => { dbGet_settings_where("database_version")} + +// ["string", "string"] +dbSet_settings_sort_week = (value) => {dbSet_settings_where("sort_week", value)} +dbGet_settings_sort_week = async () => { return (await dbGet_settings_where("sort_week")).split(',') } + +// decimal +dbSet_settings_zoom_web = (value) => { dbSet_settings_where("zoom_web", value) } +dbGet_settings_zoom_web = async () => { return await dbGet_settings_where("zoom_web") } + +// decimal +dbSet_settings_zoom_print_h = (value) => { dbSet_settings_where("zoom_print_h", value) } +dbGet_settings_zoom_print_h = () => { return dbSet_settings_where("zoom_print_h") } + +// decimal +dbSet_settings_zoom_print_v = (value) => { dbSet_settings_where("zoom_print_v", value) } +dbGet_settings_zoom_print_v = () => { return dbSet_settings_where("zoom_print_v") } diff --git a/js/database/shift-labels.js b/js/database/shift-labels.js new file mode 100644 index 0000000..7a0d631 --- /dev/null +++ b/js/database/shift-labels.js @@ -0,0 +1,57 @@ +//[{}] +dbAdd_shift_label = async (name, cut) => { + let sl = {name: name, cut: cut} + let response = await fetch("/api/shift_labels/add.php", { + method: "POST", + body: JSON.stringify(sl), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + return await response.json() +} +dbGet_shift_labels = async() => { + let response = await fetch("/api/shift_labels/get.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + let shift_labels = await response.json() + return shift_labels.shift_labels +} +// {i: int, n: string, c: string} +dbGet_shift_label = (id) => { return SHIFT_LABELS.find(l => l.id === id)} +dbGet_shift_label_text = (id) => { return dbGet_shift_label(id)?.name } +dbSet_shift_label_text = (id, value) => { + let sl = {id: id, name: value, cut: dbGet_shift_label_cut(id)} + console.log("##", sl) + fetch("/api/shift_labels/update.php", { + method: "POST", + body: JSON.stringify(sl), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} +dbGet_shift_label_cut = (id) => { return dbGet_shift_label(id)?.cut } +dbSet_shift_label_cut = (id, value) => { + let sl = {id: id, name: dbGet_shift_label_text(id), cut: value} + fetch("/api/shift_labels/update.php", { + method: "POST", + body: JSON.stringify(sl), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} +dbRemove_shift_label = (id) => { + fetch("/api/shift_labels/remove.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) +} + diff --git a/js/database/shifts.js b/js/database/shifts.js new file mode 100644 index 0000000..b170257 --- /dev/null +++ b/js/database/shifts.js @@ -0,0 +1,128 @@ +dbAdd_shift = async (year_week, day_id, person_id, start, end) => { + let response = await fetch("/api/shifts/add.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, person_id: person_id, start: start, end: end}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + + let shift_id = await response.json() + return shift_id +} +dbSet_shift_where_id = async (id, start, end) => { + let response = await fetch("/api/shifts/updateWhereId.php", { + method: "POST", + body: JSON.stringify({id: id, start: start, end: end}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let shift_id = await response.json() + return shift_id +} +dbSet_shifts_where_yearweek_and_start_lt = (year_week, value) => { + fetch("/api/shifts/updateStartWhereYearweekStartLt.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, start: value, end: end, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} +dbSet_shifts_where_yearweek_and_end_gt = (year_week, value) => { + fetch("/api/shifts/updateEndWhereYearweekEndGt.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, start: start, end: value, value: value}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) +} + +dbGet_shifts_where_person = async (person_id) => { + let response = await fetch("/api/shifts/getWherePerson.php", { + method: "POST", + body: JSON.stringify({person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let shifts = await response.json() + return shifts.shifts +} +dbGet_shifts_where_yearweek = async (year_week) => { + let response = await fetch("/api/shifts/getWhereYearweek.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let shifts = await response.json() + return shifts.shifts +} +dbGet_shifts_where_yearweek_and_person = async (year_week, person_id) => { + let response = await fetch("/api/shifts/getWhereYearweekPerson.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let shifts = await response.json() + return shifts.shifts +} +dbGet_shifts_where_yearweek_and_day = async (year_week, day_id) => { + let response = await fetch("/api/shifts/getWhereYearweekDay.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let shifts = await response.json() + return shifts.shifts +} +dbGet_shifts_where_yearweek_and_day_and_person = async (year_week, day_id, person_id) => { + let response = await fetch("/api/shifts/getWhereYearweekDayPerson.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let shifts = await response.json() + return shifts.shifts +} + +dbRemove_shift_where_id = async (id) => { + let response = await fetch("/api/shifts/removeWhereId.php", { + method: "POST", + body: JSON.stringify({id: id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_shift_where_person_and_day = async (person_id, day_id) => { + let response = await fetch("/api/shifts/removeWhereDayPerson.php", { + method: "POST", + body: JSON.stringify({day_id: day_id, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_shift_where_person_and_year_week_and_day = async (person_id, year_week, day_id) => { + let response = await fetch("/api/shifts/removeWhereYearweekDayPerson.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_shift_where_person_and_year_week_ge_and_day = async (person_id, year_week, day_id) => { + let response = await fetch("/api/shifts/removeWhereYearweekGeDayPerson.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, person_id: person_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_shift_where_person_and_year_week_and_day_and_start = async (person_id, year_week, day_id, start) => { + let response = await fetch("/api/shifts/removeWhereYearweekDayPersonStart.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id, person_id: person_id, start: start}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} +dbRemove_shift_where_year_week_and_day = async (year_week, day_id) => { + let response = await fetch("/api/shifts/removeWhereYearweekDay.php", { + method: "POST", + body: JSON.stringify({yearweek: year_week, day_id: day_id}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} diff --git a/js/fixdata.js b/js/fixdata.js new file mode 100644 index 0000000..474fb2e --- /dev/null +++ b/js/fixdata.js @@ -0,0 +1,525 @@ +// FIX FILE_DATA --> +fixPersonShift = () => { + getShiftPeriod = (person_id, day_id, roster) => { + if (typeof roster === "undefined") roster = ROSTER + let day = roster[day_id].data + let period = [] + + day.forEach((data, time_id) => { + if (typeof data.person === "undefined") return + if (data.person.indexOf(person_id) !== -1) period.push(data.time) + }) + return period + } + ROSTER_ALL.forEach((roster, roster_id) => { + if (roster.length === 0) return + delete roster.times + delete roster.timestart + delete roster.timeend + if ( typeof roster.person === "undefined" ) return + + getTI = (time, data) => { return data.map((e) => {return e.time}).indexOf(time)} + + roster.person.forEach((person, person_id) => { + delete person.hours_assigned + delete person.breaks_total + if (typeof person.shifts !== "undefined") return + roster.roster.forEach((day, day_id) => { + let period = getShiftPeriod(person_id, day_id, roster.roster) + if (typeof person.shifts === "undefined") person.shifts = [] + if (period.length === 0) return + let dd = day.data + let start = period[0] + ROSTER_ALL[roster_id].person[person_id].shifts.push({day: day_id, start: getTI(period[0], dd), end: getTI(period[period.length-1], dd)}) + }) + }) + roster.roster.forEach(day => { + day.data.forEach(data => { + delete data.person + }) + }) + roster.d = roster.date + roster.t = roster.timestep + roster.r = structuredClone(roster.roster) + roster.p = structuredClone(roster.person) + roster.s = roster.datestart + delete roster.roster + delete roster.person + delete roster.date + delete roster.timestep + delete roster.datestart + roster.r.forEach(roster => { + roster.n = roster.name + roster.d = roster.data + delete roster.name + delete roster.data + roster.d.forEach(data => { + data.t = data.time + data.a = data.amount + delete data.time + delete data.amount + }) + }) + roster.p.forEach((person) => { + person.n = person.name + person.h = person.hours + person.d = person.department + person.f = structuredClone(person.freedays) + person.p = person.preferred + person.s = structuredClone(person.shifts) + delete person.name + delete person.hours + delete person.department + delete person.freedays + delete person.preferred + delete person.shifts + person.s.forEach(shift => { + shift.d = shift.day + shift.s = shift.start + shift.e = shift.end + delete shift.day + delete shift.start + delete shift.end + }) + }) + }) +} +fixShiftFromIdToTime = () => { + ROSTER_ALL.forEach((data, data_id) => { + let person = data.p + person.forEach((person, person_id) => { + person.s.forEach(shift => { + shift.s = data.r[0].d[shift.s].t + shift.e = data.r[0].d[shift.e].t + }) + }) + }) +} +fixRosterPreVersion = () => { + ROSTER_ALL = structuredClone(DATA) + fixPersonShift() + fixShiftFromIdToTime() +} +fixVersionAddBreakday = () => { + ROSTER_ALL = structuredClone(DATA.a) + ROSTER_ALL.forEach(ra => { ra.b = [DAYBREAK_1, DAYBREAK_2] }) +} +fixVersionNewDatabase = () => { + let PERSONS_ALL = [] + ROSTER_ALL = DATA.a + ROSTER_ALL.forEach((ra, ra_id) => { + let shifts_all = DATA.a[ra_id].s = [] + ra.p.forEach((pe, pe_id) => { + let shifts = pe.s + let person = PERSONS_ALL.filter(a => {return a.n === pe.n })[0] + let p_id = pe_id + if (typeof person !== "undefined") { p_id = person.id } + shifts.forEach(shift => { + let s_d_id = shifts_all.map(function(e) { return e.d; }).indexOf(shift.d); + if (s_d_id === -1) { + shifts_all.push({d: shift.d, s: []}) + s_d_id = shifts_all.length-1 + } + let s_d = shifts_all[s_d_id].s + delete shift.d + shift.p = p_id + s_d.push(shift) + }) + if (typeof person === "undefined") { + let ill = (typeof pe.i === "undefined") ? [] : pe.i + PERSONS_ALL.push({id: pe_id, a: ROSTER_ALL[0].d, r: false, n: pe.n, h: pe.h, d: pe.d, f: pe.f, i: ill, v: pe.v, c: []}) + } + }) + }) + //ROSTER_ALL.forEach(all => { delete all.p }) + DATA.p = PERSONS_ALL + DATA.v = 1.2 +} +fixVersionAddMpaToPerson = () => { + DATA.p.forEach(person => {person.m = []; DAYS.forEach(d => person.m.push(0))}) +} +fixVersionAddDataSort = () => { + DATA.s = ["name", "name"] +} +fixVersionAddDataSortUpDown = () => { + DATA.s = [[`${DATA.s[0].substring(0, 1)}-d`], [`${DATA.s[1].substring(0, 1)}-d`]] +} +fixVersionPersonDepartmentToFloat = () => { + DATA.p.forEach(person => {person.d = parseFloat(person.d)}) +} +fixVersionAddDataZoom = () => { + DATA.z = 100 +} +fixVersionAddDataDepartment = () => { + DATA.d = structuredClone(DEPARTMENTS) + DATA.n = [{t: "Freie Tage", a: "Frei"}, {t: "mpA", a: "MPA"}] +} +fixVersionAddDataBetterment = () => { + DATA.p.forEach(person => {person.b = []}) +} +fixVersionAddDataRenames = () => { + DATA.n.push({t: "Krank", a: "Krank"}) + DATA.n.push({t: "Weiterbildung", a: "W"}) + DATA.n.push({t: "Urlaub", a: "Urlaub"}) +} +fixVersionRemoveDateRosterPerson = () => { + DATA.a.forEach(data => { + delete data.p + }) +} +fixVersionAddDatePersonOvertime = () => { + DATA.a.forEach(data => {setPersonOvertime(data.d)}) +} +fixVersionAddDatePersonOvertimeFixMpaFreeDay = () => { + DATA.a.forEach(data => {setPersonOvertime(data.d)}) +} +fixVersionAddDataPrintMode = () => { + DATA.m = 0 +} +fixVersionAddBettermentsHours = () => { + DATA.p.forEach(person => { + person.b.forEach(b => b.push(parseFloat(person.h/DAYS.length.toFixed(2)))) + }) +} +fixVersionAddMissingPersonR = () => { + DATA.p.forEach(person => { + if (typeof person.r === "undefined") {person.r = false} + }) +} +fixVersionDataRosterTime = () => { + DATA.a.sort((a, b) => {return getDateOfISOWeek(a.d) - getDateOfISOWeek(b.d)}) + DATA.a.forEach(a => {a.c = []}) + let data_r = DATA.a[0].r + + DATA.a.forEach((data, data_id) => { + let days = [] + let step = data.t + let change = false + data.r.forEach((roster, d_id) => { + let times = roster.d + amount = structuredClone(roster.d.map(d => d.a)) + if ((data_id === 0) || (JSON.stringify(times) !== JSON.stringify(DATA.a[data_id-1].r[d_id].d) )) { + DATA.a[data_id].c.push({k: "d_"+d_id, s: times[0].t, e: times[times.length-1].t, a: amount}) + } + }) + }) + DATA.a.forEach(a => {delete a.r}) +} +fixVersionAddDataClosingTime = () => { + DATA.x = [] +} +fixVersionDataOvertimeToFixed = () => { + DATA.a.forEach(data => { + if (data.s.map(a => a.s).filter(a => a.length > 0).length === 0) {data.o = []; return} + setPersonOvertime(data.d) + }) +} +fixVersionDataSortToSetting = () => { + let sort = structuredClone(DATA.s) + DATA.s = [{s: [[...sort[0]], [...sort[1]]]}] +} +fixVersionDataAddPrintZoom = () => { + DATA.s.push({z: [100, 78]}) +} +fixVersionDataEditableToR = () => { + DATA.a.forEach(data => { if (typeof data.e !== "undefined") {let e = structuredClone(data.e); data.e = {r: [...e]}}}) +} +fixVersionDataAddEditable = () => { + DATA.a.forEach(data =>{if (typeof data.e === "undefined") {data.e = {}}}) +} +fixVersionDataFixOvertimes = () => { + DATA.a.forEach(data =>{ + data.o.forEach(overtime => setPersonIdOvertime(overtime.p, data.d)) + }) +} +fixVersionDataRemovePersonR = () => { + DATA.p.forEach(p => {delete p.r}) +} +fixVersionDataAddPersonShiftSetting = () => { + DATA.p.forEach(p => { + p.c.push({d: p.a, k: "sa", v: [{d: 0, a: undefined}, {d: 1, a: undefined}, {d: 2, a: undefined}, {d: 3, a: undefined}, {d: 4, a: undefined} ]}) + let sf_0 = p.f.indexOf(0); if (sf_0 === -1) {sf_0 = false} else {sf_0 = true} + let sf_1 = p.f.indexOf(1); if (sf_1 === -1) {sf_1 = false} else {sf_1 = true} + let sf_2 = p.f.indexOf(2); if (sf_2 === -1) {sf_2 = false} else {sf_2 = true} + let sf_3 = p.f.indexOf(3); if (sf_3 === -1) {sf_3 = false} else {sf_3 = true} + let sf_4 = p.f.indexOf(4); if (sf_4 === -1) {sf_4 = false} else {sf_4 = true} + let sl_0 = p.f.indexOf(0); if (sl_0 === -1) {sl_0 = undefined} else {sl_0 = 1} + let sl_1 = p.f.indexOf(1); if (sl_1 === -1) {sl_1 = undefined} else {sl_1 = 1} + let sl_2 = p.f.indexOf(2); if (sl_2 === -1) {sl_2 = undefined} else {sl_2 = 1} + let sl_3 = p.f.indexOf(3); if (sl_3 === -1) {sl_3 = undefined} else {sl_3 = 1} + let sl_4 = p.f.indexOf(4); if (sl_4 === -1) {sl_4 = undefined} else {sl_4 = 1} + p.c.push({d: p.a, k: "sl", v: [{d: 0, l: sl_0}, {d: 1, l: sl_1}, {d: 2, l: sl_2}, {d: 3, l: sl_3}, {d: 4, l: sl_4} ]}) + p.c.push({d: p.a, k: "sf", v: [{d: 0, f: sf_0}, {d: 1, f: sf_1}, {d: 2, f: sf_2}, {d: 3, f: sf_3}, {d: 4, f: sf_4} ]}) + p.c.forEach(c => { + if (c.k === "f") { + let sf_values = getActivePersonById(p.id, c.d) + let new_sf = [] + let new_sl = [] + DAYS.forEach((day, day_id) => { + if (c.v.indexOf(day_id) > -1) { + new_sf.push({d: day_id, f: true}) + new_sl.push({d: day_id, l: 1}) + } else { + new_sf.push({d: day_id, f: false}) + new_sl.push({d: day_id, l: undefined}) + } + }) + c.k = "sf" + c.v = structuredClone(new_sf) + let check_sl = p.c.filter(sl => {return sl.d === c.d && sl.k === "sl"})[0] + if (typeof check_sl !== "undefined") { + check_sl.v = structuredClone(new_sl) + } else p.c.push({d: c.d, k: "sl", v: structuredClone(new_sl)}) + } + }) + delete p.f + }) + DATA.n.splice(0, 1) + DATA.l = structuredClone(SHIFT_LABELS) +} +fixVersionData22To224 = () => { + fixVersionDataRemovePersonR() + fixVersionDataAddPersonShiftSetting() + fixVersionDataOvertimeToFixed() + fixVersionDataFixOvertimes() +} +fixVersionDataTo224 = () => { + fixVersionDataRemovePersonR() + fixVersionDataAddPersonShiftSetting() + fixVersionDataFixOvertimes() +} +fixVersionDataAddDisplayOvertime = () => { + DATA.s.push({d: [{k: "overtime", v: false}]}) +} +fixVersionDataAddDisplayEditableWeek = () => { + DATA.s.filter(s => {return s.d})[0].d.push({k: "editable-cell", v: true}) + DATA.s.filter(s => {return s.d})[0].d.push({k: "editable-row", v: false}) +} +fixVersionDataAddClosingTimeX = () => { + DATA.x.forEach(data => data.d.forEach(d => d.x = false)) +} +fixVersionDataRemoveEmptyShiftInfo = () => { + DATA.a.forEach(a => { + if (typeof a.i !== "undefined") { + let new_i = [] + a.i.forEach(i => {if (i.t.length > 0) new_i.push(i)}) + a.i = new_i + } + }) +} +fixVersionDataFixUnsetSf = () => { + DATA.p.forEach(person => { + person.c.forEach(change => { + if (change.k === "sf") { + change.v.forEach(v => {if (typeof v.f === "undefined") {v.f = false}}) + } + }) + }) +} +fixVersionDataEditableRowBottom = () => { + DATA.s[2].d.push({k: 'editable-row-bottom', v: false}) +} +fixVersionDataMergeClosingtime = () => { + let all = [] + DATA.x.forEach(x => x.d.forEach(d => all.push(d))) + DATA.x = structuredClone(all) +} +fixVersionDataSetClosingtimeId = () => { + DATA.x.forEach((x, x_id) => {x.id = x_id}) +} +fixYWTo7 = (yw) => {return yw.length === 6 ? (yw.substring(0,5)+"0"+yw.substring(5)) : yw} +fixVersionDataSetYearWeekTo7 = () => { + DATA.a.forEach(a => { a.d = fixYWTo7(a.d) }) + DATA.p.forEach(p => { + p.a = fixYWTo7(p.a) + p.c.forEach(c => c.d = fixYWTo7(c.d)) + }) +} +fixVersionDataNewRosterChangeValue = () => { + DATA.rc = [] + DATA.a.forEach(a => {a.c.forEach(c => {c.k = parseFloat(c.k.slice(-1)); c.d = a.d; DATA.rc.push(c)}); delete a.c}) + //DATA.a.forEach(a => {a.c.forEach(c => {c.k = parseFloat(c.k.slice(-1))} )}) + //DATA.rs = [] + //let d_id = -1 + //DATA.a.forEach(a => {a.s.forEach(s => s.s.forEach(d => {d_id = d_id+1; d.id = d_id; d.d = a.d; d.k = s.d; DATA.rs.push(d)})); delete a.s}) + DATA.a.forEach(a => { + let new_s = [] + a.s.forEach(d => { + let new_sd = [] + d.s.forEach(s => new_sd.push(s)) + new_s.push(new_sd) + }) + a.s = new_s + }) +} +fixVersionDataNewSettingsValues = () => { + DATA.sd = DATA.s[0].s[0] + DATA.sw = DATA.s[0].s[1] + DATA.zh = DATA.s[1].z[0] + DATA.zv = DATA.s[1].z[1] + DATA.so = DATA.s[2].d[0].v + DATA.secr = DATA.s[2].d[1].v + DATA.sert = DATA.s[2].d[2].v + DATA.serb = DATA.s[2].d[3].v + delete DATA.s + DATA.n.forEach((n, n_id) => n.id = n_id) + DATA.a.forEach(a => {let er = []; a.e?.c?.forEach((r, r_id) => er.push({k: r.p.toString(), v: r.t})); if (er.length > 0) {a.ecr = er; delete a.e.c} }) + DATA.a.forEach(a => {let rt = []; a.e?.r?.forEach((r, r_id) => rt.push({k: r_id.toString(), v: r})); if (rt.length > 0) {a.ert = rt; delete a.e.r} }) + DATA.a.forEach(a => {let rb = []; a.e?.rb?.forEach((r, r_id) => rb.push({k: r_id.toString(), v: r})); if (rb.length > 0) {a.erb = rb; delete a.e.rb} }) + DATA.a.forEach(a => {delete a.e}) + DATA.l.forEach(l => {l.id = l.i; delete l.i}) + let dep = [{id: 0, v: ""}] + DATA.d.forEach((d, id) => dep.push({id: id+1, v: d})) + DATA.d = dep + DATA.p.forEach(p => { p.c = p.c.sort((a,b) => a.d.localeCompare(b.d)) }) + DATA.p.forEach(p => {p.d = p.d+1; p.c.forEach(c => {if (c.k === "d") {c.v = c.v+1}})}) + DATA.p.forEach(p => { + let old_sl + let sl + let r_ids = [] + p.c.forEach((c, c_id) => { + if (c.k === "sl") { + old_sl = structuredClone(sl); sl = structuredClone(c.v); + if (old_sl && JSON.stringify(sl) !== JSON.stringify(old_sl)) { + old_sl.forEach(osl => { + if (osl.l) { + !c.v.find(cc => cc.d === osl.d).l && (c.v.find(cc => cc.d === osl.d).l = false) + } + }) + } + old_sl && JSON.stringify(sl) === JSON.stringify(old_sl) && r_ids.push(c_id) + old_sl && (c.v = c.v.filter(v => typeof v.l !== "undefined")) + } + }) + r_ids.length > 0 && (p.c = p.c.filter((c, c_id) => r_ids.indexOf(c_id) === -1)) + }) + DATA.p.forEach(p => { + let old_sl + let sl + let r_ids = [] + p.c.forEach((c, c_id) => { + if (c.k === "sf") { + c.v.forEach(v => !v.f && (delete v.f)) + } + }) + p.c.forEach((c, c_id) => { + if (c.k === "sf") { + old_sl = structuredClone(sl); sl = structuredClone(c.v); + if (old_sl && JSON.stringify(sl) !== JSON.stringify(old_sl)) { + old_sl.forEach(osl => { + if (osl.f) { + !c.v.find(cc => cc.d === osl.d).f && (c.v.find(cc => cc.d === osl.d).f = false) + } + }) + } + old_sl && JSON.stringify(sl) === JSON.stringify(old_sl) && r_ids.push(c_id) + old_sl && (c.v = c.v.filter(v => typeof v.f !== "undefined")) + } + }) + r_ids.length > 0 && (p.c = p.c.filter((c, c_id) => r_ids.indexOf(c_id) === -1)) + }) + DATA.p.forEach(p => { + let old_sl + let sl + let r_ids = [] + p.c.forEach((c, c_id) => { + if (c.k === "sa") { + old_sl = structuredClone(sl); sl = structuredClone(c.v); + if (old_sl && JSON.stringify(sl) !== JSON.stringify(old_sl)) { + old_sl.forEach(osl => { + if (osl.a) { + !c.v.find(cc => cc.d === osl.d).a && (c.v.find(cc => cc.d === osl.d).a = false) + } + }) + } + old_sl && JSON.stringify(sl) === JSON.stringify(old_sl) && r_ids.push(c_id) + old_sl && (c.v = c.v.filter(v => typeof v.a !== "undefined")) + } + }) + r_ids.length > 0 && (p.c = p.c.filter((c, c_id) => r_ids.indexOf(c_id) === -1)) + }) + DATA.p.forEach(p => { p.c.sort((a,b) => b.d.localeCompare(a.d))}) + DATA.p.forEach(p => { p.c.filter(c => c.k === "m").forEach(c => {let new_v = []; c.v.forEach((v, v_id) => new_v.push({d: v_id, v: v}) ); c.v = new_v }) }) + DATA.p.forEach(p => { + let old_m = [{d: 0, v: 0}, {d: 1, v: 0}, {d: 2, v: 0}, {d: 3, v: 0}, {d: 4, v: 0} ] + let new_m + p.c.filter(c => c.k === "m").forEach(c => { + c.v = c.v.filter(v => v.v !== old_m.find(o => o.d === v.d).v) + c.v.forEach(v => old_m.find(o => o.d === v.d).v = v.v) + }) + }) + DATA.p.forEach(p => { p.c = p.c.filter(c => c.v.length > 0)}) + + DATA.pc = [] + DATA.p.forEach(p => { + p.c.forEach(c => { + c.k === "sl" && c.v.forEach(v => {v.v = v.l; delete v.l; !v.v && (v.v = false)}) + c.k === "sf" && c.v.forEach(v => {v.v = v.f; delete v.f; !v.v && (v.v = false)}) + c.k === "sa" && c.v.forEach(v => {v.v = v.a; delete v.a; !v.v && (v.v = false)}) + }) + p.c.forEach(c => { + if ((c.k === "sl") || (c.k === "sa") || (c.k === "sf") || (c.k === "m")) { + c.v.forEach(v => DATA.pc.push({p: p.id, d: c.d, t: v.d, k: c.k, v: v.v})) + } else { DATA.pc.push({p: p.id, d: c.d, k: c.k, v: c.v})} + }) + delete p.c + }) + DATA.rc.sort((a,b) => a.d.localeCompare(b.d)) + + let oldest_yw = DATA.pc.map(c => c.d).sort((a,b) => a.localeCompare(b))[0] + DATA.pc = DATA.pc.filter(c => `${c.d}-${c.k}-${c.v}` !== `${oldest_yw}-sl-false` ) + DATA.pc = DATA.pc.filter(c => `${c.d}-${c.k}-${c.v}` !== `${oldest_yw}-sf-false` ) + DATA.pc = DATA.pc.filter(c => `${c.d}-${c.k}-${c.v}` !== `${oldest_yw}-sa-false` ) + /*DATA.pc.filter(c => c.k === "sl").forEach(c => { + let free = DATA.pc.find(cf => cf.d === c.d && cf.k === "sf" && cf.t === c.t)?.v || false + c.f = free + }) + DATA.pc = DATA.pc.filter(c => c.k !== "sf")*/ + DATA.a.forEach(a => { + let new_o = [] + a.o.forEach(o => new_o.push([o.p, o.o])) + a.o = new_o + }) +} + +fixDataByVersion = (DATA) => { + if (typeof dbGet_settings_version() === "undefined") { fixRosterPreVersion(); dbSet_settings_version(1); VERSION = 1;} + + if (dbGet_settings_version() === 1) { fixVersionAddBreakday(); dbSet_settings_version(1.1); VERSION = 1.1;} + if (dbGet_settings_version() === 1.1) { fixVersionNewDatabase(); dbSet_settings_version(1.2); VERSION = 1.2;} + if (dbGet_settings_version() === 1.2) { fixVersionAddMpaToPerson(); dbSet_settings_version(1.3); VERSION = 1.3;} + if (dbGet_settings_version() === 1.3) { fixVersionAddDataSort(); dbSet_settings_version(1.4); VERSION = 1.4;} + if (dbGet_settings_version() === 1.4) { fixVersionAddDataSortUpDown(); fixVersionPersonDepartmentToFloat(); dbSet_settings_version(1.5); VERSION = 1.5;} + if (dbGet_settings_version() === 1.5) { fixVersionAddDataZoom(); fixVersionPersonDepartmentToFloat(); dbSet_settings_version(1.6); VERSION = 1.6;} + if (dbGet_settings_version() === 1.6) { fixVersionAddDataDepartment(); dbSet_settings_version(1.7); VERSION = 1.7;} + if (dbGet_settings_version() === 1.7) { fixVersionAddDataBetterment(); dbSet_settings_version(1.8); VERSION = 1.8;} + if (dbGet_settings_version() === 1.8) { fixVersionAddDataRenames(); dbSet_settings_version(1.9); VERSION = 1.9;} + if (dbGet_settings_version() === 1.9) { fixVersionRemoveDateRosterPerson(); dbSet_settings_version(1.11); VERSION = 1.11;} + if (dbGet_settings_version() === 1.11) { fixVersionAddDatePersonOvertime(); dbSet_settings_version(1.12); VERSION = 1.12;} + if (dbGet_settings_version() === 1.12) { fixVersionAddDatePersonOvertimeFixMpaFreeDay(); dbSet_settings_version(1.13); VERSION = 1.13;} + if (dbGet_settings_version() === 1.13) { fixVersionAddDataPrintMode(); dbSet_settings_version(1.14); VERSION = 1.14;} + if (dbGet_settings_version() === 1.14) { fixVersionAddBettermentsHours(); dbSet_settings_version(1.15); VERSION = 1.15;} + if (dbGet_settings_version() === 1.15) { fixVersionAddMissingPersonR(); dbSet_settings_version(1.16); VERSION = 1.16;} + if (dbGet_settings_version() === 1.16) { fixVersionDataRosterTime(); dbSet_settings_version(1.17); VERSION = 1.17;} + if (dbGet_settings_version() === 1.17) { fixVersionAddDataClosingTime(); dbSet_settings_version(1.18); VERSION = 1.18;} + if (dbGet_settings_version() === 1.18) { fixVersionDataOvertimeToFixed(); dbSet_settings_version(1.19); VERSION = 1.19;} + if (dbGet_settings_version() === 1.19) { fixVersionDataSortToSetting(); fixVersionDataAddPrintZoom(); dbSet_settings_version(1.21); VERSION = 1.21;} + if ((dbGet_settings_version() === 1.21) || (dbGet_settings_version() === 2.1)) { fixVersionDataEditableToR(); fixVersionDataAddEditable(); dbSet_settings_version(2.2); VERSION = 2.2;} + if (dbGet_settings_version() === 2.2) { fixVersionData22To224(); dbSet_settings_version(2.24); VERSION = 2.24;} + if (dbGet_settings_version() === 2.21) { fixVersionDataTo224(); dbSet_settings_version(2.24); VERSION = 2.24;} + if (dbGet_settings_version() === 2.22) { fixVersionDataRemovePersonR(); dbSet_settings_version(2.23); VERSION = 2.23;} + if (dbGet_settings_version() === 2.23) { fixVersionDataAddPersonShiftSetting(); dbSet_settings_version(2.24); VERSION = 2.24;} + if (dbGet_settings_version() === 2.24) { fixVersionDataAddDisplayOvertime(); dbSet_settings_version(2.25); VERSION = 2.25;} + if (dbGet_settings_version() === 2.25) { fixVersionDataAddDisplayEditableWeek(); dbSet_settings_version(2.26); VERSION = 2.26;} + if (dbGet_settings_version() === 2.26) { fixVersionDataAddClosingTimeX(); dbSet_settings_version(2.27); VERSION = 2.27;} + if (dbGet_settings_version() === 2.27) { fixVersionDataRemoveEmptyShiftInfo(); dbSet_settings_version(2.28); VERSION = 2.28;} + if (dbGet_settings_version() === 2.28) { fixVersionDataFixUnsetSf(); dbSet_settings_version(2.29); VERSION = 2.29;} + if (dbGet_settings_version() === 2.29) { fixVersionDataEditableRowBottom(); dbSet_settings_version(2.3); VERSION = 2.3;} + if (dbGet_settings_version() === 2.3) { fixVersionDataMergeClosingtime(); dbSet_settings_version(2.31); VERSION = 2.31;} + if (dbGet_settings_version() === 2.31) { fixVersionDataSetClosingtimeId(); dbSet_settings_version(2.32); VERSION = 2.32;} + if (dbGet_settings_version() === 2.32) { fixVersionDataSetYearWeekTo7(); dbSet_settings_version(2.33); VERSION = 2.33;} + if (dbGet_settings_version() === 2.33) { fixVersionDataNewRosterChangeValue(); dbSet_settings_version(2.34); VERSION = 2.34;} + if (dbGet_settings_version() === 2.34) { fixVersionDataNewSettingsValues(); dbSet_settings_version(2.35); VERSION = 2.35;} +} +// <-- FIX FILE_DATA + diff --git a/js/get-lawful-vacations.js b/js/get-lawful-vacations.js new file mode 100755 index 0000000..58e02a4 --- /dev/null +++ b/js/get-lawful-vacations.js @@ -0,0 +1,162 @@ +let LAWFUL_STATES = [["Alle Bundesländer", ""], ["bundesweit", "&all_states=true"], ["Baden-Württemberg", "&states=bw"], ["Bayern", "&states=by"], ["Berlin", "&states=be"], ["Brandenburg", "&states=bb"], ["Bremen", "&states=hb"], ["Hamburg", "&states=hh"], ["Hessen", "&states=he"], ["Mecklenburg-Vorpommern", "&states=mv"], ["Niedersachsen", "&states=ni"], ["Nordrhein-Westfalen", "&states=nw"], ["Rheinland-Pfalz", "&states=rp"], ["Saarland", "&states=sl"], ["Sachsen", "&states=sn"], ["Sachsen-Anhalt", "&states=st"], ["Schleswig-Holstein", "&states=sh"], ["Thüringen", "&states=th"]] + +addClosingTimeLawfulVacations = () => { + let block_popup = document.getElementById("Popup-container") + block_popup.classList.add("lawful") + block_popup.innerHTML = "" + + renderPopupButtonClose() + + let block_back = document.createElement("button") + block_back.innerHTML = "Zurück" + block_back.classList.add("button-back") + block_back.setAttribute("onClick", "window.setTimeout(() => {openClosingTime()},50)") + block_popup.appendChild(block_back) + + let block_text = document.createElement("p") + block_text.innerHTML = "Beim bestätigen wird eine anfrage an die folgende Seite geschickt: <a href='https://www.api-feiertage.de'>https://www.api-feiertage.de</a>\nDamit erklärs du dich mit den Datenschutzbedingungen dieser Seite einverstanden. Die Datenschutz bedingunen kannst du <a href='https://www.api-feiertage.de/datenschutz.html'>hier</a> einsehen." + block_popup.appendChild(block_text) + + let block_continue = document.createElement("button") + block_continue.innerHTML = "Bestätigen" + block_continue.setAttribute("onClick", "window.setTimeout(() => {continueAddClosingTimeLawfulVacations()}, 50)") + block_popup.appendChild(block_continue) +} + +continueAddClosingTimeLawfulVacations = () => { + let block_popup = document.getElementById("Popup-container") + block_popup.innerHTML = "" + + renderPopupButtonClose() + + let block_back = document.createElement("button") + block_back.innerHTML = "Zurück" + block_back.classList.add("button-back") + block_back.setAttribute("onClick", "window.setTimeout(() => {addClosingTimeLawfulVacations()},50)") + block_popup.appendChild(block_back) + + let block_label_select_year = document.createElement("label") + let block_select_year = document.createElement("select") + block_select_year.setAttribute("id", "Lawful-vacations-year") + let block_select_option_1 = document.createElement("option") + let year = new Date().getFullYear() + block_select_option_1.setAttribute("value", year) + block_select_option_1.innerHTML = year + block_select_year.appendChild(block_select_option_1) + let block_select_option_2 = document.createElement("option") + block_select_option_2.setAttribute("value", year+1) + block_select_option_2.innerHTML = year+1 + block_select_year.appendChild(block_select_option_2) + let block_select_option_3 = document.createElement("option") + block_select_option_3.setAttribute("value", year+2) + block_select_option_3.innerHTML = year+2 + block_select_year.appendChild(block_select_option_3) + block_label_select_year.appendChild(block_select_year) + block_popup.appendChild(block_label_select_year) + + let block_label_select_state = document.createElement("label") + let block_select_state = document.createElement("select") + block_select_state.setAttribute("id", "Lawful-vacations-state") + LAWFUL_STATES.forEach((state, s_id) => { + let block_option = document.createElement("option") + block_option.innerHTML = state[0] + block_option.setAttribute("value", s_id) + block_select_state.appendChild(block_option) + }) + block_label_select_state.appendChild(block_select_state) + block_popup.appendChild(block_label_select_state) + + let block_continue = document.createElement("button") + block_continue.innerHTML = "Weiter" + block_continue.setAttribute("onClick", `window.setTimeout(() => {getLawfulVacations(document.getElementById("Lawful-vacations-year").value, document.getElementById("Lawful-vacations-state").value)},50)`) + block_popup.appendChild(block_continue) +} + +createLawfulVacationsDroptown = () => { + let block_label_select = document.createElement("label") + let block_select = document.createElement("select") + LAWFUL_STATES.forEach(name => { + let block_option = document.createElement("option") + block_option.value = name[1] + block_option.innerHTML = name[0] + block_select.appendChild(block_option) + }) + block_label_select.appendChild(block_select) + return block_select +} + + + +getLawfulVacations = (year, s_id) => { + let state = LAWFUL_STATES[s_id][1] + fetch(`https://get.api-feiertage.de?years=${year}${state}`) + .then(res => res.json()) + .then((data) => { + createLawfulVacationsConfirm(s_id, year, data.feiertage) + }).catch(err => console.error(err)); +} + +createLawfulVacationsConfirm = (s_id, year, vacations) => { + let block_popup = document.getElementById("Popup-container") + block_popup.innerHTML = "" + renderPopupButtonClose() + + let block_back = document.createElement("button") + block_back.innerHTML = "Zurück" + block_back.classList.add("button-back") + block_back.setAttribute("onClick", "window.setTimeout(() => {continueAddClosingTimeLawfulVacations()},50)") + block_popup.appendChild(block_back) + + let block = document.createElement("div") + block.classList.add("lawful-vacations") + let block_container = document.createElement("div") + let block_state = document.createElement("h2") + block_state.innerHTML = LAWFUL_STATES[s_id][0] + block.appendChild(block_state) + let block_year = document.createElement("h2") + block_year.innerHTML = year + block.appendChild(block_year) + + vacations.forEach(vacation => { + let name = vacation.fname + let date = vacation.date + let date_local = new Date(date).toLocaleDateString('de', {day: '2-digit', month: '2-digit', year: '2-digit'}) + let block_label = document.createElement("label") + block_label.innerHTML = name + block_container.appendChild(block_label) + let block_date = document.createElement("div") + block_date.innerHTML = date_local + block_container.appendChild(block_date) + let block_check = document.createElement("input") + block_check.setAttribute("type", "checkbox") + block_check.setAttribute("checked", "true") + block_check.setAttribute("name", name) + block_check.setAttribute("date", date) + block_container.appendChild(block_check) + }) + block.appendChild(block_container) + let block_save = document.createElement("button") + block_save.innerHTML = "Hinzufügen" + block_save.setAttribute("onClick", "saveLawfulVacations()") + block_save.classList.add("button-save") + block.appendChild(block_save) + + block_popup.appendChild(block) + return block +} + +saveLawfulVacations = () => { + showLoading("saveLawfulVacations") + window.setTimeout(() => { + let items = document.querySelectorAll(".lawful-vacations input:checked") + items.forEach(item => { + let name = item.getAttribute("name") + let date = item.getAttribute("date") + addClosingTime(name, date, date, true) + }) + closePopup() + openClosingTime(document.getElementById("Settings-toggle-closingtime")) + + hideLoading("saveLawfulVacations") + }, 50) +} diff --git a/js/person.js b/js/person.js new file mode 100755 index 0000000..3a8890b --- /dev/null +++ b/js/person.js @@ -0,0 +1,2257 @@ + + +let EDIT_PERSONS_ACTIVATION +let EDIT_PERSONS_MPA +let EDIT_PERSONS_FREEDAYS +let EDIT_PERSONS_NAME +let EDIT_PERSONS_HOURS +let EDIT_PERSONS_DEPARTMENT +let EDIT_PERSONS_SHIFT_ACTIVATION +let EDIT_PERSONS_SHIFT_LABEL_ACTIVATION +let EDIT_PERSONS_SHIFT_LABEL +let EDIT_PERSONS_SHIFT_FREE +let EDIT_PERSONS_SHIFT_AVERAGE_ACTIVATION +let EDIT_PERSONS_SHIFT_AVERAGE + +resetEditPersonCheckValues = () => { + EDIT_PERSONS_ACTIVATION = undefined + EDIT_PERSONS_MPA = undefined + EDIT_PERSONS_FREEDAYS = undefined + EDIT_PERSONS_NAME = undefined + EDIT_PERSONS_HOURS = undefined + EDIT_PERSONS_DEPARTMENT = undefined + EDIT_PERSONS_SHIFT_ACTIVATION = undefined + EDIT_PERSONS_SHIFT_LABEL_ACTIVATION = undefined + EDIT_PERSONS_SHIFT_LABEL = undefined + EDIT_PERSONS_SHIFT_FREE = undefined + EDIT_PERSONS_SHIFT_AVERAGE_ACTIVATION = undefined + EDIT_PERSONS_SHIFT_AVERAGE = undefined +} + +getPersonById = async (person_id) => { + return getActivePersonById(person_id).then(person => { + if (typeof person === "undefined") { + return dbGet_person_removed(DATE_YEAR_WEEK, person_id).then(person => {return person}) + } else { + return person + } + }) +} +getActivePersonById = async (person_id, year_week) => { + if ((PERSONS.length > 0) && ((typeof year_week === "undefined") || (year_week === DATE_YEAR_WEEK))) { + return PERSONS.find(a => a.id === parseFloat(person_id)) + } else if (year_week === DATE_YEAR_WEEK_TABLE_FROM) { + return PERSONS_TABLE_FROM.find(a => a.id === parseFloat(person_id)) + } else if (year_week === DATE_YEAR_WEEK_TABLE_TO) { + return PERSONS_TABLE_TO.find(a => a.id === parseFloat(person_id)) + } else { + return await dbGet_person_active(year_week, parseFloat(person_id)) + } +} + +setPerson = async () => { + return dbGet_persons_active_where_yearweek(DATE_YEAR_WEEK).then(persons => { + PERSONS = persons + return sortPersonRosterWeek(0).then(() => { + return sortPersonRosterWeek(1) + }) + }) +} +setActivePerson = (person_id, year_week) => { + if ((year_week === DATE_YEAR_WEEK) || (typeof year_week === "undefined")) { + return dbGet_person_active(DATE_YEAR_WEEK, person_id).then(person => { + let ppid = PERSONS.map(p => p.id).indexOf(person_id) + let pwid = PERSONS_WEEK.map(p => p.id).indexOf(person_id) + let prid = PERSONS_ROSTER.map(p => p.id).indexOf(person_id) + if (person) { + PERSONS[ppid] = person + PERSONS_WEEK[pwid] = person + PERSONS_ROSTER[prid] = person + } else { + PERSONS = PERSONS.filter(p => p.id !== person_id) + PERSONS_WEEK = PERSONS_WEEK.filter(p => p.id !== person_id) + PERSONS_ROSTER = PERSONS_ROSTER.filter(p => p.id !== person_id) + } + return person + }) + } else if (year_week === DATE_YEAR_WEEK_TABLE_TO) { + return dbGet_person_active(year_week, person_id).then(person => { + let ppid = PERSONS_TABLE_TO.map(p => p.id).indexOf(person_id) + if (typeof person === "undefined") { + PERSONS_TABLE_TO = PERSONS_TABLE_TO.filter(p => p.id !== person_id) + } else { + PERSONS_TABLE_TO[ppid] = person + } + return person + }) + } +} + +addPerson = () => { + showLoading("addPerson") + let person_new = {activated: DATE_YEAR_WEEK, name: "", hours: HOURS_DEFAULT, department: DEPARTMENTS[0].id, mpa: []} + DAYS.forEach(d => {person_new.mpa.push(0)}) + callback = () => { + setPerson().then(() => { + editPerson(PERSON_NEW_ID, true).then(() => hideLoading("addPerson") ) + }) + } + dbAdd_person(person_new).then(pni => { + PERSON_NEW_ID = pni + person_new.id = PERSON_NEW_ID + let cl = dbGet_closingtimes_lawful() + if (cl.length === 0) { + callback() + } else { + cl.forEach((c, c_id) => { + if (getDateToRosterDate(c.end)[0] >= DATE_YEAR_WEEK) { + dbAdd_closingtime_person(c.id, PERSON_NEW_ID).then(() => { + if (c_id === cl.length-1) { + callback() + } + }) + } else { + if (c_id === cl.length-1) { + callback() + } + } + }) + } + }) +} + +removePerson = (person_id) => { + getActivePersonById(person_id).then(person => { + let block = document.getElementById("Edit-person") + block.classList.remove("active") + block.setAttribute("person", "") + block.classList.remove("active") + + block.setAttribute("person", "") + + DAYS.forEach((day, day_id) => removePersonFromShiftDay(person.id, day_id)) + + dbGet_shifts_where_person(person_id).then(shifts => { + if (shifts.length > 0) { + dbSet_person_change_where_yearweek_day_and_person_and_key(DATE_YEAR_WEEK, 999, person_id, "r", true).then(() => { + window.location = "" + }) + } else { + dbRemove_person(person_id).then(() => { + window.location = "" + }) + } + }) + }) +} + +setPersonChange = (person_id, assign_to, key, year_week, day_id, value) => { + return getActivePersonById(person_id, year_week).then(person_active => { + let old_v + if (key === "sl") {old_v = person_active.sl[day_id]} + else if (key === "sa") {old_v = person_active.sa[day_id]} + else if (key === "sf") {old_v = person_active.sf[day_id]} + + if (assign_to === "all") { + return dbSet_person_changes_where_yearweek_is_ge_and_day_and_person_and_key(person_active.activated, day_id, person_id, key, value).then(() => { + return dbSet_person_changes_where_day_and_person_and_key(day_id, person_id, key, value).then(() => { + return dbSet_person_change_where_yearweek_day_and_person_and_key(person_active.activated, day_id, person_id, key, value).then(() => { + if (key === "sf" && value) { return dbRemove_shift_where_person_and_day(person_id, day_id).then(() => {return}) } + else {return} + }) + }) + }) + } else if (assign_to === "ongoing") { + return dbSet_person_changes_where_yearweek_is_ge_and_day_and_person_and_key(year_week, day_id, person_id, key, value).then(() => { + return dbSet_person_change_where_yearweek_day_and_person_and_key(year_week, day_id, person_id, key, value).then(() => { + if (key === "sf" && value) { return dbRemove_shift_where_person_and_year_week_ge_and_day(person_id, year_week, day_id).then(() => {return})} + else {return} + }) + }) + } else if (assign_to === "justthis") { + let next_yw = getDateToRosterDate(new Date(new Date(getDateOfISOWeek(year_week)).getTime() + 7 * 24 * 60 * 60 * 1000))[0] + return dbGet_person_change_where_yearweek_and_day_and_person_and_key(next_yw, day_id, person_id, key).then(change_n => { + callS = () => { + return dbSet_person_change_where_yearweek_day_and_person_and_key(year_week, day_id, person_id, key, value).then(() => { + if (key === "sf" && value) {return dbRemove_shift_where_person_and_year_week_and_day(person_id, year_week, day_id).then(() => {return })} + else {return} + }) + } + if (change_n.length === 0) { + return dbAdd_person_change_where_yearweek_and_day_and_person_and_key(next_yw, day_id, person_id, key, old_v).then(() => { + return callS() + }) + } else { + return callS() + } + }) + + } + }) +} + +setPersonShiftActivation = async (person_id) => { + for (let i=0; i<EDIT_PERSONS_SHIFT_ACTIVATION.length; i++) { + let activation = EDIT_PERSONS_SHIFT_ACTIVATION[i] + if (activation.v) continue + let day_id = activation.d + let assign_to = document.querySelector("#Edit-person-shift-settings .select-assign-container select").value + if (i === EDIT_PERSONS_SHIFT_ACTIVATION.length-1) { + return setPersonChange(person_id, assign_to, "sl", DATE_YEAR_WEEK, day_id, false).then(() => { + return setPersonChange(person_id, assign_to, "sf", DATE_YEAR_WEEK, day_id, false).then(() => { + return setPersonChange(person_id, assign_to, "sa", DATE_YEAR_WEEK, day_id, false).then(() => { + if (i === EDIT_PERSONS_SHIFT_ACTIVATION.length-1) {return} + }) + }) + }) + } else { + await setPersonChange(person_id, assign_to, "sl", DATE_YEAR_WEEK, day_id, false).then(() => {return}) + await setPersonChange(person_id, assign_to, "sf", DATE_YEAR_WEEK, day_id, false).then(() => {return}) + await setPersonChange(person_id, assign_to, "sa", DATE_YEAR_WEEK, day_id, false).then(() => {return}) + } + } + +} +setPersonShiftLabelActivation = async (person_id) => { + let assign_to = document.querySelector("#Edit-person-shift-settings .select-assign-container select").value + for (let i=0; i<EDIT_PERSONS_SHIFT_LABEL_ACTIVATION.length; i++) { + let activation = EDIT_PERSONS_SHIFT_LABEL_ACTIVATION[i] + if (activation.v && i === EDIT_PERSONS_SHIFT_LABEL_ACTIVATION.length-1) {return} + if (activation.v) continue + if (i === EDIT_PERSONS_SHIFT_LABEL_ACTIVATION.length-1) { + return setPersonChange(person_id, assign_to, "sl", DATE_YEAR_WEEK, activation.d, false).then(() => { return}) + } else { + await setPersonChange(person_id, assign_to, "sl", DATE_YEAR_WEEK, activation.d, false).then(() => {return}) + } + } +} +setPersonShiftLabel = async (person_id) => { + let assign_to = document.querySelector("#Edit-person-shift-settings .select-assign-container select").value + for (let i=0; i<EDIT_PERSONS_SHIFT_LABEL.length; i++) { + let label = EDIT_PERSONS_SHIFT_LABEL[i] + if (i === EDIT_PERSONS_SHIFT_LABEL.length-1) { + return setPersonChange(person_id, assign_to, "sl", DATE_YEAR_WEEK, label.d, label.v).then(() => {return}) + } else { + await setPersonChange(person_id, assign_to, "sl", DATE_YEAR_WEEK, label.d, label.v).then(() => {return}) + } + } +} +setPersonShiftFree = async (person_id) => { + let assign_to = document.querySelector("#Edit-person-shift-settings .select-assign-container select").value + for (let i=0; i<EDIT_PERSONS_SHIFT_FREE.length; i++) { + let free = EDIT_PERSONS_SHIFT_FREE[i] + if (i === EDIT_PERSONS_SHIFT_FREE.length-1) { + return setPersonChange(person_id, assign_to, "sf", DATE_YEAR_WEEK, free.d, free.v).then(() => {return}) + } else { + await setPersonChange(person_id, assign_to, "sf", DATE_YEAR_WEEK, free.d, free.v).then(() => {return}) + } + } +} +setPersonShiftAverage = async (person_id) => { + let assign_to = document.querySelector("#Edit-person-shift-settings .select-assign-container select").value + + for (let i=0; i<EDIT_PERSONS_SHIFT_AVERAGE.length; i++) { + let average = EDIT_PERSONS_SHIFT_AVERAGE[i] + if (i === EDIT_PERSONS_SHIFT_AVERAGE.length-1) { + return setPersonChange(person_id, assign_to, "sa", DATE_YEAR_WEEK, average.d, average.v).then(() => {return}) + } else { + await setPersonChange(person_id, assign_to, "sa", DATE_YEAR_WEEK, average.d, average.v).then(() => {return}) + } + } +} +eventListenerEditPerson = (evt, is_new) => { + let block_container = document.getElementById("Edit-person-container") + let targetEl = evt.target + do { + if (block_container.contains(targetEl)) return + else {targetEl = ""} + } while (targetEl); + closeEditPerson(is_new) +} + +closeEditPerson = async (is_new) => { + showLoading("closeEditPerson") + let block = document.getElementById("Edit-person") + let person_id = parseFloat(block.getAttribute("person")) + let reload = false + let name = block.getElementsByClassName("name")[0].querySelector("input").value + let hours = block.getElementsByClassName("hours")[0].querySelector("input").value + if (is_new && name.length === 0) { + dbRemove_person(person_id) + window.location = "" + return + } + if ((name.length === 0) || (hours.length === 0)) { + hideLoading("closeEditPerson") + return + } + + funA = async () => {if (typeof EDIT_PERSONS_ACTIVATION !== "undefined") { reload = true; return await setPersonActivationValue(person_id)}} + funB = async () => {if (typeof EDIT_PERSONS_MPA !== "undefined") { reload = true; return await setPersonMpaValue(person_id) }} + funC = async () => {if (typeof EDIT_PERSONS_NAME !== "undefined") { reload = true; return await setPersonNameValue(person_id) }} + funD = async () => {if (typeof EDIT_PERSONS_HOURS !== "undefined") { reload = true; return await setPersonHoursValue(person_id) }} + funE = async () => {if (typeof EDIT_PERSONS_DEPARTMENT !== "undefined") { reload = true; return await setPersonDepartmentValue(person_id) }} + funF = async () => {if (typeof EDIT_PERSONS_SHIFT_ACTIVATION !== "undefined") { reload = true; return await setPersonShiftActivation(person_id) }} + funG = async () => {if (typeof EDIT_PERSONS_SHIFT_LABEL_ACTIVATION !== "undefined") { reload = true; return await setPersonShiftLabelActivation(person_id) }} + funH = async () => {if (typeof EDIT_PERSONS_SHIFT_LABEL !== "undefined") { reload = true; return await setPersonShiftLabel(person_id) }} + funI = async () => {if (typeof EDIT_PERSONS_SHIFT_FREE !== "undefined") { reload = true; return await setPersonShiftFree(person_id) }} + funJ = async () => {if (typeof EDIT_PERSONS_SHIFT_AVERAGE !== "undefined") { reload = true; return await setPersonShiftAverage(person_id) }} + Promise.all([funA(), funB(), funC(), funD(), funE(), funF(), funG(), funH(), funI(), funJ()]).then(() => { + if (is_new) { + window.location = "" + return + } else if (reload) { + setActivePerson(person_id).then((person) => { + resetEditPersonCheckValues() + if (person) reloadPersonData(person_id) + else getActiveRoster() + }) + } + document.body.onclick = null + document.body.classList.remove("noscroll") + + block.classList.remove("active") + block.setAttribute("person", "") + block.classList.remove("active") + document.getElementById("Edit-person-container").removeEventListener('click', (e) => { e.stopPropagation() }) + + block.setAttribute("person", "") + hideLoading("closeEditPerson") + }) + + +} +setPersonNameValue = async () => { + let assign_to = document.querySelector("#Edit-person .person-container .select-assign-to select").value + return changePersonValue(EDIT_PERSONS_NAME.p, "name", EDIT_PERSONS_NAME.d, undefined, assign_to).then(() => { + if (assign_to === "all") {return dbSet_person_where(EDIT_PERSONS_NAME.p, "name", EDIT_PERSONS_NAME.d).then(() => {return})} + }) +} +setPersonHoursValue = async () => { + let assign_to = document.querySelector("#Edit-person .person-container .select-assign-to select").value + return changePersonValue(EDIT_PERSONS_HOURS.p, "hours", EDIT_PERSONS_HOURS.d, undefined, assign_to).then(() => { + if (assign_to === "all") {return dbSet_person_where(EDIT_PERSONS_HOURS.p, "hours", EDIT_PERSONS_HOURS.d).then(() => {return})} + }) +} +setPersonDepartmentValue = async () => { + let assign_to = document.querySelector("#Edit-person .person-container .select-assign-to select").value + return changePersonValue(EDIT_PERSONS_DEPARTMENT.p, "department", EDIT_PERSONS_DEPARTMENT.d, undefined, assign_to).then(() => { + if (assign_to === "all") {return dbSet_person_where(EDIT_PERSONS_DEPARTMENT.p, "department", EDIT_PERSONS_DEPARTMENT.d).then(() => {return})} + }) +} +setPersonMpaValue = async () => { + let assign_to = document.querySelector("#Edit-person-mpa .select-assign-to select").value + let new_mpa + if (assign_to === "all") { + new_mpa = PERSONS.find(p => p.id === EDIT_PERSONS_MPA[0].p).mpa + } + for (let e=0; e<EDIT_PERSONS_MPA.length; e++) { + let data = EDIT_PERSONS_MPA[e] + if (e === EDIT_PERSONS_MPA.length-1) { + return changePersonValue(data.p, "mpa", data.v, data.d, assign_to).then(() => { + if (assign_to === "all") { + new_mpa[data.d] = data.v + return dbSet_person_where(EDIT_PERSONS_MPA[0].p, "mpa", new_mpa).then(() => {return}) + } + }) + } else { + await changePersonValue(data.p, "mpa", data.v, data.d, assign_to) + if (assign_to === "all") {new_mpa[data.d] = data.v} + } + } +} +setPersonActivationValue = async (person_id) => { + let value = EDIT_PERSONS_ACTIVATION + let date = getDateToRosterDate(value) + let year_week = date[0] + if (date[1] > DAYS.length-1) { + year_week = getDateToRosterDate(new Date(value.getTime() + 7 * 24 * 60 * 60 * 1000))[0] + } + let start = new Date(getDateOfISOWeek(DATE_YEAR_WEEK_OLDEST)) + let end = new Date(getDateOfISOWeek(year_week)) + end = new Date(end.getTime() - 1 * 24 * 60 * 60 * 1000); + removePersonShiftsBetweenDate(person_id, start, end, true) + return await dbSet_person_person_activated(person_id, year_week) +} + +renderChangePersonActivationInput = (person_id) => { + let block_activation_input_container = document.querySelector("#Edit-person-container .activation .input-container") + let block_dnone = document.querySelector("#Edit-person-container .select-activation") + block_dnone.classList.add("d-none") + let block_input = document.createElement("input") + block_input.setAttribute("type", "date") + block_input.setAttribute("onchange", `EDIT_PERSONS_ACTIVATION = new Date(this.value)`) + block_input.value = getDateOfISOWeek(DATE_YEAR_WEEK).toISOString().substring(0,10) + block_activation_input_container.appendChild(block_input) +} +checkChangePersonActivation = (person_id, value) => { + if (value === "Andere") { + renderChangePersonActivationInput(person_id) + return + } + EDIT_PERSONS_ACTIVATION = getDateOfISOWeek(value) +} + +renderChangePersonActivationSelect = async (person_id) => { + let person = await getActivePersonById(person_id) + let block_activation_input_container = document.querySelector("#Edit-person-container .activation .input-container") + block_activation_input_container.innerHTML = "" + let block_activation_select_label = document.createElement("label") + block_activation_select_label.classList.add("chevron-down", "chevron-select") + let block_activation_select = document.createElement("select") + block_activation_select.classList.add("select-activation") + block_activation_select.setAttribute("onChange", `checkChangePersonActivation(${person_id}, this.value)`) + let activation_options = [...ROSTERS_YEARWEEK] + if (activation_options.indexOf(person.activated) === -1) {activation_options.push(person.activated)} + activation_options.sort((a, b) => getDateOfISOWeek(b) - getDateOfISOWeek(a)) + activation_options = ["Andere",...activation_options] + activation_options.forEach( a_year_week => { + let block_option = document.createElement("option") + block_option.innerHTML = a_year_week === "Andere" ? "Datum wählen" : a_year_week + if (a_year_week === person.activated) {block_option.defaultSelected = true} + block_activation_select.appendChild(block_option) + }) + block_activation_select_label.appendChild(block_activation_select) + block_activation_input_container.appendChild(block_activation_select_label) + +} +changePersonName = (person_id, value) => { + EDIT_PERSONS_NAME = {p: person_id, d: value} +} +changePersonHours = (person_id, value) => { + EDIT_PERSONS_HOURS = {p: person_id, d: value} +} +changePersonDepartment = (person_id, value) => { + EDIT_PERSONS_DEPARTMENT = {p: person_id, d: value} +} +changePersonFreedays = (el, person_id, value) => { + el.classList.toggle("active") + if (typeof EDIT_PERSONS_FREEDAYS === "undefined") { + EDIT_PERSONS_FREEDAYS = [{p: person_id, d: value}] + } else { + let remove = EDIT_PERSONS_FREEDAYS.indexOf(value) + if (remove > -1) EDIT_PERSONS_FREEDAYS.splice(remove, 1) + else EDIT_PERSONS_FREEDAYS.push({p: person_id, d: value}) + } +} +changePersonMpa = (person_id, value, day_id) => { + value = parseFloat(value) + if (typeof EDIT_PERSONS_MPA === "undefined") { + EDIT_PERSONS_MPA = [{p: person_id, v: value, d: day_id}] + } else { + let edit_id = EDIT_PERSONS_MPA.map(m => m.d).indexOf(day_id) + if (edit_id === -1) { + EDIT_PERSONS_MPA.push({p: person_id, v: value, d: day_id}) + } else { + EDIT_PERSONS_MPA[edit_id].v = value + } + } +} +changePersonValue = async (person_id, name, value, day_id, assign_to) => { + let year_week = DATE_YEAR_WEEK + let person = await getActivePersonById(person_id) + let change_id + let add_change + + setChange = async (key, old_value, day_id) => { + if (assign_to === "all") { + return dbSet_person_changes_where_yearweek_is_ge_and_day_and_person_and_key(person.activated, day_id, person_id, key, value).then(() => { + return dbSet_person_changes_where_person_and_key(person_id, key, value) + }) + } else if (assign_to === "ongoing") { + return dbSet_person_changes_where_yearweek_is_ge_and_day_and_person_and_key(year_week, day_id, person_id, key, value).then(() => { + return dbSet_person_change_where_yearweek_day_and_person_and_key(year_week, day_id, person_id, key, value) + }) + } else if (assign_to === "justthis") { + let next_yw = DATE_YEAR_WEEK_AFTER + let change_n = await dbGet_person_change_where_yearweek_and_day_and_person_and_key(next_yw, day_id, person_id, key) + return dbSet_person_change_where_yearweek_day_and_person_and_key(year_week, day_id, person_id, key, value).then(() => { + if (change_n?.length === 0) { + return dbSet_person_change_where_yearweek_day_and_person_and_key(next_yw, day_id, person_id, key, old_value).then(() => {return}) + } else {return} + }) + } + } + if (name === "name") { + return setChange("n", person.name, 999) + } else if (name === "hours") { + value = parseFloat(value) + return setChange("h", person.hours, 999) + } else if (name === "department") { + value = parseFloat(value) + return setChange("d", person.department, 999) + } else if (name === "mpa") { + value = parseFloat(value) + return setChange("m", person.mpa[day_id], day_id) + } +} + + +createMpaItems = async (person_id) => { + let block = document.createElement("div") + block.classList.add("container") + let person = await getActivePersonById(person_id) + if (typeof person === "undefined") {person = await getPersonById(person_id)} + createB = () => { + DAYS.forEach((day, day_id) => { + let block_item = document.createElement("div") + let block_name = document.createElement("label") + let block_input = document.createElement("input") + block_item.classList.add("item") + block_name.innerHTML = day.substring(0,2) + block_input.setAttribute("onchange", `changePersonMpa(${person_id}, this.value, ${day_id})`) + block_input.setAttribute("type", "number") + block_input.setAttribute("min", "0") + block_input.setAttribute("step", "0.5") + block_input.value = person.mpa[day_id] + block_item.appendChild(block_name) + block_item.appendChild(block_input) + block.appendChild(block_item) + }) + return block + } + return createB() +} +addOvertime = async (person_id, year_week, time) => { + time = parseFloat(time) + return dbGet_person_overtime_manual_where_yearweek(year_week, person_id).then(overtime => { + if (typeof overtime === "undefined" && time === 0) {return} + return dbSet_person_overtime_manual_where_yearweek(year_week, person_id, time).then(() => { + return setActivePerson(person_id).then(() => { + return reloadPersonData(person_id) + }) + }) + }) +} +saveOvertime = (person_id) => { + let block = document.getElementById("Edit-person-overtime") + let block_add = block.getElementsByClassName("container-add")[0] + let block_save = block_add.getElementsByClassName("button-add")[0] + let block_year_week_label = block_add.querySelector("label") + let block_year_week = block_year_week_label.querySelector("select") + let block_time = block_add.querySelector("input") + + addOvertime(person_id, block_year_week.value, block_time.value).then(() => { + block_save.setAttribute("onClick", `renderAddOvertime(${person_id})`) + block_add.removeChild(block_year_week_label) + block_add.removeChild(block_time) + block_save.innerHTML = "Hinzufügen" + renderOvertimes(person_id) + }) +} +setOvertimeInputValue = async (person_id, year_week) => { + let block_add = document.querySelector("#Edit-person-overtime .container-add") + let block_time = block_add.querySelector("input") + return dbGet_person_overtime_manual_where_yearweek(year_week, person_id).then(overtime => { + if (typeof overtime === "undefined") {overtime = 0} + block_time.value = overtime + return + }) +} +cancelAddOvertime = (el, person_id) => { + block = el.parentNode + block.classList.remove("active") + window.setTimeout(() => { + block.innerHTML = `<button class="button-add button-whitegreen" onclick="renderAddOvertime(${person_id})">Hinzufügen</button>` + },50) +} +renderAddOvertime = (person_id) => { + let block_container = document.getElementById("Edit-person-overtime") + let block_add = block_container.getElementsByClassName("container-add")[0] + block_add.classList.add("active") + let block_cancel = document.createElement("button") + block_cancel.classList.add("button-cancel", "button-orange") + block_cancel.innerHTML = "Abbrechen" + block_cancel.setAttribute("onClick", `cancelAddOvertime(this, ${person_id})`) + block_add.appendChild(block_cancel) + let block_save = block_add.getElementsByClassName("button-add")[0] + block_save.setAttribute("onClick", `saveOvertime(${person_id})`) + block_save.innerHTML = "Speichern" + + let block_label_year_week = document.createElement("label") + block_label_year_week.classList.add("chevron-select", "chevron-down") + let block_select_year_week = document.createElement("select") + block_select_year_week.setAttribute("onchange", `setOvertimeInputValue(${person_id}, this.value)`) + + let year_weeks = [...ROSTERS_YEARWEEK] + year_weeks.sort((a, b) => getDateOfISOWeek(b) - getDateOfISOWeek(a)) + year_weeks.forEach(year_week => { + let block_option_year_week = document.createElement("option") + block_option_year_week.innerHTML = year_week + block_option_year_week.setAttribute("value", year_week) + if (year_week === DATE_YEAR_WEEK) {block_option_year_week.defaultSelected = true} + block_select_year_week.appendChild(block_option_year_week) + }) + + let block_input = document.createElement("input") + block_input.setAttribute("type", "number") + block_input.setAttribute("step", "0.25") + + block_label_year_week.appendChild(block_select_year_week) + block_add.appendChild(block_label_year_week) + block_add.appendChild(block_input) + + setOvertimeInputValue(person_id, DATE_YEAR_WEEK) +} + +renderOvertimes = async (person_id) => { + return getActivePersonById(person_id).then(person => { + let block_overtime = document.getElementById("Edit-person-overtime") + let block_overtime_container = block_overtime.querySelector(".container") + block_overtime_container.innerHTML = "" + + let block_table = document.createElement("table") + let block_thead = document.createElement("thead") + let block_thead_tr = document.createElement("tr") + + let block_thead_th_y = document.createElement("th") + block_thead_th_y.innerHTML = "Woche" + block_thead_tr.appendChild(block_thead_th_y) + let block_thead_th_a = document.createElement("th") + block_thead_th_a.innerHTML = "Automatisch" + block_thead_th_a.setAttribute("title", "Die Stunden ergeben sich durch die hinzugefügten Schichten.") + block_thead_tr.appendChild(block_thead_th_a) + let block_thead_th_m = document.createElement("th") + block_thead_th_m.innerHTML = "Manuell" + block_thead_th_m.setAttribute("title", "Die Stunden wurden manuell hinzugefügt.") + block_thead_tr.appendChild(block_thead_th_m) + + block_thead.appendChild(block_thead_tr) + block_table.appendChild(block_thead) + + let block_tbody = document.createElement("tbody") + block_table.appendChild(block_tbody) + + let year_weeks = [...ROSTERS_YEARWEEK] + createB = (overtimes) => { + let block_tr_t = document.createElement("tr") + let block_td_t_y = document.createElement("td") + block_td_t_y.innerHTML = "Insgesamt" + block_tr_t.appendChild(block_td_t_y) + let block_td_t_a = document.createElement("td") + block_tr_t.appendChild(block_td_t_a) + let block_td_t_m = document.createElement("td") + block_tr_t.appendChild(block_td_t_m) + block_tbody.appendChild(block_tr_t) + let total_a = 0 + let total_m = 0 + for (let ywi=0; ywi<year_weeks.length; ywi++) { + let year_week = year_weeks[ywi] + if (person.activated > year_week) continue + let ot = overtimes.find(o => o.yearweek === year_week) + if (typeof ot === "undefined") continue + let overtime = parseFloat((ot.hours_is-ot.hours_should).toFixed(2)) + let overtime_m = person.overtimes_manual.find(o => o.yearweek === year_week) + + let block_tr = document.createElement("tr") + + let block_td_y = document.createElement("td") + block_td_y.innerHTML = year_week + block_tr.appendChild(block_td_y) + + let block_td_a = document.createElement("td") + if (typeof overtime_m !== "undefined") { + overtime = parseFloat((overtime-(overtime_m.overtime)).toFixed(2)) + total_m = parseFloat((total_m+(overtime_m.overtime)).toFixed(2)) + } + total_a = parseFloat((total_a+(overtime)).toFixed(2)) + if (overtime > 0) {overtime = `+${overtime}`} + block_td_a.innerHTML = overtime + block_tr.appendChild(block_td_a) + + let block_td_m = document.createElement("td") + if (typeof overtime_m === "undefined") {overtime_m = ""} + else {overtime_m = overtime_m.overtime} + if (overtime_m > 0) overtime_m = `+${overtime_m}` + block_td_m.innerHTML = overtime_m + block_tr.appendChild(block_td_m) + + block_tbody.appendChild(block_tr) + } + if (total_a > 0) {total_a = `+${total_a}`} + else if (total_a === 0) {total_a = ` ${total_a}`} + if (total_m > 0) {total_m = `+${total_m}`} + else if (total_m === 0) {total_m = ` ${total_m}`} + block_td_t_a.innerHTML = total_a + block_td_t_m.innerHTML = total_m + block_overtime_container.appendChild(block_table) + return + } + return dbGet_person_overtimes_yearweeks(person.id).then(overtimes => { + return createB(overtimes) + }) + }) +} + +renderBlockAssignEditPersonTo = (person_id, is_new) => { + let values = [{t: "Fortlaufend", v: "ongoing"}] + let default_selected = "all" + values.push({t: "Einmalig", v: "justthis"}) + values.push({t: "Alle", v: "all"}) + if (DATE_YEAR_WEEK === DATE_YEAR_WEEK_NEWEST) {default_selected = "ongoing"} + else {default_selected = "justthis"} + let block_label_select = document.createElement("label") + block_label_select.classList.add("select-assign-to", "chevron-down", "chevron-select") + block_label_select.setAttribute("title", "Die Änderung wird auf den folgenden Zeitraum übertragen.\nAlle: Vergangene und zukünftige Dienspläne\nFortlaufend: Aktueller und zukünftige Dienspläne.\nEinmalig: nur aktuelle Dienstplanwoche") + let block_select = document.createElement("select") + if (is_new) { + block_select.setAttribute("disabled", "disabled") + } + values.forEach(data => { + let block_option = document.createElement("option") + block_option.innerHTML = data.t + block_option.value = data.v + if (is_new && data.v === "all") {block_option.defaultSelected = true} + else if (data.v === default_selected) {block_option.defaultSelected = true} + block_select.appendChild(block_option) + }) + block_label_select.appendChild(block_select) + return block_label_select +} +reactivatePerson = (person_id) => { + dbRemove_person_changes_where_person_and_key(person_id, "r").then(() => { + window.location = "" + }) +} + +activateShiftSettingAverage = (day_id) => { + let block_container = document.querySelector(`#Edit-person-shift-settings-${day_id}`) + let block_button_hours = block_container.querySelector(".button-average") + let block_item_hours = block_container.querySelector(".item-average") + let block_item_hours_input = block_item_hours.querySelector("input") + if (block_button_hours.classList.contains("active")) { + changePersonShiftSettingsAverage(day_id, undefined) + block_item_hours.classList.remove("active") + block_button_hours.classList.remove("active") + block_item_hours_input.classList.add("d-none") + } else { + block_item_hours.classList.add("active") + block_button_hours.classList.add("active") + block_item_hours_input.classList.remove("d-none") + } +} +activateShiftSettingLabel = (day_id) => { + let block_container = document.querySelector(`#Edit-person-shift-settings-${day_id}`) + let block_item_label = block_container.querySelector(".item-label") + let block_button_label = block_container.querySelector(".button-label") + let block_select_label = block_container.querySelector(".select-label-label") + let block_select = block_container.querySelector(".select-label") + let block_free = block_container.querySelector(".button-free") + let block_average = block_container.querySelector(".item-average") + let value + if (block_button_label.classList.contains("active")) { + value = false + block_button_label.classList.remove("active") + block_item_label.classList.remove("active") + block_select_label.classList.add("d-none") + block_free.classList.add("d-none") + block_free.classList.remove("active") + block_average.classList.remove("d-none") + } else { + value = true + block_button_label.classList.add("active") + block_item_label.classList.add("active") + block_select_label.classList.remove("d-none") + changePersonShiftSettingsLabel(day_id) + } + if (typeof EDIT_PERSONS_SHIFT_LABEL_ACTIVATION === "undefined") {EDIT_PERSONS_SHIFT_LABEL_ACTIVATION = []} + let a_id = EDIT_PERSONS_SHIFT_LABEL_ACTIVATION.map(a => a.d).indexOf(day_id) + if (a_id > -1) {EDIT_PERSONS_SHIFT_LABEL_ACTIVATION[a_id].v = value} + else EDIT_PERSONS_SHIFT_LABEL_ACTIVATION.push({v: value, d: day_id}) + let l_id = -1 + if (typeof EDIT_PERSONS_SHIFT_LABEL !== "undefined") {l_id = EDIT_PERSONS_SHIFT_LABEL.map(a => a.d).indexOf(day_id)} + if (typeof EDIT_PERSONS_SHIFT_LABEL === "undefined") {EDIT_PERSONS_SHIFT_LABEL = []} + if (value) { + if (l_id > -1) { + EDIT_PERSONS_SHIFT_LABEL[l_id].v = SHIFT_LABELS[0].id + } else EDIT_PERSONS_SHIFT_LABEL.push({d: day_id, v: SHIFT_LABELS[0].id}) + } else { + if (l_id > -1) { + EDIT_PERSONS_SHIFT_LABEL[l_id].v = false + } else { + EDIT_PERSONS_SHIFT_LABEL.push({d: day_id, v: false}) + } + let f_id = -1 + if (typeof EDIT_PERSONS_SHIFT_FREE !== "undefined") {f_id = EDIT_PERSONS_SHIFT_FREE.map(f => f.d).indexOf(day_id)} + if (typeof EDIT_PERSONS_SHIFT_FREE === "undefined") {EDIT_PERSONS_SHIFT_FREE = []} + if (l_id > -1) { + EDIT_PERSONS_SHIFT_FREE[l_id].v = false + } else { + EDIT_PERSONS_SHIFT_FREE.push({d: day_id, v: false}) + } + } +} +changePersonShiftSettingsLabel = (day_id) => { + let block_container = document.querySelector(`#Edit-person-shift-settings-${day_id}`) + let block_select = block_container.querySelector(".select-label") + let block_free = block_container.querySelector(".button-free") + let block_average = block_container.querySelector(".item-average") + let value = parseFloat(block_select.value) + block_free.classList.remove("d-none") + if (typeof EDIT_PERSONS_SHIFT_LABEL === "undefined") {EDIT_PERSONS_SHIFT_LABEL = []} + let l_id = EDIT_PERSONS_SHIFT_LABEL.map(a => a.d).indexOf(day_id) + let free_id = SHIFT_LABELS.find(l => l.name = "Frei").id + if (l_id > -1) { + EDIT_PERSONS_SHIFT_LABEL[l_id].v = value + } else EDIT_PERSONS_SHIFT_LABEL.push({d: day_id, v: value}) + + if (value === free_id) { + changePersonShiftSettingsFree(day_id, true) + block_free.classList.add("d-none") + } else { + changePersonShiftSettingsFree(day_id, false) + } +} +changePersonShiftSettingsFree = (day_id, value) => { + let block_container = document.querySelector(`#Edit-person-shift-settings-${day_id}`) + let block_average = block_container.querySelector(".item-average") + let block_free = block_container.querySelector(".button-free") + if (value) { + block_free.classList.add("active") + block_average.classList.add("d-none") + } else { + block_free.classList.remove("active") + block_average.classList.remove("d-none") + } + if (typeof EDIT_PERSONS_SHIFT_FREE === "undefined") {EDIT_PERSONS_SHIFT_FREE = []} + let change_id = EDIT_PERSONS_SHIFT_FREE.map(f => f.d).indexOf(day_id) + if (change_id === -1) EDIT_PERSONS_SHIFT_FREE.push({d: day_id, v: value}) + else {EDIT_PERSONS_SHIFT_FREE[change_id].v = value} +} +changePersonShiftSettingsAverage = (day_id, value) => { + if (typeof EDIT_PERSONS_SHIFT_AVERAGE === "undefined") {EDIT_PERSONS_SHIFT_AVERAGE = []} + let change_id = EDIT_PERSONS_SHIFT_AVERAGE.map(a => a.d).indexOf(day_id) + if (change_id === -1) EDIT_PERSONS_SHIFT_AVERAGE.push({d: day_id, v: value}) + else {EDIT_PERSONS_SHIFT_AVERAGE[change_id].v = value} +} +togglePersonShiftSettingsFree = (day_id) => { + let block_container = document.querySelector(`#Edit-person-shift-settings-${day_id}`) + let block_free = block_container.querySelector(".button-free") + if (block_free.classList.contains("active")) { + changePersonShiftSettingsFree(day_id, false) + } else { + changePersonShiftSettingsFree(day_id, true) + } +} +activateShiftSetting = (el, day_id) => { + let block_container = el.parentNode.parentNode.querySelector(".items") + if (typeof EDIT_PERSONS_SHIFT_ACTIVATION === "undefined") {EDIT_PERSONS_SHIFT_ACTIVATION = []} + let value + if (el.classList.contains("active")) { + value = false + el.classList.remove("active") + block_container.classList.add("d-none") + } else { + value = true + el.classList.add("active") + block_container.classList.remove("d-none") + } + let c_id = EDIT_PERSONS_SHIFT_ACTIVATION.map(c => c.d).indexOf(day_id) + if (c_id > -1) {EDIT_PERSONS_SHIFT_ACTIVATION[c_id].v = value} + else EDIT_PERSONS_SHIFT_ACTIVATION.push({v: value, d: day_id}) +} +renderEditRemovedPerson = async (person_id) => { + dbGet_person_removed(DATE_YEAR_WEEK, person_id).then(person => { + let block = document.getElementById("Popup") + block.onclick = (e) => eventListenerClosePopup(e) + let block_container = document.getElementById("Popup-container") + block.classList.add("active", "reactivate-person") + let block_name = document.createElement("h3") + block_name.innerHTML = person.name + block_container.appendChild(block_name) + + let block_activated_date = document.createElement("div") + block_activated_date.innerHTML = `Aktiviert: ${person.activated}` + block_container.appendChild(block_activated_date) + let block_removed_date = document.createElement("div") + dbGet_person_changes_where_key(person_id, "r").then(r_date => { + r_date = r_date[0].yearweek + block_removed_date.innerHTML = `Gelöscht: ${r_date }` + block_container.appendChild(block_removed_date) + + let block_reactivate = document.createElement("button") + block_reactivate.innerHTML = "Reaktivieren" + block_reactivate.setAttribute("onClick", `reactivatePerson(${person_id})`) + block_container.appendChild(block_reactivate) + }) + }) +} +editPerson = async (person_id, is_new) => { + resetEditPersonCheckValues() + let person = await getActivePersonById(person_id) + if (typeof person === "undefined") {person = await getPersonById(person_id)} + + let is_removed = await dbGet_person_changes_where_key(person_id, "r") + is_removed = is_removed[0] + if (typeof is_removed !== "undefined" && getDateOfISOWeek(is_removed.yearweek) <= getDateOfISOWeek(DATE_YEAR_WEEK)) { + renderEditRemovedPerson(person_id) + return + } + + document.body.classList.add("noscroll") + let block = document.getElementById("Edit-person") + let block_container = document.getElementById("Edit-person-container") + block.classList.add("active") + block.setAttribute("person", person_id) + + let block_close = block.getElementsByClassName("edit-close")[0] + block_close.setAttribute("onClick", `closeEditPerson(${is_new})`) + + let blockName = block.getElementsByClassName("name")[0].querySelector("input") + blockName.value = person.name + blockName.setAttribute("onChange", `changePersonName(${person_id}, this.value)`) + + let blockRemove = block.getElementsByClassName("remove")[0].querySelector("button") + blockRemove.setAttribute("onClick", 'removePerson('+person_id+'); document.body.onclick = null') + + let blockHours = block.getElementsByClassName("hours")[0].querySelector("input") + blockHours.value = person.hours + blockHours.setAttribute("onChange", `changePersonHours(${person_id}, parseFloat(this.value))`) + + + let block_select_label = document.createElement("label") + let block_select = document.createElement("select") + block_select_label.classList.add("chevron-down", "chevron-select") + + let block_department = block.getElementsByClassName("department")[0] + block_department.innerHTML = "" + let block_department_label = document.createElement("label") + block_department_label.innerHTML = "Bereich:" + block_department_label.classList.add("title") + block_department.appendChild(block_department_label) + DEPARTMENTS.forEach(department => { + let block_option = document.createElement("option") + block_option.value = department.id + block_option.innerHTML = department.name + block_select.appendChild(block_option) + }) + block_select.value = person.department + block_select.setAttribute("onChange", `changePersonDepartment(${person_id}, parseFloat(this.value))`) + block_select_label.appendChild(block_select) + block_department.appendChild(block_select_label) + + let block_person_assign_container = document.querySelector("#Edit-person-container .person-container .select-assign-container") + block_person_assign_container.innerHTML = "" + let block_person_assign_to = renderBlockAssignEditPersonTo(person_id, is_new) + block_person_assign_container.appendChild(block_person_assign_to) + + + renderChangePersonActivationSelect(person_id) + + let block_shift_setting = document.getElementById("Edit-person-shift-settings") + let block_shift_setting_assign_container = block_shift_setting.querySelector(".select-assign-container") + block_shift_setting_assign_container.innerHTML = "" + let block_shift_setting_assign_to = renderBlockAssignEditPersonTo(person_id, is_new) + block_shift_setting_assign_container.appendChild(block_shift_setting_assign_to) + let block_shift_setting_container = block_shift_setting.querySelector(".container") + block_shift_setting_container.innerHTML = "" + for (let day_id=0;day_id<DAYS.length;day_id++) { + let day = DAYS[day_id] + let setting_day_sl = person.sl[day_id] + let setting_day_sa = person.sa[day_id] + let setting_day_sf = person.sf[day_id] + let setting_day_active = true + if ((setting_day_sl === false || typeof setting_day_sl === "undefined") && !setting_day_sa && !setting_day_sf) {setting_day_active = false} + let block_s_container = document.createElement("div") + block_s_container.setAttribute("id", `Edit-person-shift-settings-${day_id}`) + block_s_container.classList.add("edit-person-shift-settings-day") + let block_name_container = document.createElement("div") + block_name_container.classList.add("button-activate-container") + let block_name = document.createElement("button") + block_name.innerHTML = day + block_name.classList.add("button-activate") + if (setting_day_active) block_name.classList.add("active") + block_name.setAttribute("title", "Schichteinstellung aktivieren") + block_name.setAttribute("onClick", `activateShiftSetting(this, ${day_id})`) + block_name_container.appendChild(block_name) + block_s_container.appendChild(block_name_container) + + let block_s_items = document.createElement("div") + block_s_items.classList.add("items") + if (!setting_day_active) block_s_items.classList.add("d-none") + let block_shift_label_container = document.createElement("div") + block_shift_label_container.classList.add("item", "item-label") + if ((setting_day_sl !== false && typeof setting_day_sl !== "undefined")) block_shift_label_container.classList.add("active") + block_shift_label_container.setAttribute("title", "Bezeichnung aktivieren.\nIn den Einstellungen können neue Bezeichnungen hinzugefügt werden.\nDie Bezeichnung erscheint in der Legende der Dienstplanwoche,\ndie Abkürzung erscheint im Schichtplan") + let block_shift_label = document.createElement("button") + block_shift_label.innerHTML = "Bezeichnung" + block_shift_label.classList.add("button-label") + if ((setting_day_sl !== false && typeof setting_day_sl !== "undefined")) block_shift_label.classList.add("active") + block_shift_label.setAttribute("onClick", `activateShiftSettingLabel(${day_id})`) + block_shift_label_container.appendChild(block_shift_label) + let block_shift_label_select_label = document.createElement("label") + block_shift_label_select_label.classList.add("chevron-down", "chevron-select", "select-label-label") + if ((setting_day_sl === false || typeof setting_day_sl === "undefined")) block_shift_label_select_label.classList.add("d-none") + let block_shift_label_select = document.createElement("select") + block_shift_label_select.classList.add("select-label") + block_shift_label_select.setAttribute("onchange", `changePersonShiftSettingsLabel(${day_id})`) + let longest_option_length = SHIFT_LABELS.map(d => d.name).reduce((a, b) => a.length > b.length ? a : b, '').length + SHIFT_LABELS.forEach(l => { + let block_option = document.createElement("option") + block_option.classList.add("font-number") + block_option.innerHTML = `${l.name}${" ".repeat(longest_option_length-l.name.length+1)}| ${l.cut}` + block_option.setAttribute("value", l.id) + if (setting_day_sl === l.id) {block_option.defaultSelected = true} + block_shift_label_select.appendChild(block_option) + }) + block_shift_label_select_label.appendChild(block_shift_label_select) + block_shift_label_container.appendChild(block_shift_label_select_label) + block_s_items.appendChild(block_shift_label_container) + + let block_free = document.createElement("button") + block_free.classList.add("item", "button-free", "d-none") + block_free.innerHTML = "Frei" + block_free.setAttribute("title", "Hiermit kann an diesem Tag keine Schicht vergeben werden.") + block_free.setAttribute("onClick", `togglePersonShiftSettingsFree(${day_id})`) + let free_id = SHIFT_LABELS.find(l => l.name = "Frei").id + if (setting_day_sf) {block_free.classList.add("active"); block_free.classList.remove("d-none")} + if (setting_day_sl === free_id) {block_free.classList.add("d-none")} + else if ((setting_day_sl !== false && typeof setting_day_sl !== "undefined")) block_free.classList.remove("d-none") + block_s_items.appendChild(block_free) + + let block_hours_container = document.createElement("div") + block_hours_container.classList.add("item", "item-average") + if (setting_day_sa) block_hours_container.classList.add("active") + block_hours_container.setAttribute("title", "Benutzerdefinierte durchschnittliche Arbeitszeit aktivieren.") + let block_hours_label = document.createElement("button") + block_hours_label.setAttribute("onClick", `activateShiftSettingAverage(${day_id})`) + block_hours_label.classList.add("button-average") + if (setting_day_sa) block_hours_label.classList.add("active") + block_hours_label.innerHTML = "Ø Stunden" + block_hours_container.appendChild(block_hours_label) + let block_hours = document.createElement("input") + if (!setting_day_sa) block_hours.classList.add("d-none") + block_hours.setAttribute("type", "number") + block_hours.setAttribute("step", TIME_STEP) + block_hours.setAttribute("onchange", `changePersonShiftSettingsAverage(${day_id}, parseFloat(this.value))`) + let pav = await getPersonAverageHoursDefault(person_id, day_id) + block_hours.value = pav + if (setting_day_sa) {block_hours.value = setting_day_sa} + block_hours_container.appendChild(block_hours) + block_s_items.appendChild(block_hours_container) + + block_s_container.appendChild(block_s_items) + block_shift_setting_container.appendChild(block_s_container) + } + + let block_mpa = document.getElementById("Edit-person-mpa") + let block_mpa_assign_container = block_mpa.querySelector(".select-assign-container") + block_mpa_assign_container.innerHTML = "" + let block_mpa_assign_to = renderBlockAssignEditPersonTo(person_id, is_new) + block_mpa_assign_container.appendChild(block_mpa_assign_to) + block_mpa.appendChild(block_mpa_assign_container) + let block_mpa_container = block_mpa.getElementsByClassName("container")[0] + let block_mpa_items = await createMpaItems(person_id) + if (block_mpa_container) block_mpa.removeChild(block_mpa_container) + block_mpa.appendChild(block_mpa_items) + + let block_vacation = document.getElementById("Settings-vacations") + let block_vacation_container_add = block_vacation.getElementsByClassName("container-add")[0] + let block_vacation_button = document.createElement("button") + renderVacations(person_id) + block_vacation_button.classList.add("button-add", "button-whitegreen") + block_vacation_button.setAttribute("onClick", `renderAddVacation(${person_id})`) + block_vacation_button.innerHTML = "Hinzugügen" + block_vacation_container_add.innerHTML = "" + block_vacation_container_add.appendChild(block_vacation_button) + + let block_illnes = document.getElementById("Edit-person-illnesses") + let block_illnes_container_add = block_illnes.getElementsByClassName("container-add")[0] + let block_illnes_button = document.createElement("button") + renderIllnesses(person_id) + block_illnes_button.classList.add("button-add", "button-whitegreen") + block_illnes_button.setAttribute("onClick", `renderAddIllnes(${person_id})`) + block_illnes_button.innerHTML = "Hinzugügen" + block_illnes_container_add.innerHTML = "" + block_illnes_container_add.appendChild(block_illnes_button) + + + let block_betterment = document.getElementById("Edit-person-betterments") + let block_betterment_container_add = block_betterment.getElementsByClassName("container-add")[0] + let block_betterment_button = document.createElement("button") + renderBetterments(person_id) + block_betterment_button.classList.add("button-add", "button-whitegreen") + block_betterment_button.setAttribute("onClick", `renderAddBetterment(${person_id})`) + block_betterment_button.innerHTML = "Hinzugügen" + block_betterment_container_add.innerHTML = "" + block_betterment_container_add.appendChild(block_betterment_button) + + let block_overtime = document.getElementById("Edit-person-overtime") + let block_overtime_container_add = block_overtime.querySelector(".container-add") + renderOvertimes(person_id) + let block_overtime_button = document.createElement("button") + block_overtime_button.classList.add("button-add", "button-whitegreen") + block_overtime_button.setAttribute("onClick", `renderAddOvertime(${person_id})`) + block_overtime_button.innerHTML = "Hinzugügen" + block_overtime_container_add.innerHTML = "" + block_overtime_container_add.appendChild(block_overtime_button) + + window.setTimeout(() => { + document.body.onclick = (e) => eventListenerEditPerson(e, is_new) + }, 100) +} + +getVacationsMonth = (vacation) => { + let start = new Date(vacation[0]).toLocaleString('default', { month: 'long' }) + let end = new Date(vacation[1]).toLocaleString('default', { month: 'long' }) + start = start.substring(0,3) + end = end.substring(0,3) + if (start === end) { return start + } else { return `${start}-${end}` } +} + +renderVacations = async (person_id) => { + let block = document.getElementById("Settings-vacations") + let block_vacation_container = block.getElementsByClassName("container")[0] + let block_vacations = await createBlockVacations(person_id) + if (block_vacation_container) block.removeChild(block_vacation_container) + if (block_vacations) block.appendChild(block_vacations) +} + + +createBlockVacations = async (person_id) => { + let person = await getActivePersonById(person_id) + let vacations = person.vacations.sort((a,b) => b.start.localeCompare(a.start)) + let block = document.createElement("div") + block.classList.add("container") + + cB = () => { + let year_old + let block_container_year + let block_year_title + let block_year_items + for (let vs=0; vs<vacations.length;vs++) { + let vacation = vacations[vs] + let year = vacation.start.substring(0,4) + if (year !== year_old) { + year_old = year + block_container_year = document.createElement("div") + block_year_title = document.createElement("div") + block_year_items = document.createElement("div") + block_year_title.classList.add("year") + block_year_title.innerHTML = year + block_year_items.classList.add("container-items") + block_container_year.setAttribute("id", `Vacations-container-${year}`) + block_container_year.classList.add("container-data", "font-number") + block_container_year.appendChild(block_year_title) + block_container_year.appendChild(block_year_items) + block.appendChild(block_container_year) + } + + let start = vacation.start + let end = vacation.end + let description = vacation.name + + let block_container = document.createElement("div") + let block_label = document.createElement("div") + + block_container.classList.add("item") + + + let text_start_day = parseFloat(start.substring(8,10)) + let text_start_month = start.substring(5,7) + if (text_start_day.toString().length === 1) { text_start_day = ` ${text_start_day}` } + let text_start = `${text_start_day}.${text_start_month}` + + let text_end_day = parseFloat(end.substring(8,10)) + let text_end_month = end.substring(5,7) + if (text_end_day.toString().length === 1) { text_end_day = ` ${text_end_day}` } + let text_end = `${text_end_day}.${text_end_month}` + block_label.classList.add("date") + block_label.innerHTML = `${text_start} - ${text_end}.${end.substring(0,4)}` + + block_container.appendChild(block_label) + + if (typeof vacation.closingtime_id !== "undefined" && vacation.lawful === 0) { + let block_remove = document.createElement("button") + block_remove.innerHTML = "löschen" + block_remove.classList.add("button-remove") + block_remove.setAttribute("onClick", `removeVacation(${person_id}, ${vacation.closingtime_id}, true)`) + block_container.appendChild(block_remove) + } else if (typeof vacation.id !== "undefined") { + let block_remove = document.createElement("button") + block_remove.innerHTML = "löschen" + block_remove.classList.add("button-remove") + block_remove.setAttribute("onClick", `removeVacation(${person_id}, ${vacation.id})`) + block_container.appendChild(block_remove) + } else { + let block_remove = document.createElement("div") + block_container.appendChild(block_remove) + } + let block_description = document.createElement("div") + if (typeof description !== "undefined") { + block_description.classList.add("description") + block_description.innerHTML = description + } + block_container.appendChild(block_description) + block_year_items.appendChild(block_container) + + } + return block + } + return cB() +} + +removeVacation = async (person_id, vacation_id, is_closing) => { + return getActivePersonById(person_id).then((person) => { + let vacation + if (is_closing) { + vacation = person.vacations.find(v => v.closingtime_id === vacation_id) + } else { + vacation = person.vacations.find(v => v.id === vacation_id) + } + callback = () => { + return setActivePerson(person_id).then((person_n) => { + if (getDateToRosterDate(new Date(vacation.start))[0] <= DATE_YEAR_WEEK && getDateToRosterDate(new Date(vacation.end))[0] >= DATE_YEAR_WEEK) { + renderVacations(person_id) + reloadPersonData(person_id) + } else { + renderVacations(person_id) + } + return + }) + } + if (is_closing && vacation.lawful === 0) { + return dbRemove_closingtime_person(vacation_id, person_id).then(() => {return callback()}) + } else { + return dbRemove_person_vacation(vacation_id, person_id).then(() => { return callback() }) + } + }) +} + +saveVacation = async (person_id, start, end) => { + return getActivePersonById(person_id).then(person => { + let already_set = person.vacations.find(v => v.start <= start && v.end >= end) + let update = person.vacations.find(v => (v.start >= start && v.end <= start) || (v.start >= end && v.end <= end)) + + callback = () => { + removePersonShiftsBetweenDate(person_id, new Date(start), new Date(end)) + return setActivePerson(person_id).then(() => { + renderVacations(person_id) + if (getDateToRosterDate(new Date(start))[0] <= DATE_YEAR_WEEK && getDateToRosterDate(new Date(end))[0] >= DATE_YEAR_WEEK) { + reloadPersonData(person_id) + } + return + }) + } + if (typeof already_set !== "undefined") { return } + if (typeof update !== "undefined") { + return dbSet_person_vacation(person_id, update.id, start, end).then(() => {return callback()}) + } else { + return dbAdd_person_vacation(person_id, start, end).then(() => {return callback()}) + } + }) + +} +editVacation = async (person_id, vacation_id, start, end) => { + return await dbSet_person_vacation(person_id, vacation_id, start, end).then(() => { + setActivePerson(person_id).then(() => {return}) + }) +} +getSaveVacation = (person_id) => { + let block = document.getElementById("Settings-vacations") + let block_add = block.getElementsByClassName("container-add")[0] + let block_save = block_add.getElementsByClassName("button-add")[0] + let block_start = block_add.getElementsByClassName("start")[0] + let block_end = block_add.getElementsByClassName("end")[0] + let start = block_start.value + let end = block_end.value + + saveVacation(person_id, start, end) + cancelAddVacation(block_add.querySelector(".button-cancel"), person_id) +} + +setVacationEndDate = (max_date) => { + let block_container = document.getElementById("Settings-vacations") + let block_add = block_container.getElementsByClassName("container-add")[0] + let block_end = block_add.getElementsByClassName("end")[0] + let tomorrow = new Date(max_date) + tomorrow.setDate(tomorrow.getDate() + 1); + tomorrow = new Date(tomorrow.getTime() - tomorrow.getTimezoneOffset() * 60000) + + if (!isValidDate(tomorrow)) {return} + block_end.setAttribute("min", max_date) + block_end.value = tomorrow.toISOString().substr(0, 10) +} + +checkIfDateIsDuringVacation = async (person_id, date) => { + return getActivePersonById(person_id).then((person) => { + let vacations = person.vacations + if (typeof vacations === "undefined") return false + let is_true = false + vacations.forEach(vacation => { + let start = vacation.start + let end = vacation.end + if (date >= start && date <= end) { is_true = true; return } + }) + return is_true + }) +} + +createPersonVacationsTextFuture = (person_id) => { + return getActivePersonById(person_id).then(person => { + let vacations = person.vacations.sort((a,b) => a.start.localeCompare(b.start)) + + let vacations_text_all = [] + let date = getDateOfISOWeek(DATE_YEAR_WEEK) + for (let i=0; i<vacations.length; i++) { + let vacation = vacations[i] + if (vacation.end < date) {continue} + year = vacation.start.substring(0,4) + month_start = vacation.start.substring(5,7) + month_end = vacation.end.substring(5,7) + if (year > DATE_YEAR && vacations_text_all.indexOf(year) === -1) { + vacations_text_all.push(year) + } else { + let value = getVacationsMonth([vacation.start, vacation.end]) + if (vacations_text_all.indexOf(value) === -1) { + vacations_text_all.push(value) + } + } + } + return vacations_text_all.join([separator = ', ']) + }) +} + +cancelAddVacation = (el, person_id) => { + block = el.parentNode + block.classList.remove("active") + window.setTimeout(() => { + block.innerHTML = `<button class="button-add button-whitegreen" onclick="renderAddVacation(${person_id})">Hinzufügen</button>` + },50) +} +renderAddVacation = (person_id) => { + let block_container = document.getElementById("Settings-vacations") + let block_add = block_container.getElementsByClassName("container-add")[0] + block_add.classList.add("active") + let block_save = block_add.getElementsByClassName("button-add")[0] + let block_cancel = document.createElement("button") + block_cancel.classList.add("button-cancel", "button-orange") + block_cancel.innerHTML = "Abbrechen" + block_cancel.setAttribute("onClick", `cancelAddVacation(this, ${person_id})`) + block_add.appendChild(block_cancel) + let today = new Date() + today = new Date(today.getTime() - today.getTimezoneOffset() * 60000) + let tomorrow = new Date() + tomorrow.setDate(tomorrow.getDate() + 1); + tomorrow = new Date(tomorrow.getTime() - tomorrow.getTimezoneOffset() * 60000) + + + let block_start = document.createElement("input") + block_start.classList.add("start") + block_start.setAttribute("type", "date") + block_start.setAttribute("onchange", `setVacationEndDate(this.value)`) + block_start.value = today.toISOString().substr(0, 10) + + let block_end = document.createElement("input") + block_end.classList.add("end") + block_end.setAttribute("type", "date") + block_end.setAttribute("min", today) + block_end.value = tomorrow.toISOString().substr(0, 10); + + block_add.appendChild(block_start) + block_add.appendChild(block_end) + + block_save.setAttribute("onClick", `getSaveVacation(${person_id})`) + block_save.innerHTML = "Speichern" +} + +getIllnessesMonth = (illnes) => { + let start = new Date(illnes.start).toLocaleString('default', { month: 'long' }) + let end = new Date(illnes.end).toLocaleString('default', { month: 'long' }) + start = start.substring(0,3) + end = end.substring(0,3) + if (start === end) { return start + } else { return `${start}-${end}` } +} + +sortPeoplIllnessesByYear = async (person_id) => { + let sorted = [] + let illnesses = await dbGet_person_illnesses(person_id) + if (illnesses.length === 0) return + illnesses.sort((a, b) => { return new Date(a.start) - new Date(b.start)}) + + illnesses.forEach(illnes => { + let illnes_id = illnes.id + let start = new Date(illnes.start) + let year = start.getFullYear() + if (sorted.find(data => {return data.year === year})) { + sorted.find(data => {return data.year === year}).ids.push(illnes_id) + } else { + sorted.push({year: year, ids: [illnes_id]}) + } + + }) + sorted.sort((a, b) => { return a.year - b.year }) + + return sorted +} + +addIllnesToday = (person_id, day_id) => { + let date = getDayDateByDayid(day_id) + addIllnesDate(person_id, date, date) + closeRosterPersonMenu(person_id, day_id) + setActivePerson(person_id).then(() => { + reloadPersonData(person_id) + }) +} + +addIllnesDate = async (person_id, start, end) => { + let before_start = new Date(start) + before_start.setDate(before_start.getDate() - 1) + before_start = before_start.toISOString().substr(0, 10) + let after_end = new Date(end) + after_end.setDate(after_end.getDate() - 1) + after_end = after_end.toISOString().substr(0, 10) + + + let check = true + let change_start_id + let change_end_id + getActivePersonById(person_id).then((person) => { + let illnesses = person.illnesses + illnesses.forEach(data => { + let id = data.id + if (start >= data.start && end <= data.end) { check = false; return} + if (before_start === data.end) {change_start_id = id } + if (after_end === data.start) {change_end_id = id } + }) + + callback = () => { + removePersonShiftsBetweenDate(person_id, new Date(start), new Date(end)) + setActivePerson(person_id).then(() => { + renderIllnesses(person_id) + if (getDateToRosterDate(new Date(start))[0] <= DATE_YEAR_WEEK && getDateToRosterDate(new Date(end))[0] >= DATE_YEAR_WEEK) { + reloadPersonData(person_id) + } + }) + } + if (typeof change_start_id !== "undefined") { + let illnes = illnesses.find(i => i.id === change_start_id) + dbSet_person_illnes(change_start_id, person_id, illnes.start, end).then(() => callback()) + } else if (typeof change_end_id !== "undefined") { + let illnes = illnesses.find(i => i.id === change_end_id) + dbSet_person_illnes(change_end_id, person_id, start, illnes.end).then(() => callback()) + } + else if (check) { + dbAdd_person_illnes(person_id, start, end).then(() => callback()) + } + }) +} + +saveIllnes = (person_id) => { + let block = document.getElementById("Edit-person-illnesses") + let block_add = block.getElementsByClassName("container-add")[0] + let block_save = block_add.getElementsByClassName("button-add")[0] + let block_start = block_add.getElementsByClassName("start")[0] + let block_end = block_add.getElementsByClassName("end")[0] + let start = block_start.value + let end = block_end.value + + addIllnesDate(person_id, start, end) + cancelAddIllnes(block_add.querySelector(".button-cancel"), person_id) +} + +removeIllnes = (person_id, illnes_id) => { + let illnes = PERSONS.find(p => p.id === person_id).illnesses.find(i => i.id === illnes_id) + dbRemove_person_illnes(illnes_id, person_id).then(() => { + setActivePerson(person_id).then(() => { + renderIllnesses(person_id) + if (getDateToRosterDate(new Date(illnes.start))[0] <= DATE_YEAR_WEEK && getDateToRosterDate(new Date(illnes.end))[0] >= DATE_YEAR_WEEK) { + reloadPersonData(person_id) + } + }) + }) +} + +createPersonLabelsText = async (person_id) => { + let text = "" + let person = await getActivePersonById(person_id) + if (typeof person === "undefined") {person = await getPersonById(person_id)} + + person.sl.forEach((sl, sl_d) => { + if ((sl === false || typeof sl === "undefined")) return + text = `${text}<div><div>${DAYS[sl_d].substring(0,2)}</div><div>${dbGet_shift_label_cut(sl)}</div></div>` + }) + + return text +} +createPersonMpaText = async (person_id) => { + let text = "" + let person = await getActivePersonById(person_id) + if (typeof person === "undefined") {person = await getPersonById(person_id)} + + person.mpa.forEach((mpa, day_id) => { + if (mpa === 0) return + text = `${text}<div><div>${DAYS[day_id].substring(0,2)}</div><div>${mpa}</div></div>` + }) + + return text +} + +createPersonIllnessesTextFuture = async (person_id) => { + let illnesses_sorted = await sortPeoplIllnessesByYear(person_id) + let illnesses_all = await dbGet_person_illnesses(person_id) + + let illnesses_text_all = [] + if (typeof illnesses_sorted === "undefined") { return illnesses_text_all} + getI = () => { + illnesses_sorted.forEach(year_data => { + let year = year_data.year + year_data.ids.forEach(illnes_id => { + let illnes = illnesses_all.find(il => il.id === illnes_id) + let checkDate = new Date(new Date(illnes.end).getTime() - new Date(illnes.end).getTimezoneOffset() * 60000) + if (checkDate.toISOString().substr(0, 10) < new Date(DATE).toISOString().substr(0, 10)) return + if (year === DATE.getFullYear()) { illnesses_text_all.push(getIllnessesMonth(illnes)) } + else { if (illnesses_text_all.indexOf(year) === -1) { illnesses_text_all.push(year) } } + }) + }) + return illnesses_text_all + } + return getI().join([separator = ', ']) +} + +renderIllnesses = async (person_id) => { + let block = document.getElementById("Edit-person-illnesses") + let block_illnes_container = block.getElementsByClassName("container")[0] + let block_illnesses = await createBlockIllnesses(person_id) + if (block_illnes_container) block.removeChild(block_illnes_container) + if (block_illnesses) block.appendChild(block_illnesses) +} + +setIllnesEndDate = (max_date) => { + let block_container = document.getElementById("Edit-person-illnesses") + let block_add = block_container.getElementsByClassName("container-add")[0] + let block_end = block_add.getElementsByClassName("end")[0] + let tomorrow = new Date(max_date) + if (!isValidDate(tomorrow)) {return} + tomorrow.setDate(tomorrow.getDate() + 1); + + block_end.setAttribute("min", max_date) + block_end.value = tomorrow.toISOString().substr(0, 10) +} + +checkIfDateIsDuringIllnes = (person_id, date) => { + return getActivePersonById(person_id).then((person) => { + let illnesses = person.illnesses + if (typeof illnesses === "undefined") return false + let is_true = false + illnesses.forEach(illnes => { + let start = illnes.start + let end = illnes.end + if (date >= start && date <= end) { is_true = true; return } + }) + return is_true + }) +} + +createBlockIllnesses = async (person_id) => { + let illnesses = await dbGet_person_illnesses(person_id) + if ( (typeof illnesses === "undefined") || (illnesses.length === 0) ) return + let block = document.createElement("div") + block.classList.add("container") + + let illnesses_sorted = await sortPeoplIllnessesByYear(person_id) + cB = () => { + illnesses_sorted.forEach(data => { + let year = data.year + let block_container_year = document.createElement("div") + let block_year_title = document.createElement("div") + let block_year_items = document.createElement("div") + block_year_title.classList.add("year") + block_year_title.innerHTML = year + block_year_items.classList.add("container-items") + block_container_year.setAttribute("id", `Illnesses-container-${year}`) + block_container_year.classList.add("container-data", "font-number") + block_container_year.appendChild(block_year_title) + + data.ids.forEach(illnes_id => { + let illnes = illnesses.find(i => i.id === illnes_id) + let start = new Date(illnes.start) + let end = new Date(illnes.end) + + let block_container = document.createElement("div") + let block_label = document.createElement("div") + let block_remove = document.createElement("button") + block_remove.classList.add("button-remove") + + block_container.classList.add("item") + + block_remove.innerHTML = "löschen" + block_remove.setAttribute("onClick", `removeIllnes(${person_id}, ${illnes_id})`) + + let text_start_day = start.getDate() + let text_start_month = start.getMonth()+1 + if (text_start_day.toString().length === 1) { text_start_day = ` ${text_start_day}` } + if (text_start_month.toString().length === 1) { text_start_month = `0${text_start_month}` } + let text_start = `${text_start_day}.${text_start_month}` + + let text_end_day = end.getDate() + let text_end_month = end.getMonth()+1 + if (text_end_day.toString().length === 1) { text_end_day = ` ${text_end_day}` } + if (text_end_month.toString().length === 1) { text_end_month = `0${text_end_month}` } + let text_end = `${text_end_day}.${text_end_month}` + block_label.classList.add("date") + block_label.innerHTML = `${text_start} - ${text_end}.${end.getFullYear() % 100}` + + block_container.appendChild(block_label) + block_container.appendChild(block_remove) + block_year_items.appendChild(block_container) + }) + + block_container_year.appendChild(block_year_items) + block.appendChild(block_container_year) + }) + return block + } + return cB() +} + + +cancelAddIllnes = (el, person_id) => { + block = el.parentNode + block.classList.remove("active") + window.setTimeout(() => { + block.innerHTML = `<button class="button-add button-whitegreen" onclick="renderAddIllnes(${person_id})">Hinzufügen</button>` + },50) +} +renderAddIllnes = (person_id) => { + let block_container = document.getElementById("Edit-person-illnesses") + let block_add = block_container.getElementsByClassName("container-add")[0] + block_add.classList.add("active") + let block_save = block_add.getElementsByClassName("button-add")[0] + let block_cancel = document.createElement("button") + block_cancel.classList.add("button-cancel", "button-orange") + block_cancel.innerHTML = "Abbrechen" + block_cancel.setAttribute("onClick", `cancelAddIllnes(this, ${person_id})`) + block_add.appendChild(block_cancel) + let tomorrow = new Date() + let after_tomorrow = new Date() + tomorrow.setDate(tomorrow.getDate() + 1); + tomorrow = new Date(tomorrow.getTime() - tomorrow.getTimezoneOffset() * 60000) + after_tomorrow.setDate(after_tomorrow.getDate() + 2); + after_tomorrow = new Date(after_tomorrow.getTime() - after_tomorrow.getTimezoneOffset() * 60000) + + + let block_start = document.createElement("input") + block_start.classList.add("start") + block_start.setAttribute("type", "date") + block_start.setAttribute("onchange", `setIllnesEndDate(this.value)`) + block_start.value = tomorrow.toISOString().substr(0, 10) + + let block_end = document.createElement("input") + block_end.classList.add("end") + block_end.setAttribute("type", "date") + block_end.setAttribute("min", tomorrow) + block_end.value = after_tomorrow.toISOString().substr(0, 10); + + block_add.appendChild(block_start) + block_add.appendChild(block_end) + + block_save.setAttribute("onClick", `saveIllnes(${person_id})`) + block_save.innerHTML = "Speichern" +} + + +renderBetterments = async (person_id) => { + let block = document.getElementById("Edit-person-betterments") + let block_betterment_container = block.getElementsByClassName("container")[0] + let block_betterments = await createBlockBetterments(person_id) + if (block_betterment_container) block.removeChild(block_betterment_container) + if (block_betterments) block.appendChild(block_betterments) +} + +setBettermentEndDate = (max_date) => { + max_date = new Date(max_date) + if (!isValidDate(max_date)) {return} + let block_container = document.getElementById("Edit-person-betterments") + let block_add = block_container.getElementsByClassName("container-add")[0] + let block_end = block_add.getElementsByClassName("end")[0] + + block_end.setAttribute("min", max_date) + block_end.value = max_date.toISOString().substr(0, 10) +} + +checkIfDateIsDuringBetterment = async (person_id, date) => { + return getActivePersonById(person_id).then(person => { + let betterments = person.betterments + if (typeof betterments === "undefined") return false + let is_true = false + betterments.forEach(betterment => { + let start = betterment.start + let end = betterment.end + if (date >= start && date <= end) { is_true = true; return } + }) + return is_true + }) +} + +createBlockBetterments = async (person_id) => { + let betterments = await dbGet_person_betterments(person_id) + if ( (typeof betterments === "undefined") || (betterments.length === 0) ) return + let block = document.createElement("div") + block.classList.add("container") + + let betterments_sorted = await sortPersonBettermentsByYear(person_id) + cB = () => { + betterments_sorted.forEach(data => { + let year = data.year + let block_container_year = document.createElement("div") + let block_year_title = document.createElement("div") + let block_year_items = document.createElement("div") + block_year_title.classList.add("year") + block_year_title.innerHTML = year + block_year_items.classList.add("container-items") + block_container_year.setAttribute("id", `Betterments-container-${year}`) + block_container_year.classList.add("container-data", "font-number") + block_container_year.appendChild(block_year_title) + + data.ids.forEach(betterment_id => { + let betterment = betterments.find(b => b.id === betterment_id) + let start = new Date(betterment.start) + let end = new Date(betterment.end) + + let block_container = document.createElement("div") + let block_label = document.createElement("div") + let block_remove = document.createElement("button") + block_remove.classList.add("button-remove") + + block_container.classList.add("item") + + block_remove.innerHTML = "löschen" + block_remove.setAttribute("onClick", `removeBetterment(${person_id}, ${betterment_id})`) + + let text_start_day = start.getDate() + let text_start_month = start.getMonth()+1 + if (text_start_day.toString().length === 1) { text_start_day = ` ${text_start_day}` } + if (text_start_month.toString().length === 1) { text_start_month = `0${text_start_month}` } + let text_start = `${text_start_day}.${text_start_month}` + + let text_end_day = end.getDate() + let text_end_month = end.getMonth()+1 + if (text_end_day.toString().length === 1) { text_end_day = ` ${text_end_day}` } + if (text_end_month.toString().length === 1) { text_end_month = `0${text_end_month}` } + let text_end = `${text_end_day}.${text_end_month}` + block_label.classList.add("date") + block_label.innerHTML = `${text_start} - ${text_end}.${end.getFullYear() % 100}` + + let block_hours = document.createElement("div") + block_hours.innerHTML = betterment.hours + + block_container.appendChild(block_label) + block_container.appendChild(block_hours) + block_container.appendChild(block_remove) + block_year_items.appendChild(block_container) + }) + + block_container_year.appendChild(block_year_items) + block.appendChild(block_container_year) + }) + return block + } + return cB() +} + + +cancelAddBetterment = (el, person_id) => { + block = el.parentNode + block.classList.remove("active") + window.setTimeout(() => { + block.innerHTML = `<button class="button-add button-whitegreen" onclick="renderAddBetterment(${person_id})">Hinzufügen</button>` + },50) +} +renderAddBetterment = async (person_id) => { + let person = await getActivePersonById(person_id) + let block_container = document.getElementById("Edit-person-betterments") + let block_add = block_container.getElementsByClassName("container-add")[0] + block_add.classList.add("active") + let block_save = block_add.getElementsByClassName("button-add")[0] + let block_cancel = document.createElement("button") + block_cancel.classList.add("button-cancel", "button-orange") + block_cancel.innerHTML = "Abbrechen" + block_cancel.setAttribute("onClick", `cancelAddBetterment(this, ${person_id})`) + block_add.appendChild(block_cancel) + let today = new Date() + + + let block_start = document.createElement("input") + block_start.classList.add("start") + block_start.setAttribute("type", "date") + block_start.setAttribute("onchange", `setBettermentEndDate(this.value)`) + block_start.value = today.toISOString().substr(0, 10) + block_add.appendChild(block_start) + + let block_end = document.createElement("input") + block_end.classList.add("end") + block_end.setAttribute("type", "date") + block_end.setAttribute("min", today) + block_end.value = today.toISOString().substr(0, 10); + block_add.appendChild(block_end) + + let block_hours = document.createElement("input") + block_hours.classList.add("hours") + block_hours.setAttribute("title", "Stunden pro Tag") + block_hours.setAttribute("type", "number") + block_hours.setAttribute("step", "0.25") + block_hours.value = 8 + block_add.appendChild(block_hours) + + block_save.setAttribute("onClick", `saveBetterment(${person_id})`) + block_save.innerHTML = "Speichern" +} + + +getBettermentsMonth = (betterment) => { + let start = new Date(betterment.start).toLocaleString('default', { month: 'long' }) + let end = new Date(betterment.end).toLocaleString('default', { month: 'long' }) + start = start.substring(0,3) + end = end.substring(0,3) + if (start === end) { return start + } else { return `${start}-${end}` } +} + + +sortPersonBettermentsByYear = async (person_id) => { + let sorted = [] + let betterments = await dbGet_person_betterments(person_id) + betterments.sort((a, b) => { return new Date(a.start) - new Date(b.start)}) + + betterments.forEach(betterment => { + let betterment_id = betterment.id + let start = new Date(betterment.start) + let year = start.getFullYear() + if (sorted.find(data => {return data.year === year})) { + sorted.find(data => {return data.year === year}).ids.push(betterment_id) + } else { + sorted.push({year: year, ids: [betterment_id]}) + } + + }) + sorted.sort((a, b) => { return a.year - b.year }) + + return sorted +} +createPersonBettermentsTextFuture = async (person_id) => { + let betterments_sorted = await sortPersonBettermentsByYear(person_id) + let betterments_all = await dbGet_person_betterments(person_id) + + let betterments_text_all = [] + if (typeof betterments_sorted === "undefined") { return betterments_text_all} + getB = () => { + betterments_sorted.forEach(data => { + data.ids.forEach(betterment_id => { + betterment = betterments_all.find(b => b.id === betterment_id) + let checkDate = new Date(new Date(betterment.end).getTime() - new Date(betterment.end).getTimezoneOffset() * 60000) + if (checkDate.toISOString().substr(0, 10) < new Date(DATE).toISOString().substr(0, 10)) return + let year = new Date(betterment.start).getUTCFullYear() + if (year === DATE.getFullYear()) { betterments_text_all.push(getBettermentsMonth(betterment)) } + else { if (betterments_text_all.indexOf(year) === -1) { betterments_text_all.push(year) } } + }) + }) + return betterments_text_all + } + return getB().join([separator = ', ']) + +} + +addMpaToday = (person_id, day_id, hours) => { + //let date = getDayDateByDayid(day_id) + changePersonValue(person_id, "mpa", hours, day_id, "justthis").then(() => { + setActivePerson(person_id).then(() => { + reloadPersonData(person_id) + closeRosterPersonMenu(person_id, day_id) + }) + }) +} + +addBettermentToday = (person_id, day_id, hours) => { + let date = getDayDateByDayid(day_id) + addBettermentDate(person_id, date, date, hours) + closeRosterPersonMenu(person_id, day_id) + getActiveRoster() +} + +addBettermentDate = (person_id, start, end, hours) => { + hours = parseFloat(hours) + dbAdd_person_betterment(person_id, start, end, hours).then(() => { + removePersonShiftsBetweenDate(person_id, new Date(start), new Date(end)) + setActivePerson(person_id).then(() => { + renderBetterments(person_id) + if (getDateToRosterDate(new Date(start))[0] <= DATE_YEAR_WEEK && getDateToRosterDate(new Date(end))[0] >= DATE_YEAR_WEEK) { + reloadPersonData(person_id) + } + }) + }) +} +saveBetterment = (person_id) => { + let block = document.getElementById("Edit-person-betterments") + let block_add = block.getElementsByClassName("container-add")[0] + let block_save = block_add.getElementsByClassName("button-add")[0] + let block_start = block_add.getElementsByClassName("start")[0] + let block_end = block_add.getElementsByClassName("end")[0] + let block_hours = block_add.getElementsByClassName("hours")[0] + let start = block_start.value + let end = block_end.value + let hours = block_hours.value + + addBettermentDate(person_id, start, end, hours) + cancelAddBetterment(block_add.querySelector(".button-cancel"), person_id) +} + +removeBetterment = (person_id, betterment_id) => { + let betterment = PERSONS.find(p => p.id === person_id).betterments.find(i => i.id === betterment_id) + dbRemove_person_betterment(betterment_id, person_id).then(() => { + setActivePerson(person_id).then(() => { + renderBetterments(person_id) + if (getDateToRosterDate(new Date(betterment.start))[0] <= DATE_YEAR_WEEK && getDateToRosterDate(new Date(betterment.end))[0] >= DATE_YEAR_WEEK) { + reloadPersonData(person_id) + } + }) + }) +} + +getIfPersonDayIsFree = async (person_id, day_id, year_week) => { + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK} + let is_ture = false + let day = getIsoStringFromDay(day_id, year_week) + let person_active = await getActivePersonById(person_id, year_week) + let closingtime = new Promise((res, rej) => {res(dbGet_closingtime_person_during_date(person_id, day))}) + closingtime = await closingtime + let vacations_check = new Promise((res, rej) => {res(checkIfDateIsDuringVacation(person_id, day))}) + vacations_check = await vacations_check + let illnesses_check = new Promise((res, rej) => {res(checkIfDateIsDuringIllnes(person_id, day))}) + illnesses_check = await illnesses_check + let betterments_check = new Promise((res, rej) => {res(checkIfDateIsDuringBetterment(person_id, day))}) + betterments_check = await betterments_check + if (closingtime) {is_ture = closingtime.name} + else if (vacations_check) {is_ture = dbGet_settings_label_cut(3)} + else if (illnesses_check) {is_ture = dbGet_settings_label_cut(1)} + else if (betterments_check) {is_ture = dbGet_settings_label_cut(2)} + else if (person_active.sf[day_id]) { + is_ture = dbGet_shift_label_cut(person_active.sl[day_id]) + } + return is_ture +} + + +checkIfPersonDayIsFree = async (person_id, day_id, year_week) => { + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK} + return await getActivePersonById(person_id, year_week).then(person => { + let free_1 = person.freedays[day_id] + let free_2 = person.sf[day_id] + if (free_1) { + return free_1 + } else if (free_2) { + if (person.sl[day_id]) { + return SHIFT_LABELS.find(s => s.id === person.sl[day_id]).cut + } else {return true} + } else { + return false + } + }) +} + +setSelectRenderPerson = (el, value) => { + let buttons_all = document.querySelectorAll("#Person-list-buttons button") + for (i=0; i< buttons_all.length; i++) { + if (el !== buttons_all[i]) buttons_all[i].classList.remove("active") + } + if (!el.classList.contains("active")) el.classList.add("active") + renderPerson(value) +} + +getOvertimeTitleText = (overtime, name) => { + let overtime_t = overtime.toString() + let firstChar = overtime_t[0]; + if (!Number.isInteger(parseFloat(firstChar))) { + overtime_t = overtime_t.substr(1) + } + + if (overtime > 0) { + return `${name} hat ${overtime_t} Stunden zu lang gearbeitet.` + } else if ((overtime === 0) || (typeof overtime === "undefined")) { + return `${name} hat keine Überstunden.` + } else if (overtime < 0) { + return `${name} hat ${overtime_t} Stunden zu kurz gearbeitet.` + } +} + +renderPersonTableRow = (person_id) => { + createR = (person) => { + let block = document.querySelector(`#Person-table-tr-${person.id}`) + block.innerHTML = "" + let nameBlock = document.createElement("td") + let hoursBlock = document.createElement("td") + let departmentBlock = document.createElement("td") + let freedaysBlock = document.createElement("td") + let block_labels = document.createElement("td") + let block_mpa = document.createElement("td") + let block_illnesses = document.createElement("td") + let block_betterments = document.createElement("td") + block_betterments.classList.add("td-overflow", "betterment") + let block_betterments_text = document.createElement("div") + let block_vacation = document.createElement("td") + block_vacation.classList.add("td-overflow", "vacation") + let block_vacation_text = document.createElement("div") + let block_overtime = document.createElement("td") + + + nameBlock.innerHTML = person.name + hoursBlock.innerHTML = person.hours + departmentBlock.innerHTML = dbGet_department_where_id(person.department) + + block.appendChild(nameBlock) + block.appendChild(hoursBlock) + let d_color = DEPARTMENT_COLORS[DEPARTMENTS.map(d => d.id).indexOf(person.department)] + block.style.background = d_color + if (PERSONS.map(p => p.id).indexOf(person.id) === -1) { + block.classList.add("inactive") + return + } + + let freedays = [] + person.sf.forEach((sf, sf_d) => { if (sf) freedays.push(DAYS[sf_d].slice(0,2))}) + freedaysBlock.innerHTML = freedays + + block_labels.classList.add("labels") + createPersonLabelsText(person.id).then(labels_text => { + block_labels.innerHTML = labels_text + }) + + block_mpa.classList.add("mpa") + createPersonMpaText(person.id).then(mpa_text => { + block_mpa.innerHTML = mpa_text + }) + + createPersonIllnessesTextFuture(person.id).then(illnesses_text => { + block_illnesses.innerHTML = illnesses_text + }) + + createPersonVacationsTextFuture(person.id).then(vacations_text => { + block_vacation_text.innerHTML = vacations_text + block_vacation.appendChild(block_vacation_text) + }) + + createPersonBettermentsTextFuture(person.id).then(betterments_text => { + block_betterments_text.innerHTML = betterments_text + block_betterments.appendChild(block_betterments_text) + }) + + let overtime = person.overtime + if (overtime > 0) { + ov_text = `${person.name} hat ${overtime} Stunden zu lang gearbeitet.` + overtime = `+${overtime}` + } else if ((overtime === 0) || (typeof overtime === "undefined")) { + ov_text = `${person.name} hat keine Überstunden.` + } else if (overtime < 0) { + ov_text = `${person.name} hat ${overtime.toString().substring(1)} Stunden zu kurz gearbeitet.` + } + block_overtime.innerHTML = overtime + block_overtime.classList.add("td-overtime") + block_overtime.setAttribute("title", getOvertimeTitleText(overtime, person.name)) + + block.appendChild(departmentBlock) + block.appendChild(freedaysBlock) + block.appendChild(block_labels) + block.appendChild(block_mpa) + block.appendChild(block_illnesses) + block.appendChild(block_betterments) + block.appendChild(block_vacation) + block.appendChild(block_overtime) + } + getActivePersonById(person_id).then(person => { + createR(person) + }) +} + +renderPerson = async (selection) => { + showLoading("renderPerson") + if (typeof selection === "undefined") {selection = "active"} + settingsContainerHideAll("Person-container") + + let conPpl = document.getElementById("Person") + let tb = document.createElement("tbody") + conPpl.removeChild(conPpl.querySelector("tbody")) && + conPpl.appendChild(tb) + + let person_all = [] + if (selection === "active") {person_all = structuredClone(PERSONS)} + else if (selection === "all") { + person_all = structuredClone(PERSONS) + let persons_removed = await dbGet_persons_removed(DATE_YEAR_WEEK) + persons_removed.forEach(p => person_all.push(p)) + + } else if (selection === "removed") { + let persons_removed = await dbGet_persons_removed(DATE_YEAR_WEEK) + persons_removed.forEach(p => person_all.push(p)) + } + if (person_all.length === 0) { + hideLoading("renderPerson") + return + } + + person_all.sort(function (a, b) { + if (a.n < b.n) { + return -1; + } + if (a.n > b.n) { + return 1; + } + return 0; + }); + + + renPe = async (pp) => { + let ppl = document.createElement("tr") + tb.appendChild(ppl) + ppl.setAttribute("class", "Person-tr") + ppl.setAttribute("id", `Person-table-tr-${pp.id}`) + ppl.setAttribute("title", `${pp.name} bearbeiten`) + ppl.setAttribute("onClick", `editPerson(${pp.id})`) + + renderPersonTableRow(pp.id) + } + person_all.forEach((pp, id) => { + renPe(pp).then(() => {if (parseFloat(id) === person_all.length-1) hideLoading("renderPerson")}) + }) +} + +getPersonAverageHoursDefault = async (person_id, day_id, year_week) => { + let person = await getActivePersonById(person_id, year_week) + let days_free = 0 + for (let day_id=0; day_id<DAYS.length; day_id++) { + let cf = new Promise((res, rej) => {res(checkIfPersonDayIsFree(person_id, day_id, year_week))}) + cf = await cf + if (cf !== false) + {days = days_free+1} + } + return person.hours/(DAYS.length-days_free) +} +getPersonAverageHours = async (person_id, day_id, year_week) => { + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK} + return getActivePersonById(person_id, year_week).then(person => { + if (typeof day_id !== "undefined") { + let person_sa = person.sa[day_id] + if (person_sa !== false) { + let hours = person_sa+TIME_STEP + return hours + } + } + return getPersonHoursWithFreedays(person_id, year_week).then(async hours => { + let day_count = DAYS.length + let sa_check = false + let s_check = 0 + let roster = await getActiveRosterData(year_week) + let time_step = roster[day_id].d[1].t-roster[day_id].d[0].t + for (let d_id=0; d_id<roster.length; d_id++) { + let free = await checkIfPersonDayIsFree(person_id, d_id, year_week) + let sa_check = false + let d_hours = await getPersonDayHoursAndBreaks(person_id, d_id, year_week)[0] + if (typeof day_id !== "undefined" && !free && d_hours > 0) { + sa_check = true + hours = hours-d_hours + } else if (typeof day_id !== "undefined" && !free) { + let p_sa = person.sa[d_id] + if (typeof p_sa.a !== "undefined") { + sa_check = true + hours = hours-p_sa.a + } + } + if ((free !== false) || (sa_check)) { + day_count = day_count-1 + sa_check = false + hours = hours-person.mpa[d_id] + } + } + + let average + if ((hours === 0) || (day_count === 0)) {average = TIME_STEP} + else { average = parseFloat((hours/day_count).toFixed(2)) } + + if (TIME_STEP === 0.25) { + average = (Math.round(average * 4) / 4).toFixed(2) + } else if (TIME_STEP === 0.5) { + average = (Math.round(average * 2) / 2).toFixed(1) + } else { + average = Math.round(average) + } + average = parseFloat(average) + if (average < time_step) {average = time_step} + return average+time_step + }) + }) +} + +getPersonHoursWithFreedays = async (person_id, year_week) => { + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK} + let person = await getActivePersonById(person_id, year_week) + let day_count = 0 + + let roster = await getActiveRosterData(year_week) + for (let day_id=0; day_id<roster.length;day_id++) { + let free = new Promise((res, rej) => {res(checkIfPersonDayIsFree(person_id, day_id, year_week))}) + free = await free + if (free === dbGet_settings_label_cut(2)) continue + if (person.sf[day_id]) continue + if ((free === "Frei") || (!free)) continue + day_count = day_count+1 + } + hours = person.hours-day_count*(person.hours/(DAYS.length-person.sf.filter(sf => {return sf === true}).length)) + return parseFloat(hours.toFixed(2)) +} + + +getPersonDayHoursAndBreaks = async (person_id, day_id, year_week) => { + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK} + let person = await getActivePersonById(person_id, year_week) + let hours = person.shifts.filter(s => s.day_id === day_id)?.map(s => s.hours)?.reduce((a,b) => a+b, 0) + breaks = person.shifts.filter(s => s.day_id === day_id).map(s => s.breaks).reduce((a,b) => a+b, 0) + if ((person.freedays[day_id] === false) && (person.sf[day_id] === false)) { + hours = hours+person.mpa[day_id] + } + let check_date = getIsoStringFromDay(day_id, year_week) + let betterments = person.betterments.filter(b => b.start <= check_date && b.end >= check_date) + if (betterments.length > 0) { + hours = hours+betterments.map(b => b.hours).reduce((a,b) => a+b, 0) + } + return [hours, breaks] +} +getOvertimesManualYearweek = (person_id, yearweek) => { + person = PERSONS.find(p => p.id === person_id) + return person.overtimes_manual.find(o => o.yearweek === yearweek)?.overtime || 0 +} +getPersonHoursAndBreaks = async (person_id, year_week) => { + let hours = 0 + let breaks = 0 + getD = async () => { + for (let d=0; d<DAYS.length; d++) { + let hb = await getPersonDayHoursAndBreaks(person_id, d, year_week) + hours = hours+hb[0] + breaks = breaks+hb[1] + if (d === DAYS.length-1) {hours = hours+getOvertimesManualYearweek(person_id, year_week)} + } + return [ hours, breaks ] + } + return await getD() +} + +removePersonShiftDuringDate = (person_id, date, noreload) => { + let date_roster = getDateToRosterDate(date) + let year_week = date_roster[0] + let day_id = date_roster[1] + + return removePersonFromShiftDay(person_id, day_id, year_week, noreload) +} + +removePersonShiftsBetweenDate = (person_id, start, end, noreload) => { + start = new Date(start) + end = new Date(end) + let date = new Date(structuredClone(start)) + let date_string = date.toISOString().substring(0,10) + while (date_string >= start.toISOString().substring(0,10) && date_string <= end.toISOString().substring(0,10)) { + removePersonShiftDuringDate(person_id, date, noreload) + date.setDate(date.getDate()+1) + date_string = new Date(date).toISOString().substring(0,10) + } +} + diff --git a/js/popup.js b/js/popup.js new file mode 100644 index 0000000..9c4ac0d --- /dev/null +++ b/js/popup.js @@ -0,0 +1,43 @@ +renderPopupButtonClose = (onclick) => { + if (typeof onclick === "undefined") { + onclick = "closePopup()" + } + let block_popup = document.getElementById("Popup-container") + let block_close = document.createElement("button") + block_close.classList.add("button-x") + block_close.setAttribute("onClick", onclick) + block_popup.appendChild(block_close) +} + + +closePopup = () => { + document.getElementById("Popup-container").innerHTML = "" + document.getElementById("Popup-container").style = "" + document.getElementById("Popup").onclick = null + document.getElementById("Popup").removeAttribute("class") + document.body.classList.remove("noscroll") +} + +eventListenerClosePopup = (evt, type) => { + let clickEl = document.getElementById("Popup-container") + let targetEl = evt.target + do { + if (targetEl == clickEl) return + targetEl = targetEl.parentNode; + } while (targetEl); + + + showLoading("eventListenerClosePopup") + window.setTimeout(() => { + if (type === "closingtime") { + closeClosingTime() + } else if (type === "copypersonselect"){ + closeCopyPersonPopupSelect() + } else if (type === "copyperson"){ + closeCopyPersonPopup() + } else if (type === "help") { + closeHelp() + } else {closePopup()} + hideLoading("eventListenerClosePopup") + }, 50) +} diff --git a/js/roster-person-menu.js b/js/roster-person-menu.js new file mode 100755 index 0000000..d7e490c --- /dev/null +++ b/js/roster-person-menu.js @@ -0,0 +1,252 @@ + +setPersonMenuCopyMpaToday = (person_id, day_id, el) => { + setP = (person) => { + let block_container = document.createElement("div") + block_container.classList.add("free", "set-mpa") + let block_label = document.createElement("label") + block_label.innerHTML = "Stunden:" + block_container.appendChild(block_label) + let block_input = document.createElement("input") + block_input.setAttribute("id", "Get-menu-mpas-hours") + block_input.setAttribute("type", "number") + block_input.setAttribute("step", "0.25") + block_input.value = person.mpa[day_id] + block_container.appendChild(block_input) + let block_button = document.createElement("button") + block_button.innerHTML = "✓" + block_button.setAttribute("onClick", `addMpaToday(${person_id}, ${day_id}, document.getElementById("Get-menu-mpas-hours").value)`) + block_container.appendChild(block_button) + document.querySelector(`.menu-${person_id}-day-${day_id} div .menu-extras`).insertBefore(block_container, document.querySelector(`.menu-${person_id}-day-${day_id} .add-mpa`)) + el.style.display = "none" + } + getActivePersonById(person_id).then(person => setP(person)) + +} + +setPersonMenuCopyBettermentToday = async (person_id, day_id, el) => { + let block_container = document.createElement("div") + block_container.classList.add("free", "set-betterment") + let block_label = document.createElement("label") + block_label.innerHTML = "Stunden:" + block_container.appendChild(block_label) + let block_input = document.createElement("input") + block_input.setAttribute("id", "Get-menu-betterments-hours") + block_input.setAttribute("type", "number") + block_input.setAttribute("step", "0.25") + block_input.value = 8 + block_container.appendChild(block_input) + let block_button = document.createElement("button") + block_button.innerHTML = "✓" + block_button.setAttribute("onClick", `addBettermentToday(${person_id}, ${day_id}, document.getElementById("Get-menu-betterments-hours").value)`) + block_container.appendChild(block_button) + document.querySelector(`.menu-${person_id}-day-${day_id} div .menu-extras`).insertBefore(block_container, document.querySelector(`.menu-${person_id}-day-${day_id} .add-betterment`)) + el.style.display = "none" +} + +createPersonMenuCopyExtras = (person_id, day_id) => { + let block_menu_extras = document.createElement("div") + block_menu_extras.classList.add("menu-extras") + + let block_mpa = document.createElement("button") + block_mpa.innerHTML = getRenames("m").t + block_mpa.setAttribute("onClick", `setPersonMenuCopyMpaToday(${person_id}, ${day_id}, this)`) + block_mpa.setAttribute("title", `Einmalig mpa hinzufügen,- nur für diesen Tag.`) + block_mpa.classList.add("free", "add-mpa") + block_menu_extras.appendChild(block_mpa) + + let block_ill = document.createElement("button") + block_ill.innerHTML = getRenames("i").t + block_ill.setAttribute("onClick", `addIllnesToday(${person_id}, ${day_id})`) + block_ill.classList.add("free") + block_menu_extras.appendChild(block_ill) + + let block_betterment = document.createElement("button") + block_betterment.innerHTML = getRenames("b").t + block_betterment.setAttribute("onClick", `setPersonMenuCopyBettermentToday(${person_id}, ${day_id}, this)`) + block_betterment.classList.add("free", "add-betterment") + block_menu_extras.appendChild(block_betterment) + return block_menu_extras +} +createPersonMenuCopyTo = (person_id, day_id) => { + let person = PERSONS.find(p => p.id === person_id) + let block_menu = document.createElement("div") + let block_title = document.createElement("p") + let block_remove = document.createElement("button") + block_title.innerHTML = "Schicht übertragen nach:" + block_remove.innerHTML = "Schicht löschen" + block_remove.setAttribute("onClick", "closeRosterPersonMenu("+person_id+", "+day_id+"),removePersonFromShiftDay("+person_id+", "+day_id+")") + block_remove.classList.add("remove", "button-remove") + block_menu.appendChild(block_remove) + + let blocks_day = [] + let shifts = person.shifts.filter(s => s.day_id === day_id) + if (shifts.length === 0) return + let onclick_string_all = "" + for (let d_id=0; d_id<DAYS.length;d_id++) { + let day = DAYS[d_id] + if (d_id === day_id) continue + let cf = person.freedays[day_id] + if (cf) continue + let block_day = document.createElement("button") + block_day.innerHTML = day + + let onclick_string = "" + let add_function + let noshifts_reload = true + shifts.forEach((shift, sid) => { + if (sid === shifts.length-1) {noshifts_reload = false} + if (sid === 0) {add_function = `addNewShiftToRoster(${person_id}, ${d_id}, ${shift.start}, ${shift.end}, "${DATE_YEAR_WEEK}", ${noshifts_reload})`} + else {add_function = `addShift("${DATE_YEAR_WEEK}", ${d_id}, ${person_id}, ${shift.start}, ${shift.end}, ${noshifts_reload})`} + onclick_string = onclick_string+`${add_function}; ` + }) + onclick_string_all = onclick_string_all+onclick_string + + block_day.setAttribute("onClick", `closeRosterPersonMenu(${person_id}, ${day_id}); ${onclick_string}`) + blocks_day.push(block_day) + } + if (blocks_day.length > 0) { + block_menu.appendChild(block_title) + blocks_day.forEach(block => block_menu.appendChild(block)) + } + let block_all = document.createElement("button") + block_all.innerHTML = "Alle" + block_all.setAttribute("onClick", `closeRosterPersonMenu(${person_id}, ${day_id}); ${onclick_string_all}`) + block_menu.appendChild(block_all) + + let onclick_string_next_week = "" + let should_delete = true + shifts.forEach((shift, sid) => { + if (sid === 0) {add_function = `addNewShiftToRoster(${person_id}, ${day_id}, ${shift.start}, ${shift.end}, "${DATE_YEAR_WEEK_AFTER}")`} + else {add_function = `addShift("${DATE_YEAR_WEEK_AFTER}", ${day_id}, ${person_id}, ${shift.start}, ${shift.end})`} + onclick_string_next_week = onclick_string_next_week+`${add_function}; ` + }) + let block_next_week = document.createElement("button") + block_next_week.classList.add("prev-next") + block_next_week.innerHTML = "Nächste Woche" + block_next_week.setAttribute("onClick", "closeRosterPersonMenu("+person_id+", "+day_id+"); "+onclick_string_next_week) + block_menu.appendChild(block_next_week) + + + block_menu.appendChild(createPersonMenuCopyExtras(person_id, day_id)) + + return block_menu +} + +createPersonMenuCopyFrom = (person_id, day_id) => { + let person = PERSONS.find(p => p.id === person_id) + let block_menu = document.createElement("div") + let block_title = document.createElement("p") + block_title.innerHTML = "Schicht kopieren von:" + block_menu.appendChild(block_title) + + cretePreWeek = async (roster, date, str) => { + if (typeof roster !== "undefined") { + return dbGet_shifts_where_yearweek_and_day_and_person(date, day_id, person_id).then(shifts => { + if (shifts.length === 0) {return} + let onclick_string = "" + let html_string = str+" Woche " + let break_d = true + callback = () => { + let add_function + let noshifts_reload = true + shifts.forEach((shift, sid) => { + if (shifts.length === 0) return + if (sid === shifts.length-1) {noshifts_reload = false} + if (sid === 0) {add_function = `addNewShiftToRoster(${person_id}, ${day_id}, ${shift.start}, ${shift.end}, "${DATE_YEAR_WEEK}", ${noshifts_reload})`} + else {add_function = `addShift("${DATE_YEAR_WEEK}", ${day_id}, ${person_id}, ${shift.start}, ${shift.end}, ${noshifts_reload})`} + onclick_string = onclick_string+`${add_function}; ` + html_string = html_string+"("+timeToHHMM(shift.start)+"-"+timeToHHMM(shift.end)+") " + break_d = false + }) + let block_button_last_week = document.createElement("button") + block_button_last_week.classList.add("prev-next") + block_button_last_week.innerHTML = html_string + block_button_last_week.setAttribute("onClick", `closeRosterPersonMenu(${person_id}, ${day_id}); ${onclick_string}`) + block_menu.appendChild(block_button_last_week) + return + } + return callback() + }) + } + } + DAYS.forEach((day, d_id) => { + if (d_id === day_id) return + let block_day = document.createElement("button") + let shifts = person.shifts.filter(s => s.day_id === d_id) + if (shifts.length === 0) return + let onclick_string = "" + let html_string = "" + let break_d = true + let add_function + let noshifts_reload = true + shifts.forEach((shift, sid) => { + if (sid === shifts.length-1) {noshifts_reload = false} + if (sid === 0) {add_function = `addNewShiftToRoster(${person_id}, ${day_id}, ${shift.start}, ${shift.end}, "${DATE_YEAR_WEEK}", ${noshifts_reload})`} + else {add_function = `addShift("${DATE_YEAR_WEEK}", ${day_id}, ${person_id}, ${shift.start}, ${shift.end}, ${noshifts_reload})`} + onclick_string = onclick_string+`${add_function}; ` + html_string = html_string+day+" ("+timeToHHMM(shift.start)+"-"+timeToHHMM(shift.end)+") " + break_d = false + }) + if (break_d) return + block_day.innerHTML = html_string + block_day.setAttribute("onClick", `closeRosterPersonMenu(${person_id}, ${day_id}); ${onclick_string};`) + block_menu.appendChild(block_day) + }) + + + return cretePreWeek(ROSTER_WEEK_BEFORE, DATE_YEAR_WEEK_BEFORE, "Letzte").then(() => { + return cretePreWeek(ROSTER_WEEK_BEFORE_WEEK, DATE_YEAR_WEEK_BEFORE_WEEK, "Vorletzte").then(() => { + block_menu.appendChild(createPersonMenuCopyExtras(person_id, day_id)) + return block_menu + }) + }) + +} + +openRosterPersonMenu = async (person_id, day_id) => { + document.getElementById("Td-name-"+person_id+"-day-"+day_id).classList.add("active") + let block_menu = document.getElementsByClassName("menu-"+person_id+"-day-"+day_id)[0] + let person = PERSONS.find(p => p.id === person_id) + let shifts = person.shifts.filter(s => s.day_id === day_id) + let block_entry = shifts.length === 0 ? + (await createPersonMenuCopyFrom(person_id, day_id)) : + createPersonMenuCopyTo(person_id, day_id) + + block_menu.style.top = 0 + block_menu.innerHTML = "" + block_menu.appendChild(block_entry) + + block_menu.classList.add("active") + + let ar = document.querySelector(`#Table-${day_id}-container tbody`).getBoundingClientRect().top + let am = document.getElementsByClassName(`menu-${person_id}-day-${day_id}`)[0].getBoundingClientRect().top + let ah = document.getElementsByClassName(`menu-${person_id}-day-${day_id}`)[0].getBoundingClientRect().height + let br = document.querySelector(`#Table-${day_id}-container .table-times`).getBoundingClientRect().bottom + let bm = document.getElementsByClassName(`menu-${person_id}-day-${day_id}`)[0].getBoundingClientRect().bottom + let bb = br-bm-60 + let aa = ar-am+ah + let block_h = document.querySelector(`#Td-name-${person_id}-day-${day_id}`) + if (bb < 0 && aa < 0) { + block_menu.style = `top: ${bb}px; bottom: unset;` + } else { + block_menu.style = "top: 0; bottom: unset;" + } + + window.setTimeout(() => { + document.body.onclick = (e) => eventListenerPersonMenu(e, person_id, day_id) + }, 100) +} + +closeRosterPersonMenu = (person_id, day_id) => { + document.getElementById("Td-name-"+person_id+"-day-"+day_id).classList.remove("active") + let block_menu = document.getElementsByClassName("menu-"+person_id+"-day-"+day_id)[0] + block_menu.classList.remove("active") + block_menu.innerHTML = "" + document.body.onclick = null +} +eventListenerPersonMenu = (evt, person_id, day_id) => { + let clickEl = document.getElementsByClassName("menu-"+person_id+"-day-"+day_id)[0] + if (!clickEl.contains(evt.target)){ + closeRosterPersonMenu(person_id, day_id) + } +} diff --git a/js/roster.js b/js/roster.js new file mode 100755 index 0000000..9665c99 --- /dev/null +++ b/js/roster.js @@ -0,0 +1,1868 @@ +// get Roster Data ROSTER +getActiveRosterData = async (year_week) => { + if (year_week === DATE_YEAR_WEEK) { + return ROSTER + } else if (year_week === DATE_YEAR_WEEK_TABLE_FROM) { + return ROSTER_TABLE_FROM + } else if (year_week === DATE_YEAR_WEEK_TABLE_TO) { + return ROSTER_TABLE_TO + } else { + return getDataRosterToRoster(year_week) + } +} + +getDataRosterToRoster = async (year_week) => { + let roster = ROSTERS.find(ro => ro.year_week === year_week)?.roster + pushR = (r) => { + ROSTERS.push({year_week: year_week, roster: [...r]}) + } + if (typeof roster !== "undefined") { + return roster + } else if (ROSTERS_YEARWEEK.indexOf(year_week) === -1) { + return createDataA(year_week).then(() => { + return dbGet_roster_active(year_week).then(r => {pushR(r); return r}) + }) + } else { + return dbGet_roster_active(year_week).then(r => {pushR(r); return r}) + } +} + +getRosterBefore = async (d) => { + let yws = ROSTERS_YEARWEEK + let r_id = yws.indexOf(DATE_YEAR_WEEK)+d + if (r_id && r_id < yws.length) {return await getDataRosterToRoster(yws[r_id]) } +} + +// create new Roster +createDataA = async (year_week) => { + if (!year_week) {year_week = DATE_YEAR_WEEK} + createR = (changes) => { + return dbSet_roster(year_week, TIME_STEP, [DAYBREAK_1, DAYBREAK_2]).then(() => { + if (year_week < DATE_YEAR_WEEK_OLDEST) { + changes.forEach(c => dbSet_roster_change_where_yearweek_and_day(year_week, c.day_id, c.start, c.end, c.amount)) + } + + return dbGet_rosters_yearweek().then((yws) => { + ROSTERS_YEARWEEK = yws + if (year_week === DATE_YEAR_WEEK) { + DATE_YEAR_WEEK_NEWEST = ROSTERS_YEARWEEK[0] + DATE_YEAR_WEEK_OLDEST = ROSTERS_YEARWEEK[ROSTERS_YEARWEEK.length-1] + } + return yws + }) + }) + } + if (year_week < DATE_YEAR_WEEK_OLDEST) { + return dbGet_roster_changes_where_yearweek(DATE_YEAR_WEEK_OLDEST).then((changes) => { + return createR(changes) + }) + } else { + return createR() + } +} + +// get Active Roster +getActiveRoster = async (reload) => { + showLoading("getActiveRoster") + EDITABLE_ROWS_TOP = await dbGet_roster_editable_rows_top(DATE_YEAR_WEEK) + EDITABLE_ROWS_BOTTOM = await dbGet_roster_editable_rows_bottom(DATE_YEAR_WEEK) + EDITABLE_CELLS_RIGHT = await dbGet_roster_editable_cells_right(DATE_YEAR_WEEK) + ROSTER_PERSON_INFOS = await dbGet_roster_info_where_yearweek(DATE_YEAR_WEEK) + let yws = await dbGet_rosters_yearweek() + let roster_data + if (yws.indexOf(DATE_YEAR_WEEK) > -1) { + roster_data = await dbGet_roster_where_yearweek(DATE_YEAR_WEEK) + } else { + roster_data = await dbGet_roster_where_yearweek(yws[0]) + } + DAYBREAK_1 = roster_data.break_60 + DAYBREAK_2 = roster_data.break_90 + TIME_STEP = roster_data.time_step + + callback_1 = () => { + return getSettings().then(() => { + if ((EDITABLE_ROW) || (EDITABLE_ROWS_TOP.length > 0)) { + setEditableRowTrue() + } else {document.querySelector("#Roster-week-add-editable-row button.row-top").classList.remove("active")} + if ((EDITABLE_ROW_BOTTOM) ||(EDITABLE_ROWS_BOTTOM.length > 0)) { + setEditableRowBottomTrue() + } else {document.querySelector("#Roster-week-add-editable-row button.row-bottom").classList.remove("active")} + if ((EDITABLE_CELLS_RIGHT.length > 0) || EDITABLE_CELL) { + EDITABLE_CELL = true; document.querySelector("#Roster-week-add-editable-cell button").classList.add("active") + } else if (DISPLAY_EDITABLE_CELL.v) { + setEditableCellTrue() + } else {document.querySelector("#Roster-week-add-editable-cell button").classList.remove("active")} + + renderPerson() + let person_list_buttons = document.querySelectorAll("#Person-list-buttons button") + for (let i=0; i<person_list_buttons.length; i++) {person_list_buttons[i].classList.remove("active")} + if (person_list_buttons.length > 0) person_list_buttons[0].classList.add("active") + + loadRosterTableWeek() + return loadRosterTable().then(() => { + hideLoading("getActiveRoster") + setZoomLevel(SETTINGS.zoom_web) + return + }) + }) + } + callback_0 = () => { + if (ROSTERS_YEARWEEK.indexOf(DATE_YEAR_WEEK) === -1) { + return createDataA().then(() => {return callback_1()}) + } else { + return callback_1() + } + } + return callback_0() +} + +getActiveRosterWeek = async (reload) => { + showLoading("getActiveRoster") + EDITABLE_ROWS_TOP = await dbGet_roster_editable_rows_top(DATE_YEAR_WEEK) + EDITABLE_ROWS_BOTTOM = await dbGet_roster_editable_rows_bottom(DATE_YEAR_WEEK) + EDITABLE_CELLS_RIGHT = await dbGet_roster_editable_cells_right(DATE_YEAR_WEEK) + ROSTER_PERSON_INFOS = await dbGet_roster_info_where_yearweek(DATE_YEAR_WEEK) + let yws = await dbGet_rosters_yearweek() + let roster_data + if (yws.indexOf(DATE_YEAR_WEEK) > -1) { + roster_data = await dbGet_roster_where_yearweek(DATE_YEAR_WEEK) + } else { + roster_data = await dbGet_roster_where_yearweek(yws[0]) + } + DAYBREAK_1 = roster_data.break_60 + DAYBREAK_2 = roster_data.break_90 + TIME_STEP = roster_data.time_step + NOWEEKEDIT = true + + callback_1 = () => { + return getSettings().then(() => { + if ((DISPLAY_EDITABLE_ROW.v) || (EDITABLE_ROWS_TOP.length > 0)) { + EDITABLE_ROW = true + } else {EDITABLE_ROW = false } + if ((DISPLAY_EDITABLE_ROW_BOTTOM.v) ||(EDITABLE_ROWS_BOTTOM.length > 0)) { + EDITABLE_ROW_BOTTOM = true + } else {EDITABLE_ROW_BOTTOM = false} + if (EDITABLE_CELLS_RIGHT.length > 0) { + EDITABLE_CELL = true + } else if (DISPLAY_EDITABLE_CELL.v) { + EDITABLE_CELL = true + } else {EDITABLE_CELL = false} + + loadRosterTableWeek() + hideLoading("getActiveRoster") + }) + } + callback_0 = () => { + if (ROSTERS_YEARWEEK.indexOf(DATE_YEAR_WEEK) === -1) { + hideLoading("getActiveRoster") + return + } else { + return callback_1() + } + } + return callback_0() +} + +// Roster Amount per day +changeTimeAmount = async (el, day_id, direction, ael) => { + let roster = ROSTER[day_id] + let blocks_multiple = document.getElementById(`Table-times-thead-tr-${day_id}`).querySelectorAll(".th-amount-container.active") + let block_this_active = document.getElementById(`Table-times-thead-tr-${day_id}`).getElementsByClassName("th-amount-container")[ael] + if (!block_this_active.classList.contains("active")) { + if (blocks_multiple.length > 0) { + for (i=0; i< blocks_multiple.length; i++) { + blocks_multiple[i].classList.remove("active") + } + blocks_multiple = [] + } + } + + if (blocks_multiple.length > 0) { + for (i=0; i< blocks_multiple.length; i++) { + let block = blocks_multiple[i] + let block_time = block.parentNode.parentNode + let time = parseFloat(block_time.getAttribute("time")) + let t_id = roster.d.map(a => {return a.t}).indexOf(time) + let amount = roster.d[t_id].a + let newAmount = amount + if (direction === "up") { + if (amount < PERSONS.length) newAmount = amount+1 + } else { + if (amount > 0) newAmount = amount-1 + } + + ROSTER[day_id].d[t_id].a = newAmount + block_time.getElementsByClassName("time-amount-max")[0].innerHTML = newAmount + + } + setTimeAmountTh(day_id) + let change_times = structuredClone(ROSTER[day_id].d) + change_times.forEach(data => {data.time = data.t; data.amount = data.a; delete data.t; delete data.a}) + setDataAC(DATE_YEAR_WEEK, day_id, change_times) + return + } + let amount = roster.d[ael].a + let newAmount = amount + if (direction === "up") { + if (amount < PERSONS.length) newAmount = amount+1 + } else { + if (amount > 0) newAmount = amount-1 + } + + if (amount === newAmount) return + + ROSTER[day_id].d[ael].a = newAmount + let change_times = structuredClone(ROSTER[day_id].d) + change_times.forEach(data => {data.time = data.t; data.amount = data.a; delete data.t; delete data.a}) + setDataAC(DATE_YEAR_WEEK, day_id, change_times) + document.getElementById("Roster-"+day_id).getElementsByClassName("time-amount-max")[ael].innerHTML = newAmount + setTimeAmountTh(day_id) +} + +getPersonAmountForDay = (day_id) => { + let amount_day = [] + ROSTER[day_id].d.forEach(time => amount_day.push({ time: time.t, is: getPersonAmountForDayTime(day_id, time.t).length, max: time.a }) ) + return amount_day +} +getPersonAmountForDayTime = (day_id, time) => { + let shifts = PERSONS.map(p => p.shifts).flat(1).filter(s => s.day_id === day_id) + let shifts_in_time = [] + shifts.forEach(shift => { + if (shift.start <= time && shift.end >= time) shifts_in_time.push(shift) + }) + return shifts_in_time +} + +setTimeAmountTh = async (day_id) => { + for (let id=0; id<ROSTER[day_id].d.length; id++) { + let el = ROSTER[day_id].d[id] + let amount = getPersonAmountForDayTime(day_id, el.t).length + let color_id = Math.round((amount*colors_red_orange_green.length)/ROSTER[day_id].d[id].a) + let color = colors_red_orange_green[color_id] + if (color_id >= colors_red_orange_green.length) color = colors_red_orange_green[colors_red_orange_green.length-1] + if (amount > ROSTER[day_id].d[id].a) color = "#458caf" + else if (amount === ROSTER[day_id].d[id].a) color = "#61a64d" + + let block_th = document.getElementById("Table-times-thead-tr-"+day_id).querySelector('[time="'+el.t+'"]') + + block_th.setAttribute("style", `background-color: ${color}; border-color: ${color}87;`) + block_th.getElementsByClassName("time-amount-is")[0].innerHTML = amount+"/" + } +} + + +setTimeAmount = async (person_id) => { + let person = PERSONS.find(p => p.id === person_id) + for (let day_id=0; day_id<ROSTER.length; day_id++) { + let blocks_name = document.querySelectorAll(`#Roster-days-container .tr-name-${person_id}`) + + let hours_breaks = await getPersonDayHoursAndBreaks(person_id, day_id) + let hours = hours_breaks[0] + let breaks = hours_breaks[1] + + let hours_breaks_a = await getPersonHoursAndBreaks(person_id) + let hours_a = hours_breaks_a[0] + let breaks_a = hours_breaks_a[1] + + let hours_total = new Promise((res, rej) => {res(getPersonHoursWithFreedays(person_id))}) + hours_total = await hours_total + hours_total = parseFloat(hours_total.toFixed(2)) + + for (var i = 0; i < blocks_name.length; i++) { + blocks_name[i].getElementsByClassName("hours-given")[0].innerHTML = hours_a+"/"+hours_total + } + + document.querySelector(`#Tr-${person_id}-day-${day_id} .hours-today`).innerHTML = hours-person.mpa[day_id] + document.querySelector(`#Tr-${person_id}-day-${day_id} .break-today`).innerHTML = breaks + let block_overtime = document.querySelector(`#Tr-${person_id}-day-${day_id} .td-overtime`) + let overtime = person.overtime + if (overtime === 0) {block_overtime.classList.add("green"); block_overtime.classList.remove("orange", "red")} + else if (overtime > 0) {overtime = `+${overtime}`; block_overtime.classList.add("red"); block_overtime.classList.remove("green", "orange")} + else if (overtime < 0) {block_overtime.classList.add("orange"); block_overtime.classList.remove("green", "red")} + block_overtime.innerHTML = overtime + + document.querySelector(`#Person-table-tr-${person_id} .td-overtime`).innerHTML = overtime + setTimeAmountTh(day_id) + } +} + +getBlockTimeTd = (person_id, day_id, time) => { + let block_table_row = document.getElementById(`Tr-${person_id}-day-${day_id}`) + if (!block_table_row) return + let block_td = block_table_row.querySelector('[time="'+time+'"]') + return block_td +} + +removePersonFromShiftDay = async (person_id, day_id, year_week, noreload) => { + if (!year_week) { year_week = DATE_YEAR_WEEK} + if (day_id >= DAYS.length) return + if (ROSTERS_YEARWEEK.indexOf(year_week) === -1) return + let shifts = [] + let year_week_set = false + return dbRemove_shift_where_person_and_year_week_and_day(person_id, year_week, day_id).then(() => { + if (year_week !== DATE_YEAR_WEEK) return + if (!noreload) { + return setActivePerson(person_id).then((person) => { + return reloadPersonDayData(person_id, day_id, year_week) + }) + } + return + }) +} + +// get auto shift +getBestShiftStarts = async (person_id, day_id) => { + let amount_sortet = getPersonAmountForDay(day_id).sort((a, b) => {return (b.max-b.is)-(a.max-a.is) }) + let average = new Promise((res, rej) => {res(getPersonAverageHours(person_id, day_id))}) + average = await average + let best = [] + let max_diff = amount_sortet.map(da => (da.max-da.is))[0] + getMax = (max, is) => { + let re = max-is + if (re < 0) {re = (re*max_diff/100)*max_diff} + else {re = (re*max_diff/100) } + return re + } + ROSTER[day_id].d.forEach(d => { + max_diff = amount_sortet.map(da => (da.max-da.is))[0] + let rank = amount_sortet.filter(da => { return da.time >= d.t && da.time < d.t+average}).map(da => ((getMax(da.max, da.is)*100)/da.max)).reduce((a, b) => a + b, 0) + best.push({time: d.t, rank: rank}) + }) + + return best.sort((a,b) => b.rank-a.rank) +} +getAutoTimeStart = async (person_id, day_id) => { + let average = await getPersonAverageHours(person_id, day_id) + let start = await getBestShiftStarts(person_id, day_id) + start = start[0].time + if (start+average > ROSTER[day_id].d[ROSTER[day_id].d.length-1].t) {start = ROSTER[day_id].d[ROSTER[day_id].d.length-1].t-average} + if (start < ROSTER[day_id].d[0].t) {start = ROSTER[day_id].d[0].t} + return start +} +/* +autoAddShifts = async (rerun) => { + showLoading("autoAddShifts") + let person_without = new Promise((res, rej) => {res(getPersonWithoutShifts())}) + person_without = await person_without + if (person_without.length === 0) return + while (person_without.length > 0) { + let max_id = person_without.map(p => p[2] === person_without[0][2]).indexOf(false)-1 + if (!max_id >= 0) {max_id = 0} + let person_without_id = Math.floor(Math.random() * max_id) + let person = person_without[person_without_id] + let person_id = person[0] + let days = person[1] + for (let di=0; di<days.length;di++) { + let day_id = days[di] + let as = new Promise((res, rej) => {res(getAutoTimeStart(person_id, day_id))}) + as = await as + addNewShiftToRoster(person_id, day_id, as, undefined, undefined, true) + } + person_without.splice(person_without_id, 1) + } + getActiveRoster().then(() => hideLoading("autoAddShifts")) +} + */ +addExtrashiftToRoster = (person_id, day_id, time_start, start, end) => { + let prev_duration + let average + getD = async () => { + prev_duration = await getPersonDayHoursAndBreaks(person_id, day_id) + prev_duration = prev_duration [0] + average = new Promise((res, rej) => {res(getPersonAverageHours(person_id, day_id))}) + average = await average + } + setD = () => { + let duration = average-prev_duration-TIME_STEP + if (duration < 0) {duration = 2} + + let time_end = time_start+duration + if (time_start < start) { + if (time_end > start-(TIME_STEP*2)) {time_end = start-(TIME_STEP*2)} + } + if (time_start > end) { + if (time_end > ROSTER[day_id].d[ROSTER[day_id].d.length-1].t) {time_end = ROSTER[day_id].d[ROSTER[day_id].d.length-1].t} + } + if (time_end < time_start) { time_end = time_start} + + addShift(DATE_YEAR_WEEK, day_id, person_id, time_start, time_end) + } + getD().then(() => setD()) +} +addShiftToNextRoster = (person_id, day_id, time_start, time_end, should_delete) => { + let next_yw = getDateToRosterDate(new Date(getDateOfISOWeek(DATE_YEAR_WEEK).getTime() + 7 * 24 * 60 * 60 * 1000))[0] + ROSTERS_YEARWEEK.indexOf(next_yw === -1) && + createDataA(next_yw) + should_delete && + dbRemove_shift_where_person_and_year_week_and_day(person_id, next_yw, day_id).then(() => { + dbAdd_shift(next_yw, day_id, person_id, time_start, time_end) + }) +} +getShiftEnd = async (person_id, day_id, time_start, year_week) => { + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK} + let roster = await getActiveRosterData(year_week) + let person_average_hours = await getPersonAverageHours(person_id, day_id, year_week) + if (person_average_hours > 6) person_average_hours = person_average_hours+DAYBREAK_1 + if (person_average_hours > 9) person_average_hours = person_average_hours+DAYBREAK_2 + let time_end = time_start+person_average_hours-TIME_STEP + + if (time_start === roster[day_id].d[0].t && roster[day_id].d[1].t-roster[day_id].d[0].t !== TIME_STEP) { + time_end = time_end-TIME_STEPS[TIME_STEPS.indexOf(TIME_STEP)-1] + } + if (time_end > roster[day_id].d[roster[day_id].d.length-1].t+TIME_STEP) time_end = roster[day_id].d[roster[day_id].d.length-1].t+TIME_STEP + + return time_end +} +setShift = async (year_week, day_id, person_id, shift_id) => { + showLoading(`setShift-${shift_id}`) + if (year_week === DATE_YEAR_WEEK) { + setActivePerson(person_id, year_week).then((persons) => { + reloadPersonDayData(person_id, day_id) + hideLoading(`setShift-${shift_id}`) + }) + } + if (document.getElementById("Roster-week-table-to")) { + setActivePerson(person_id, year_week).then((persons) => { + reloadPersonDayData(person_id, day_id, year_week, "Roster-week-table-to").then(() => { + hideLoading(`setShift-${shift_id}`) + }) + }) + } +} +addShift = async (year_week, day_id, person_id, start, end, noreload) => { + return dbAdd_shift(year_week, day_id, person_id, start, end).then(shift => { + if ((year_week === DATE_YEAR_WEEK) || (year_week === DATE_YEAR_WEEK_TABLE_TO)) { + if (!noreload) { + return setShift(year_week, day_id, person_id, shift.id) + } + } + return shift.shift_id + }) +} +updateShift = async (shift, start, end, noreload) => { + dbSet_shift_where_id(shift.id, start, end).then(() => { + if (!noreload) { + setShift(shift.yearweek, shift.day_id, shift.person_id, shift.id) + } + }) +} +addNewShiftToRoster = async (person_id, day_id, time_start, time_end, year_week, noreload) => { + let person = await getActivePersonById(person_id) + let year_week_set = false + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK; year_week_set = true} + let cif = await checkIfPersonDayIsFree(person_id, day_id, year_week) + if (cif !== false) return + + let roster = await getActiveRosterData(year_week) + if (typeof time_end === "undefined") { + time_end = await getShiftEnd(person_id, day_id, time_start, year_week) + } + add = () => { + ROSTERS_YEARWEEK.indexOf(year_week) === -1 && createDataA(year_week) + return removePersonFromShiftDay(person.id, day_id, year_week, true).then(() => { + return addShift(year_week, day_id, person_id, time_start, time_end, noreload) + }) + } + return add() +} + +splitShift = (person_id, day_id, shift_id, time, start, end) => { + dbRemove_shift_where_id(shift_id).then(() => { + addShift(DATE_YEAR_WEEK, day_id, person_id, start, time) + addShift(DATE_YEAR_WEEK, day_id, person_id, time+TIME_STEP, end) + }) +} + +modifyShift = (year_week, day_id, shift_id, person_id, time, direction) => { + showLoading("modifyShift") + getActivePersonById(person_id, year_week).then(person => { + let shifts = person.shifts.filter(s => s.day_id === day_id) + let shift = shifts.find(s => s.id === shift_id) + let shift_b = shifts.find(s => s.start !== shift.start) + + + if (time < ROSTER[day_id].d[0].t) {time = ROSTER[day_id].d[0].t} + else if (time > ROSTER[day_id].d[ROSTER[day_id].d.length-1].t) {time = ROSTER[day_id].d[ROSTER[day_id].d.length-1].t} + if (direction !== 1 && time > shift.end) { + addNewShiftToRoster(person_id, day_id, time, undefined, year_week) + return + } + + if ((typeof shift_b !== "undefined" && time-TIME_STEP === shift_b.end) || (typeof shift_b !== "undefined" && time+TIME_STEP === shift_b.start)) { + let start + let end + let new_shift + if (time-TIME_STEP === shift_b.end) { + start = shift_b.start + end = shift.end + } else if (time+TIME_STEP === shift_b.start) { + start = shift.start + end = shift_b.end + } + addNewShiftToRoster(person_id, day_id, start, end, year_week) + } else if (direction === 1) { + updateShift(shift, shift.start, time+TIME_STEP) + } else { + updateShift(shift, time, shift.end) + } + hideLoading("modifyShift") + }) +} + +timeHasShift = (time, shifts) => { + let has_shift = false + shifts.forEach(shift => { + if (shift.start <= time && shift.end > time) has_shift = true + }) + return has_shift +} + +createBlockExtraShift = (person, day_id, time, start, end) => { + let person_id = person.id + let block_add = document.createElement("button") + block_add.innerHTML = "+" + block_add.classList.add("roster-add-extra-shift") + block_add.setAttribute("title", `${person.name}\nExtra Schicht hinzufügen\n${timeToHHMM(time)}`) + block_add.setAttribute("onClick", `addExtrashiftToRoster(${person_id}, ${day_id}, ${time}, ${start}, ${end})`) + return block_add +} + +// load editable Roster +addRosterButtonInnerShiftExtendShort = (person_id, day_id, shift_id, time) => { + getActivePersonById(person_id).then(person => { + let shift = person.shifts.find(s => s.id === shift_id) + let start = shift.start + let end = shift.end + if (end-start <= TIME_STEP) return + let block_td = getBlockTimeTd(person_id, day_id, time) + let block_td_container = block_td.getElementsByClassName("container")[0] + + let block_container = document.createElement("div") + let block_button_shorten = document.createElement("button") + let block_button_extend = document.createElement("button") + + let block_container_remove = block_td_container.getElementsByClassName("shiftmodify-buttons-container-inner")[0] + let block_extend_remove = block_td_container.getElementsByClassName("roster-extend-shift")[0] + if (typeof block_container_remove !== "undefined") block_container_remove.remove() + if (typeof block_extend_remove !== "undefined") block_extend_remove.remove() + + block_container.classList.add("shiftmodify-buttons-container-inner") + + if (time !== start) { + block_button_extend.classList.add("chevron-right") + block_button_extend.setAttribute("onclick", `modifyShift("${DATE_YEAR_WEEK}", ${day_id}, ${shift_id}, ${person_id}, ${time}, 0)`) + block_button_extend.setAttribute("title", `${person.name}\nSchichtstart verschieben\n${timeToHHMM(time)}`) + block_container.appendChild(block_button_extend) + } + + if (time !== end) { + block_button_shorten.classList.add("chevron-left") + block_button_shorten.setAttribute("onclick", `modifyShift("${DATE_YEAR_WEEK}", ${day_id}, ${shift_id}, ${person_id}, ${time}, 1)`) + block_button_shorten.setAttribute("title", `${person.name}\nSchichtende verschieben\n${timeToHHMM(time+TIME_STEP)}`) + block_container.appendChild(block_button_shorten) + } + + block_td_container.appendChild(block_container) + + + if (time === start) { + block_button_shorten.setAttribute("style", "width: 100%;") + } else if (time === end) { + block_button_extend.setAttribute("style", "width: 100%;") + } + }) +} + +addRosterButtonExtendShift = (person, day_id, shift_id, time, direction) => { + let person_id = person.id + let block_td = getBlockTimeTd(person_id, day_id, time) + let block_container = block_td.getElementsByClassName("container")[0] + let block_container_mod = block_container.getElementsByClassName("shiftmodify-buttons-container")[0] + + if (typeof block_container_mod === "undefined") return + let block_button = document.createElement("button") + let chevron = "chevron-left" + let click = `modifyShift("${DATE_YEAR_WEEK}", ${day_id}, ${shift_id}, ${person_id}, ${time}, 0)` + let title_text = `${person.name}\nSchichtstart verschieben\n${timeToHHMM(time)}` + if (direction === 1) { + chevron = "chevron-right" + click = `modifyShift("${DATE_YEAR_WEEK}", ${day_id}, ${shift_id}, ${person_id}, ${time}, 1)` + title_text = `${person.name}\nSchichtende verschieben\n${timeToHHMM(time+TIME_STEP)}` + } + + block_button.classList.add("roster-extend-shift", chevron) + block_button.setAttribute("title", title_text) + block_button.setAttribute("onClick", click) + block_container_mod.appendChild(block_button) +} + +addRosterButtonSplitShift = (person, day_id, shift_id, time, start, end) => { + let person_id = person.id + let block_td = getBlockTimeTd(person_id, day_id, time) + let block_td_container = block_td.getElementsByClassName("container")[0] + let block_remove_button = block_td.getElementsByClassName("container")[0].getElementsByClassName("shift-split")[0] + if (block_remove_button) block_td_container.removeChild(block_remove_button) + + let block_button = document.createElement("button") + block_button.classList.add("shift-split", "button-x", "shiftmodify-button-header") + + block_button.setAttribute("title", `${person.name}\nSchicht teilen\n${timeToHHMM(time)}`) + block_button.setAttribute("onClick", `splitShift(${person_id}, ${day_id}, ${shift_id}, ${time}, ${start}, ${end})`) + block_td_container.appendChild(block_button) +} + +loadEditablePersonDayShift = (person_id, day_id, noWReload) => { + showLoading("loadEditablePersonDayShift") + let person = PERSONS.find(p => p.id === person_id) + let shifts = person.shifts.filter(s => s.day_id === day_id) + shifts.sort((a, b) => a.start-b.start) + let shift = shifts[0] + if (shift) { + // remove extra shift buttons + let block_tr = document.getElementById(`Tr-${person_id}-day-${day_id}`) + let remove_splits = block_tr.querySelectorAll(".shift-split") + let remove_adds = block_tr.querySelectorAll(".roster-add-extra-shift") + let remove_extend = block_tr.querySelectorAll(".roster-extend-shift") + let removes_mod_inner = block_tr.querySelectorAll(".shiftmodify-buttons-container-inner") + let removes = [...remove_splits, ...remove_adds, ...removes_mod_inner, ...remove_extend ] + for (i=0; i<removes.length; i++) { + removes[i].parentNode.removeChild(removes[i]) + } + + let is_before = true + let is_after = false + let is_during = false + ROSTER[day_id].d.forEach(data => { + let time = data.t + let block_td = getBlockTimeTd(person_id, day_id, time) + let block_container = block_td.querySelector(".container") + block_td.classList.remove("assigned") + let has_shift = timeHasShift(time, shifts) + if (has_shift) { + is_during = true + is_before = false + if (is_after) {is_after = false; shift = shifts[1]} + block_td.classList.add("assigned") + } else if (is_during) { + is_during = false + is_after = true + } + if (has_shift) { + block_td.classList.add("assigned") + addRosterButtonInnerShiftExtendShort(person_id, day_id, shift.id, time) + if (shifts.length === 1 && time !== shift.start && time !== shift.end-TIME_STEP) + addRosterButtonSplitShift(person, day_id, shifts[0].id, time, shifts[0].start, shifts[0].end) + } else if (is_before) { + if (time !== shift.start-TIME_STEP && shifts.length === 1) block_container.appendChild(createBlockExtraShift(person, day_id, time, shift.start, shift.end)) + addRosterButtonExtendShift(person, day_id, shift.id, time) + } else if (is_after) { + if (time !== shift.end && shifts.length === 1) block_container.appendChild(createBlockExtraShift(person, day_id, time, shift.start, shift.end)) + addRosterButtonExtendShift(person, day_id, shift.id, time, 1) + } + }) + } + checkIfPersonDayIsFree(person_id, day_id).then(check_if_free => { + let h_mpa = check_if_free ? 0 : person.mpa[day_id] + if (h_mpa === 0) {h_mpa = ""} + let block_mpa = document.querySelector(`#Tr-${person_id}-day-${day_id} .hours-mpa`) + if (block_mpa) { block_mpa.innerHTML = `<div>${h_mpa}</div>`} + }) + hideLoading("loadEditablePersonDayShift") +} + +loadEditableDataIntoRosterTable = (el, day_id) => { + showLoading("loadEditableDataIntoRosterTable") + window.onmousemove = (e) => eventListenerEditRosterDay(e, day_id) + el.classList.add("d-none") + let block = document.querySelector(`#Roster-${day_id}`) + if (block.classList.contains("editable")) { + hideLoading("loadEditableDataIntoRosterTable") + return + } + block.classList.add("editable") + + PERSONS.forEach(person => { + loadEditablePersonDayShift(person.id, day_id) + }) + hideLoading("loadEditableDataIntoRosterTable") +} + +getShiftTimeText = (shift, day_id, table_id) => { + if (typeof table_id === "undefined") {table_id = "Roster-week-table"} + let shift_start = shift.start + let shift_end = shift.end + + let text_start = timeToHHMM(shift_start) + if (text_start.length === 4) {text_start = " "+text_start} + let text_end = timeToHHMM(shift_end) + if (text_end.length === 4) {text_end = " "+text_end} + if (EDITABLE_TABLES.indexOf(table_id) > -1) { + return `<input type="time" title="Schichtstart ändern" required onfocusout='modifyShift("${shift.yearweek}", ${day_id}, ${shift.id}, ${shift.person_id}, hhMMToTime(this.value), 0)' value="${timeToFullHHMM(shift_start)}" class="start" time="${shift_start}"><p> - </p><input type="time" title="Schichtende ändern" required onfocusout='modifyShift("${shift.yearweek}", ${day_id}, ${shift.id}, ${shift.person_id} , hhMMToTime(this.value)-TIME_STEP, 1)' value="${timeToFullHHMM(shift_end)}" class="end" time="${shift_end}">` + } else { + return `<p class="start" time="${shift_start}">${text_start}</p><p> - </p><p class="end" time="${shift_end}">${text_end}</p>` + } +} + + +// reload Person data +reloadPersonData = (person_id, year_week, table_id) => { + showLoading(`reloadPersonData${person_id}`) + DAYS.forEach((day, day_id) => { + reloadPersonDayData(person_id, day_id, year_week, table_id).then(() => { + hideLoading(`reloadPersonData${person_id}`) + }) + }) +} + +reloadPersonDayData = async (person_id, day_id, year_week, table_id) => { + showLoading(`reloadPersonDayData-${person_id}-${day_id}`) + if (!year_week) {year_week = DATE_YEAR_WEEK} + if (!table_id) {table_id = "Roster-week-table"} + getActivePersonById(person_id, year_week).then(person => { + // set week + if (year_week === DATE_YEAR_WEEK && table_id !== "Roster-week-table") { + renderRosterTableWeekPersonDay(person, day_id, year_week, document.querySelector(`#Roster-week-table .Roster-week-td-name-${person_id}-day-${day_id}`), table_id) + } + renderRosterTableWeekPersonDay(person, day_id, year_week, document.querySelector(`#${table_id} .Roster-week-td-name-${person_id}-day-${day_id}`), table_id).then(() => { + // set week hours and breaks + let block_name = document.querySelector(`#${table_id} .Roster-week-tr-${person_id} .Roster-week-td-name`) + if (!block_name) {hideLoading(`reloadPersonDayData-${person_id}-${day_id}`); return} + let block_td_hours = block_name.querySelector(".hours") + let block_td_breaks = block_name.querySelector(".breaks") + getPersonHoursAndBreaks(person_id, year_week).then(hours_breaks_all => { + let breaks_all = hours_breaks_all[1] + getPersonHoursWithFreedays(person_id, year_week).then(hours_total => { + hours_total = parseFloat(hours_total.toFixed(2)) + block_td_hours.innerHTML = hours_breaks_all[0]+"/"+hours_total + block_td_breaks.innerHTML = hours_breaks_all[1] + }) + }) + }) + if (year_week === DATE_YEAR_WEEK) { + // set Person Table row + renderPersonTableRow(person_id) + // set roster + createBlockRosterTablePersonRow(person, ROSTER[day_id], day_id, document.querySelector(`#Tr-${person_id}-day-${day_id}`)).then(() => { +// set roster hours and breaks + setTimeAmount(person_id) + loadEditablePersonDayShift(person_id, day_id, true) + hideLoading(`reloadPersonDayData-${person_id}-${day_id}`) + }) + } else { + hideLoading(`reloadPersonDayData-${person_id}-${day_id}`) + } + }) +} + +loadTableWeekPersonData = async (person_id, year_week, table_id) => { + showLoading(`loadTableWeekPersonData-${person_id}`) + if (typeof year_week === "undefined") { year_week = DATE_YEAR_WEEK} + if (typeof table_id === "undefined") { table_id = "Roster-week-table"} + + let person = await getActivePersonById(person_id, year_week) + let block_table = document.querySelector(`#${table_id}`) + if (EDITABLE_TABLES.indexOf(table_id) > -1) + block_table.classList.add("Roster-week-editable") + + for (let day_id=0; day_id<DAYS.length; day_id++) { + renderRosterTableWeekPersonDay(person, day_id, year_week, document.querySelector(`#${table_id} .Roster-week-td-name-${person_id}-day-${day_id}`), table_id).then(() => { + if (day_id === DAYS.length-1) hideLoading(`loadTableWeekPersonData-${person_id}`) + }) + } +} + +rosterWeekDisplayOvertime = (el) => { + if (DISPLAY_OVERTIME) { + el.classList.remove("active") + dbSet_settings_overtime_default(false) + DISPLAY_OVERTIME = false + } else { + el.classList.add("active") + dbSet_settings_overtime_default(true) + DISPLAY_OVERTIME = true + } + loadRosterTableWeek() +} +rosterWeekAddEditableRow = (el) => { + if (EDITABLE_ROW) { + el.classList.remove("active") + EDITABLE_ROW = false + dbRemove_roster_editable_rows_top(DATE_YEAR_WEEK) + EDITABLE_ROWS_TOP = [] + } else { + el.classList.add("active") + EDITABLE_ROW = true + EDITABLE_ROWS_TOP = [] + //for (let i=0; i<6; i++) {EDITABLE_ROWS_TOP.push({id: i.toString(), yearweek: DATE_YEAR_WEEK, text: ''})} + } + loadRosterTableWeek() +} +rosterWeekAddEditableRowBottom = (el) => { + if (EDITABLE_ROW_BOTTOM) { + el.classList.remove("active") + EDITABLE_ROW_BOTTOM = false + dbRemove_roster_editable_rows_bottom(DATE_YEAR_WEEK) + EDITABLE_ROWS_BOTTOM = [] + } else { + el.classList.add("active") + EDITABLE_ROW_BOTTOM = true + EDITABLE_ROWS_BOTTOM = [] + //for (let i=0; i<6; i++) {EDITABLE_ROWS_BOTTOM.push({id: i.toString(), yearweek: DATE_YEAR_WEEK, text: ''})} + } + + loadRosterTableWeek() +} +rosterWeekAddEditableCell = (el) => { + if (EDITABLE_CELL) { + el.classList.remove("active") + EDITABLE_CELL = false + dbRemove_roster_editable_cells_right(DATE_YEAR_WEEK) + EDITABLE_CELLS_RIGHT = [] + loadRosterTableWeek() + } else { + setEditableCellTrue() + dbGet_roster_editable_cells_right(DATE_YEAR_WEEK).then(ec => { + EDITABLE_CELLS_RIGHT = ec + loadRosterTableWeek() + }) + /*EDITABLE_CELLS_RIGHT = [] + EDITABLE_CELLS_RIGHT.push({id: "i", yearweek: DATE_YEAR_WEEK, text: ""}) + PERSONS.forEach(person => { + EDITABLE_CELLS_RIGHT.push({id: person.id, yearweek: DATE_YEAR_WEEK, text: ""}) + })*/ + } +} +setEditableCell = (cell, id, text) => { + id = id.toString() + if (cell === "row_top") dbSet_roster_editable_rows_top_where_key(DATE_YEAR_WEEK, id, text) + else if (cell === "row_bottom") dbSet_roster_editable_rows_bottom_where_key(DATE_YEAR_WEEK, id, text) + else if (cell === "cell_right") dbSet_roster_editable_cells_right_where_key(DATE_YEAR_WEEK, id, text) +} +renderRosterTableWeekPersonDay = async (person, day_id, year_week, block_td, table_id) => { + if (!block_td) {return} + block_td.innerHTML = "" + block_td.classList.remove("v-bottom", "free", "v-bottom") + let shifts = person.shifts.filter(s => s.day_id === day_id) + let person_id = person.id +// set info + let info_set = false + setInfo = async (person_id, day_id, block_td) => { + if (info_set) return + block_info = document.createElement("div") + block_info.classList.add("info") + let info + if (year_week === DATE_YEAR_WEEK) { + info = ROSTER_PERSON_INFOS.find(i => i.day_id === day_id && i.id === person_id.toString())?.text + } else if (year_week === DATE_YEAR_WEEK_TABLE_FROM) { + info = ROSTER_PERSON_INFOS_TABLE_FROM.find(i => i.day_id === day_id && i.id === person_id.toString())?.text + } else if (year_week === DATE_YEAR_WEEK_TABLE_TO) { + info = ROSTER_PERSON_INFOS_TABLE_TO.find(i => i.day_id === day_id && i.id === person_id.toString())?.text + } else { + info = await dbGet_roster_info_where_yearweek_and_day_and_person(year_week, day_id, person_id) + } + if (typeof info !== "undefined") { + let block_info_text = document.createElement("div") + block_info_text.innerHTML = info + block_info.appendChild(block_info_text) + block_td.appendChild(block_info) + } else { + block_td.classList.remove("v-bottom") + } + info_set = true + } +// set free + let ch_free = await checkIfPersonDayIsFree(person_id, day_id, year_week) + if (ch_free) { + block_td.classList.add("free") + let block_free = document.createElement("div") + block_free.classList.add("free") + let block_time = document.createElement("p") + + block_time.classList.add("time") + block_time.innerHTML = ch_free + block_free.appendChild(block_time) + block_td.appendChild(block_free) + if (ch_free === dbGet_settings_label_cut(2)) { + let block_duration = document.createElement("p") + block_duration.classList.add("duration") + //let duration = await getPersonDayHoursAndBreaks(person_id, day_id, year_week)[0] + block_td.appendChild(block_duration) + } + setInfo(person_id, day_id, block_td) + return + } else { + block_td.classList.remove("free") + } +// set empty shift + if (shifts.length === 0) { + block_td.classList.add("no-shift") + block_td.classList.add("v-bottom") + setInfo(person_id, day_id, block_td) + return + } +// set shift + let block_td_container = document.createElement("div") + block_td.appendChild(block_td_container) + let block_time_container = document.createElement("div") + if (EDITABLE_TABLES.indexOf(table_id) > -1) { + getAutoTimeStart(person_id, day_id).then(auto_start => { + if (shifts.length === 0) block_time_container.setAttribute("onClick", `addNewShiftToRoster(${person_id}, ${day_id}, ${auto_start}, undefined, "${year_week}")`) + }) + } + block_time_container.classList.add("time") + block_td_container.classList.add("container") + shifts.sort((a, b) => { + return a.start - b.start; + }); + + let title_shift_text = person.name + shifts.forEach((shift, shift_id) => { + let block_time = document.createElement("div") + let shift_text = getShiftTimeText(shift, day_id, table_id) + block_time.innerHTML = shift_text + block_time_container.appendChild(block_time) + }) + block_td_container.appendChild(block_time_container) +// set hours + getPersonDayHoursAndBreaks(person_id, day_id, year_week).then(hours_breaks => { + let duration = hours_breaks[0].toString() + duration = duration-person.mpa[day_id] + if (Math.floor(hours_breaks[0]).toString().length === 1) {duration = " "+duration} + let block_duration = document.createElement("p") + block_duration.classList.add("duration") + block_duration.setAttribute("title", "Stunden") + block_duration.innerHTML = parseFloat(duration) === 0 ? "" : duration + block_td_container.appendChild(block_duration) +// set break + let block_break = document.createElement("p") + let break_day = hours_breaks[1] + block_break.classList.add("break") + block_break.setAttribute("title", "Pause") + if (break_day < 10) {break_day = ` ${break_day} `} + block_break.innerHTML = parseFloat(duration) === 0 ? "" : break_day + block_td_container.appendChild(block_break) + }) + +// set mpa + let block_mpa = document.createElement("div") + let block_mpa_title = document.createElement("div") + let block_mpa_value = document.createElement("div") + if (person.mpa[day_id] > 0) { + if (EDITABLE_TABLES.indexOf(table_id) > -1) { + block_mpa_value = document.createElement("input") + block_mpa_value.setAttribute("value", person.mpa[day_id]) + block_mpa_value.setAttribute("title", `${getRenames("m").a} ändern.`) + block_mpa_value.setAttribute("type", `number`) + block_mpa_value.setAttribute("step", `0.25`) + block_mpa_value.setAttribute("onchange", `addMpaToday(${person_id}, ${day_id}, this.value)`) + } else { + block_mpa_value.innerHTML = person.mpa[day_id] + } + block_mpa_title.innerHTML = getRenames("m").a + } else { + if (EDITABLE_TABLES.indexOf(table_id) > -1) { + block_mpa.setAttribute("onClick", `showLoading("addMpaToday"); window.setTimeout(() => {addMpaToday(${person_id}, ${day_id}, 1); hideLoading("addMpaToday")},50)`) + block_mpa.setAttribute("title", `${getRenames("m").a} mit 1h für diesen Tag hinzufügen.`) + } + } + block_mpa.classList.add("mpa") + block_mpa.appendChild(block_mpa_title) + block_mpa.appendChild(block_mpa_value) + block_td_container.appendChild(block_mpa) +// set shift label + let label_sl = person.sl[day_id] + if (label_sl !== false) { + block_td_container.style = 'grid-template-areas: "time time time time" "break mpa label duration";' + let block_sl = document.createElement("div") + block_sl.classList.add("label") + block_sl.innerHTML = dbGet_shift_label_cut(label_sl) + block_td_container.appendChild(block_sl) + } + + setInfo(person_id, day_id, block_td) +} + +createBlockRosterTableWeek = async (year_week, table_id) => { + if (typeof table_id === "undefined") { + table_id = "Roster-week-table" + } + if (typeof year_week === "undefined") { + year_week = DATE_YEAR_WEEK + } + let date = getDateOfISOWeek(year_week) + + let block_table = document.createElement("table") + block_table.setAttribute("id", table_id) + if (EDITABLE_TABLES.indexOf(table_id) > -1) block_table.classList.add("Roster-week-editable") + + let block_thead = document.createElement("thead") + let block_thead_row = document.createElement("tr") + let block_th = document.createElement("th") + block_th.classList.add("Roster-week-th-name") + let block_th_name = document.createElement("p") + block_th_name.innerHTML = "Name" + block_th.appendChild(block_th_name) + block_thead_row.appendChild(block_th) + + let roster = await getActiveRosterData(year_week) + roster.forEach((roster, day_id) => { + let day_date = new Date(date) + day_date.setDate(day_date.getDate() - (day_date.getDay() + 6) % 7 + day_id) + + let block_th = document.createElement("th") + let block_th_day = document.createElement("p") + let block_th_day_date = document.createElement("p") + + block_th.classList.add("Roster-week-th") + block_th.setAttribute("day_id", day_id) + block_th_day.innerHTML = roster.n + block_th_day_date.innerHTML = day_date.toLocaleDateString('de', {day: '2-digit', month: '2-digit', year: '2-digit'}) + block_th.appendChild(block_th_day) + block_th.appendChild(block_th_day_date) + block_thead_row.appendChild(block_th) + }) + if (EDITABLE_CELL) { + let block_th_cell = document.createElement("th") + block_th_cell.classList.add("td-editable-cell", `Roster-week-td-editable-cell-i`) + if (!NOWEEKEDIT) block_th_cell.setAttribute("contenteditable", "true") + block_th_cell.addEventListener('focusout', (e) => setEditableCell("cell_right", "i", e.target.innerHTML)) + if (EDITABLE_ROW) block_th_cell.setAttribute("rowspan", "2") + block_th_cell.innerHTML = EDITABLE_CELLS_RIGHT.find(c => c.id === "i")?.text || "" + block_thead_row.appendChild(block_th_cell) + } + + block_thead.appendChild(block_thead_row) + + let block_tbody = document.createElement("tbody") + addEmptyRow = () => { + let block_tbody_row = document.createElement("tr") + block_tbody_row.classList.add("tr-empty") + let block_td = document.createElement("td") + if (EDITABLE_CELL) { + block_td.setAttribute("colspan", DAYS.length+2) + } else { + block_td.setAttribute("colspan", DAYS.length+1) + } + block_tbody_row.appendChild(block_td) + block_tbody.appendChild(block_tbody_row) + } + if (table_id === "Roster-week-table" && EDITABLE_ROW) { + let block_thead_row_1 = document.createElement("tr") + block_thead_row_1.classList.add("tr-editable") + for (let i=0; i<6; i++) { + let block_th_er = document.createElement("th") + block_th_er.setAttribute("id", `Roster-week-th-editable-${i}`) + if (!NOWEEKEDIT) block_th_er.setAttribute("contenteditable", `true`) + block_th_er.addEventListener('focusout', (e) => setEditableCell("row_top", i, e.target.innerHTML)) + block_th_er.innerHTML = EDITABLE_ROWS_TOP.find(c => c.id === i.toString())?.text || "" + block_thead_row_1.appendChild(block_th_er) + } + block_thead.appendChild(block_thead_row_1) + addEmptyRow() + } + block_table.appendChild(block_thead) + + + let sort_d = false + if ((SETTINGS.sort_week.indexOf("d-d") > -1) || (SETTINGS.sort_week.indexOf("d-u") > -1)) {sort_d = true} + let person_week + if (year_week === DATE_YEAR_WEEK) { + person_week = PERSONS_WEEK + } else if (year_week === DATE_YEAR_WEEK_TABLE_FROM) { + person_week = PERSONS_TABLE_FROM + } else if (year_week === DATE_YEAR_WEEK_TABLE_TO) { + person_week = PERSONS_TABLE_TO + } else { + person_week = await getSortedPersonRosterWeek(1, year_week) + } + let sort_d_c = person_week[0].department + if (typeof sort_d_c === "undefined") return + for (let pw=0; pw<person_week.length; pw++) { + let person = person_week[pw] + if (sort_d && sort_d_c !== person.department) {addEmptyRow(); sort_d_c = person.department} + let person_id = person.id + let block_tbody_row = document.createElement("tr") + let block_td = document.createElement("td") + let block_td_container = document.createElement("div") + let block_td_name = document.createElement("p") + let block_td_overtime = document.createElement("p") + let block_td_hours = document.createElement("p") + let block_td_breaks = document.createElement("p") + block_td.classList.add("Roster-week-td-name") + block_td.setAttribute("person_id", person_id) + block_td_name.innerHTML = person.name + block_td_overtime.classList.add("overtime", "font-number") + + let overtime_t = getOvertimeTitleText(person.overtime, person.name) + block_td_overtime.setAttribute("title", overtime_t) + block_td_hours.classList.add("hours", "font-number") + block_td_hours.setAttribute("title", "Stunden insgesamt") + block_td_breaks.classList.add("breaks", "font-number") + block_td_breaks.setAttribute("title", "Pause insgesamt") + + block_td_container.classList.add("td-name") + block_td_container.appendChild(block_td_name) + block_td_container.appendChild(block_td_overtime) + block_td_container.appendChild(block_td_hours) + block_td_container.appendChild(block_td_breaks) + block_td.appendChild(block_td_container) + block_tbody_row.appendChild(block_td) + block_tbody_row.classList.add("Roster-week-tr-"+person_id) + block_tbody_row.setAttribute("person_id", person_id) + +// set hours and breaks + let hours_breaks_all = await getPersonHoursAndBreaks(person_id, year_week) + let breaks_all = hours_breaks_all[1] + let hours_total = new Promise((res, rej) => {res(getPersonHoursWithFreedays(person_id, year_week))}) + hours_total = await hours_total + hours_total = parseFloat(hours_total.toFixed(2)) + block_td_hours.innerHTML = hours_breaks_all[0]+"/"+hours_total + block_td_breaks.innerHTML = hours_breaks_all[1] + +// set overtime + if (DISPLAY_OVERTIME) { + block_td_overtime.innerHTML = person.overtime + } + + for (let day_id=0; day_id<DAYS.length; day_id++) { + block_td = document.createElement("td") + block_td.classList.add("Roster-week-td", `Roster-week-td-name-${person_id}-day-${day_id}`) + block_td.setAttribute("person_id", person_id) + block_td.setAttribute("day_id", day_id) + block_tbody_row.appendChild(block_td) + renderRosterTableWeekPersonDay(person, day_id, year_week, block_td, table_id) + + } + if (table_id === "Roster-week-table" && EDITABLE_CELL) { + let block_td_cell = document.createElement("td") + block_td_cell.classList.add("td-editable-cell", `Roster-week-td-editable-cell-${person_id}`) + if (!NOWEEKEDIT) block_td_cell.setAttribute("contenteditable", "true") + block_td_cell.addEventListener('focusout', (e) => setEditableCell("cell_right", person_id, e.target.innerHTML)) + block_td_cell.innerHTML = EDITABLE_CELLS_RIGHT.find(c => c.id === person_id.toString())?.text || "" + block_tbody_row.appendChild(block_td_cell) + } + block_tbody.appendChild(block_tbody_row) + } + + if (EDITABLE_ROW_BOTTOM) { + addEmptyRow() + let block_tr_editable = document.createElement("tr") + block_tr_editable.classList.add("tr-editable") + for (let i=0; i<6; i++) { + let block_td_ediatable = document.createElement("td") + block_td_ediatable.setAttribute("id", `Roster-week-td-bottom-editable-${i}`) + if (!NOWEEKEDIT) block_td_ediatable.setAttribute("contenteditable", `true`) + block_td_ediatable.addEventListener('focusout', (e) => setEditableCell("row_bottom", i, e.target.innerHTML)) + block_td_ediatable.innerHTML = EDITABLE_ROWS_BOTTOM.find(c => c.id === i.toString())?.text || "" + block_tr_editable.appendChild(block_td_ediatable) + } + block_tbody.appendChild(block_tr_editable) + } + block_table.appendChild(block_tbody) + + return block_table +} + +loadRosterTableWeekData = async (year_week, table_id) => { + if (PERSONS.length === 0) return + showLoading("loadRosterTableWeekData") + if (typeof year_week === "undefined") { year_week = DATE_YEAR_WEEK } + if (typeof table_id === "undefined") { + table_id = "Roster-week-table" + } + let person_all + if (year_week === DATE_YEAR_WEEK) { + person_all = PERSONS + } else if (year_week === DATE_YEAR_WEEK_TABLE_TO) { + person_all = PERSONS_TABLE_TO + } else if (year_week === DATE_YEAR_WEEK_TABLE_FROM) { + person_all = PERSONS_TABLE_FROM + } else { + person_all = dbGet_persons_active_where_yearweek(year_week) + } + for (let i=0; i<person_all.length; i++) { + let person_id = person_all[i].id + loadTableWeekPersonData(person_id, year_week, table_id).then(() => { + if (i === person_all.length-1) { + hideLoading("loadRosterTableWeekData") + } + }) + } + DAYS.forEach((day, day_id) => { + let day_date = new Date(getIsoStringFromDay(day_id, year_week)) + document.querySelectorAll(`#${table_id} .Roster-week-th`)[day_id].querySelectorAll("p")[1].innerHTML = day_date.toLocaleDateString('de', {day: '2-digit', month: '2-digit', year: '2-digit'}) + }) +} + +loadRosterTableWeek = () => { + if (PERSONS.length === 0) return + let block_roster_container = document.getElementById("Roster-week-container") + let block_header = document.createElement("h2") + let block_print = document.createElement("button") + block_roster_container.innerHTML = "" + + block_header.innerHTML = "Woche "+DATE_WEEK + block_print.innerHTML = "Drucken" + block_print.classList.add("button-print") + block_print.setAttribute("onClick", `printTable("Roster-week-container", ${DATE_YEAR_WEEK})`) + block_roster_container.appendChild(block_header) + block_roster_container.appendChild(block_print) + + + createB = async () => { + let create_block = new Promise((res, rej) => {res(createBlockRosterTableWeek())}) + create_block = await create_block + block_roster_container.appendChild(create_block ) + } + createB().then(() => { + let block_week_info = document.createElement("div") + block_week_info.setAttribute("id", "Roster-week-info") + block_week_info.innerHTML = "" + let info = ROSTER_PERSON_INFOS.find(i => i.day_id === 999 && i.id === "all")?.text + if (typeof info !== "undefined") { + let block_week_info_text = document.createElement("div") + block_week_info_text.innerHTML = info + block_week_info.appendChild(block_week_info_text) + document.querySelector("#Roster-week-week-info").classList.add("active") + document.getElementById("Set-week-info-container").querySelector("textarea").value = info + document.getElementById("Set-week-info-container").classList.remove("d-none") + } + block_roster_container.appendChild(block_week_info) + }) +} + + +eventListenerEditRosterDay = (event, day_id) => { + let block_container = document.getElementById(`Roster-${day_id}`) + if (!block_container.contains(event.target)) { + let button = block_container.querySelector(".button-edit-table") + button.classList.remove("d-none") + window.onmousemove = null + } + +} + + +createDaysOption = (day_id) => { + let blocks = [] + DAYS.forEach((day, d_id) => { + if (day_id === d_id) return + let block = document.createElement("option") + block.value = d_id + block.innerHTML = day + blocks.push(block) + }) + return blocks +} + +copyRosterDay = async (day_id, from_id) => { + showLoading("copyRosterDay") + setS = async (shifts, did, yw) => { + let noreload = shifts.length === 1 ? false : true + if (yw !== DATE_YEAR_WEEK) {noreload = true} + if (shifts.length === 0) return + return addNewShiftToRoster(shifts[0].person_id, did, shifts[0].start, shifts[0].end, yw, noreload).then(() => { + if (shifts.length > 1) { return addShift(yw, did, shifts[1].person_id, shifts[1].start, shifts[1].end) } + return + }) + } + asyncMain = () => { + let new_roster_data + let year_week + let year_week_to = DATE_YEAR_WEEK + if (day_id === "all") { + year_week = DATE_YEAR_WEEK + from_id = parseFloat(from_id) + setAs = async() => { + for (let p = 0; p<PERSONS.length; p++) { + let person = PERSONS[p] + let person_id = person.id + let shifts = person.shifts.filter(s => s.day_id === from_id) + for (let d_id=0; d_id<DAYS.length;d_id++) { + if (d_id === from_id) { + if (p === PERSONS.length-1) { hideLoading("copyRosterDay")} + continue + } + checkIfPersonDayIsFree(person_id, d_id).then(cf => { + if (cf === false) { + setS(shifts, d_id, year_week_to).then(() => { + if (p === PERSONS.length-1) { hideLoading("copyRosterDay")} + }) + } else if (p === PERSONS.length-1) { hideLoading("copyRosterDay")} + }) + } + } + } + setAs() + } else { + if (from_id === "week_before") { + year_week = DATE_YEAR_WEEK_BEFORE + from_id = day_id + day_id = parseFloat(day_id) + } else if (from_id === "week_before_week") { + year_week = DATE_YEAR_WEEK_BEFORE + from_id = day_id + day_id = parseFloat(day_id) + } else if (day_id === "next"){ + year_week = DATE_YEAR_WEEK + year_week_to = DATE_YEAR_WEEK_AFTER + from_id = parseFloat(from_id) + day_id = from_id + } else { + year_week = DATE_YEAR_WEEK + from_id = parseFloat(from_id) + day_id = parseFloat(day_id) + } + + + loopP = (persons_yw) => { + for (let p=0; p<persons_yw.length; p++) { + let shifts = persons_yw[p].shifts.filter(s => s.day_id === from_id) + checkIfPersonDayIsFree(persons_yw[p].id, day_id, year_week_to).then(cf => { + if (cf === false) { + setS(shifts, day_id, year_week_to).then(() => { + if (p === persons_yw.length-1) { hideLoading("copyRosterDay")} + }) + } else if (p === persons_yw.length-1) { hideLoading("copyRosterDay")} + }) + } + } + if (ROSTERS_YEARWEEK.indexOf(year_week_to) === -1) { + createDataA(year_week_to).then(() => { + loopP(PERSONS) + }) + } else if (DATE_YEAR_WEEK === year_week) { + loopP(PERSONS) + } else { + dbGet_persons_active_where_yearweek(year_week).then(persons_yw => loopP(persons_yw)) + } + } + } + asyncMain() +} + +removeDayShifts = (day_id) => { + showLoading("removeDayShifts") + checkElementInView("main") + dbRemove_shift_where_year_week_and_day(DATE_YEAR_WEEK, day_id).then(() => { + setPerson().then(() => { + getActiveRoster().then(() => { + if (INVIEW.length > 0) document.querySelector(INVIEW)?.scrollIntoView() + hideLoading("removeDayShifts") + }) + }) + }) +} + +requestRemoveDayShifts = (day_id) => { + document.body.classList.add("noscroll") + document.getElementById("Popup").classList.add("active", "request-remove") + let block = document.getElementById("Popup-container") + block.style.width = "300px" + + let block_text = document.createElement("p") + block_text.innerHTML = "Sicher dass du alle Schichten für <b>"+DAYS[day_id]+" löschen</b> möchtest?" + block.appendChild(block_text) + + let block_button_cancel = document.createElement("button") + block_button_cancel.setAttribute("onClick", "closePopup()") + block_button_cancel.innerHTML = "abbrechen" + block.appendChild(block_button_cancel) + + let block_button_remove = document.createElement("button") + block_button_remove.setAttribute("onClick", "removeDayShifts("+day_id+");closePopup()") + block_button_remove.innerHTML = "löschen" + block.appendChild(block_button_remove) + + document.getElementById("Popup").onclick = (e) => eventListenerClosePopup(e) +} + +scrollTimeIntoView = (day_id, time) => { + document.getElementById("Table-times-thead-tr-"+day_id).querySelector(`[time="${time}"]`).scrollIntoView({behavior: "smooth", inline: "center", block: "nearest"}) +} + +addRosterPersonDayInfo = (person_id, day_id, text) => { + while (text.slice(-1) === "\n") {text = text.substring(0, text.length-1)} + + let info = ROSTER_PERSON_INFOS.find(i => i.day_id === day_id && i.id === person_id.toString()) + if (typeof info !== "undefined") {info.text = text} + else ROSTER_PERSON_INFOS.push({id: person_id.toString(), yearweek: DATE_YEAR_WEEK, day_id: day_id, text: text}) + dbSet_roster_info_where_yearweek_and_day_and_person(DATE_YEAR_WEEK, day_id, person_id, text) +} + +removeRosterPersonDayInfo = (person_id, day_id) => { + ROSTER_PERSON_INFOS = ROSTER_PERSON_INFOS.filter(i => `${i.id}-${i.day_id}` !== `${person_id}-${day_id}`) + dbRemove_roster_info_where_yearweek_and_day_and_person(DATE_YEAR_WEEK, day_id, person_id) +} + +closePersonDayInfoInput = (person_id, day_id, block) => { + let block_text = block.querySelector("textarea") + let text = block_text.value + if (text.length === 0) { + removeRosterPersonDayInfo(person_id, day_id) + block.querySelector("button").classList.remove("set") + } else if (text.length > 0) { + block.querySelector("button").classList.add("set") + addRosterPersonDayInfo(person_id, day_id, text) + } + + block.removeChild(block_text) + document.getElementById(`Td-name-${person_id}-day-${day_id}`).classList.remove("active") + document.body.onclick = null + reloadPersonDayData(person_id, day_id) +} + +eventListenerClosePersonDayInfoInput = (evt, person_id, day_id, block) => { + let targetEl = evt.target + let clickEl = block + do { + if (targetEl == clickEl) return + targetEl = targetEl.parentNode; + } while (targetEl); + closePersonDayInfoInput(person_id, day_id, block) +} + +openPersonDayInfoInput = (person_id, day_id, el) => { + let block = el.parentNode + let block_input = document.createElement("textarea") + document.getElementById(`Td-name-${person_id}-day-${day_id}`).classList.add("active") + let info = ROSTER_PERSON_INFOS.find(i => i.day_id === day_id && i.id === person_id.toString())?.text + if (typeof info !== "undefined") block_input.value = info + block.appendChild(block_input) + window.setTimeout(() => { + document.body.onclick = (e) => eventListenerClosePersonDayInfoInput(e, person_id, day_id, block) + }, 100) +} + +createBlockRosterTablePersonRow = async (person, roster, day_id, block_tbody_row) => { + document.querySelector(`#Roster-${day_id}`).classList.remove("editable") + let year_week = DATE_YEAR_WEEK + let person_id = person.id + let shifts_all = person.shifts + let shifts = shifts_all.filter(s => s.day_id === day_id) + + block_tbody_row.innerHTML = "" + + // create table name + let block_name_td = document.createElement("td") + let block_td_name_hours_container = document.createElement("div") + block_td_name_hours_container.classList.add("td-name-hours-container") + let block_name_td_container = document.createElement("div") + let d_color = DEPARTMENT_COLORS[DEPARTMENTS.map(d => d.id).indexOf(person.department)] + block_name_td.style.background = `linear-gradient(to right, black 1px, ${d_color} 1px, ${d_color} calc(100% - 1px), black 1px)` + block_name_td_container.classList.add("td-name-container") + block_name_td.setAttribute("id", "Td-name-"+person_id+"-day-"+day_id) + block_name_td.classList.add(`name-${person_id}`, "td-name", "td-name-hours", "td-sticky") + + let block_name_hours = document.createElement("div") + block_name_hours.classList.add("hours-amount") + + let block_name_td_container_hours = document.createElement("div") + block_name_td_container_hours.classList.add("hours-container") + let block_name_td_name = document.createElement("div") + block_name_td_name.classList.add("name") + block_name_td_name.innerHTML = person.name + block_name_td_container.appendChild(block_name_td_name) + + let block_name_td_overtime = document.createElement("div") + block_name_td_overtime.classList.add("td-overtime") + let overtime = person.overtime + let overtime_t = getOvertimeTitleText(overtime, person.name) + if (overtime === 0) {block_name_td_overtime.classList.add("green"); block_name_td_overtime.classList.remove("orange", "red")} + else if (overtime > 0) {overtime = `+${overtime}`; block_name_td_overtime.classList.add("red"); block_name_td_overtime.classList.remove("green", "orange")} + else if (overtime < 0) {block_name_td_overtime.classList.add("orange"); block_name_td_overtime.classList.remove("green", "red")} + block_name_td_overtime.innerHTML = overtime + block_name_td_overtime.setAttribute("title", overtime_t) + block_name_td_container.appendChild(block_name_td_overtime) + + + let hours_breaks = await getPersonDayHoursAndBreaks(person_id, day_id, year_week) + let hours = hours_breaks[0] + let breaks = hours_breaks[1] + let hours_total = await getPersonHoursWithFreedays(person_id) + hours_total = parseFloat(hours_total.toFixed(2)) + let hours_breaks_all = await getPersonHoursAndBreaks(person_id, year_week) + let hours_a = hours_breaks_all[0] + let breaks_a = hours_breaks_all[1] + let block_name_hours_vs_given = document.createElement("div") + block_name_hours_vs_given.setAttribute("title", "Stunden vergeben/Stunden max") + block_name_hours_vs_given.classList.add("hours-given") + block_name_hours_vs_given.innerHTML = hours_a+"/"+hours_total + block_name_hours.appendChild(block_name_hours_vs_given) + + + block_name_td_container_hours.appendChild(block_name_hours) + + block_name_td_container.appendChild(block_name_td_container_hours) + block_td_name_hours_container.appendChild(block_name_td_container) + block_name_td.appendChild(block_td_name_hours_container) + + + // create table name hours + + // top + let block_td_top_bottom = document.createElement("div") + block_td_top_bottom.classList.add("td-top-bottom") + let block_td_top = document.createElement("div") + block_td_top.classList.add("td-top") + + let block_name_mpa = document.createElement("div") + block_name_mpa.setAttribute("title", getRenames("m").a) + block_name_mpa.classList.add("hours-mpa") + let mpa = person.mpa[day_id] + let check_if_free = await checkIfPersonDayIsFree(person_id, day_id) + if (check_if_free) {mpa = 0} + let check_betterment = check_if_free === getRenames("b").a ? true : false + + let block_name_mpa_value = document.createElement("div") + block_name_mpa_value.innerHTML = mpa === 0 ? "" : person.mpa[day_id] + block_name_mpa.style.zIndex = mpa === 0 ? "-1" : "0" + block_name_mpa.appendChild(block_name_mpa_value) + block_td_top.appendChild(block_name_mpa) + + let block_name_td_info = document.createElement("div") + block_name_td_info.classList.add("td-info") + let block_name_td_info_button = document.createElement("button") + + let info = ROSTER_PERSON_INFOS.find(i => i.day_id === day_id && i.id === person_id.toString())?.text + + info && info.length > 0 && block_name_td_info_button.classList.add("set") + block_name_td_info_button.classList.add("button-info") + block_name_td_info_button.setAttribute("onClick", `openPersonDayInfoInput(${person_id}, ${day_id}, this)`) + block_name_td_info_button.setAttribute("title", "Informationen zu der Schicht hinzufügen") + block_name_td_info_button.innerHTML = "i" + block_name_td_info.appendChild(block_name_td_info_button) + block_td_top.appendChild(block_name_td_info) + + let block_name_td_menu = document.createElement("div") + let block_name_td_button = document.createElement("button") + block_name_td_button.classList.add("button-menu", "hamburger") + block_name_td_button.innerHTML = "<span></span><span></span><span></span>" + block_name_td_button.setAttribute("onClick", "openRosterPersonMenu("+person_id+", "+day_id+")") + block_name_td_menu.classList.add("menu", "menu-"+person_id+"-day-"+day_id) + block_td_top.appendChild(block_name_td_button) + if (check_if_free) { + block_name_td_button.setAttribute("disabled", "true") + } + block_td_top.appendChild(block_name_td_menu) + + block_td_top_bottom.appendChild(block_td_top) + + // bottom + let block_td_bottom = document.createElement("div") + block_td_bottom.classList.add("td-bottom") + + let block_name_break = document.createElement("div") + block_name_break.setAttribute("title", "Pause heute") + block_name_break.classList.add("break-today") + block_name_break.innerHTML = breaks + block_td_bottom.appendChild(block_name_break) + + + let block_name_hours_today = document.createElement("div") + block_name_hours_today.setAttribute("title", "Schichtstunden heute ohne MPA") + block_name_hours_today.classList.add("hours-today") + block_name_hours_today.innerHTML = check_betterment ? hours : hours-person.mpa[day_id] + block_td_bottom.appendChild(block_name_hours_today) + + block_td_top_bottom .appendChild(block_td_bottom) + block_td_name_hours_container.appendChild(block_td_top_bottom) + + // create table time + block_tbody_row.setAttribute("onmouseover", `this.classList.add("hover");`) + block_tbody_row.setAttribute("onmouseout", `this.classList.remove("hover");`) + + block_tbody_row.setAttribute("id", `Tr-${person_id}-day-${day_id}`) + block_tbody_row.classList.add("tr-name-"+person_id) + + block_tbody_row.appendChild(block_name_td) + + // create table td + + callback_r = (name) => { + let block_td_after = document.createElement("td") + block_td_after.classList.add("td-name-after") + block_td_after.innerHTML = name + return block_td_after + } + + let label = person.sl[day_id] + roster.d.forEach((data, time_id) => { + let time = data.t + let block_times_td = document.createElement("td") + let block_times_container = document.createElement("div") + block_times_container.classList.add("container") + let block_times_content + block_times_td.setAttribute("person", person.name) + block_times_td.setAttribute("time", time) + block_times_td.classList.add("td-day-time") + if (check_if_free === false) { + block_times_content = document.createElement("div") + block_times_content.classList.add("shiftmodify-buttons-container") + let block_times_button_shift = document.createElement("button") + block_times_button_shift.classList.add("roster-add-shift") + if (label !== false) { + block_times_button_shift.innerHTML = dbGet_shift_label_cut(label) + } else { + block_times_button_shift.innerHTML = "" + } + block_times_button_shift.setAttribute("title", `${person.name}\nNeue Schicht\n${timeToHHMM(time)}`) + block_times_button_shift.setAttribute("onClick", "addNewShiftToRoster("+person_id+", "+day_id+", "+time+")") + + block_times_content.appendChild(block_times_button_shift) + block_times_container.appendChild(block_times_content) + } else { + block_times_td.classList.add("free") + block_times_content = document.createElement("p") + block_times_content.innerHTML = check_if_free + block_times_container.innerHTML = "" + block_times_container.appendChild(block_times_content) + } + block_times_td.appendChild(block_times_container) + block_tbody_row.appendChild(block_times_td) + if (time_id === roster.d.length-1) block_tbody_row.appendChild(callback_r(person.name)) + if (shifts.find(s => s.start <= time && s.end >time)) { + block_times_td.classList.add("assigned") + } + }) +} + +renderRosterSort = () => { + let block_roster_container = document.getElementById("Roster-days-container") + let block = document.createElement("div") + let block_remove = document.querySelector("#Sort-roster-by") + block.setAttribute("id", "Sort-roster-by") + block.classList.add("settings-box") + let block_box = document.createElement("div") + block_box.classList.add("sort-box") + let block_name = document.createElement("button") + block_name.setAttribute("id", "Sort-roster-by-name") + block_name.classList.add("sort-roster-by", "sort") + block_name.setAttribute("name", "n") + block_name.setAttribute("onClick", "sortRosterBy('days', this)") + block_name.innerHTML = "Name" + let block_dep = document.createElement("button") + block_dep.setAttribute("id", "Sort-roster-by-department") + block_dep.classList.add("sort-roster-by", "sort") + block_dep.setAttribute("name", "d") + block_dep.setAttribute("onClick", "sortRosterBy('days', this)") + block_dep.innerHTML = "Bereich" + let block_hou = document.createElement("button") + block_hou.setAttribute("id", "Sort-roster-by-hours") + block_hou.classList.add("sort-roster-by", "sort") + block_hou.setAttribute("name", "h") + block_hou.setAttribute("onClick", "sortRosterBy('days', this)") + block_hou.innerHTML = "Stunden" + if (block_remove) block_roster_container.removeChild(block_remove) + block_box.appendChild(block_name) + block_box.appendChild(block_dep) + block_box.appendChild(block_hou) + block.appendChild(block_box) + block_roster_container.appendChild(block) + setRosterSortButtons(0) +} +loadRosterTable = async () => { + let block_roster_container = document.getElementById("Roster-days-container") + block_roster_container.innerHTML = "" + renderRosterSort() + let day = structuredClone(DATE) + day.setDate(day.getDate() - 1) + for (let day_id=0; day_id<ROSTER.length; day_id++) { + let roster = ROSTER[day_id] + day.setDate(day.getDate() + 1) + let block_container_roster = document.createElement("div") + let block_container_roster_head = document.createElement("div") + block_container_roster_head.classList.add("Roster-container-head") + + let block_header_day = document.createElement("h2") + block_header_day.setAttribute("id", `Roster-${day_id}-title`) + + block_container_roster.setAttribute("id","Roster-"+day_id) + block_container_roster.classList.add("Roster-container") + block_container_roster.appendChild(block_header_day) + addDragToScroll(block_container_roster) + + + let block_container_copy_from_to = document.createElement("div") + block_container_copy_from_to.classList.add("container-copy-from-to") + + let block_button_copy_from = document.createElement("select") + block_button_copy_from.classList.add("select-copy-from", "select-copy") + block_button_copy_from.setAttribute("title", "Den gesamten Plan von einem Wochentag, oder selben Tag der Vorwoche kopieren.\nDies löscht alle vorhandenen Schichten des Tages") + block_button_copy_from.setAttribute("onchange", "copyRosterDay("+day_id+", this.value)") + block_button_copy_from.innerHTML = '<option disabled="disabled" selected="selected">Übertragen von</option>' + + let block_option_wb = document.createElement("option") + block_option_wb.value = "week_before" + block_option_wb.innerHTML = "Letzte Woche" + block_button_copy_from.appendChild(block_option_wb) + let block_option_wbw = document.createElement("option") + block_option_wbw.value = "week_before_week" + block_option_wbw.innerHTML = "Vorletze Woche" + block_button_copy_from.appendChild(block_option_wbw) + createDaysOption(day_id).forEach(block => block_button_copy_from.appendChild(block)) + block_container_copy_from_to.appendChild(block_button_copy_from) + + let block_button_copy_to = document.createElement("select") + block_button_copy_to.classList.add("select-copy-to", "select-copy") + block_button_copy_to.setAttribute("title", "Den gesamten Plan dieses Tages, auf einen Anderen Tag übertragen.\nDies löscht alle vorhandenen Schichten des zieltages.") + block_button_copy_to.setAttribute("onchange", "copyRosterDay(this.value, "+day_id+")") + block_button_copy_to.innerHTML = '<option disabled="disabled" selected="selected">Übertragen nach</option><option value="next">Nächste Woche</option>' + createDaysOption(day_id).forEach(block => block_button_copy_to.appendChild(block)) + let block_copy_to_all = document.createElement("option") + block_copy_to_all.setAttribute("value", "all") + block_copy_to_all.innerHTML = "Alle" + block_button_copy_to.appendChild(block_copy_to_all) + block_container_copy_from_to.appendChild(block_button_copy_to) + + block_container_roster_head.appendChild(block_container_copy_from_to) + + let block_table_container = document.createElement("div") + block_table_container.setAttribute("id", "Table-"+day_id+"-container") + block_table_container.classList.add("tables-container") + + let block_button_edit_table = document.createElement("button") + block_button_edit_table.setAttribute("onClick", `loadEditableDataIntoRosterTable(this, ${day_id})`) + block_button_edit_table.classList.add("button-edit-table") + let block_button_edit_table_text = document.createElement("div") + block_button_edit_table_text.innerHTML = "Bearbeiten" + block_button_edit_table.appendChild(block_button_edit_table_text) + block_table_container.appendChild(block_button_edit_table) + + let block_table = document.createElement("table") + block_table.classList.add("table-times") + let block_thead = document.createElement("thead") + let block_tbody = document.createElement("tbody") + let block_thead_row = document.createElement("tr") + block_thead_row.setAttribute("id", "Table-times-thead-tr-"+day_id) + + let block_time_scroll = document.createElement("div") + block_time_scroll.classList.add("time-scroll-container") + block_container_roster_head.appendChild(block_time_scroll) + + block_container_roster.appendChild(block_container_roster_head) + let block_button_remove = document.createElement("button") + block_button_remove.innerHTML = "löschen" + block_button_remove.classList.add("button-remove-day-shifts", "button-remove") + block_button_remove.setAttribute("onClick", "requestRemoveDayShifts("+day_id+")") + block_container_roster_head.appendChild(block_button_remove) + let block_th_name = document.createElement("th") + let block_th_name_day = document.createElement("div") + block_th_name_day.innerHTML = DAYS[day_id] + block_th_name.appendChild(block_th_name_day) + block_thead_row.appendChild(block_th_name) + + + block_thead.appendChild(block_thead_row) + block_table.appendChild(block_thead) + block_table.appendChild(block_tbody) + block_table_container.appendChild(block_table) + block_container_roster.appendChild(block_table_container) + block_roster_container.appendChild(block_container_roster) + for (let time_id=0; time_id<roster.d.length; time_id++) { + let time = roster.d[time_id] + if (checkNaturalNumber(time.t)) { + let button = document.createElement("button") + button.setAttribute("onClick", `scrollTimeIntoView(${day_id}, ${time.t})`) + button.setAttribute("title", `Zur Uhrzeit ${time.t}:00 scrollen`) + button.innerHTML = time.t + block_time_scroll.appendChild(button) + } + + let block_th = document.createElement("th") + let block_th_time = document.createElement("p") + let block_th_amount = document.createElement("div") + let block_th_amount_container = document.createElement("div") + let block_th_amount_max = document.createElement("p") + let block_th_amount_is = document.createElement("p") + let block_th_amount_buttons = document.createElement("div") + let block_th_amount_button_up = document.createElement("button") + let block_th_amount_button_down = document.createElement("button") + block_th.setAttribute("time", time.t) + block_th.classList.add("th-day-time", "font-number") + block_th.setAttribute("style", "background-color: "+colors_red_orange_green[0]+";") + block_th_time.classList.add("time", "font-number") + let time_text = timeToHHMM(time.t) + if (time_text.length === 4) time_text = ` ${time_text}` + block_th_time.innerHTML = time_text + block_th_amount_buttons.classList.add("th-amount-buttons") + block_th_amount_button_up.classList.add("chevron-up") + block_th_amount_button_up.setAttribute("onClick", "changeTimeAmount(this, "+day_id+", 'up', "+time_id+")") + block_th_amount_button_down.classList.add("chevron-down") + block_th_amount_button_down.setAttribute("onClick", "changeTimeAmount(this, "+day_id+", 'down', "+time_id+")") + + block_th_amount_buttons.appendChild(block_th_amount_button_up) + block_th_amount_buttons.appendChild(block_th_amount_button_down) + + block_th_amount_container.setAttribute("onClick", "this.classList.toggle('active')") + block_th_amount_container.setAttribute("title", "vergebene Schichten/Gewünschte Anzahl\nUm mehrere zu erhöhen auf mehrere dieser Zahlen drücken.\nUm alle Markierungen zu entfernen eine unmarkierte Zahl verändern.") + block_th_amount_container.classList.add("th-amount-container") + block_th_amount_max.innerHTML = time.a + block_th_amount_max.classList.add("time-amount-max") + block_th_amount_is.innerHTML = "0/" + block_th_amount_is.classList.add("time-amount-is") + + block_th_amount_container.appendChild(block_th_amount_is) + block_th_amount_container.appendChild(block_th_amount_max) + block_th_amount.appendChild(block_th_amount_container) + block_th_amount.appendChild(block_th_amount_buttons) + block_th_amount.classList.add("time-amount") + + block_th.appendChild(block_th_amount) + block_th.appendChild(block_th_time) + + block_thead_row.appendChild(block_th) + + let amount = await getPersonAmountForDayTime(day_id, time.t).length + let color_id = Math.round((amount*colors_red_orange_green.length)/time.a) + let color = colors_red_orange_green[color_id] + if (color_id >= colors_red_orange_green.length) color = colors_red_orange_green[colors_red_orange_green.length-1] + if (amount > time.a) color = "#458caf" + else if (amount === time.a) color = "#61a64d" + + + block_th.setAttribute("style", `background-color: ${color}; border-color: ${color}87;`) + block_th_amount_is.innerHTML = amount+"/" + } + let time_last = timeToHHMM(ROSTER[day_id].d[ROSTER[day_id].d.length-1].t+TIME_STEP) + let block_th = document.createElement("th") + block_th.setAttribute("colspan", "2") + let block_th_p = document.createElement("p") + + block_th_p.innerHTML = time_last + block_th_p.classList.add("time") + block_th.classList.add("th-day-time") + block_th.appendChild(block_th_p) + block_thead_row.appendChild(block_th) + + let log_date = performance.now() + for (let pr=0; pr<PERSONS_ROSTER.length;pr++) { + log_date = performance.now() + let person = PERSONS_ROSTER[pr] + let block_tbody_row = document.createElement("tr") + block_tbody.appendChild(block_tbody_row) + createBlockRosterTablePersonRow(person, roster, day_id, block_tbody_row) + } + + let day_date = structuredClone(DATE) + day_date.setDate(day_date.getDate() - (day_date.getDay() + 6) % 7 + day_id) + block_header_day.innerHTML = roster.n+" "+day_date.toLocaleDateString('de', {day: '2-digit', month: '2-digit', year: '2-digit'}) + addDragToScroll(block_container_roster, day_id) + } +} + +toggleTableWeekEditeable = (table_name) => { + showLoading("toggleTableWeekEditeable") + let year_week = DATE_YEAR_WEEK + let table_id = EDITABLE_TABLES.indexOf(table_name) + if (table_id > -1) { EDITABLE_TABLES.splice(table_id, 1) } + else { + EDITABLE_TABLES.push(table_name) + } + if (document.querySelector("#Popup .item-table-to .select-roster")) { + year_week = document.querySelector("#Popup .item-table-to .select-roster").value + } + loadRosterTableWeekData(year_week, table_name).then(() => { + hideLoading("toggleTableWeekEditeable") + }) +} diff --git a/js/scroll.js b/js/scroll.js new file mode 100755 index 0000000..a347a29 --- /dev/null +++ b/js/scroll.js @@ -0,0 +1,58 @@ +addDragToScroll = (slider, day_id) => { + let isDown = false; + let startX; + let startY; + let scrollLeft; + let scrollTop; + let new_scrollLeft + let new_scrollTop + let check_remove = false + let block_button + + if (typeof day_id !== "undefined") { + block_button = document.querySelector(`#Table-${day_id}-container .button-edit-table`) + } + slider.addEventListener('mousedown', (e) => { + isDown = true; + slider.classList.add('active'); + startX = e.pageX - slider.offsetLeft; + startY = e.pageY - slider.offsetTop; + scrollLeft = slider.scrollLeft; + scrollTop = slider.scrollTop; + slider.style = "cursor: grabbing !important;" + }); + slider.addEventListener('mouseleave', () => { + isDown = false; + slider.classList.remove('active'); + }); + slider.addEventListener('mouseup', () => { + isDown = false; + slider.classList.remove('active'); + slider.style = "cursor: auto;" + window.setTimeout(() => { + check_remove = false + if (typeof day_id !== "undefined") { + block_button.setAttribute("onClick", `loadEditableDataIntoRosterTable(this, ${day_id})`) + } + }, 50) + }); + slider.addEventListener('mousemove', (e) => { + if(!isDown) return; + + e.preventDefault(); + const x = e.pageX - slider.offsetLeft; + const y = e.pageY - slider.offsetTop; + const walk = (x - startX) * 3; //scroll-fast + const walk_y = (y - startY) * 3; //scroll-fast + new_scrollLeft = scrollLeft - walk; + new_scrollTop = scrollTop - walk_y; + if (scrollLeft !== new_scrollLeft && !check_remove) { + check_remove = true; + if (typeof day_id !== "undefined") { + block_button.removeAttribute("onClick") + } + } + slider.scrollLeft = new_scrollLeft + slider.scrollTop = new_scrollTop + }); +} diff --git a/js/settings.js b/js/settings.js new file mode 100755 index 0000000..a92c9bf --- /dev/null +++ b/js/settings.js @@ -0,0 +1,1389 @@ +const TIME_STEPS_VALUES = [ 15, 30, 60 ] +const TIME_STEPS = [ 0.25, 0.5, 1 ] +const MINUTE_STEPS_VALUES = [ 15, 30, 45, 60 ] +const MINUTE_STEPS = [ 0.25, 0.5, 0.75, 1 ] +let TIME_STEP = 0.5 +let TIME_START = 7 +let TIME_END = 16 +let TIME_SPECIALSTART = false + +let block_settings = document.getElementById("Settings") + +let improvement_texts = [ +[false, "geteilte Schichten reparieren"], +[false, "schichtplan sortierbar"], +[false, "MPA einbauen"], +[false, "Einstellungen ausblenden"], +[false, "Personen bearbeiten button"], +[false, "Personenveränderungen nur in der Zukunft"], +[false, "Scroll with drag"], +[false, "Extrainfos für Schichten"], +[false, "Extrainfos für die gesamte Woche"], +[false, "Sort by department and hour"], +[false, "Weiterbildung für Personen"], +[false, "Bereiche umbenennbar in Einstellungen(Bereich, Freie Tage)"], +[false, "MPA in Tabelle anzeigen"], +[false, "Überstunden der letzten Wochen anzeigen"], +[false, "change portrait print scale to zoom"], +[false, "Add roster zoom button(style.zoom)"], +[false, "roster Übertragen nach -> Alle"], +[false, "restructure roster database for times"], +[false, "add user zoom lvl for printing"], +[false, "Schließzeiten"], +[false, "Übersicht der erstelleten Dienstplanwochen"], +[false, "Bearbeiten overlay gegen versehentliches hinzufügen von Schichten?"], +[false, "keep old roster for faster loading"], +[false, "add extrabutton for splitted shift"], +[false, "add Activation of person"], +[false, "reduce use of getActivePerson function"], +[false, "button ->apply person changes on all rosters"], +[false, "create add department in settings"], +[false, "person table -> view all, just ativated, removed"], +[false, "reactivate persons button"], +[false, "rework freedays"], +[false, "add peolpe shift labels"], +[false, "add/remove shift labels"], +[false, "add copy shift to next week"], +[false, "add shift hover info to name field"], +[false, "possibility to display overtime in week table"], +[false, "fix roster menu no overflow"], +[false, "add setting editable row/cell default active"], +[false, "firefox is smashing my tables -> just during print preview,...."], +[false, "fix closingtime adds wrong date in roster"], +[false, "Urlaubs übersicht"], +[false, "info button keeps active also it shouldnt"], +[false, "add dropdown to add persons shifts of prev week"], +[false, "fix stupid date-string comparisons"], +[false, "fix person overview -> all sf not found"], +[false, "clean up the code a bit"], +[false, "add copy shifts from yw to yw table "], +[false, "fix loading screen"], +[false, "add editable row bottom"], +[false, "fix bug split shift sometimes not knowing the end time"], +[false, "keyboard shortcuts for rosters?"], +[false, "add mpa through roster person menu"], +[false, "bug remve shift keeps button extra shift"], +[false, "roster days max 100vh"], +[false, "roster drag vertical"], +[false, "scrollstep for roster"], +[false, "automatically add lawful vacations"], +[false, "lawful vacations add back button"], +[false, "fix if vacation name is too long"], +[false, "add edit shifts from within table view"], +[false, "troll vacations overview is rubbish"], +[true, "css colors to variables"], +[true, "Übertragen nach -> nächste woche"], +[true, "what happens if vacation overwrites vacation?"], +[true, "make inactive person editable"], +[true, "add closingtime edit to vacations-overview"], +[true, "transfer person => add name search"], +[true, "display total vacation days of person"], +[true, "add toggleable legend for cut infos to roster-week"], +[true, "Übersicht der Personen (veränderungen, überstunden pro woche, etc.)"], +[true, "Add button for possibility to display shift info outside of table"], +[true, "warn if copy shift overwrites shift"], +[true, "warn if person change changes roster"], +[true, "better layout for printing settings"], +[true, "weekinfo more customeable (li, h2, fontsize,..)"], +[true, "fix crosshair for zoomlevel"], +[true, "update help section"], +[true, "clean up the code"], +[true, "Layout überarbeiten"], +] +getImprovementText = () => { + let text = "" + improvement_texts.reverse().forEach(data => { + if (data[0]) {text = `${text}<li>${data[1]}</li>`} + else {text = `${text}<li><del>${data[1]}</del></li>`} + }) + return text +} + +const HELP = [ + ["Personen", `Die <b>Stundenzahl</b> der Personen sollte <b>ohne Pausenzeiten</b> angegeben werden. Pausen werden automatisch hinzugerechnet: 30min nach mehr als 6 Stunden, insgesamt 45min oder eine Stunde (Jeh nach Einstellung) nach 9 Stunden. Die Stunden werden in Stunden und nicht in minuten angegeben. Das bedeutet 1=60min, 0.5=30min.\n\nSollten bereits Schichten vergeben worden sein werden <b>Änderungen</b> in den Bereichen "Name, Stunden, Bereich, Freie Tage, MPA" <b>nicht für vergangene Wochen</b> übernommen. Als beispiel: Die Freien Tage in der Woche 49 werden nicht durch eine Änderung der Freien Tage in der Woche 50 beeinträchtigt.\nDer Berreich <b>mpA</b> bedeutet "mittelbar pädagogische Arbeit" und bezieht sich auf eine Arbeitszeit die <b>unabhängig vom Schichtplan</b> gearbeitet wird. Die Zeit wird wie bei den Stunden vergeben, was bedeutet 1=60min, 0.5=30min.`], + ["Einstellungen", `Die Einstellungen werden pro Woche gespeichert.\nEs gibt nur eine Einstellungsmöglichkeit für eine Pause nach 9 Stunden. Bei der Angabe ist eine 30 minuten Pause nach 6 Stunden mit eingerechnet.`], + ["Tastenkürzel", "Um schnell auf der Seite navigieren zu können gibt es die folgenden Tastenkürzel:\nw:\tWochenübersicht\n1-7:\tMo-Fr\np:\tPersonen tablle\ne:\tEinstellungen\nh:\tDatum ändern -> Heute\nn:\tDatum ändern -> nächste Woche\nv:\tDatum ändern -> vorherige Woche\nz:\tzuletzt gesehene Woche\nx:\tExportieren\nd:\tDrucken\n+:\tZoom vergrößern +15\n-:\tZoom verkleinern -15\n0:\tZoom normal"], + ["Datum ändern", `Zum ändern des Datums findest du in dem Menu unten in der Mitte neben den Wochennamen einen Pfeil nach links um zur vorherigen Woche zu gelangen, sowie einen Pfeil nach links um zur nächsten Woche zu gelangen.\nUnter der Personenübersichtstabelle findest du ein Datumsfeld, in welches du ein Datum eintragen kannst, oder eines auswählen kannst indem du auf das icon links drückst.`], + ["Schichten", `Um eine neue Schicht <b>hinzuzufügen</b> kannst du auf das große Feld bei der gewünschten Person während der gewünschten Zeit drücken. Eine neue Schicht wird mit der durchschnittlichen Arbeitszeit hinzugefügt. Bei eine Schicht länger als 6 Stunden wird eine Pause von 30min auf die gesamte Arbeitszeit hinzugerechnet, ab 9 Stunden insgesamt 45min oder eine Stunde, abhängig der Angabe in den Einstellungen. Die MPA Zeit wird von der Schicht abgerechnet.\n\nUm eine Schicht zu <b>verlängern</b> findest du vor oder nach der Schicht in der gewüschten Zeit einen Pfeil welcher die Schicht bis dort verlängert.\nUm eine Schicht zu <b>verkürzen</b> findest du während der Schicht in der gewünschten Zeit unten einen Pfeil nach rechts, welcher die Startzeit dort hin setzt, so wie einen Pfeil nach links, welcher die Endzeit verkürzt.\nSollte dein Zeitintervall auf 30min stehen findest im letzten grünen Feld der Schicht im oberen Teil einen Pfeil nach Links, welcher die Endzeit <b>um 15min verkürzt</b>.\n In den mittleren Feldern während einer Schicht findest du oben rechts ein "x" mit welchem du eine <b>geteilte Schicht</b> erstellen kannst. Um die Schichten wieder zusammen zu fügen musst du die zweite Schicht bis zur ersten verlängern.\n\nBeim neu laden von Schichten werden <b>nicht alle Buttons geladen</b>, was mit einer langen Ladezeit zusammen hängt. Um alle Buttons wider zu laden muss eine Schicht veränderert, bzw. erneut angelegt werden`], + ["Tagesübersicht", `Um schnell zu einem Tag zu gelangen kannst du in dem Menu unten in der Mitte auf einen Tag klicken.\nIn der Tagesübersicht wird der Dienstplan erstellt.\nZum <b>scrollen nach links oder rechts</b> kannst du mit geklickter Maus den Plan verschieben\n<b>Über der Tabelle</b> findest du <b>links zwei Buttons</b> zum kopieren des gesamten Tages, <b>in der Mitte</b> Zahlen um schnell zu einer gewünschten Zeit zu scrollen, <b>rechts</b> einen Button zum löschen des gesamten Tages. In den <b>Namensfeldern</b> findest du unten <b>links</b> die vergenenen Stunden pro Woche/ die maximalen Stunden pro Woche. In der <b>mitte</b>, falls vorhanden, die MPA Zeit. <b>Rechts</b> findest du die Pausenzeit. Der <b>button oben rechts</b> im Namensfeld ist zum kopieren von Schichten\nIn den <b>Zeitfeldern</b> findest du <b>über der Zeit</b> die gewünschte Personenanzahl/die maximal gewünschten Personen. Die Anzahl kann mit den Pfeilen nebendran erhöht oder verringert werden. Um die Anzahl bei mehreren Zeiten gleichzeitig zu erhöhen kannst du mehrerere zahlen markieren indem du auf sie drückst. Um die Markierungen schnell wieder aufzuheben kannst du eine unmarkierte Zahl verändern.\nDie Zeitfelder werden jeh nach Belegung <b>farbig</b> hinterlegt: Rot bedeutet zu wenig vergebene Schichten, grün ist die gewünschte Anzahl, blau ist eine Überbelegung. Zwischen rot und grün gibt es sieben Abstufungen.`], + ["Wochenübersicht", `Um schnell zu der Wochenübersicht zu gelangen gibt es im Menu unten links einen Button "Woche XY". XY ist die aktuelle Wochennummer (Wochen pro Jahr).\n<b>Unter den Namen</b> findest du <b>links</b> die vergenenen Stunden pro Woche/ die maximalen Stunden pro Woche. Zu den maximalen Stunden werden die Pausenzeiten dazugerechnet.\n<b>Rechts</b> findest du die gesamte Pausenzeit pro Woche.\n<b>In den Zeitfeldern</b> findest du <b>oben</b> die Schichtzeit. <b>Unten links</b> die gesamte Stundenanzahl, in der <b>Mitte</b> die MPA Zeit, <b>unten rechts</b> die Pausenzeit.`], + ["Drucken", `Zum Drucken eines Dienstplans gibt es ganz unten auf der Seite über der Wochenübersicht einen Button "Drucken". Beim dücken dieses öffnet sich eine neue Seite mit der Wochenübersicht, sowie ein Fenster welches das Drucken oder abspeichern als PDF ermöglicht. Sollte das Format des Druckes nicht passen, hast du die Möglichkeit in dem Druckfenster, welches von deiner Distribution (Linux, Mac, Windows,..) geöffnet wird, die Einstellungen anzupassen. `], + ["Speichern", `Zum speichern gibt es im Menu unten auf der rechten Seite einen Button <b>"Exportieren"</b>.\nBeim drücken diese wird entweder eine Datei automatisch in deinen Download Ordner gespeichert, oder du wirst aufgefordert einen Ort zum speichern zu wählen (diese Einstellung lässt sich in deinen Browsereinstellungen ändern).\nDie gespeicherte Datei wird einen namen wie beispielsweise "<b>dienstplan-2022-49.json</b>" bekommen. der Name setzt sich aus dem Jahr und der Wochennummer (Wochen pro jahr) des zuletzt erstellten dienstplans zusammen.\nDie Datei ist eine JSON Datei und beinhaltet die zuvor erstellte Datenbank.`], + ["Importieren", `Eine Datei welche zuvor gespeichert wurde kann auf der Startseite mit dem Button <b>"Datei importieren"</b>, oder bei einem Diensplan direkt mit dem Button oben rechts über den Einstellungen <b>"Importieren"</b>, importiert werden. Dafür öffnet sich ein Dateifenster in welchem du die gewünschte Datei auswählen kannst.\nDas importieren stellt alle zuvor gespeicherten Daten wieder her. `], + ["Code", `Der Code dieser Seite ist mit html, javascript und css geschrieben und kann über den Quelltext eingesehen werden. Ich verzichte auf jegliche Zusatzpakete wie jquery, sass oder ähnliche npm/yarn Pakete.\nBei einem Zugriff auf diese Seite werden die folgenden Daten zur abwehr schädlicher Angriffe gespeichert:\n[Datum Zeitzone], IP-Adresse, "Art des Zugriffes", Erfolg(200/404..), Datenmenge\nEin so genannter "Log" sieht wie folgt aus:\n[26/Apr/2022:20:24:54 +0200] 0.0.0.0 "GET / HTTP/1.1" 200 11161.\nIch verzichte auf Cookies, google und co und habe kein interesse an deinen Daten.`], + ["Zukünftige Verbesserungen", `<ul>${getImprovementText()}</ul>`]] + + + +checkNaturalNumber = (n) => { + return n >= 0 && Math.floor(n) === +n; +} + +isValidDate = (d) => { + return d instanceof Date && !isNaN(d); +} + +toggleSettingsMenu = () => { + let block = document.querySelector("#Menu-settings") + block.classList.contains("visible") ? + block.classList.remove("visible") : + block.classList.add("visible") +} +checkHideSettingsMenu = () => { + let check = isElementInViewport(document.querySelector("#Settings")) + let block_menu = document.querySelector("#Menu-settings") + if (!block_menu) {return} + let block_toggle = block_menu.querySelector(".toggle-menu") + if (check) { + block_menu.classList.add("active") + block_menu.classList.remove("visible")} + else { + block_menu.classList.remove("active") + block_menu.classList.remove("visible") + } +} + +checkElementInView = (where) => { + let elements = [] + let elements_day = [] + DAYS.forEach((day, day_id) => elements_day.push("#Roster-"+day_id)) + if (where === "main") {elements = ["#Settings-default", "#Roster-days-container", "#Person-container", "#Closingtimes", "#Vacations-overview", "#Roster-container-week"]} + checkEls = (els) => { + els.forEach(el_name => { + let el = document.querySelector(el_name) + if (el && !el.classList.contains("d-none")) { + let check = isElementInViewport(el) + if (check) { + if (el_name === "#Roster-days-container") { + checkEls(elements_day) + } else { + INVIEW = el_name + return + } + } + } + }) + } + checkEls(elements) +} +isElementInViewport = (el) => { + let rect = el.getBoundingClientRect(); + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); +} + +visiteAdministration = () => { + window.location = "/useradmin.php" +} + +showLoading = (loading_function) => { + LOADINGS.push(loading_function) + document.getElementById("Loading-screen").classList.remove("d-none") +} +hideLoading = (loading_function) => { + LOADINGS.splice(LOADINGS.indexOf(loading_function), 1) + if (LOADINGS.length === 0) document.getElementById("Loading-screen").classList.add("d-none") +} + +settingsContainerHideAll = (donthide) => { + document.querySelector("#Settings").scrollIntoView() + let blocks_hide = document.querySelectorAll("#Settings-container >*") + for (let i=0; i<blocks_hide.length; i++) { + blocks_hide[i].getAttribute("id") === donthide ? + blocks_hide[i].classList.remove("d-none") : + blocks_hide[i].classList.add("d-none") + } + let blocks_hide_menu = document.querySelectorAll("#Menu-settings > *") + for (let i=0; i<blocks_hide_menu.length; i++) { + if (blocks_hide_menu[i].classList.contains(`Menu-${donthide}`)) { + blocks_hide_menu[i].classList.add("active") + if (donthide === "Closingtimes") { + blocks_hide_menu[i].classList.add("closingtime") + blocks_hide_menu[i].classList.remove("vacation") + } else if (donthide === "Vacations-overview") { + blocks_hide_menu[i].classList.add("vacation") + blocks_hide_menu[i].classList.remove("closingtime") + } + } else { + blocks_hide_menu[i].classList.remove("active") + } + } +} + +changePrintZoomLvl = (z_id, el) => { + if (SETTINGS.printmode === 0) { + SETTINGS.zoom_print_h = parseFloat(el.value) + dbSet_settings_zoom_print_h(parseFloat(el.value)) + } else { + SETTINGS.zoom_print_v = parseFloat(el.value) + dbSet_settings_zoom_print_v(parseFloat(el.value)) + } + document.querySelector("#Roster-week-print-zoom .zoom-value").innerHTML = `${el.value}%` +} +setPrintZoomLevelValue = (change) => { + if (SETTINGS.printmode === 0) { + SETTINGS.zoom_print_h = SETTINGS.zoom_print_h+(change) + dbSet_settings_zoom_print_h(SETTINGS.zoom_print_h) + } else { + SETTINGS.zoom_print_v = SETTINGS.zoom_print_v+(change) + dbSet_settings_zoom_print_v(SETTINGS.zoom_print_v) + } + setPrintZoomLevel() +} +setPrintZoomLevel = async () => { + let block_zoom = document.getElementById("Roster-week-print-zoom") + if (!block_zoom) {return} + let block_input = block_zoom.querySelector("input") + let block_value = block_zoom.querySelector(".zoom-value") + let value = SETTINGS.printmode === 0 ? SETTINGS.zoom_print_h : SETTINGS.zoom_print_v + block_input.value = value + block_value.innerHTML = `${value}%` + block_input.setAttribute("onchange", `changePrintZoomLvl(${SETTINGS.printmode}, this)`) + block_zoom.setAttribute("title", `${value}%\nVergrößerung, beim Drucken sichtbar.`) +} + +changePrintMode = (el) => { + if (SETTINGS.printmode === 0) { + dbSet_settings_printmode(1) + SETTINGS.printmode = 1 + } else { + dbSet_settings_printmode(0) + SETTINGS.printmode = 0 + } + el.innerHTML = PRINT_MODES[SETTINGS.printmode] + setPrintZoomLevel() +} + +hideSettingsWeekly = () => { + document.getElementById("Settings-weekly-button").classList.remove("active") + document.getElementById("Settings-weekly").classList.add("d-none") +} +renderSettingsWeekly = (el) => { + el.classList.add("active") + document.getElementById("Settings-weekly").classList.remove("d-none") + hideSettingsGlobal() +} + +hideSettingsGlobal = () => { + document.getElementById("Settings-global-button").classList.remove("active") + document.getElementById("Settings-global").classList.add("d-none") +} +renderSettingsGlobal = (el) => { + el.classList.add("active") + document.getElementById("Settings-global").classList.remove("d-none") + hideSettingsWeekly() +} + +getRenames = (value) => { + if (value === "m") {return {t: dbGet_settings_label_text(0), a: dbGet_settings_label_cut(0)}} + else if (value === "i") {return {t: dbGet_settings_label_text(1), a: dbGet_settings_label_cut(1)}} + else if (value === "b") {return {t: dbGet_settings_label_text(2), a: dbGet_settings_label_cut(2)}} + else if (value === "v") {return {t: dbGet_settings_label_text(3), a: dbGet_settings_label_cut(3)}} +} + +renameFields = (field_id, field_value, value) => { + if (value === "") return + setN = async () => { + SETTINGS_LABELS = await dbGet_settings_labels() + if (field_id === 0 && field_value === "t") { + document.getElementById("Person-table-mpa").innerHTML = getRenames("m").t + document.querySelector("#Edit-person-mpa .title").innerHTML = getRenames("m").t + } else if (field_id === 1 && field_value === "t") { + document.getElementById("Person-table-illnes").innerHTML = getRenames("i").t + document.querySelector("#Edit-person-illnesses .title").innerHTML = getRenames("i").t + } else if (field_id === 2 && field_value === "t") { + document.getElementById("Person-table-betterment").innerHTML = getRenames("b").t + document.querySelector("#Edit-person-betterments .title").innerHTML = getRenames("b").t + } else if (field_id === 3 && field_value === "t") { + document.getElementById("Person-table-vacation").innerHTML = getRenames("v").t + document.querySelector("#Settings-vacations .title").innerHTML = getRenames("v").t + } + getActiveRoster().then(() => { + renderSettings() + changeSettingsView(document.querySelector("#Settings-global-button"), 'global') + }) + } + if (field_value === "t") {dbSet_settings_label_text(field_id, value).then(() => setN())} + else if (field_value === "a") {dbSet_settings_label_cut(field_id, value).then(() => setN())} + +} + +removeDepartment = (d_id) => { + dbRemove_department(d_id).then(() => { + dbGet_departments().then(dep => { + DEPARTMENTS = dep + setPerson().then(() => { + renderPerson() + addSettingsGlobal() + getActiveRoster().then(() => { + renderSettings() + changeSettingsView(document.querySelector("#Settings-global-button"), 'global') + }) + }) + }) +}) +} +renderAddDepartment = () => { + document.querySelector("#Settings-global .add-department").classList.remove("d-none") +} +addDepartment = () => { + let name = document.querySelector("#Settings-global .add-department input")?.value + if (name.length === 0) {return} + dbAdd_department(name).then(() => { + dbGet_departments().then((d) => { + DEPARTMENTS = d + addSettingsGlobal() + }) + }) +} +changeShiftLabel = async (l_id, key, value) => { + showLoading("changeShiftLabel") + if (key === "n") dbSet_shift_label_text(l_id, value) + else if (key === "c") dbSet_shift_label_cut(l_id, value) + SHIFT_LABELS = await dbGet_shift_labels() + getActiveRoster().then(() => { + renderSettings() + changeSettingsView(document.querySelector("#Settings-global-button"), 'global') + hideLoading("changeShiftLabel") + }) +} +removeShiftLabel = async (l_id) => { + showLoading("removeShiftLabel") + dbGet_person_changes_where_key_and_value("sl", l_id).then((changes) => { + let free_id = SHIFT_LABELS.sort((a,b) => a.id-b.id).find(l => l.name === "Frei").id + for (let c=0; c<changes.length; c++) { + let change = changes[c] + dbGet_person_change_where_yearweek_and_day_and_person_and_key(change.yearweek, change.day_id, change.person_id, "sf").then((change_sf) => { + if (change_sf.length > 0 && (change_sf[0].value === "true" || change_sf[0].value === "1")) { + dbSet_person_change_where_yearweek_day_and_person_and_key(change.yearweek, change.day_id, change.person_id, "sl", free_id) + } else { + dbRemove_person_change_where_yearweek_and_day_and_person_and_key(change.yearweek, change.day_id, change.person_id, "sl") + } + }) + } + + dbRemove_shift_label(l_id) + dbGet_shift_labels().then(l => { + SHIFT_LABELS = l + setPerson().then(() => { + renderSettingsShiftLables() + renderPerson().then(() => { + getActiveRoster().then(() => { + renderSettings() + changeSettingsView(document.querySelector("#Settings-global-button"), 'global') + hideLoading("removeShiftLabel") + }) + }) + }) + }) + + }) +} +addShiftLabel = () => { + let block_title = document.querySelector("#Settings-global-labels .add-shiftlabel .title") + let block_cut = document.querySelector("#Settings-global-labels .add-shiftlabel .cut") + if ((block_title.value.length === 0) || (block_cut.value.length === 0)) {return} + dbAdd_shift_label(block_title.value, block_cut.value).then(() => { + dbGet_shift_labels().then(l => { + SHIFT_LABELS = l + renderSettingsShiftLables() + block_title.value = "" + block_cut.value = "" + document.querySelector("#Settings-global-labels .add-shiftlabel").classList.add("d-none") + }) + }) +} +setEditableCellTrue = () => { + EDITABLE_CELL = true + document.querySelector("#Roster-week-add-editable-cell button").classList.add("active") +} +toggleEditableCellDefault = (el) => { + if (SETTINGS.default_edit_cell_right) { + SETTINGS.default_edit_cell_right = 0 + dbSet_settings_edit_cell_default(0) + el.classList.remove("active") + } else { + SETTINGS.default_edit_cell_right = 1 + dbSet_settings_edit_cell_default(1) + el.classList.add("active") + if (!EDITABLE_CELL) { + setEditableCellTrue() + loadRosterTableWeek() + } + } +} +setEditableRowTrue = () => { + EDITABLE_ROW = true + document.querySelector("#Roster-week-add-editable-row button.row-top").classList.add("active") +} +setEditableRowBottomTrue = () => { + EDITABLE_ROW_BOTTOM = true + document.querySelector("#Roster-week-add-editable-row button.row-bottom").classList.add("active") +} +toggleEditableRowDefault = async (el) => { + if (SETTINGS.default_row_top) { + SETTINGS.default_row_top = 0 + dbSet_settings_edit_row_top_default(0) + el.classList.remove("active") + } else { + SETTINGS.default_row_top = 1 + dbSet_settings_edit_row_top_default(1) + el.classList.add("active") + if (!EDITABLE_ROW) { + setEditableRowTrue() + loadRosterTableWeek() + } + } +} +toggleEditableRowBottomDefault = async (el) => { + if (SETTINGS.default_row_bottom) { + SETTINGS.default_row_bottom = 0 + dbSet_settings_edit_row_bottom_default(0) + el.classList.remove("active") + } else { + SETTINGS.default_row_bottom = 1 + dbSet_settings_edit_row_bottom_default(1) + el.classList.add("active") + if (!EDITABLE_ROW_BOTTOM) { + setEditableRowBottomTrue() + loadRosterTableWeek() + } + } +} + +renderSettingsToggleEditableWeek = async () => { + let block_editable_container = document.getElementById("Settings-global-editable-week") + block_editable_container.innerHTML = "" + + let block_editable_title = document.createElement("h4") + block_editable_title.innerHTML = "Wochenübersicht editierbare Zellen" + block_editable_container.appendChild(block_editable_title) + + let block_editable_cell = document.createElement("div") + let block_cell_button = document.createElement("button") + block_cell_button.innerHTML = "Spalte aktiv" + block_cell_button.classList.add("button-default-cell") + block_cell_button.setAttribute("title", "Die editierbare Spalte ist als Standart eingeblendet.") + block_cell_button.setAttribute("onCLick", "toggleEditableCellDefault(this)") + if (SETTINGS.default_edit_row_top) block_cell_button.classList.add("active") + block_editable_container.appendChild(block_cell_button) + + let block_editable_row = document.createElement("div") + let block_row_button = document.createElement("button") + block_row_button.innerHTML = "Zeile oben aktiv" + block_row_button.setAttribute("title", "Die editierbare Zeile ist als Standart eingeblendet.") + block_row_button.setAttribute("onCLick", "toggleEditableRowDefault(this)") + block_row_button.classList.add("button-default-row") + if (SETTINGS.default_editable_row_top) block_row_button.classList.add("active") + block_editable_container.appendChild(block_row_button) + + let block_editable_row_bottom = document.createElement("div") + let block_row_bottom_button = document.createElement("button") + block_row_bottom_button.innerHTML = "Zeile unten aktiv" + block_row_bottom_button.setAttribute("title", "Die editierbare Zeile ist als Standart eingeblendet.") + block_row_bottom_button.setAttribute("onCLick", "toggleEditableRowBottomDefault(this)") + block_row_bottom_button.classList.add("button-default-row-bottom") + if (SETTINGS.default_editable_row_bottom) block_row_bottom_button.classList.add("active") + block_editable_container.appendChild(block_row_bottom_button) +} +renderSettingsShiftLables = () => { + let block_labels = document.getElementById("Settings-global-labels") + block_labels.innerHTML = "" + let block_title_container = document.createElement("div") + block_title_container.classList.add("title-container") + let block_labels_title = document.createElement("h4") + block_labels_title.innerHTML = "Schichtlabels" + block_title_container.appendChild(block_labels_title) + let block_add = document.createElement("button") + block_add.innerHTML = "Hinzufügen" + block_add.setAttribute("onClick", 'document.querySelector("#Settings-global-labels .add-shiftlabel").classList.remove("d-none")') + block_add.classList.add("button-whitegreen", "button-add") + block_title_container.appendChild(block_add) + let block_labels_add_input = document.createElement("div") + block_labels_add_input.classList.add("add-shiftlabel", "add-container", "d-none") + block_labels_add_input.innerHTML = `<button onClick="this.parentNode.classList.add('d-none')" class="cancel button-orange">Abbrechen</button><div><label>Titel</label><input class="title"><label>Abkürzung</label><input class="cut"><button class="button-whitegreen" onClick="addShiftLabel()">Speichern</button></div>` + block_title_container.appendChild(block_labels_add_input) + block_labels.appendChild(block_title_container) + + let block_labels_container = document.createElement("div") + block_labels_container.classList.add("items") + + SHIFT_LABELS.forEach(label => { + let l_id = label.id + let block_label_item = document.createElement("div") + block_label_item.classList.add("item") + let block_label_text_label = document.createElement("label") + block_label_text_label.innerHTML = "Titel" + block_label_item.appendChild(block_label_text_label) + let block_label_text + if (label.id === 1) { + block_label_text = document.createElement("div") + block_label_text.innerHTML = label.name + } + else { + block_label_text = document.createElement("input") + block_label_text.setAttribute("onchange", `changeShiftLabel(${l_id}, "n", this.value)`) + block_label_text.value = label.name + } + block_label_item.appendChild(block_label_text) + let block_label_cut_label = document.createElement("label") + block_label_cut_label.innerHTML = "Abkürzung" + block_label_item.appendChild(block_label_cut_label) + let block_label_cut = document.createElement("input") + block_label_cut.value = label.cut + block_label_cut.setAttribute("onchange", `changeShiftLabel(${l_id}, "c", this.value)`) + block_label_item.appendChild(block_label_cut) + if (l_id !== 1) { + let block_remove = document.createElement("button") + block_remove.innerHTML = "Löschen" + block_remove.classList.add("button-remove") + block_remove.setAttribute("onClick", `removeShiftLabel(${l_id})`) + block_label_item.appendChild(block_remove) + } + block_labels_container.appendChild(block_label_item) + }) + + block_labels.appendChild(block_labels_container) +} +addSettingsGlobal = () => { + let block = document.getElementById("Settings-global") + block.innerHTML = "" + + let block_editable = document.createElement("div") + block_editable.setAttribute("id", "Settings-global-editable-week") + block.appendChild(block_editable) + renderSettingsToggleEditableWeek() + + let block_labels = document.createElement("div") + block_labels.setAttribute("id", "Settings-global-labels") + block.appendChild(block_labels) + renderSettingsShiftLables() + + + let block_rename_label = document.createElement("h4") + let block_rename_department = document.createElement("div") + block_rename_department.setAttribute("id", "Settings-global-departments") + let block_rename_department_label = document.createElement("div") + let block_department_title_container = document.createElement("div") + block_department_title_container.classList.add("title-container") + block_rename_label.innerHTML = "Bereiche:" + block_department_title_container.appendChild(block_rename_label) + let block_department_add = document.createElement("button") + block_department_add.setAttribute("onClick", `renderAddDepartment()`) + block_department_add.classList.add("button-add", "button-whitegreen") + block_department_add.innerHTML = "Hinzufügen" + block_department_title_container.appendChild(block_department_add) + let block_department_add_input = document.createElement("div") + block_department_add_input.classList.add("add-department", "add-container", "d-none") + block_department_add_input.innerHTML = `<button class="cancel button-orange" onClick="this.parentNode.classList.add('d-none')">Abbrechen</button><div><input placehlder="Name"><button class="button-whitegreen" onClick="addDepartment(this)">Speichern</button></div>` + block_department_title_container.appendChild(block_department_add_input) + block_rename_department.appendChild(block_department_title_container) + + DEPARTMENTS.forEach(department => { + if (department.name === "") return + let block_department_container = document.createElement("div") + let block_department = document.createElement("input") + block_department.value = department.name + block_department.setAttribute("onchange", `changeDepartmentName(${department.id}, this.value)`) + block_department_container.appendChild(block_department) + let block_department_remove = document.createElement("button") + block_department_remove.setAttribute("onClick", `removeDepartment(${department.id})`) + block_department_remove.classList.add("button-remove") + block_department_remove.innerHTML = "Löschen" + block_department_container.appendChild(block_department_remove) + block_rename_department.appendChild(block_department_container) + }) + block.appendChild(block_rename_department) + + let block_rename_feelds = document.createElement("div") + block_rename_feelds.setAttribute("id", "Settings-global-rename-fields") + let block_rename_feelds_label = document.createElement("h4") + block_rename_feelds_label.innerHTML = "Felder" + block_rename_feelds.appendChild(block_rename_feelds_label) + + SETTINGS_LABELS.forEach((data, data_id) => { + let block_rename = document.createElement("div") + block_rename.classList.add("item") + let block_rename_label = document.createElement("div") + block_rename_label.innerHTML = dbGet_settings_label_text(data_id) + + + let block_rename_title_container = document.createElement("div") + block_rename_title_container.setAttribute("title", "in der Personentabelle als überschrift sichtbar") + let block_rename_text_label = document.createElement("label") + block_rename_text_label.innerHTML = "Titel" + let block_rename_text_input = document.createElement("input") + block_rename_text_input.setAttribute("onchange", `renameFields(${data_id}, "t", this.value)`) + block_rename_text_input.value = dbGet_settings_label_text(data_id) + block_rename_title_container.appendChild(block_rename_text_label) + block_rename_title_container.appendChild(block_rename_text_input) + block_rename.appendChild(block_rename_title_container) + + let block_rename_cut_container = document.createElement("div") + block_rename_cut_container.setAttribute("title", "im Schichtplan sichtbar") + let block_rename_cut_label = document.createElement("label") + block_rename_cut_label.innerHTML = "Abkürzung" + let block_rename_cut_input = document.createElement("input") + block_rename_cut_input.setAttribute("onchange", `renameFields(${data_id}, "a", this.value)`) + block_rename_cut_input.value = dbGet_settings_label_cut(data_id) + block_rename_cut_container.appendChild(block_rename_cut_label) + block_rename_cut_container.appendChild(block_rename_cut_input) + block_rename.appendChild(block_rename_cut_container) + + block_rename_feelds.appendChild(block_rename) + }) + + block.appendChild(block_rename_feelds) +} + +changeDepartmentName = (department_id, value) => { + if (value === "") return + dbSet_department(department_id, value) + renderPerson() +} + +changeSettingsView = (el, value) => { + if (value === "weekly") { + renderSettingsWeekly(el) + } else { + renderSettingsGlobal(el) + } +} + +changeZoomLevel = (value) => { + dbSet_settings_zoom_web(value) + setZoomLevel(value) +} +setZoomLevel = (value) => { + showLoading("setZoomLevel") + window.setTimeout(() => { + let items = document.querySelectorAll("#Roster-days-container .tables-container") + for (i=0; i<items.length; i++) { + items[i].style.zoom = `${value}%` + } + if (value !== 100) { + let lines = document.querySelectorAll(".line-cursor") + for (i=0; i<lines.length; i++) {lines[i].classList.add("d-none")} + } + hideLoading("setZoomLevel") + },50) +} + +getTimeAsMinute = (a) => { + let b = Math.ceil(a) + let minutes = MINUTE_STEPS_VALUES[MINUTE_STEPS.indexOf(1-(b-a))] + if (minutes === 60) minutes = "00" + return Math.floor(a)+":"+minutes +} + +createTimeSteps = () => { + let block_timesteps_container = block_settings.getElementsByClassName("timesteps-container")[0] + let block_timesteps_label = document.createElement("label") + let block_timesteps_select_label = document.createElement("label") + let block_timesteps_select = document.createElement("select") + + if (!block_timesteps_container) {return } + block_timesteps_container.innerHTML = "" + TIME_STEPS_VALUES.forEach((step, step_id) => { + let block_timesteps_option = document.createElement("option") + block_timesteps_option.setAttribute("value", TIME_STEPS[step_id]) + block_timesteps_option.innerHTML = step+" min" + if (parseFloat(TIME_STEP) === TIME_STEPS[step_id]) block_timesteps_option.defaultSelected = true + block_timesteps_select.appendChild(block_timesteps_option) + }) + block_timesteps_label.innerHTML = "Zeitintervall:" + block_timesteps_select_label.classList.add("chevron-down", "chevron-select") + block_timesteps_select.setAttribute("onchange", "setTimeStep(this.value)") + block_timesteps_container.appendChild(block_timesteps_label) + block_timesteps_select_label.appendChild(block_timesteps_select) + block_timesteps_container.appendChild(block_timesteps_select_label) +} + +changeDayBreak = (value) => { + showLoading("changeDayBreak") + dbSet_roster_shiftbreak_90(DATE_YEAR_WEEK, parseFloat(value)).then(() => { + DAYBREAK_2 = parseFloat(value) + window.location = "/#settings" + location.reload() + }) +} + +createDayBreaks = () => { + let block_daybreaks_container = block_settings.getElementsByClassName("daybreaks-container")[0] + if (!block_daybreaks_container) {return} + block_daybreaks_container.innerHTML = "" + + let block_daybreaks_label = document.createElement("label") + block_daybreaks_label.innerHTML = "Pause nach 9h:" + block_daybreaks_container.appendChild(block_daybreaks_label) + + let block_daybreaks_label_container = document.createElement("label") + block_daybreaks_label_container.classList.add("chevron-down", "chevron-select") + + let block_daybreaks_select = document.createElement("select") + block_daybreaks_select.setAttribute("onchange", `changeDayBreak(this.value)`) + + + + let block_option_0 = document.createElement("option") + block_option_0.innerHTML = "30 min" + block_option_0.setAttribute("value", "0") + if (DAYBREAK_2 === 0) block_option_0.defaultSelected = true + block_daybreaks_select.appendChild(block_option_0) + + let block_option_1 = document.createElement("option") + block_option_1.innerHTML = "45 min" + block_option_1.setAttribute("value", "0.25") + if (DAYBREAK_2 === 0.25) block_option_1.defaultSelected = true + block_daybreaks_select.appendChild(block_option_1) + + let block_option_2 = document.createElement("option") + block_option_2.innerHTML = "60 min" + block_option_2.setAttribute("value", "0.5") + if (DAYBREAK_2 === 0.5) block_option_2.defaultSelected = true + block_daybreaks_select.appendChild(block_option_2) + + block_daybreaks_label_container.appendChild(block_daybreaks_select) + block_daybreaks_container.appendChild(block_daybreaks_label_container) +} + + + +createTimeOption = (value, text) => { + let option = document.createElement('option'); + if (text.toString().length === 1) text = "0"+text + option.text = text; + option.value = value; + return option; +} + +toggleHelpText = (el) => { + let close_els = document.querySelectorAll("#Popup .container.active") + let close_els_buttons = document.querySelectorAll("#Popup .container button.active") + for (i=0; i< close_els.length; i++) {close_els[i].classList.remove("active")} + for (i=0; i< close_els_buttons.length; i++) {close_els_buttons[i].classList.remove("active")} + el.classList.toggle('active') + el.parentNode.classList.toggle('active') + el.parentNode.scrollIntoView({block: "nearest", inline: "center"}) +} + +renderHelp = () => { + let block_popup = document.getElementById("Popup") + block_popup.classList.add("help") + block_popup.onclick = (e) => eventListenerClosePopup(e, "help") + block_popup.classList.add("active") + document.body.classList.add("noscroll") + let block = document.getElementById("Popup-container") + let block_close = document.createElement("button") + block_close.setAttribute("onClick", "closeHelp()") + block_close.classList.add("button-x") + block.appendChild(block_close) + HELP.forEach(data => { + let title = data[0] + let text = data[1] + let block_container = document.createElement("div") + let block_title_button = document.createElement("button") + let block_title = document.createElement("h3") + let block_text = document.createElement("p") + block_title_button.setAttribute("onCLick", "toggleHelpText(this)") + block_title.innerHTML = title + block_text.innerHTML = text + block_title_button.appendChild(block_title) + block_container.classList.add("container") + block_container.appendChild(block_title_button) + block_container.appendChild(block_text) + block.appendChild(block_container) + }) +} + +closeHelp = () => { + closePopup() +} + +toggleHelp = (el) => { + let block_popup = document.getElementById("Popup") + if (el.classList.contains("active")) { + closeHelp() + } else { + el.classList.add("active") + renderHelp() + block_popup.onclick = (e) => eventListenerClosePopup(e, "help") + block_popup.classList.add("active") + document.body.classList.add("noscroll") + } +} + + +toggleEditPerson = (el) => { + let block_person = document.getElementById("Person-container") + if (el.classList.contains("active")) { + el.classList.remove("active") + block_person.classList.remove("active") + } else { + el.classList.add("active") + block_person.classList.add("active") + } +} + +renderSettings = () => { + settingsContainerHideAll("Settings-default") + document.getElementsByClassName("settings-box")[0].scrollIntoView({block: "nearest", inline: "center"}) +} + +createRosterSelect = () => { + let block_select = document.createElement("select") + block_select.setAttribute("onchange", "changeDate(getDateOfISOWeek(this.value))") + let year_weeks = ROSTERS_YEARWEEK + year_weeks.forEach(year_week => { + let block_option = document.createElement("option") + block_option.innerHTML = year_week + block_option.setAttribute("value", year_week) + if (year_week === DATE_YEAR_WEEK) { block_option.defaultSelected = true } + block_select.appendChild(block_option) + }) + return block_select +} + +getSettings = async () => { + ROSTER = await getDataRosterToRoster(DATE_YEAR_WEEK) + ROSTER_WEEK_BEFORE = await getRosterBefore(1) + ROSTER_WEEK_BEFORE_WEEK = await getRosterBefore(2) + + let block_person_mpa_label = document.getElementById("Person-table-mpa") + if (block_person_mpa_label) {block_person_mpa_label.innerHTML = getRenames("m").t} + createTimeSteps() + createDayBreaks() + createRosterDayTimes() + block_yws = document.getElementById("Week-select-overview") + if (block_yws) { + block_yws.innerHTML = "" + block_yws.appendChild(createRosterSelect()) + } + block_yws = document.getElementById("Menu-week-select") + block_yws.innerHTML = "" + block_yws.appendChild(createRosterSelect()) +} + +setTimeStep = (step_value) => { + showLoading("setTimeStep") + TIME_STEP = step_value + dbSet_roster_timestep(DATE_YEAR_WEEK, parseFloat(step_value)).then(() => { + let specials = [] + + //createRosterDayTimes() + ROSTER.forEach((day, day_id) => { + times = [] + TIMES = [] + let block_container = document.getElementById(`Settings-day-time-change-${day_id}`) + let block_start = block_container.getElementsByClassName("select-start")[0] + let start = day.d[0].t + let end = day.d[day.d.length-1].t + + let duration = end-start + let duration_steps = duration*(1/TIME_STEP) + for (let i=0; i<=duration_steps; i++) { + time = { t: TIME_START+(i*TIME_STEP), a: PERSONS.length} + TIMES.push(time) + times.push({time: TIME_START+(i*TIME_STEP), amount: PERSONS.length}) + } + day.d = TIMES + setDataAC(DATE_YEAR_WEEK, day_id, times).then(() => { + if (day_id === ROSTER.length-1) { + window.location = "/#settings" + location.reload() + } + }) + }) + }) +} + +createRosterDefault = (times) => { + ROSTER_DEFAULT = [] + ROSTER = [] + DAYS.forEach((day, index) => { + ROSTER_DEFAULT.push({n: day, d: []}) + times.forEach((times) => { + ROSTER_DEFAULT[index].d.push({t: times.t, a: 0}) + }) + }) + ROSTER = structuredClone(ROSTER_DEFAULT) +} + + +getYearWeekNewest = () => { + return ROSTERS_YEARWEEK[0] +} +getYearWeekNewestAfter = () => { + let year_week_newest = getYearWeekNewest() + let date_week_after = new Date(getDateOfISOWeek(year_week_newest )) + date_week_after.setDate(date_week_after.getDate() + 1 * 7) + return `${date_week_after.getFullYear()}-${date_week_after.getWeek()}` +} +getYearWeekNewestAfterWeek = () => { + let year_week_newest = getYearWeekNewest() + let date_week_after_week = new Date(getDateOfISOWeek(year_week_newest)) + date_week_after_week.setDate(date_week_after_week.getDate() + 2 * 7) + return `${date_week_after_week.getFullYear()}-${date_week_after_week.getWeek()}` +} +getDateValues = () => { + DATE_YEAR = DATE.getFullYear().toString(); + DATE_WEEK = DATE.getWeek().toString(); + DATE_WEEK.length === 1 && (DATE_WEEK = "0"+DATE_WEEK) + DATE_YEAR_WEEK_OLD = DATE_YEAR_WEEK + DATE_YEAR_WEEK = `${DATE_YEAR}-${DATE_WEEK}` + if (DATE_YEAR_WEEK_OLD.length === 0) {DATE_YEAR_WEEK_OLD = DATE_YEAR_WEEK} + let date_week_before = new Date(DATE - 7 * 24 * 60 * 60 * 1000) + let date_week_before_week_before = new Date(date_week_before - 7 * 24 * 60 * 60 * 1000) + + let date_week_before_week = date_week_before.getWeek().toString() + if (date_week_before_week.length === 1) {date_week_before_week = `0${date_week_before_week}`} + + let date_week_before_week_before_week = date_week_before_week_before.getWeek().toString() + if (date_week_before_week_before_week.length === 1) {date_week_before_week_before_week = `0${date_week_before_week_before_week}`} + + DATE_YEAR_WEEK_BEFORE = `${date_week_before.getFullYear()}-${date_week_before_week}` + DATE_YEAR_WEEK_BEFORE_WEEK = `${date_week_before_week_before.getFullYear()}-${date_week_before_week_before_week}` + let date_week_after = new Date(DATE.getTime() + 7 * 24 * 60 * 60 * 1000) + let date_week_after_week = date_week_after.getWeek().toString() + if (date_week_after_week.length === 1) {date_week_after_week = `0${date_week_after_week}`} + DATE_YEAR_WEEK_AFTER = `${date_week_after.getFullYear()}-${date_week_after_week}` + let yws = ROSTERS_YEARWEEK + if (yws.length === 0) { + DATE_YEAR_WEEK_OLDEST = DATE_YEAR_WEEK + DATE_YEAR_WEEK_NEWEST = DATE_YEAR_WEEK + } else { + DATE_YEAR_WEEK_OLDEST = yws[yws.length-1] + DATE_YEAR_WEEK_NEWEST = yws[0] + } + let date_week_after_newest = new Date(getDateOfISOWeek(DATE_YEAR_WEEK_NEWEST)) + date_week_after_newest.setDate(date_week_after_newest.getDate() + 1 * 7) + let date_week_after_newest_week = new Date(getDateOfISOWeek(DATE_YEAR_WEEK_NEWEST)) + date_week_after_newest_week.setDate(date_week_after_newest_week.getDate() + 2 * 7) + DATE_YEAR_WEEK_NEWEST_AFTER = `${date_week_after_newest.getFullYear()}-${date_week_after_newest.getWeek()}` + DATE_YEAR_WEEK_NEWEST_AFTER_WEEK = `${date_week_after_newest_week.getFullYear()}-${date_week_after_newest_week.getWeek()}` + + document.getElementById("Menu-item-week").getElementsByTagName("button")[0].innerHTML = "Woche "+DATE_WEEK +} + +getDateOfISOWeek = (year_week) => { + let y = parseFloat(year_week.substring(0,4)) + let w = parseFloat(year_week.substring(5)) + if ((isNaN(y)) || (isNaN(w))) return false + var simple = new Date(y, 0, 1 + (w - 1) * 7); + var dow = simple.getDay(); + var ISOweekStart = simple; + if (dow <= 4) + ISOweekStart.setDate(simple.getDate() - simple.getDay() + 1); + else + ISOweekStart.setDate(simple.getDate() + 8 - simple.getDay()); + + return new Date(ISOweekStart.getTime() - ISOweekStart.getTimezoneOffset()*60000).toISOString().substring(0, 10) +} + +getDateToRosterDate = (date) => { + date = new Date(date) + let date_monday = structuredClone(date) + date_monday = new Date(date_monday.setDate(date_monday.getDate() - (date_monday.getDay() + 6) % 7)) + let difference = date.getTime() - date_monday.getTime(); + let day_id = difference / (1000 * 3600 * 24); + let year_week = `${date_monday.getFullYear()}-${date_monday.getWeek()}` + year_week = year_week.length === 6 ? (year_week.substring(0,5)+"0"+year_week.substring(5)) : year_week + + return [year_week, day_id] +} + +convertDate = (date) => { + let year = date.substring(0,4) + let month = date.substring(5,7) + let day = date.substring(8,10) + return `${day}.${month}.${year}` +} + +changeDate = (date) => { + checkElementInView("main") + let new_date + let new_d + if (date === "next") { + new_date = DATE_YEAR_WEEK_AFTER + } else if (date === "prev") { + new_date = DATE_YEAR_WEEK_BEFORE + } else { + new_date = new Date(date) + new_date = getDateToRosterDate(new_date)[0] + } + window.setTimeout(() => { + window.location = `?${new_date}${INVIEW}` + },50) +} + +setRosterDate = (new_date) => { + new_date = new Date(new_date) + new_date.setDate(new_date.getDate() - (new_date.getDay() + 6) % 7) + new_date.setHours(1) + new_date.setMinutes(1) + new_date.setSeconds(1) + DATE = new_date + getDateValues() + let block_input = document.getElementById("Roster-week-input") + block_input && (block_input.valueAsDate = DATE) +} + +createTimeRange = (day_id, time_start, time_end, time_specialstart) => { + let duration = time_end-time_start + let duration_steps = duration*(1/TIME_STEP) + times = [] + let amount = 0 + if (ROSTER[day_id].d[0].t === time_start) { amount = ROSTER[day_id].d[0].a } + + if (time_specialstart && time_start !== 0) times.push({ time: time_start-TIME_STEPS[TIME_STEPS.indexOf(TIME_STEP)-1], amount: amount}) + for (let i=0; i<=duration_steps; i++) { + let time_t = time_start+(i*TIME_STEP) + let roster_time_id = ROSTER[day_id].d.map(d => {return d.t}).indexOf(time_t) + amount = 0 + if (roster_time_id > -1 && ROSTER[day_id].d[roster_time_id].t === time_t) { amount = ROSTER[day_id].d[roster_time_id].a } + time = { time: time_t, amount: amount} + times.push(time) + } + return times +} + +changeTimeOfDay = (day_id, direction) => { + showLoading("changeTimeOfDay") + window.setTimeout(() => { + let block_container = document.getElementById("Settings-day-time-change-"+day_id) + let block_start = block_container.getElementsByClassName("select-start")[0].getElementsByTagName("select")[0] + let block_end = block_container.getElementsByClassName("select-end")[0].getElementsByTagName("select")[0] + let name = DAYS[day_id] + let time_default = 0 + let time_start = parseFloat(block_start.value) + let time_end = parseFloat(block_end.value)-TIME_STEP + let block_time_specialstart = document.getElementById("Settings-special-time-input-"+day_id) + let time_specialstart = false + if (block_time_specialstart) { time_specialstart = block_time_specialstart.checked } + let times = createTimeRange(day_id, time_start, time_end, time_specialstart) + let new_roster_data = [] + times.forEach((time, time_id) => { + let is_data = ROSTER[day_id].d.filter(ti => {return ti.t === time.time}) + if (is_data.length > 0) { time_default = is_data[0].a } + new_roster_data.push({t: time.time, a: time_default}) + }) + + // FIX ME !! + /*direction === "start" ? + dbSet_shifts_where_yearweek_and_start_lt(DATE_YEAR_WEEK, time_start) : + dbSet_shifts_where_yearweek_and_end_gt(DATE_YEAR_WEEK, time_end) + */ + + createEndSelect(day_id) + + + setDataAC(DATE_YEAR_WEEK, day_id, times).then(() => { + window.location = "/#settings" + location.reload() + hideLoading("changeTimeOfDay") + }) + }, 50) +} + +createStartSelect = (day_id) => { + let block_timestart_select_label = document.createElement("label") + let block_timestart_select = document.createElement("select") + + block_timestart_select_label.classList.add("chevron-down", "chevron-select") + block_timestart_select.setAttribute("onchange", `changeTimeOfDay(${day_id}, "start")`) + for(let i = 0; i <= 24; i++){ + let text_i = i.toString() + if (text_i.length === 1) text_i = "0"+i + for(let n = 0; n < 60; n += TIME_STEPS_VALUES[TIME_STEPS.indexOf(TIME_STEP)]) { + let text_n = n.toString() + let value_n = n + if (text_n.length === 1) text_n = "0"+n + if (value_n !== 0) value_n = MINUTE_STEPS[MINUTE_STEPS_VALUES.indexOf(value_n)] + value_n = i+value_n + let block_option = createTimeOption(value_n, text_i+":"+text_n) + let check_t + if (ROSTER.length > 0) { + check_t = ROSTER[day_id].d[0].t + let check_tt = ROSTER[day_id].d[1].t + if (check_tt-check_t !== TIME_STEP) check_t = check_tt + } else { + check_t = TIME_START + } + if (check_t === value_n) block_option.defaultSelected = true + block_timestart_select.add(block_option); + } + } + + block_timestart_select_label.appendChild(block_timestart_select) + return block_timestart_select_label +} + +createEndSelect = (day_id) => { + let block_timeend_select_label = document.createElement("label") + let block_timeend_select = document.createElement("select") + + block_timeend_select_label.classList.add("chevron-down", "chevron-select") + block_timeend_select.setAttribute("onchange", `changeTimeOfDay(${day_id}, "end")`) + + let block_start = document.getElementById("Settings-day-time-change-"+day_id).getElementsByClassName("select-start")[0].querySelector("select") + + let start = block_start.value + if (ROSTER.length > 0) { start = Math.floor(ROSTER[day_id].d[0].t+1) } + if (start === TIME_START) start = start+1 + + for(let i = start; i <= 24; i++){ + let text_i = i.toString() + if (text_i.length === 1) text_i = "0"+i + for(let n = 0; n < 60; n += TIME_STEPS_VALUES[TIME_STEPS.indexOf(TIME_STEP)]) { + if (i === 24 && n > 0) continue + let text_n = n.toString() + let value_n = n + if (text_n.length === 1) text_n = "0"+n + if (value_n !== 0) value_n = MINUTE_STEPS[MINUTE_STEPS_VALUES.indexOf(value_n)] + value_n = i+value_n + let block_option = createTimeOption(value_n, text_i+":"+text_n) + if (ROSTER.length > 0) { + if (ROSTER[day_id].d[ROSTER[day_id].d.length -1].t+TIME_STEP === value_n) block_option.defaultSelected = true + } else { + if (TIME_END+TIME_STEP === value_n) block_option.defaultSelected = true + } + block_timeend_select.add(block_option); + } + } + + block_timeend_select_label.appendChild(block_timeend_select) + return block_timeend_select_label +} + +createRosterDayTimes = () => { + let block = document.getElementById("Settings-day-time-change") + if (!block) {return} + block.innerHTML = "" + DAYS.forEach((day, day_id) => { + let block_select_start_end = document.createElement("div") + block_select_start_end.setAttribute("id", "Settings-day-time-change-"+day_id) + block_select_start_end.classList.add("select-start-end") + + let block_select_name = document.createElement("p") + block_select_name.classList.add("select-name") + block_select_name.innerHTML = day + + let block_select_start = createStartSelect(day_id) + block_select_start.classList.add("select-start") + + + block.appendChild(block_select_name) + block_select_start_end.appendChild(block_select_start) + block.appendChild(block_select_start_end) + + let block_select_end = createEndSelect(day_id) + block_select_end.classList.add("select-end") + block_select_start_end.appendChild(block_select_end) + + }) + +} + +getIsoStringFromDay = (day_id, year_week) => { + let date = new Date(getDayDateByDayid(day_id, getDateOfISOWeek(year_week || DATE_YEAR_WEEK))) + return date.toISOString().substr(0, 10) +} +getDayDateByDayid = (day_id, start) => { + if (typeof start === "undefined") start = getDateOfISOWeek(DATE_YEAR_WEEK) + let date = new Date(start) + date.setDate(date.getDate()+day_id) + return date.toISOString().substr(0, 10) +} + +sortPersonRosterWeek = async (period_id) => { + return getSortedPersonRosterWeek(period_id).then(persons => { + if (period_id === 0) {PERSONS_ROSTER = persons;} + if (period_id === 1) {PERSONS_WEEK = persons;} + return persons + }) +} +getSortedPersonRosterWeek = async (period_id, year_week) => { + if (typeof year_week === "undefined") {year_week = DATE_YEAR_WEEK} + let sort_all = period_id === 0 ? SETTINGS.sort_days : SETTINGS.sort_week + if (sort_all.length === 0) return + + let person_all + if (year_week === DATE_YEAR_WEEK) { + person_all = structuredClone(PERSONS) + } else { + person_all = await dbGet_persons_active_where_yearweek(year_week) + } + let person + sortD = (d_id) => { + person.sort((a, b) => { + let v = sort_all[d_id].split('-') + let n = v[0] + if (n === "n") {nn = "name"} + else if (n === "h") {nn = "hours"} + else if (n === "d") {nn = "department"} + let d = v[1] + let d_0 + let d_1 + let a_d = eval(`a.${nn}`) + let b_d = eval(`b.${nn}`) + if (d === "u") {d_0 = 1; d_1 = -1} + if (d === "d") {d_0 = -1; d_1 = 1} + + if (a_d < b_d) { return d_0; } + if (a_d > b_d) { return d_1; } + return 0; + }) + } + let d_n = false + let d_d + let n_n = false + let n_d + let h_n = false + let h_d + sort_all.forEach((c, c_id) => { + if (c.split('-')[0] === "d") {d_n = c_id; d_d = c.split('-')[1]} + if (c.split('-')[0] === "n") {n_n = c_id; n_d = c.split('-')[1]} + if (c.split('-')[0] === "h") {h_n = c_id; h_d = c.split('-')[1]} + }) + + person = person_all + if (sort_all.length === 1) { sortD(0) } + else { + let person_new = [] + departments = structuredClone(DEPARTMENTS) + d_d === "u" ? departments.sort((a, b) => a.name.localeCompare(b.name)) : departments.sort((a, b) => b.name.localeCompare(a.name)) + + departments.forEach(name => { + let n_id = name.id + person = structuredClone(person_all.filter(a => {return a.department === n_id})) + if (n_n) sortD(n_n) + else if (h_n) sortD(h_n) + person.forEach(p => {person_new.push(p)}) + }) + person_all = person_new + } + + return person_all +} + +setRosterSortButtons = async (period_id) => { + let period_n + if (period_id === 0) { period_n = "roster" } + if (period_id === 1) { period_n = "week" } + let block = document.getElementById(`Sort-${period_n}-by`) + if (!block) {return} + let all_els = block.querySelectorAll(`.sort-${period_n}-by`) + for (i=0; i<all_els.length; i++) { + all_els[i].classList.remove("active", "chevron-down", "chevron-up") + } + let sort = period_id === 0 ? SETTINGS.sort_days : SETTINGS.sort_week + sort.forEach(name => { + let name_split = name.split('-') + let n = name_split[0] + let d = name_split[1] + let d_n = "chevron-up" + let el + for (i=0; i<all_els.length; i++) { if (all_els[i].getAttribute("name") === n) {el = all_els[i]; continue}} + if (d === "u") {d_n = "chevron-down"} + el.classList.add("active", d_n) + }) +} + +sortRosterBy = (period, el) => { + checkElementInView("main") + + let selector + let period_id + if (period === "days") { period_id = 0; selector = "roster" } + else if (period === "week") { period_id = 1; selector = "week" } + let name = el.getAttribute("name") + let sort = period_id === 0 ? SETTINGS.sort_days : SETTINGS.sort_week + + let l_id = sort.map(i => i.split("-")[0]).indexOf(name) + let dir = sort[l_id]?.split("-")[1] + next_dir = dir === "u" ? "d" : "u" + + if (name === "n") { + r_id = sort.map(i => i.split("-")[0]).indexOf("h") + r_id > -1 && sort.splice(r_id, 1) + l_id > -1 ? (sort[l_id] = `n-${next_dir}`) : sort.push("n-d") + } else if (name === "h") { + r_id = sort.map(i => i.split("-")[0]).indexOf("n") + r_id > -1 && sort.splice(r_id, 1) + l_id > -1 ? (sort[l_id] = `h-${next_dir}`) : sort.push("h-d") + } else if (name === "d") { + if (l_id === -1) { + sort.push("d-u") + } else if (dir === "u") { + sort[l_id] = `d-d` + } else if (dir === "d") { + sort.splice(l_id, 1) + } + } + + if (period_id === 0) { + dbSet_settings_sort_days(sort) + SETTINGS.sort_days = sort + } else { + dbSet_settings_sort_week(sort) + SETTINGS.sort_week = sort + } + + setRosterSortButtons(period_id) + + sortPersonRosterWeek(period_id) + if (period === "week") { + loadRosterTableWeek() + } else { + getActiveRoster(true).then(() => { + if (INVIEW.length > 0) document.querySelector(INVIEW)?.scrollIntoView() + }) + } +} + +setWeekInfo = (text) => { + dbSet_roster_info_where_yearweek_and_day_and_person(DATE_YEAR_WEEK, 999, "all", text) + + let info = ROSTER_PERSON_INFOS.find(i => i.day_id === 999 && i.id === "all") + if (typeof info !== "undefined") {info.text = text} + else ROSTER_PERSON_INFOS.push({id: "all", yearweek: DATE_YEAR_WEEK, day_id: 999, text: text}) + + if (text.length > 0) { + let block_text = document.createElement("div") + block_text.innerHTML = text + let block = document.getElementById("Roster-week-info") + block.innerHTML = "" + block.appendChild(block_text) + } +} + +toggleSetWeekInfo = async (el) => { + let block_info = document.getElementById("Set-week-info-container") + if (el.classList.contains("active")) { + el.classList.remove("active") + block_info.classList.add("d-none") + document.querySelector("#Roster-week-info").innerHTML = "" + dbRemove_roster_info_where_yearweek_and_day_and_person(DATE_YEAR_WEEK, 999, "all").then(() => { + ROSTER_PERSON_INFOS = ROSTER_PERSON_INFOS.filter(i => i.id !== "all") + }) + } else { + el.classList.add("active") + block_info.classList.remove("d-none") + let info = await dbGet_roster_info_where_yearweek_and_day_and_person(DATE_YEAR_WEEK, 999, "all") + if (info) (document.getElementById("Set-week-info-container").querySelector("textarea").value = info.text ? info.text : "") + } +} + +setDataAC = async (year_week, key, value) => { + let s = value[0].time + let e = value[value.length-1].time + let a = value.map(t => t.amount) + let response = await dbSet_roster_change_where_yearweek_and_day(year_week, key, s, e, a) + return response +} + + diff --git a/js/shortcuts.js b/js/shortcuts.js new file mode 100755 index 0000000..704060e --- /dev/null +++ b/js/shortcuts.js @@ -0,0 +1,25 @@ +rosterShortcuts = (e) => { + if (!(e.target.isContentEditable) && !(e.target instanceof HTMLTextAreaElement) && !(e.target instanceof HTMLInputElement)) { + if (CONSOLE) watchConsole(e) + else if (e.key === 'w') document.getElementById("Roster-container-week").scrollIntoView() + else if (e.key === 'p') renderPerson() + else if (e.key === 'e') renderSettings() + else if (e.key === 'v') changeDate('prev') + else if (e.key === 'h') changeDate(new Date()) + else if (e.key === 'n') changeDate('next') + else if (e.key === 'z') changeDate(getDateOfISOWeek(DATE_YEAR_WEEK_OLD)) + else if (e.key === 'd') printTable("Roster-week-container", DATE_YEAR_WEEK) + else if (e.key === '1' && document.getElementById("Roster-0")) document.getElementById("Roster-0").scrollIntoView() + else if (e.key === '2' && document.getElementById("Roster-1")) document.getElementById("Roster-1").scrollIntoView() + else if (e.key === '3' && document.getElementById("Roster-2")) document.getElementById("Roster-2").scrollIntoView() + else if (e.key === '4' && document.getElementById("Roster-3")) document.getElementById("Roster-3").scrollIntoView() + else if (e.key === '5' && document.getElementById("Roster-4")) document.getElementById("Roster-4").scrollIntoView() + else if (e.key === '6' && document.getElementById("Roster-5")) document.getElementById("Roster-5").scrollIntoView() + else if (e.key === '7' && document.getElementById("Roster-6")) document.getElementById("Roster-6").scrollIntoView() + else if (e.key === '+') changeZoomLevel(dbGet_settings_zoom_web()+15) + else if (e.key === '-') changeZoomLevel(dbGet_settings_zoom_web()-15) + else if (e.key === '0') changeZoomLevel(100) + else if (e.key === ':') devConsole() + } +} +document.addEventListener('keyup', rosterShortcuts, false); diff --git a/js/startpage.js b/js/startpage.js new file mode 100755 index 0000000..5870db4 --- /dev/null +++ b/js/startpage.js @@ -0,0 +1,121 @@ +let block_start = document.getElementById("Start") + +startRoster = async () => { + showLoading("startRoster") + VERSION = 1 + SETTINGS = await dbGet_settings() + document.querySelector("#Menu-settings > h3").innerHTML = SETTINGS.institution + //fixDataByVersion() + + DEPARTMENTS = await dbGet_departments() + + SETTINGS_LABELS = await dbGet_settings_labels() + + SHIFT_LABELS = await dbGet_shift_labels() + + DISPLAY_EDITABLE_CELL = SETTINGS.default_edit_cell_right + if (DISPLAY_EDITABLE_CELL) {EDITABLE_CELL = true} + DISPLAY_EDITABLE_ROW = SETTINGS.default_row_top + if (DISPLAY_EDITABLE_ROW ) {EDITABLE_ROW = true} + DISPLAY_EDITABLE_ROW_BOTTOM = SETTINGS.default_row_bottom + if (DISPLAY_EDITABLE_ROW_BOTTOM ) {EDITABLE_ROW_BOTTOM = true} + DISPLAY_OVERTIME = SETTINGS.default_overtime + + DATE_YEAR_WEEK_OLD = DATE_YEAR_WEEK + + CLOSINGTIMES = await dbGet_closingtimes() + + ROSTERS_YEARWEEK = await dbGet_rosters_yearweek() + + renderMenuWeeks() + setPrintZoomLevel() + let date = window.location.search.slice(1) + if (!getDateOfISOWeek(date)) { date = ROSTERS_YEARWEEK[0]} + setRosterDate(getDateOfISOWeek(date)) + + callback = async () => { + if (SETTINGS.default_overtime) document.querySelector("#Roster-week-display-overtime button").classList.add("active") + setPerson().then(async () => { + getActiveRoster().then(() => { + document.querySelector("#Roster-copy-person-from").setAttribute("onClick", `openCopyPersonTablePopup("${DATE_YEAR_WEEK_BEFORE}", "${DATE_YEAR_WEEK}"); document.getElementById("Roster-week-container")?.scrollIntoView();`) + let printmode = SETTINGS.printmode + document.querySelector("#Roster-week-print-mode button").innerHTML = PRINT_MODES[printmode] + + document.getElementById("Zoom-roster").value = SETTINGS.zoom_web + + setRosterSortButtons(0) + setRosterSortButtons(1) + addSettingsGlobal() + + let scroll = window.location.hash + if (scroll === "#settings") { renderSettings()} + else if (scroll) { document.querySelector(`${scroll}`)?.scrollIntoView()} + hideLoading("startRoster") + }) + }) + } + if (ROSTERS_YEARWEEK.indexOf(DATE_YEAR_WEEK) === -1) { + let get_yw + if (ROSTERS_YEARWEEK[0] < DATE_YEAR_WEEK) { get_yw = ROSTERS_YEARWEEK[0]} + else if (ROSTERS_YEARWEEK[ROSTERS_YEARWEEK.length-1] > DATE_YEAR_WEEK) { get_yw = ROSTERS_YEARWEEK[ROSTERS_YEARWEEK.length-1]} + else { get_yw = ROSTERS_YEARWEEK.find(y => y < DATE_YEAR_WEEK)} + let roster_old = await dbGet_roster_where_yearweek(get_yw) + let changes + if (DATE_YEAR_WEEK < DATE_YEAR_WEEK_OLDEST) { + changes = await dbGet_roster_changes_where_yearweek(DATE_YEAR_WEEK_OLDEST) + } + dbSet_roster(DATE_YEAR_WEEK, roster_old.time_step, [roster_old.break_60, roster_old.break_90]).then(() => { + if (DATE_YEAR_WEEK < DATE_YEAR_WEEK_OLDEST) { + changes.forEach(c => dbSet_roster_change_where_yearweek_and_day(DATE_YEAR_WEEK, c.day_id, c.start, c.end, c.amount)) + } + callA = async () => { + dbGet_rosters_yearweek().then(year_weeks => { + ROSTERS_YEARWEEK = year_weeks + DATE_YEAR_WEEK_NEWEST = ROSTERS_YEARWEEK[0] + DATE_YEAR_WEEK_OLDEST = ROSTERS_YEARWEEK[ROSTERS_YEARWEEK.length-1] + callback() + }) + } + callA() + }) + } else { + callback() + } +} +startVisitor = async () => { + showLoading("startRoster") + VERSION = 1 + SETTINGS = await dbGet_settings() + document.querySelector("h2.main-title").innerHTML = SETTINGS.institution + + DEPARTMENTS = await dbGet_departments() + + SETTINGS_LABELS = await dbGet_settings_labels() + + SHIFT_LABELS = await dbGet_shift_labels() + + DISPLAY_EDITABLE_CELL = SETTINGS.default_edit_cell_right + DISPLAY_EDITABLE_ROW = SETTINGS.default_row_top + DISPLAY_EDITABLE_ROW_BOTTOM = SETTINGS.default_row_bottom + DISPLAY_OVERTIME = SETTINGS.overtime + + DATE_YEAR_WEEK_OLD = DATE_YEAR_WEEK + + CLOSINGTIMES = await dbGet_closingtimes() + + ROSTERS_YEARWEEK = await dbGet_rosters_yearweek() + + setPrintZoomLevel() + let date = window.location.search.slice(1) + if ((!getDateOfISOWeek(date)) || (ROSTERS_YEARWEEK.indexOf(date) === -1)) { date = ROSTERS_YEARWEEK[0]} + setRosterDate(getDateOfISOWeek(date)) + + return setPerson().then(async () => { + return getActiveRosterWeek().then(() => { + let printmode = SETTINGS.printmode + setRosterSortButtons(1) + hideLoading("startRoster") + return + }) + }) +} diff --git a/js/user-administration.js b/js/user-administration.js new file mode 100644 index 0000000..c7fff48 --- /dev/null +++ b/js/user-administration.js @@ -0,0 +1,239 @@ + +logout = () => { + fetch("/api/logout.php", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then(() => {window.location = "login.php"}) +} +addNewUser = () => { + let block = document.querySelector(".Popup-add-new-user") + let block_hint = block.querySelector(".hint") + let password = block.querySelector(".password").value + let password_1 = block.querySelector(".password-confirm").value + let role = block.querySelector(".select-role").value + let connected = block.querySelector(".connect").checked + let name + let connected_id + if (role === "admin" && !connected) { + name = block.querySelector(".name").value + } else { + connected_id = parseFloat(block.querySelector(".name").value) + name = PERSONS.find(p => p.id === connected_id).name + } + if (password !== password_1) { + block_hint.innerHTML = "Passwörter stimmen nicht überein." + return + } + if (password.length < 8) { + block_hint.innerHTML = "Das passwort sollte mindestens 8 stellen haben." + return + } + addU = async () => { + connected = connected_id ? connected_id : "false" + let response = await fetch("/api/account/addUserDefaultData.php", { + method: "POST", + body: JSON.stringify({name: name, password: password, role: role, connected: connected}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let user_id = await response.json() + if (isNaN(user_id)) { + block_hint.innerHTML = user_id + } else { + renderUsers() + closeAddUser() + } + } + addU() +} +closeAddUser = () => { + let block = document.querySelector(".Popup-add-new-user") + block.querySelector(".hint").innerHTML = "" + block.querySelector(".name").value = "" + block.querySelector(".password").value = "" + block.querySelector(".password-confirm").value = "" + block.classList.remove("active") +} +changeConnected = (value) => { + if (value) { + renderNameSelect() + } else { + let block = document.querySelector(".Popup-add-new-user") + let block_name_container = block.querySelector(".container-name") + let block_name = document.createElement("input") + block_name.classList.add("name") + block_name_container.innerHTML = "" + block_name_container.appendChild(block_name) + } +} +changeRoleSelect = (value) => { + let block = document.querySelector(".Popup-add-new-user") + let block_input_connect = block.querySelector(".connect") + let block_label_connect = block.querySelector(".connect-label") + if (value === "admin" && PERSONS.length === 0) { + block.querySelector(".hint-user").innerHTML = "" + block_input_connect.classList.add("d-none") + block_label_connect.classList.add("d-none") + changeConnected(false) + block.querySelector(".connect").checked = false + block.querySelector(".confirm").classList.remove("d-none") + } else if (value === "admin") { + block.querySelector(".hint-user").innerHTML = "" + block_input_connect.classList.remove("d-none") + block_label_connect.classList.remove("d-none") + } else { + changeConnected(true) + block_input_connect.classList.add("d-none") + block_label_connect.classList.add("d-none") + } +} +renderNameSelect = () => { + let block = document.querySelector(".Popup-add-new-user") + block.querySelector(".hint-user").innerHTML = "" + block.querySelector(".confirm").classList.remove("d-none") + if (PERSONS.length === 0) { + block.querySelector(".hint-user").innerHTML = "Um Benutzer hinzufügen zu können musst du im Schichtplan Personen hinzufügen." + block.querySelector(".confirm").classList.add("d-none") + } + let block_select_container = block.querySelector(".container-name") + block_select_container.innerHTML = "" + let block_select_label = document.createElement("label") + block_select_label.classList.add("chevron-select", "chevron-down") + let block_select_name = document.createElement("select") + block_select_name.classList.add("name") + for (let i=0; i<PERSONS.length; i++) { + let person = PERSONS[i] + if (USERS.map(u => u.connected_person).indexOf(person.id) > -1) {continue} + let block_option = document.createElement("option") + block_option.setAttribute("value", person.id) + block_option.innerHTML = person.name + block_select_name.appendChild(block_option) + } + block_select_label.appendChild(block_select_name) + block_select_container.appendChild(block_select_label) +} +renderAddUser = async () => { + let block = document.querySelector(".Popup-add-new-user") + if (PERSONS.length === 0) { + changeRoleSelect("admin") + document.querySelector(".Popup-add-new-user .select-role").value = "admin" + } else { + renderNameSelect() + } + block.classList.add("active") +} +changePassword = () => { + let block = document.querySelector(".Popup-edit-user") + let user_id = parseFloat(block.getAttribute("user_id")) + let pw_1 = block.querySelector(".password_1").value + let pw_2 = block.querySelector(".password_2").value + if (pw_1 !== pw_2) { + block.querySelector(".hint-password").innerHTML = "Die Passwörter stimmen nicht überein." + return + } + fetch("/api/account/updatePassword.php", { + method: "POST", + body: JSON.stringify({id: user_id, password: pw_1}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then((response) => response.json()).then(data => { + if (data === user_id) { + window.location = "/useradmin.php" + } else { + block.querySelector(".hint-password").innerHTML = data + } + }) + +} +changeName = () => { + let block = document.querySelector(".Popup-edit-user") + let user_id = parseFloat(block.getAttribute("user_id")) + let user_name = block.querySelector(".container-name .name").value + fetch("/api/account/updateName.php", { + method: "POST", + body: JSON.stringify({id: user_id, name: user_name}), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }).then((response) => response.json()).then(data => { + if (data === user_name) { + window.location = "/useradmin.php" + } else { + block.querySelector(".hint-name").innerHTML = data + } + }) + +} +getPersons = async () => { + let response_persons = await fetch("/api/persons_active/getAllActiveIdAndName.php", { + method: "POST", + body: JSON.stringify({yearweek: DATE_YEAR_WEEK}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let persons = await response_persons.json() + return persons.sort((a,b) => a.name.localeCompare(b.name)) +} +renderEditUser = (user_id, user_name) => { + let block = document.querySelector(".Popup-edit-user") + let block_title_name = block.querySelector("h2.name") + block_title_name.innerHTML = user_name + block.classList.add("active") + block.setAttribute("user_id", user_id) + block.querySelector("input.name").value = user_name +} +renderUsers = async () => { + PERSONS = await getPersons() + let ROLES = [{c: "user", n: "Benutzer"}, {c: "admin", n: "Einrichtungs-Administrator"}] + USERS = await dbGet_users() + let block = document.querySelector("#Users") + block.innerHTML = "" + let block_name_title = document.createElement("div") + block_name_title.innerHTML = "Name" + block_name_title.classList.add("title") + block.appendChild(block_name_title) + let block_role_title = document.createElement("div") + block_role_title.innerHTML = "Rolle" + block_role_title.classList.add("title") + block.appendChild(block_role_title) + let block_created_title = document.createElement("div") + block_created_title.innerHTML = "Erstellt" + block_created_title.classList.add("title") + block.appendChild(block_created_title) + let block_edit_title = document.createElement("div") + block_edit_title.classList.add("title") + block.appendChild(block_edit_title) + USERS.forEach(user => { + let block_name = document.createElement("div") + block_name.innerHTML = user.name + block.appendChild(block_name) + let block_role = document.createElement("div") + block_role.innerHTML = ROLES.find(r => r.c === user.role).n + block.appendChild(block_role) + let block_created = document.createElement("div") + block_created.innerHTML = `${user.created_at.substring(8, 10)}.${user.created_at.substring(5, 7)}.${user.created_at.substring(0, 4)}` + block.appendChild(block_created) + let block_edit = document.createElement("button") + block_edit.innerHTML = "Bearbeiten" + block_edit.setAttribute("onClick", `renderEditUser(${user.id}, "${user.name}")`) + block.appendChild(block_edit) + }) + let block_add = document.createElement("button") + block_add.setAttribute("onClick", `renderAddUser()`) + block_add.setAttribute("id", "Users-add-button") + block_add.innerHTML = "Hinzufügen" + block.appendChild(block_add) + +} + +closePopup = () => { + let popups = document.querySelectorAll(".Popup.active") + for (let i=0; i<popups.length; i++) { + popups[i].classList.remove("active") + } + let clear_inputs = document.querySelectorAll(".Popup input") + for (i=0; i<clear_inputs.length; i++) { + clear_inputs[i].value = "" + } +} diff --git a/js/user.js b/js/user.js new file mode 100644 index 0000000..5e0df01 --- /dev/null +++ b/js/user.js @@ -0,0 +1,132 @@ +createUserVacations = (vacations) => { + let block_vacations = document.createElement("div") + block_vacations.setAttribute("id", "User-vacations") + block_vacations.classList.add("table-two") + block_vacations.innerHTML = '<h2 class="title">Urlaub</h2><div class="title">Datum</div><div class="title">Name</div>' + vacations = vacations.sort((a,b) => b.start.localeCompare(a.start)) + vacations.forEach((v) => { + let block_date = document.createElement("div") + if (v.start === v.end) { + block_date.innerHTML = convertDate(v.start) + } else { + block_date.innerHTML = `${convertDate(v.start)} - ${convertDate(v.end)}` + } + block_vacations.appendChild(block_date) + let block_name = document.createElement("div") + if (typeof v.name !== "undefined") { block_name.innerHTML = v.name } + block_vacations.appendChild(block_name) + }) + let br = document.createElement("div") + br.appendChild(block_vacations) + return br +} +createUserBetterments = (betterments) => { + let block_betterments = document.createElement("div") + block_betterments.setAttribute("id", "User-betterments") + block_betterments.classList.add("table-two") + block_betterments.innerHTML = '<h2 class="title">Weiterbildung</h2><div class="title">Datum</div><div class="title">Stunden</div>' + betterments = betterments.sort((a,b) => b.start.localeCompare(a.start)) + betterments.forEach((v) => { + let block_date = document.createElement("div") + if (v.start === v.end) { + block_date.innerHTML = convertDate(v.start) + } else { + block_date.innerHTML = `${convertDate(v.start)} - ${convertDate(v.end)}` + } + block_betterments.appendChild(block_date) + let block_name = document.createElement("div") + block_name.innerHTML = v.hours + block_betterments.appendChild(block_name) + }) + let br = document.createElement("div") + br.appendChild(block_betterments) + return br +} +createUserIllnesses = (illnesses) => { + let block_illnesses = document.createElement("div") + block_illnesses.setAttribute("id", "User-illnesses") + block_illnesses.classList.add("table-one") + block_illnesses.innerHTML = '<h2 class="title">Krankschreibung</h2><div class="title">Datum</div>' + illnesses = illnesses.sort((a,b) => b.start.localeCompare(a.start)) + illnesses.forEach((v) => { + let block_date = document.createElement("div") + if (v.start === v.end) { + block_date.innerHTML = convertDate(v.start) + } else { + block_date.innerHTML = `${convertDate(v.start)} - ${convertDate(v.end)}` + } + block_illnesses.appendChild(block_date) + }) + let br = document.createElement("div") + br.appendChild(block_illnesses) + return br +} +createUserOvertimes = (overtimes, overtimes_manual) => { + let block_overtimes = document.createElement("div") + block_overtimes.setAttribute("id", "User-overtimes") + block_overtimes.classList.add("table-three") + block_overtimes.innerHTML = '<h2 class="title">Überstunden</h2><div class="title">Woche</div><div class="title">Automatisch</div><div class="title">Manuell</div>' + overtimes = overtimes.sort((a,b) => b.yearweek.localeCompare(a.yearweek)) + let last_yw + let bl_total_name = document.createElement("div") + bl_total_name.innerHTML = "Insgesamt" + block_overtimes.appendChild(bl_total_name) + let bl_total_val = document.createElement("div") + bl_total_val.classList.add("font-number") + block_overtimes.appendChild(bl_total_val) + let bl_total_m_val = document.createElement("div") + bl_total_m_val.classList.add("font-number") + block_overtimes.appendChild(bl_total_m_val) + let total = 0 + let total_m = 0 + for (let v=0; v<overtimes.length; v++) { + overtime = overtimes[v] + if (overtime.yearweek < DATE_YEAR_WEEK_OLDEST) {continue} + let block_date = document.createElement("div") + block_date.innerHTML = overtime.yearweek + block_overtimes.appendChild(block_date) + let block_overtime = document.createElement("div") + block_overtime.classList.add("font-number") + let oo = parseFloat((overtime.hours_is-overtime.hours_should).toFixed(2)) + let om = overtimes_manual.find(o => o.yearweek === overtime.yearweek)?.overtime + if (om) { total_m = parseFloat((total_m+(om)).toFixed(2))} + if (om) { oo = parseFloat((oo-(om)).toFixed(2))} + total = parseFloat((total+(oo)).toFixed(2)) + if (oo === 0) {oo = " 0"} + else if (oo > 0) {oo = `+${oo}`} + block_overtime.innerHTML = oo + block_overtimes.appendChild(block_overtime) + let block_overtime_m = document.createElement("div") + block_overtime_m.classList.add("font-number") + if (om === 0) {om = " 0"} + else if (om > 0) {om = `+${om}`} + block_overtime_m.innerHTML = om || "" + block_overtimes.appendChild(block_overtime_m) + } + let to = Math.round(total* 100)/100 + if (to >0) {to = `+${to}`} + else if (to === 0) {to = ` ${to}`} + bl_total_val.innerHTML = to + let tm = Math.round(total_m* 100)/100 + if (tm >0) {tm = `+${tm}`} + else if (tm === 0) {tm = ` ${tm}`} + bl_total_m_val.innerHTML = tm + let br = document.createElement("div") + br.appendChild(block_overtimes) + return br +} +renderUserDetails = async () => { + let response_person = await fetch("/api/persons_active/getUserActive.php", { + method: "POST", + body: JSON.stringify({yearweek: DATE_YEAR_WEEK}), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + let person = await response_person.json() + let overtimes = await dbGet_person_overtimes_yearweeks(person.id) + let block = document.querySelector("#User-details") + block.appendChild(createUserOvertimes(overtimes, person.overtimes_manual)) + block.appendChild(createUserVacations(person.vacations)) + block.appendChild(createUserBetterments(person.betterments)) + block.appendChild(createUserIllnesses(person.illnesses)) + document.querySelector(`.Roster-week-tr-${person.id}`).classList.add("active") +} diff --git a/js/vacations-overview.js b/js/vacations-overview.js new file mode 100755 index 0000000..b39cb10 --- /dev/null +++ b/js/vacations-overview.js @@ -0,0 +1,318 @@ + +closeVacationOverviewAdd = () => { + let blocks_r_active = document.querySelectorAll("#Vacations-overview tbody .active") + for (let i=0; i<blocks_r_active.length; i++) { + blocks_r_active[i].classList.remove("active") + } + let block_remove = document.querySelector("#Vacations-overview .vacations-overview-popup-edit") + document.querySelector("#Vacations-overview").removeEventListener('click', eventListenerCloseVacationsOverviewEdit); + window.setTimeout(() => { + block_remove.parentNode.removeChild(block_remove) + },50) +} + +closeVacationOverviewEditRemove = (person_id, vacation_id, month) => { + removeVacation(person_id, vacation_id).then(() => { + closeVacationOverviewAdd() + let block = document.querySelector(`#Vacations-overview .td-${person_id}-month-${month}`) + window.setTimeout(() => { + openVacationsOverview(document.getElementById("Settings-open-vacations-overview")) + },50) + }) +} + +closeVacationOverviewEditSave = (person_id, vacation_id, month) => { + let start = document.querySelector(`.td-${person_id}-month-${month} .input-start`).value + let end = document.querySelector(`.td-${person_id}-month-${month} .input-end`).value + editVacation(person_id, vacation_id, start, end).then(() => { + closeVacationOverviewAdd() + let block = document.querySelector(`#Vacations-overview .td-${person_id}-month-${month}`) + window.setTimeout(() => { + openVacationsOverview(document.getElementById("Settings-open-vacations-overview")) + },50) + }) +} + +closeVacationOverviewAddSave = (person_id, month) => { + let start = document.querySelector(`.td-${person_id}-month-${month} .input-start`).value + let end = document.querySelector(`.td-${person_id}-month-${month} .input-end`).value + saveVacation(person_id, start, end).then(() => { + setActivePerson(person_id).then(() => { + closeVacationOverviewAdd() + let block = document.querySelector(`#Vacations-overview .td-${person_id}-month-${month}`) + window.setTimeout(() => { + openVacationsOverview(document.getElementById("Settings-open-vacations-overview")) + },50) + }) + }) +} +eventListenerCloseVacationsOverviewEdit = (e) => { + if (! document.querySelector('#Vacations-overview .vacations-overview-popup-edit').contains(e.target)){ + closeVacationOverviewAdd() + } +} +editNewVacationFromOverview = (el, person_id, vacation_id, month) => { + let person = PERSONS.find(p => p.id === person_id) + let vacation = person.vacations.find(v => v.id === vacation_id) + let block_to_remove = document.querySelector("#Vacations-overview .vacations-overview-popup-edit") + if (block_to_remove) closeVacationOverviewAdd() + el.closest("tr").classList.add("active") + let start = vacation.start + let end = vacation.end + let block = document.createElement("div") + block.classList.add("vacations-overview-popup-edit") + let block_container = document.createElement("div") + block_container.classList.add("container") + + let block_name = document.createElement("h4") + block_name.innerHTML = person.name + block_container.appendChild(block_name) + + let block_close = document.createElement("button") + block_close.classList.add("button-x") + block_close.setAttribute("onCLick", "closeVacationOverviewAdd()") + block.appendChild(block_close) + + let block_start = document.createElement("input") + block_start.classList.add("input-start") + block_start.setAttribute("type", "date") + block_start.setAttribute("title", "Startdatum") + block_start.value = start + block_container.appendChild(block_start) + + let block_end = document.createElement("input") + block_end.classList.add("input-end") + block_end.setAttribute("type", "date") + block_end.setAttribute("title", "Enddatum") + block_end.value = end + block_container.appendChild(block_end) + + block.appendChild(block_container) + + let block_remove = document.createElement("button") + block_remove.classList.add("button-remove") + block_remove.setAttribute("onClick", `closeVacationOverviewEditRemove(${person_id}, ${vacation_id}, ${month})`) + block_remove.innerHTML = "Löschen" + block.appendChild(block_remove) + + let block_save = document.createElement("button") + block_save.classList.add("button-save", "button-whitegreen") + block_save.setAttribute("onClick", `closeVacationOverviewEditSave(${person_id}, ${vacation_id}, ${month})`) + block_save.innerHTML = "Speichern" + block.appendChild(block_save) + + document.querySelector(`#Vacations-overview .td-${person_id}-month-${month}`).appendChild(block) + + window.setTimeout(() => { + document.querySelector("#Vacations-overview").addEventListener('click', eventListenerCloseVacationsOverviewEdit); + }, 100) +} +addNewVacationFromOverview = (person_id, year, month) => { + let block_remove = document.querySelector("#Vacations-overview .vacations-overview-popup-edit") + if (block_remove) closeVacationOverviewAdd() + let month_s = month.toString() + if (month_s.length === 1) {month_s = `0${month}`} + let person = PERSONS.find(p => p.id === person_id) + let start = `${year}-${month_s}-01` + let end = `${year}-${month_s}-07` + let block = document.createElement("div") + block.classList.add("vacations-overview-popup-edit", "add") + let block_container = document.createElement("div") + block_container.classList.add("container") + + let block_name = document.createElement("h4") + block_name.innerHTML = person.name + block_container.appendChild(block_name) + + let block_close = document.createElement("button") + block_close.classList.add("button-x") + block_close.setAttribute("onCLick", "closeVacationOverviewAdd()") + block.appendChild(block_close) + + let block_start = document.createElement("input") + block_start.classList.add("input-start") + block_start.setAttribute("type", "date") + block_start.setAttribute("title", "Startdatum") + block_start.value = start + block_container.appendChild(block_start) + + let block_end = document.createElement("input") + block_end.classList.add("input-end") + block_end.setAttribute("type", "date") + block_end.setAttribute("title", "Enddatum") + block_end.value = end + block_container.appendChild(block_end) + + block.appendChild(block_container) + + let block_save = document.createElement("button") + block_save.classList.add("button-save") + block_save.setAttribute("onClick", `closeVacationOverviewAddSave(${person_id}, ${month})`) + block_save.innerHTML = "Speichern" + block.appendChild(block_save) + + + document.querySelector(`#Vacations-overview .td-${person_id}-month-${month}`).appendChild(block) + + window.setTimeout(() => { + document.querySelector("#Vacations-overview").addEventListener('click', eventListenerCloseVacationsOverviewEdit); + }, 100) +} +renderVacationsOverviewTableButton = (person_id, name, start, end, isclosing, vacation_id) => { + let year = DATE_YEAR.toString() + daysInMonth = (month) => { + return new Date(year, month, 0).getDate(); + } + + let block_container = document.querySelector("#Vacations-overview .table-container") + let view = true + block_container.classList.add("view") + + let year_e = start.slice(0,4) + let month_s = parseFloat(start.slice(5,7)) + let month_e = parseFloat(end.slice(5,7)) + let day_s = parseFloat(start.slice(8,10)) + let day_e = parseFloat(end.slice(8,10)) + let text = `${day_s}.${month_s}-${day_e}.${month_e}` + if (day_s === day_e) {text = `${day_s}.${month_s}`} + let block_button = document.createElement("div") + block_button.setAttribute("title", `${name}\n${text}`) + let block_spacer + let block_text = document.createElement("button") + block_text.innerHTML = text + block_button.appendChild(block_text) + if (year_e === year && month_s === month_e) { + if (view) { + let days = daysInMonth(month_s) + let left = (day_s-1)*100/(days) + let right = (days-month_e)*100/(days) + let width = ((day_e-day_s)+1)*100/(days) + block_button.style = `position: absolute; left: ${left}%; min-width: unset; padding: 0; top: 0; width: ${width}%;` + } else { + block_button.innerHTML = text + } + } else if (year_e === year) { + let add_border_width = (month_e-month_s) + if (view) { + let days_s = daysInMonth(month_s) + let days_e = daysInMonth(month_e) + let add_width = (month_e-month_s-1)*100 + let start_width = ((days_s-(day_s-1))*100)/(days_s) + let end_width = (day_e*100)/(days_e) + let left = (day_s-1)*100/(days_s) + let width = add_width+start_width+end_width + block_button.style = `position: absolute; left: ${left}%; min-width: unset; padding: 0; top: 0; width: calc(${width}% + ${add_border_width}px);` + } else { + block_button.innerHTML = text + let width = ((month_e-month_s)+1)*100-100 + block_button.style = `position: absolute; min-width: unset; left: 50%; top: 13px; width: calc(${width}% + ${add_border_width}px);` + + block_button.classList.add("button-vacation-overflow") + for (let i=month_s; i<=month_e; i++) { + VACATIONS_OVERVIEW_BUTTONS_SPACER.push([person_id,i]) + } + } + } + if (isclosing) block_button.classList.add("isclosing") + if (!isclosing) block_text.setAttribute("onCLick", `editNewVacationFromOverview(this, ${person_id}, ${vacation_id}, ${month_s})`) + block_button.classList.add("button-vacation") + let block_td_active = block_container.querySelector(`.td-${person_id}-month-${month_s}`) + block_td_active.appendChild(block_button) +} + +let VACATIONS_OVERVIEW_BUTTONS_SPACER = [] +renderVacationsOverviewTable = async () => { + VACATIONS_OVERVIEW_BUTTONS_SPACER = [] + let year = DATE_YEAR.toString() + let block_container = document.querySelector("#Vacations-overview .table-container") + block_container.innerHTML = "" + let block_table = document.createElement("table") + let block_thead = document.createElement("thead") + let block_thead_tr = document.createElement("tr") + let block_tbody = document.createElement("tbody") + let block_th_names = document.createElement("th") + block_thead_tr.appendChild(block_th_names) + + let block_closingtime_tr = document.createElement("tr") + block_closingtime_tr.classList.add("tr-x") + let block_closingtime_td_name = document.createElement("td") + block_closingtime_td_name.innerHTML = "Schließzeiten" + block_closingtime_td_name.classList.add("td-name") + block_closingtime_tr.appendChild(block_closingtime_td_name) + for (let i=1; i<13; i++) { + let block_td_c = document.createElement("td") + block_td_c.classList.add(`td-x-month-${i}`) + block_closingtime_tr.appendChild(block_td_c) + } + block_tbody.appendChild(block_closingtime_tr) + + let person = PERSONS + for (let i=1; i<13; i++) { + let month = new Date(`${year}-${i}`).toLocaleString("default", {month: "long"}) + let block_th = document.createElement("th") + block_th.innerHTML = month + block_thead_tr.appendChild(block_th) + } + person.forEach(pe => { + let block_tr = document.createElement("tr") + let block_td = document.createElement("td") + block_td.classList.add(`td-${pe.id}`, "td-name") + block_td.innerHTML = pe.name + block_tr.appendChild(block_td) + + for (let month=1; month<13; month++) { + let block_td_m = document.createElement("td") + block_td_m.classList.add(`td-${pe.id}-month-${month}`) + let button_new = document.createElement("button") + button_new.innerHTML = "+" + button_new.classList.add("button-new") + button_new.setAttribute("onClick", `addNewVacationFromOverview(${pe.id}, ${year}, ${month})`) + button_new.setAttribute("title", `neuen Urlaub hinzufügen`) + block_td_m.appendChild(button_new) + block_tr.appendChild(block_td_m) + } + block_tbody.appendChild(block_tr) + }) + block_thead.appendChild(block_thead_tr) + block_table.appendChild(block_thead) + block_table.appendChild(block_tbody) + block_container.appendChild(block_table) + + closingtimes = CLOSINGTIMES + for (let co=0; co<closingtimes.length;co++) { + let closingtime = closingtimes[co] + renderVacationsOverviewTableButton("x", closingtime.name, closingtime.start, closingtime.end, true) + } + person.forEach(pe => { + pe.vacations.forEach((vacation, v_id) => { + if (vacation.start.slice(0,4) !== year) return + if (typeof vacation.id === "undefined") { + renderVacationsOverviewTableButton(pe.id, pe.name, vacation.start, vacation.end, true, vacation.closingtime_id) + } else { + renderVacationsOverviewTableButton(pe.id, pe.name, vacation.start, vacation.end, false, vacation.id) + } + }) + }) + + + VACATIONS_OVERVIEW_BUTTONS_SPACER.forEach(s => { + let block_spacer = block_container.querySelector(`.td-${s[0]}-month-${s[1]} .button-vacation:not(.button-vacation-overflow)`) + if (block_spacer) { block_spacer.style.marginTop = "24px" } + }) +} + +openVacationsOverview = (el) => { + settingsContainerHideAll("Vacations-overview") + let year = DATE_YEAR.toString() + let block = document.getElementById("Vacations-overview") + let block_container = document.getElementById("Vacations-overview") + block_container.innerHTML = "" + block.classList.add("active", "vacations-overview") + let block_name = document.createElement("h2") + block_name.innerHTML = "Urlaubsübersicht" + block_container.appendChild(block_name) + let block_table_container = document.createElement("div") + block_table_container.classList.add("table-container", "view") + block_container.appendChild(block_table_container) + renderVacationsOverviewTable() +} diff --git a/login.php b/login.php new file mode 100644 index 0000000..58c2fbd --- /dev/null +++ b/login.php @@ -0,0 +1,120 @@ +<!DOCTYPE html> +<?php + +session_start(); + +require './api/config/db_inc.php'; +require './api/objects/account_class.php'; + +$account = new Account(); +$login = FALSE; + +try { + $login = $account->sessionLogin(); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +if ($login) { + if ($_SESSION["user_role"] === "superadmin") { + header('Location: /admin.php'); + } else { + header('Location: /'); + } +} else if ($account->isAuthenticated()) { + if ($_SESSION["user_role"] === "superadmin") { + header('Location: /admin.php'); + } else { + header('Location: /'); + } +} +?> +<html> + <head> + <link rel="stylesheet" href="style-colors.css"> + <link rel="stylesheet" href="style-defaults.css"> + <link rel="stylesheet" href="style-login.css"> + <script src="js/settings.js" defer></script> + <script src="js/database/shifts.js" defer></script> +<script> + +login = (event) => { + event.preventDefault(); + let name = document.getElementById("Login-input-name").value + let password = document.getElementById("Login-input-password").value + let data_id = document.querySelector("#Login-select-institution").value + let login_data = {name: name, password: password, data_id: data_id} + fetch("/api/login.php", { + method: "POST", + body: JSON.stringify(login_data), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + .then(response => response.json()).then(data => { + if (data === "mismatch") { + document.querySelector(".container .errormessage").innerHTML = "Passwort und Name stimmen nicht überein." + } else { + window.location = "/redirect.php" + } + }) + .catch(error => { + fetch("/api/login.php", { + method: "POST", + body: JSON.stringify(login_data), + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + .then(response_a => response_a.json()).then(data => { + if (data === "mismatch") { + document.querySelector(".container .errormessage").innerHTML = "Passwort und Name stimmen nicht überein." + } else { + window.location = "/redirect.php" + } + }) + }) +} + +dbGet_institutions = async () => { + let response = await fetch("/api/institution/getAll.php", { + method: "POST", + headers: { "Content-Type": "application/json; charset=UTF-8" } + }) + return await response.json() +} + +renderInstitutions = () => { +let el = document.querySelector("#Login-select-institution") + el.innerHTML = '<option value="superadmin">Administrator</option>' + dbGet_institutions().then(institutions => { + institutions.forEach((inst, i) => { + let block = document.createElement("option") + if (i === 0) { + block.setAttribute("selected", "selected") + } + block.setAttribute("value", inst.id) + block.innerHTML = inst.name + el.appendChild(block) + }) + }) +} + +</script> + </head> + <body> + <div class="container"> + <h1 class="title">Dienstplan Login</h1> + <form id="Login-form" method="post"> + <label>Name</label><input value="" autofocus id="Login-input-name"> + <label>Passwort</label><input value="" type="password" id="Login-input-password"> + <label>Einrichtung</label> + <label><select id="Login-select-institution"></select></label> + <input class="button-login" type="submit" value="Login"/> + </form> + <p class="errormessage"></p> + </div> +<script> +let form = document.getElementById("Login-form"); +form.addEventListener("submit", login, true); +renderInstitutions() +</script> + </body> +</html> diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..5db3181 --- /dev/null +++ b/logout.php @@ -0,0 +1,17 @@ +<?php +header("Access-Control-Allow-Origin: *"); +header("Content-Type: application/json; charset=UTF-8"); +header("Access-Control-Allow-Methods: POST"); +header("Access-Control-Max-Age: 3600"); +header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"); + +session_start(); + +require './api/config/db_inc.php'; +require './api/objects/account_class.php'; + +$account = new Account(); +$account->logout(); +//header('Location: ./login.php'); +?> + diff --git a/pngs/icons8-island-32.png b/pngs/icons8-island-32.png new file mode 100644 index 0000000..805763b Binary files /dev/null and b/pngs/icons8-island-32.png differ diff --git a/redirect.php b/redirect.php new file mode 100644 index 0000000..b60cb83 --- /dev/null +++ b/redirect.php @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<?php + +session_start(); + +require './api/config/db_inc.php'; +require './api/objects/account_class.php'; + +$account = new Account(); +$login = FALSE; + +try { + $login = $account->sessionLogin(); +} catch (Exception $e) { + echo $e->getMessage(); + die(); +} + +if ($login) { + if ($_SESSION["user_role"] === "superadmin") { + header('Location: /admin.php'); + } else { + header('Location: /'); + } +} else if ($account->isAuthenticated()) { + if ($_SESSION["user_role"] === "superadmin") { + header('Location: /admin.php'); + } else { + header('Location: /'); + } +} else { + header('Location: /login.php'); +} +?> diff --git a/style-admin.css b/style-admin.css new file mode 100644 index 0000000..6f48613 --- /dev/null +++ b/style-admin.css @@ -0,0 +1,42 @@ +button {border-radius: 0 !important; text-align: center; justify-content: center;} + + +body { margin: 45px;} +body >.container{ display: grid; gap: 50px; grid-template-columns: auto auto;} + +label > select {width: 100%;} +.hint {all: unset !important; color: var(--color-red) !important;} + +#Logout-button { background-color: var(--color-lightblue-background); border-radius: 0; position: fixed; right: 0; top: 0; z-index: 10000000;} + +#Institutions { border-top: 1px solid black; display: grid; grid-template-columns: auto auto; max-width: max-content; margin-bottom: 20px} +#Institutions >*:not(button) { border-bottom: 1px solid black; display: flex; align-items: center; } +#Institutions >*.container-remove { padding-left: 8px; } +#Institutions >.name { padding: 8px; } +#Institution-add-button {grid-column: 1 / -1; display: flex; justify-content: center; align-items: center; } + +.Popup-request-remove-institution .hint { color: red; font-size: 12px;} + +.container-users .role-hints {border-top: 1px solid black; display: grid; font-size: 12px; gap: 0 6px; grid-template-columns: auto auto; max-width: max-content; margin-bottom: 16px; padding-top: 8px; } +#Users { display: grid; grid-template-columns: auto auto auto auto auto auto; max-width: max-content; } +#Users >*:not(#Users-add-button) { border-bottom: 1px solid black; padding: 8px; display: flex; align-items: center; } +#Users >.title { border-bottom: 2px solid black !important; border-top: 1px solid black; margin-bottom: 1px; } +#Users-add-button {grid-column: 1 / -1; display: flex; justify-content: center; align-items: center; } + +.Popup-container { padding: 20px; box-sizing: border-box;} +.Popup-container h2 { margin-top: 0; } +.Popup-container h2.name { color: var(--color-text-orange);} +.container-title { display: flex;} +.Popup-container >.container { display: flex; flex-direction: column; gap: 16px; } +.Popup-container >.container >* { display: flex; align-items: center; gap: 8px;} + +.Popup-add-new-user .container {display: grid; grid-template-columns: auto auto; max-width: max-content;} +.Popup-add-new-user .hint { color: red; font-size: 12px;} + + +.Popup-edit-user .hint {all: unset; color: var(--color-red);} +.Popup-edit-user .container > div { max-width: max-content; } +.Popup-edit-user .container .container-name {display: flex; flex-direction: column; align-items: flex-start; } +.Popup-edit-user .container .container-buttons {display: flex; gap: 8px;} +.Popup-edit-user .container .container-password {display: grid; grid-template-columns: auto auto;} +.Popup-edit-user .container .container-password h3 {grid-column: 1 / -1;} diff --git a/style-colors.css b/style-colors.css new file mode 100644 index 0000000..6696336 --- /dev/null +++ b/style-colors.css @@ -0,0 +1,36 @@ +:root { + --color-black: #1e2122; + --color-lightblack: #3a5962; + --color-lightblue: lightblue; + --color-whiteblue: #d4eaf1; + --color-blue: #9eb9d7; + --color-darkblue: #477a8b; + --color-whitegreen: #c1e7b6; + --color-whitegreen-hover: #8ac572; + --color-gray: #838383; + --color-whitegray: #efefef; + --color-lightgray: lightgray; + --color-yellow: #ede68d; + --color-lightred: #b97e82; + --color-red: #a55052; + --color-orange: #ffbc00; + --color-orange-hover: orange; + --color-darkorange: #ebaa17; + --color-darkorange-hover: #df9204; + --color-transparent-white: #ecf5ffd9; + --color-transparent-lightblue: #add8e66e; + --color-lightblue-background: #e4f4f9; + --color-normal-background: #ecf5ff; + --color-outline-hover: #ffbc40; + --color-text-green: green; + --color-text-red: red; + --color-text-orange: #e9750f; + --button-normal-border: lightblue; + --button-normal-hover-background: #d4eaf5; + --button-normal-active-background: lightblue; + --button-normal-active-hover-background: #c8e5ee; + --button-remove-background: #b97e82; + --button-remove-hover-background: #a55052; + --button-save-background: #77b964; + --button-save-hover-background: #9dd18e; +} diff --git a/style-defaults.css b/style-defaults.css new file mode 100644 index 0000000..1728da8 --- /dev/null +++ b/style-defaults.css @@ -0,0 +1,165 @@ +body { + background-color: var(--color-normal-background); + color: var(--color-black); + font-family: Arial, Helvetica, sans-serif; + font-size: 14px; + position: relative; + scroll-behavior: smooth; + height: 100vh; + padding-bottom: 40px; + box-sizing: border-box; + margin: 0; +} + +* { + -ms-overflow-style: none; /* Internet Explorer 10+ */ + scrollbar-width: none; /* Firefox */ +} +*::-webkit-scrollbar { + display: none; /* Safari and Chrome */ +} + +button, input:not([type="checkbox"]), select { + all: unset; + appearance: none; + border-radius: 20px; + border: 1px solid var(--button-normal-border); + box-shadow: none; + padding: 4px 10px; + -webkit-appearance: none; + -moz-appearance: none; +} +button, input, select, option { background-color: white; cursor: pointer; font-family: Arial, Helvetica, sans-serif; min-height: 32px; min-width: 96px; box-sizing: border-box; } +select { padding: 6px 10px 2px; position: relative; } +option { background-color: white !important; } +button { text-align: center;} +button:hover, select:hover, button:active, select:active { background-color: var(--button-normal-hover-background); } +button.active { background-color: var(--button-normal-active-background); } +button.active:hover { background-color: var(--button-normal-active-hover-background); } + +button.sort:before { float: right; line-height: 16px; } + +.button-whitegreen {background: var(--color-whitegreen); border-color: var(--color-whitegreen);} +.button-whitegreen:hover {background: var(--color-whitegreen-hover)} +.button-orange {background: var(--color-orange); border-color: var(--color-orange);} +.button-orange:hover {background: var(--color-orange-hover)} +.button-orange.active {background: var(--color-orange-hover)} +.button-orange.active:hover {background: var(--color-orange)} + +input::-webkit-file-upload-button { opacity: 0; } + + +.icon { height: 14px; width: auto;} + +.chevron-up:before { content:"\2039"; display: inline-block; font-size: 25px; transform: rotate(90deg); } +.chevron-right:before { content:"\203A"; display: inline-block; float: right; font-size: 25px; } +.chevron-down:before { content:"\203A"; display: inline-block; font-size: 25px; transform: rotate(90deg); } +.chevron-left:before { content:"\2039"; display: inline-block; float: left; font-size: 25px; } +.chevron-left.left:before { float: left !important } +.chevron-right.right:before { float: right !important } +.chevron-select:before { position: absolute; right: 10px; top: 2px; } +.chevron-select { background: white; border-radius: 20px; box-sizing: border-box; position: relative; width: auto !important; } +.chevron-select select { background: transparent; padding-right: 23px !important; } + +.button-x:after{ display: inline-block; content: "\00d7"; margin: auto; } +.button-info { + min-width: 19px; + padding: 0; + font-weight: bold; + display: flex; + justify-content: center; + align-items: center; + max-width: 19px; + font-size: 13px; + color: var(--color-lightblue); + min-height: 22px; + max-height: 22px; +} +.button-remove { + min-height: unset; + font-size: 13px; + line-height: 15px; + height: auto; + min-width: unset; + padding: 8px 16px; + background-color: var(--button-remove-background); +} +.button-remove:hover {background-color: var(--button-remove-hover-background);} +.button-save { background-color: var(--button-save-background);} +.button-save:hover { background-color: var(--button-save-hover-background);} +.d-none {display: none !important; } +.noscroll {overflow: hidden;} +.v-bottom {vertical-align: bottom !important;} +.cursor-wait * {cursor: wait !important;} + +.font-number { font-family: Arial, Helvetica, monospace !important; white-space: pre; } + +table { border-collapse: collapse; } +table, th, td { border: 1px solid; } +.tr-empty td {height: 5px !important;} + +.noscroll { overflow: hidden !important; } + +.hamburger { + all: unset; + background: white; + box-sizing: border-box; + cursor: pointer; + display: flex; + flex-direction: column; + height: 22px; + justify-content: space-between; + padding: 5px 4px; + width: 26px; +} +.hamburger span { + background: var(--color-lightblue); + border-radius: 1px; + height: 1px; +} + + +.page { height: 100%; box-sizing: border-box; overflow: auto; scroll-snap-align: start; padding: 0 18px 0 30px;} + + +.Popup, +#Popup { + background-color: var(--color-transparent-white); + box-sizing: border-box; + cursor: pointer; + display: none; + height: 100%; + left: 0; + padding: 20px 20px 60px; + position: fixed; + top: 0; + width: 100%; + z-index: 100000; +} +.Popup.active, +#Popup.active { display: flex; } +.Popup-container, +#Popup-container { + background-color: white; + border: 1px solid var(--color-lightblue); + border-radius: 8px; + cursor: unset; + margin: auto; + max-width: 600px; + max-height: 80vh; + min-width: 70vw; + overflow: auto; + position: relative; + padding-top: 0 !important; + white-space: break-spaces; + z-index: 1; +} +.Popup-container .button-back, +#Popup-container .button-back { position: absolute; top: 0; left: 0; border-radius: 8px 0 0 0; border: 0; background: var(--color-lightblue); op +acity: .6; } +.Popup-container .button-x, +#Popup-container .button-x { position: sticky; left: 100%; transform: translate(21px, 0); top: 0; width: 50px; border: 0; border-radius: 0 8px 0 0; background: var(--color-lightblue); opacity: .6; } +.Popup-container .button-x:hover, +#Popup-container .button-x:hover { opacity: 1; } +.Popup-container p, +#Popup-container p { padding: 0 20px; font-size: 16px; } diff --git a/style-login.css b/style-login.css new file mode 100644 index 0000000..b69a3cd --- /dev/null +++ b/style-login.css @@ -0,0 +1,9 @@ +body {display: flex; min-height: 100vh;} +.title {text-align: center} +.container { max-width: max-content; margin: auto;} +form { display: grid; grid-template-columns: auto auto; align-items: center; gap: 8px; background: orange; padding: 20px;} +input {background: white !important; } +.button-login { border-radius: 0 !important; grid-column: 1 / -1 !important; text-align: center !important; cursor: pointer !important;} +.button-login:hover { background: var(--color-lightblue-background) !important; } +.errormessage { color: var(--color-red);} +#Login-select-institution { width: 100%; min-height: 26px; padding: 4px 8px;} diff --git a/style-user.css b/style-user.css new file mode 100644 index 0000000..93d5813 --- /dev/null +++ b/style-user.css @@ -0,0 +1,20 @@ +#User-details { display: grid; grid-template-columns: repeat(4, auto); grid-template-rows: auto 1fr; align-items: flex-start; overflow: auto; background: white; border: 1px solid black; padding: 0 10px;} +#User-details >.main-title {grid-column: 1 / -1 !important; background: var(--color-lightblue); margin: 0; padding: 10px 20px; margin-left: -10px; width: 100%;} +#User-details >*:not(.main-title) {max-height: 300px; overflow: scroll; min-width: 260px; border-right: 1px solid black; padding: 20px 10px; min-height: 100%; box-sizing: border-box;} +#User-details >*:last-child {border-right: 0;} + +.table-three {display: grid; grid-template-columns: auto auto auto; max-width: max-content; gap: 4px 8px;} +.table-three >h2.title {grid-column: 1 / -1; } +.table-three >div.title {font-weight: bold; } + +.table-two {display: grid; grid-template-columns: auto auto; max-width: max-content; gap: 4px 8px;} +.table-two >h2.title {grid-column: 1 / -1;} +.table-two >div.title {font-weight: bold; } + +.table-one {display: grid; grid-template-columns: auto; max-width: max-content; gap: 4px 8px;} +.table-one >div.title {font-weight: bold; } +table tr.active {background-color: var(--color-whiteblue)} + +#Week-select { display: flex; align-items: center;} +#Week-select button:first-child { border-left: 1px solid black; } +#Logout-button { border-left: 1px solid black !important;} diff --git a/style-useradmin.css b/style-useradmin.css new file mode 100644 index 0000000..f571ad1 --- /dev/null +++ b/style-useradmin.css @@ -0,0 +1,35 @@ +button {border-radius: 0 !important;} + + +body { margin: 45px;} +body >.container{ display: grid; grid-template-columns: 1fr 1fr;} + +label > select {width: 100%;} + +#Back-button { background-color: var(--color-lightblue-background); border-radius: 0; position: fixed; left: 0; top: 0; z-index: 10000000;} +#Logout-button { background-color: var(--color-lightblue-background); border-radius: 0; position: fixed; right: 0; top: 0; z-index: 10000000;} + +.container-users .role-hints {border-top: 1px solid black; display: grid; font-size: 12px; gap: 0 6px; grid-template-columns: auto auto; max-width: max-content; margin-bottom: 16px; padding-top: 8px; } +#Users { display: grid; grid-template-columns: auto auto auto auto; max-width: max-content; } +#Users >*:not(#Users-add-button) { border-bottom: 1px solid black; padding: 8px; display: flex; align-items: center; } +#Users >.title { border-bottom: 2px solid black !important; border-top: 1px solid black; margin-bottom: 1px; } +#Users-add-button {grid-column: 1 / -1; display: flex; justify-content: center; align-items: center; } + +.Popup-container { padding: 20px; box-sizing: border-box;} +.Popup-container h2 { margin-top: 0; } +.Popup-container h2.name { color: var(--color-text-orange);} +.container-title { display: flex;} +.Popup-container >.container { display: flex; flex-direction: column; gap: 16px; } +.Popup-container >.container >* { display: flex; align-items: center; gap: 8px;} + +.Popup-add-new-user .container {display: grid; grid-template-columns: auto auto; max-width: max-content;} +.Popup-add-new-user .container-name > *{display: flex; width: 100% !important; } +.Popup-add-new-user .hint-user {grid-column: 1 / -1 !important;} +.Popup-add-new-user .connect { min-height: 20px !important; } + +.hint {all: unset !important; color: var(--color-red) !important;} +.Popup-edit-user .container > div { max-width: max-content; } +.Popup-edit-user .container .container-name {display: flex; flex-direction: column; align-items: flex-start; } +.Popup-edit-user .container .container-buttons {display: flex; gap: 8px;} +.Popup-edit-user .container .container-password {display: grid; grid-template-columns: auto auto;} +.Popup-edit-user .container .container-password h3 {grid-column: 1 / -1;} diff --git a/style-visitor.css b/style-visitor.css new file mode 100644 index 0000000..fab8df7 --- /dev/null +++ b/style-visitor.css @@ -0,0 +1,11 @@ +#Settings {display: none; } + +#Menu {display: grid; grid-template-columns: auto auto auto;} +#Menu-settings {justify-content: flex-start; padding-left: 20px;} +#Roster-week-input {background: white; } +#Roster-container-week {max-height: unset; max-height: calc(100vh - 40px); overflow: scroll;} +#Week-select-overview {display: inline-block;} +#Week-select-overview >select { min-height: 28px; padding: 5px 10px 4px; height: 28px;} +#Week-select-overview:before { top: 0;} +table thead tr:first-child { position: sticky; top: 0; background: white;} + diff --git a/style.css b/style.css new file mode 100644 index 0000000..d9b30f3 --- /dev/null +++ b/style.css @@ -0,0 +1,1043 @@ +#Superadmin-back-button { background-color: var(--color-lightblue-background); border-radius: 0; left: 0; top: 0; position: fixed; z-index: 100000000;} + +#Start #Version-control { + color: var(--color-blue); + position: fixed; + top: 18px; + left: 20px; + border: 0; + font-weight: bold; + font-size: 12px; + border: 0; + display: grid; + grid-template-columns: auto 1fr; + grid-gap: 2px 6px; + height: auto; +} +#Start { + align-items: center; + background: white; + display: flex; + flex-direction: column; + height: 100%; + justify-content: center; + left: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 100000; +} +#Start > div { + border-top: 1px solid var(--color-black); + height: 58px; + max-width: 100vw; + width: 350px; +} +#Start .start-button-container {border-left: 1px solid var(--color-black); border-right: 1px solid var(--color-black);} +#Start .start-example-container {border-bottom: 1px solid var(--color-black); margin-bottom: 100px;} +#Start .start-login {opacity: 0;} +#Start .file-input:hover + .button-start { opacity: .7;} +#Start .button-start { + all: unset; + align-items: center; + background-color: orange; + cursor: pointer; + display: flex; + font-size: 18px; + font-weight: bold; + height: 100%; + justify-content: center; + width: 100%; +} +#Start .button-start:hover { + opacity: .7; +} + +#Start .start-import-container { + position: relative; +} +#Start .start-import-container input { + all: unset; + color: transparent; + cursor: pointer; + position: absolute; + height: 100%; + left: 0; + opacity: 0; + top: 0; + width: 100%; + z-index: 1; +} +#Start .start-import-container input:hover { cursor: pointer; } +#Start .Footer { + border: 0; + bottom: 0; + height: 20px; + position: absolute; + right: 0; +} + +#Menu { + background: var(--color-orange); + bottom: 0; + display: flex; + height: 40px; + justify-content: space-between; + left: 0; + position: fixed; + width: 100vw; + z-index: 10000000; +} +#Menu button { + all: unset; + border-right: 1px solid var(--color-black); + cursor: pointer; + font-weight: bold; + height: 100%; + min-width: max-content; + padding: 0 10px; +} +#Menu button:hover { + background-color: var(--color-orange-hover); +} +#Menu .right {display: flex;} +#Menu .right >*{border: 0; border-left: 1px solid black;} +.menu-item-days-container { display: flex; overflow: auto; } +#Menu-item-days { display: flex; } +#Menu .menu-item-days-container .chevron-left, #Menu #Menu-item-export { border-left: 1px solid var(--color-black); } +#Menu #Menu-item-export { border-right: 0; } +#Menu #Zoom-roster { background: white; height: 9px; box-sizing: border-box; margin: auto 20px auto 8px; width: 100px; } + +#Menu-item-week {display: flex; } +#Menu-week-select {background: transparent; height: 100%; border-right: 1px solid black; border-radius: 0; width: 20px; overflow: hidden; } +#Menu-week-select:hover {background: var(--color-orange-hover)} +#Menu-week-select:before {right: 6px; top: 5px;} +#Menu-week-select select { min-width: unset; max-width: 20px; border-radius: 0; border: 0; padding: 0; cursor: pointer; } + + +#Menu-settings >*.active {background: var(--button-normal-active-background);} +#Menu-settings.visible >*.active {background: white;} +#Menu-settings:not(.active):not(.visible) {width: 30px; overflow: hidden; border-radius: 0 0 8px 0;} +#Menu-settings:not(.active):not(.visible) > *:not(.toggle-menu) {opacity: 0; } +#Menu-settings .toggle-menu { all: unset; background: transparent; position: absolute; left: 0; top: 0; width: auto; min-width: auto; z-index: 1; width: 30px; height: 100%; align-items: center; justify-content: center;} +#Menu-settings:not(.active) .toggle-menu { display: flex !important;} +#Menu-settings:not(.active):not(.visible) .toggle-menu .left {display: none; } +#Menu-settings:not(.active) .toggle-menu .right {display: flex !important; } +#Menu-settings:not(.active).visible .toggle-menu .right {display: none !important; } +#Menu-settings:not(.active) h3 {display: none;} +#Menu-settings { background: var(--color-lightblue); display: flex; width: 100%; align-items: center; justify-content: flex-end; position: fixed; top: 0; left: 0; z-index: 111111; transition: all ease .4s} +#Menu-settings h3 { margin: 0 auto 0 20px; } +#Menu-settings >*:not(h3) { border-radius: 0; border-right: 0; font-weight: bold; color: gray; min-height: 40px; position: relative; cursor: pointer; font-family: Arial, Helvetica, sans-serif; min-width: 96px; box-sizing: border-box; padding: 4px 10px; border: 1px solid var(--button-normal-border); display: flex; justify-content: center; align-items: center; background: white; } +#Menu-settings >*.active { color: black;} +#Menu-settings >label {position: relative; cursor: pointer; font-family: Arial, Helvetica, sans-serif; width: 96px !important; box-sizing: border-box; display: flex !important; justify-content: center; align-items: center; margin: 0 !important; background: white; border: 1px solid var(--button-normal-border); border-right: 0;} +#Menu-settings >*:not(h3):hover {background-color: var(--button-normal-hover-background) !important;} +#Menu-settings .dropdown:hover >div {display: flex !important} +#Menu-settings .dropdown >div {flex-direction: column; position: absolute; top: 38px; left: -1px;} +#Menu-settings .dropdown >div button {border-radius: 0; border-top: 0; color: gray !important; text-align: left;} +#Menu-settings .dropdown >div button:hover {color: black !important;} +#Menu-settings .dropdown.active.closingtime button.closingtime {color: black !important; background: var(--button-normal-active-background);} +#Menu-settings .dropdown.active.vacation button.vacation {color: black !important; background: var(--button-normal-active-background);} + + +.main-import-container { + grid-area: import; + margin-left: auto; + margin-top: -40px; + text-align: center; + align-items: center; + background-color: orange; + display: flex; + float: right; + font-weight: bold; + height: 40px; + justify-content: center; + opacity: .6; + position: relative; + width: 130px; +} +.main-import-container input { + background-color: transparent; + border-radius: 0; + border: 0; + cursor: pointer; + font-size: 0; + height: 100%; + left: 0; + opacity: 0; + padding: 0; + position: absolute; + top: 0; + width: 100%; +} + +#Is-visitor-text {color: var(--color-red); margin: 8px 0 8px 100px; position: fixed; top: 0; left: 0; z-index: 1111111; background: var(--color-lightblue-background);} + +.main-container { box-sizing: border-box; height: 100%; max-height: 100%; overflow: auto; position: relative; scroll-snap-type: y mandatory;} + +#Settings-container {height: 100%; display: flex; width: 100%; } +#Settings-container >* {width: 100%;} + +#Settings { display: flex; flex-direction: column; padding-top: 32px; } +#Settings > h1 { margin-top: 40px;} +#Settings .settings-box { background: white; box-sizing: border-box; padding: 16px; } +#Settings #Settings-default { display: flex; flex-direction: column; padding: 0;} +#Settings-default >h2 { padding: 16px 16px 0;} +#Settings #Settings-default > button { margin-bottom: 8px; text-align: center; } +#Settings .settings-box .container { display: none; } +#Settings .settings-box.active .container { display: inline-block; overflow: auto; padding: 0 16px 40px; grid-area: con; min-width: max-content;} +#Settings-default .container .container-buttons { display: flex; margin-left: -16px; text-align: center; margin-bottom: 8px; position: sticky; top: 0; padding-top: 16px; background: linear-gradient(white 80%, transparent);} +#Settings-default .container .container-buttons button { border-radius: 0; width: 100%; max-width: 190px; margin-bottom: 20px; } +#Settings-default .container .container-buttons button.button-remove { grid-area: rem; } +#Settings-default .container .container-buttons button.button-save { grid-area: sav; } +#Settings-weekly-button {border-left: 0;} + +#Settings .settings-item { margin-bottom: 8px; } +#Settings label { display: inline-block; margin-right: 8px; width: 120px; white-space: nowrap; } +#Settings select { width: 80px; } +#Settings #Week-select { display: flex; grid-area: week-select; } +#Settings #Week-select >* { max-height: 32px; box-sizing: border-box; } +#Settings #Week-select #Roster-week-input { display: flex; align-items: center; } +#Settings #Week-select button { border-radius: 0; border-left: 0; min-width: max-content; } +#Settings #Week-select button:nth-child(2) { border-left: 1px solid var(--button-normal-border); border-radius: 20px 0 0 20px; margin-left: 8px; } +#Settings #Week-select button:nth-child(4) { border-radius: 0 20px 20px 0; } +#Settings #Week-select #Week-select-overview { margin-left: 8px; } + +#Sort-roster-by { display: flex; align-items: center; gap: 8px; position: sticky; top: 0; float: right; z-index: 11111;} +#Sort-roster-by button:nth-child(1) {border-radius: 0 0 0 10px;} +#Sort-roster-by button:nth-child(2) {border-radius: 0;} +#Sort-roster-by button:nth-child(3) {border-radius: 0 0 10px 0; border-right: 1px solid var(--button-normal-border);} + + +#Roster-week-buttons-edit-sort {display: flex; gap: 8px; padding-left: 240px; padding-top: 18px; margin-bottom: -42px;} + +#Table-week-editable-button { max-width: 200px;} +#Sort-week-by { } +.sort-box {display: flex; } +.sort-box button {border-right: 0;} +.sort-box button:nth-child(1) {border-radius: 20px 0 0 20px;} +.sort-box button:nth-child(2) {border-radius: 0;} +.sort-box button:nth-child(3) {border-radius: 0 20px 20px 0; border-right: 1px solid var(--button-normal-border);} +.sort-box button.active +button { border-left: 1px solid white;} + +#Settings-day-time-change { align-items: center; display: grid; grid-template-columns: auto 1fr; grid-gap: 0 8px; max-width: max-content; min-width: max-content; } +#Settings-day-time-change .select-name { padding-right: 8px; } +#Settings-day-time-change .select-start-end { min-width: max-content; } +#Settings-day-time-change .select-start-end label { margin-right: 0; } + +#Settings-day-time-change .select-start select { border-right: 0; border-radius: 20px 0 0 20px; } +#Settings-day-time-change .select-end select { border-radius: 0 20px 20px 0; } + +#settings-global .title-container { align-items: center; display: flex; gap: 16px; } +#Settings-global .title-container button { min-height: 26px; height: 26px; } +#Settings-global .button-add { border-radius: 0; margin-left: -18px; margin-bottom: 8px; padding-left: 18px;} +#Settings-global .button-remove { margin-left: 16px; padding: 4px 10px;} + +#Settings-global-departments > div{margin-bottom: 8px;} +#Settings-global-departments > div:not(.title-container){display: flex;} + +#Settings-global-editable-week { margin-bottom: 16px; } + +#Settings-global-editable-week .button-default-cell { margin-right: 6px; } +#Settings-global-editable-week .button-default-row { border-radius: 20px 0 0 20px;} +#Settings-global-editable-week .button-default-row.active { border-right: 1px solid white;} +#Settings-global-editable-week .button-default-row-bottom { border-radius: 0 20px 20px 0; border-left: 0; } + +#Settings-global-labels .items {display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; } +#Settings-global-labels .item { align-items: center; display: flex;} +#Settings-global-labels .item >*:nth-child(1) {width: auto;} +#Settings-global-labels .item >*:nth-child(2) {width: 100%; max-width: 122px; margin-right: 16px; min-width: 122px; box-sizing: border-box;} +#Settings-global-labels .item >*:nth-child(3) {width: auto;} +#Settings-global-labels .item >*:nth-child(4) {max-width: 46px;} +#Settings-global .add-container {padding: 0 8px 8px 18px; margin-bottom: 8px;margin-top: -34px; margin-left: -18px; background: white; z-index: 1; position: relative; background: var(--color-lightblue-background)} +#Settings-global .add-container .cancel {border-radius: 0; margin-left: -18px; margin-bottom: 8px; padding-left: 18px;} +#Settings-global .add-container label {width: auto; } +#Settings-global .add-container input {background: white; } +#Settings-global .add-container input { width: 100%; max-width: 122px; margin-right: 16px; min-width: 122px; box-sizing: border-box; } +#Settings-global .add-shiftlabel input.cut { max-width: 46px; min-width: 46px; box-sizing: content-box; } + +#Settings-global-rename-fields {margin-top: 16px;} +#Settings-global-rename-fields .item { display: flex; gap: 16px; margin-bottom: 8px;} +#Settings-global-rename-fields .item >div { align-items: center; display: flex; min-width: unset; } +#Settings-global-rename-fields .item >div label { width: auto; } +#Settings-global-rename-fields .item >div:nth-child(1) input { max-width: 100px; } +#Settings-global-rename-fields .item >div:nth-child(2) input { max-width: 46px; } + +#Person-container { display: flex; flex-direction: column; } +#Person-container .button-add-person { text-align: center; width: max-content; border-radius: 0 0 10px 10px; } +#Person-container.active .button-add-person { display: inline-block;} +#Person tbody {position: relative;} +#Person tbody:after {content: ""; position: absolute; height: 100%; left: 0; top: 0; width: 100%; z-index: 1; } +#Person-container.active #Person tbody:after { display: none;} + +#Person, #Person th, #Person td { border: 0; } +#Person { + display: block; + max-width: -moz-fit-content; + max-width: fit-content; + min-height: 200px; + margin: 0; + overflow: -moz-scrollbars-vertical; + overflow: auto; + padding-top: 0 !important; + position: relative; + white-space: nowrap; + max-height: calc(100vh - 204px); + border-top: 1px solid black; + border-bottom: 1px solid black; +} +#Person thead { position: sticky; top: 0; z-index: 1; } +#Person thead th { background-color: white; border-bottom: 2px solid black !important;} +#Person th, #Person td { border-bottom: 1px solid black; padding: 8px; text-align: left; border-right: 1px solid lightgray;} +#Person th:last-child, #Person td:last-child { border-right: 0; } +#Person th:first-child, #Person td:first-child { padding-left: 18px; } +#Person th:last-child, #Person th:last-child { padding-right: 18px; } +#Person-list-buttons {display: flex;} +#Person-list-buttons button { min-height: 20px; border-bottom: 0; border-right: 0; padding: 0; min-width: 82px;} +#Person-list-buttons button:hover { border-left: 1px solid white;} +#Person-list-buttons button:nth-child(1) { border-radius: 5px 0 0 0;} +#Person-list-buttons button:nth-child(2) { border-radius: 0;} +#Person-list-buttons button:nth-child(3) { border-radius: 0 5px 0 0; border-right: 1px solid var(--button-normal-border);} +#Person .Person-tr { position: relative; } +#Person .Person-tr:not(.inactive):hover td { background: var(--color-lightblue); } +#Person .Person-tr.inactive { background-color: var(--color-blue) !important;} +#Person .Person-tr td.labels { font-size: 12px; padding: 2px 8px;} +#Person .Person-tr td.labels >div { display: inline-block; margin-right: 3px; } +#Person .Person-tr td.labels >div >div { border-right: 1px solid gray; padding-right: 2px; } +#Person .Person-tr td.labels >div:last-child >div { border-right: 0; } +#Person .Person-tr td.mpa { font-size: 12px; padding: 2px 8px;} +#Person .Person-tr td.mpa >div { display: inline-block; margin-right: 3px; } +#Person .Person-tr td.mpa >div >div { border-right: 1px solid gray; padding-right: 2px; } +#Person .Person-tr td.mpa >div:last-child >div { border-right: 0; } +#Person .td-overflow { max-width: 62px; position: relative; } +#Person .td-overflow >div { overflow: hidden; display: inline-block; max-width: 100%; } + +#Person tr:last-child td { padding-bottom: 8px; } +#Person tbody tr:hover { background-color: var(--color-lightblue); cursor: pointer; } +#Person tr:hover .td-overflow:hover >div { background: white; min-width: max-content; overflow-x: unset; padding-right: 4px; } + + +#Edit-person { + background-color: var(--color-transparent-white); + cursor: pointer; + display: none; + height: 100%; + left: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 10001; +} +#Edit-person.active { display: flex; } +#Edit-person-container { + background-color: white; + border: 1px solid var(--color-lightblue); + border-radius: 8px; + cursor: unset; + margin: auto; + max-height: calc(100vh - 100px); + overflow: auto; + position: relative; + z-index: 1; +} +#Edit-person-container > div { cursor: unset; } +#Edit-person-container input, #Edit-person-container select { width: 128px; height: 26px; box-sizing: border-box; } +#Edit-person-container select { padding: 3px 10px; } +#Edit-person-container input[type=number] { box-sizing: border-box; width: 72px; } +#Edit-person-container .button-add { min-height: 26px; } +#Edit-person-container .edit-box { border-bottom: 1px solid var(--color-lightblue); padding: 20px; position: relative;} +#Edit-person-container .edit-box .title { display: inline-block; font-weight: bold; margin-bottom: 4px; min-width: 130px; width: 100%;} +#Edit-person-container .edit-box .container { max-height: 150px; overflow: auto; } +#Edit-person-container .remove { position: absolute; right: 0; top: 0; z-index: 1;} +#Edit-person-container .remove button { + border-top: 0; + border-right: 0; + border-radius: 0 0 0 10px; + font-weight: bold; + letter-spacing: .03em; + padding: 0 10px; + margin: 0; + min-height: 26px; + opacity: .6; +} +#Edit-person-container .person-container { display: flex; gap: 16px; padding: 0;} +#Edit-person-container .person-container >.container { border-right: 1px solid var(--color-lightblue); display: flex; gap: 16px; max-width: unset; padding: 35px 20px 20px; position: relative;} +#Edit-person-container .person-container >.container > div { display: flex; flex-direction: column; } +#Edit-person-container .person-container >.container .title {min-width: unset;} +#Edit-person-container .person-container >.container .select-assign-to select { min-width: 150px; } +#Edit-person-container .person-container >.activation { display: flex; flex-direction: column; margin-left: auto; padding: 35px 0 20px 0} +#Edit-person-container .person-container >.activation .title { min-width: 127px; } +#Edit-person-container .person-container label { margin-bottom: 6px; } +#Edit-person-container .select-assign-container { position: absolute; right: 0; top: 0;} +#Edit-person-container .chevron-select { display: inline-block; min-height: 26px; } +#Edit-person-container .chevron-select select { min-height: 26px; padding: 4px 10px 0;} +#Edit-person-container .select-assign-to.chevron-select select { border-radius: 0 0 0 10px; border-top: 0; border-right: 0; } +#Edit-person-container .chevron-select:before { top: 0; } + +#Edit-person-shift-settings .container {display: flex;} +#Edit-person-shift-settings .edit-person-shift-settings-day {padding: 0 8px; border-left: 1px solid var(--color-lightblue); border-right: 1px solid var(--button-normal-border); margin-left: 1px; overflow: auto; } +#Edit-person-shift-settings .edit-person-shift-settings-day:first-child {padding-left: 0; border-left: 0; margin-left: 0; } +#Edit-person-shift-settings .edit-person-shift-settings-day:last-child {border-right: 0; } +#Edit-person-shift-settings .button-activate-container {background: white; position: sticky; top: 0; z-index: 111;} +#Edit-person-shift-settings .button-activate { width: 100%; min-height: 26px; margin-bottom: 8px;} +#Edit-person-shift-settings .button-free { width: 100%; min-height: 26px; justify-content: center; } +#Edit-person-shift-settings .container label {min-width: 100px;} +#Edit-person-shift-settings .container button {min-height: 26px; width: 100%} +#Edit-person-shift-settings .container input {background-color: white;} +#Edit-person-shift-settings .container .item {display: flex; align-items: center; margin-bottom: 6px; flex-direction: column; gap: 6px; justify-content: center; } +#Edit-person-shift-settings .container .item.active:not(.button-free) { background: var(--color-lightblue-background); border: 1px solid var(--button-normal-border); padding: 6px;} +#Edit-person-shift-settings .container .item-average input { width: 72px; } + +#Edit-person-container .freedays button { border-radius: 0; border-left: 0; line-height: 2px; margin-top: 4px; min-height: 26px; text-align: center; } +#Edit-person-container .freedays button:first-child { border-radius: 20px 0 0 20px; border-left: 1px solid var(--button-normal-border); } +#Edit-person-container .freedays button:last-child { border-radius: 0 20px 20px 0; } +#Edit-person-container .freedays button.active { background-color: var(--button-normal-active-background); } +#Edit-person-mpa .container { display: flex; gap: 16px; } +#Edit-person-mpa .item label { width: auto; margin-right: 6px; } +#Edit-person-container .edit-close { bottom: 0; border: 0; border-radius: 0 0 8px 8px; left: 0; position: sticky; text-align: center; width: 100%; z-index: 11;} + +#Edit-person-container .container-add {padding: 0 20px 8px 20px; margin-bottom: 8px; margin-left: -20px; background: white; z-index: 1; position: relative; width: calc(100% + 20px); transition: all ease .25s; } +#Edit-person-container .container-add.active { background: var(--color-lightblue-background); display: grid; grid-template-areas: "cancel cancel cancel" "start end save"; grid-template-columns: auto auto 1fr; gap: 8px; padding-bottom: 20px;} +#Edit-person-container .container-add:not(.active) >*:not(.button-add) {display: none;} +#Edit-person-container .container-add .button-add {grid-area: save;} +#Edit-person-container .container-add.active .button-add {max-width: max-content;} +#Edit-person-container .container-add:not(.active) .button-add {border-radius: 0; border-left: 0; margin-left: -20px; padding-left: 20px; width: 111px;} +#Edit-person-container .container-add .button-cancel {grid-area: cancel; grid-area: cancel; width: 111px; margin-left: -20px; border-radius: 0; padding: 4px 10px 4px 20px; min-height: 26px; } +#Edit-person-container .container-add input {background: white;} +#Edit-person-container .container-add .start {grid-area: start} +#Edit-person-container .container-add .end {grid-area: end} +#Edit-person-betterments .container-add.active {grid-template-areas: "cancel cancel cancel cancel" "start end hours save"; grid-template-columns: auto auto auto 1fr;} +#Edit-person-betterments .container-add.active .hours {grid-area: hours;} +#Edit-person-betterments .container-data .item >*:nth-child(2) { width: auto; display: flex; justify-content: center; align-items: center; } +#Edit-person-betterments .container-data .item >*:nth-child(3) { width: 68px; margin: 5px; } + +.edit-person-table-container > .container { margin-top: 16px; } +.edit-person-table-container .container-data { display: flex; border-top: 1px solid var(--color-black); } +.edit-person-table-container .container-data .year { border-right: 1px solid var(--color-black); padding: 8px 8px 8px 0; } +.edit-person-table-container .container-data .item { display: flex; } +.edit-person-table-container .container-data .item button { min-height: unset; padding: 0 8px; font-size: 13px; line-height: 15px; height: auto; min-width: unset; } +.edit-person-table-container .container-data .item >*:nth-child(2) { width: 68px; margin: 5px; } +.edit-person-table-container .container-data .date { padding: 8px 16px 8px 8px; } +.edit-person-table-container .container-data .description { padding: 8px 16px 8px 8px; } + +#Edit-person-overtime .container-add { display: inline-block;} +#Edit-person-overtime .container-add select { min-height: 26px; padding: 4px 10px 0; width: 100px;} +#Edit-person-overtime .container-add > input {max-width: 82px;} +#Edit-person-overtime table {border: 0;} +#Edit-person-overtime table th, #Edit-person-overtime table td {padding: 4px 8px;} +#Edit-person-overtime table th:first-child, #Edit-person-overtime table td:first-child {border-left: 0;} +#Edit-person-overtime table th:last-child, #Edit-person-overtime table td:last-child {border-right: 0;} +#Edit-person-overtime table tbody tr:last-child td {border-bottom: 0;} + + +#Roster-days-container { scroll-snap-type: y mandatory; position: relative;} +#Roster-days-container .Roster-container { display: inline-block; max-width: 100%; max-height: 100%; position: relative; scroll-snap-align: start; overflow: auto; min-width: 100%; min-height: 50%} +#Roster-days-container .Roster-container > h2{ background-color: var(--color-normal-background); position: sticky; left: 0; margin: 0; padding: 0.83em 0; z-index: 101; } +#Roster-days-container .Roster-container-head { + background: var(--color-normal-background); + display: flex; + gap: 8px; + justify-content: space-between; + left: 0; + overflow-x: auto; + overflow-y: hidden; + position: sticky; + top: 0; + z-index: 1001; +} +#Roster-days-container .Roster-container .container-copy-from-to { display: flex; } +#Roster-days-container .Roster-container .select-copy-from { border-radius: 8px 0 0 0; padding: 6px 10px 2px; } +#Roster-days-container .Roster-container .select-copy-to { border-radius: 0 8px 0 0; padding: 6px 10px 2px; border-left: 0; } +#Roster-days-container .Roster-container .time-scroll-container { display: flex; } +#Roster-days-container .Roster-container .time-scroll-container button { + border-bottom: 0; + border-radius: 0; + border-right: 0; + min-width: auto; + padding: 4px 6px; + text-align: center; + width: 37px; +} +#Roster-days-container .Roster-container .time-scroll-container button:first-child { border-radius: 8px 0 0 0; } +#Roster-days-container .Roster-container .time-scroll-container button:last-child { border-radius: 0 8px 0 0; border-right: 1px solid var(--button-normal-border); } +#Roster-days-container .Roster-container .button-remove-day-shifts { border: 0; border-radius: 8px 8px 0 0; padding-top: 7px; position: sticky; right: 0; text-align: center; transform: translateY(1px); } + + + +.table-times { border-left: 0; position: relative; overflow: auto !important; } +#Roster-days-container .tables-container { display: flex; min-width: max-content; margin-bottom: 40px; position: relative; } + +#Roster-days-container .button-edit-table { + all: unset; + display: flex; + align-items: flex-start; + justify-content: flex-start; + background-color: var(--color-transparent-lightblue); + box-sizing: border-box; + color: var(--color-lightblack); + cursor: pointer; + font-size: 30px; + font-weight: bold; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + z-index: 1000; +} +#Roster-days-container .button-edit-table > div { position: sticky; left: 50%; width: max-content; top: calc(50% + 50px); transform: translate(-50%, -50%); } +#Roster-days-container .Roster-container .line-cursor > div { color: var(--color-black); display: inline-block; font-size: 14px; white-space: pre;} +#Roster-days-container .Roster-container .line-v { + display: none; + background: linear-gradient(rgba(255,255,255,1) 50%, rgba(0,0,0,0) 50%, rgba(0,0,0,0) 0), #75a5b5; + background-size: auto 2px; + bottom: 40px; + position: absolute; + top: 0; + height: 0; + width: 0; + z-index: 10000; +} +#Roster-days-container .Roster-container .line-h { + display: none; + background: linear-gradient(90deg, rgba(255,255,255,1) 50%, rgba(0,0,0,0) 50%, rgba(0,0,0,0) 0), #75a5b5; + background-size: 2px auto; + height: 0; + width: 0; + left: 0; + position: absolute; + right: 0; + z-index: 10000; +} + +#Roster-days-container table { border-collapse: collapse; z-index: 1; overflow: hidden; } +#Roster-days-container table thead tr:first-child { background: var(--color-normal-background); position: sticky; top: 10px; z-index: 11;} +#Roster-days-container table th { padding: 0 8px; height: 68px; } +#Roster-days-container table th:first-child { padding: 0; position: sticky; min-width: 200px; box-sizing: border-box; left: 0; z-index: 1001; line-height: 30px; font-size: 16px; vertical-align: bottom; border-left: 0;} +#Roster-days-container table th:first-child >div { background-color: var(--color-normal-background); box-sizing: border-box; padding-left: 28px; left: 0; z-index: 1001; line-height: 30px; font-size: 16px; vertical-align: bottom; height: 100%; width: 100%; display: flex; justify-content: center; align-items: flex-end; max-width: calc(100% - 28px); border-left: 1px solid black;} +#Roster-days-container table th:last-child { vertical-align: bottom; background-color: var(--color-normal-background);} +#Roster-days-container tr.active {position: relative; z-index: 100;} +#Roster-days-container tr.hover td:not(.td-name) { border: 1px solid var(--color-outline-hover) !important; border-left: 0 !important;} +#Roster-days-container tr.hover td.td-name { border-color: var(--color-outline-hover) !important; box-shadow: inset 0 0 4px var(--color-outline-hover);} +#Roster-days-container tr.hover +tr td { border-top-color: var(--color-outline-hover) !important; } +#Roster-days-container tr.hover .td-top-bottom { border-color: var(--color-outline-hover) !important; position: relative;} +#Roster-days-container tr th .th-amount-container.active { color: var(--color-lightblue); } +#Roster-days-container tr th .th-amount-container { cursor: pointer; display: flex; } +#Roster-days-container tr th .th-amount-buttons { + display: flex; + flex-direction: column; + justify-content: center; + margin-left: 4px; + opacity: .7; + padding: 3px 0; +} +#Roster-days-container tr th .th-amount-buttons button { + all: unset; + cursor: pointer; + line-height: 0.5; + padding: 4px; +} +#Roster-days-container tr th .th-amount-buttons button:hover { color: gray; } +#Roster-days-container tr th .th-amount-buttons button:before { font-size: 21px; } +#Roster-days-container tr th .th-amount-buttons button.chevron-up { padding-bottom: 0; } +#Roster-days-container tr th .th-amount-buttons button.chevron-down { padding-top: 0; } + + +#Roster-days-container td, #Roster-days-container th { position: relative; min-width: 68px; } +#Roster-days-container td {border: 1px solid var(--color-black); border-bottom: 0;} + +#Roster-days-container tr td { height: 48px !important; max-height: 48px !important; padding: 0; vertical-align: bottom; } +#Roster-days-container tr.disabled td:not(td:first-child) { border-style: dotted; opacity: .5; } +#Roster-days-container tr.disabled +tr td:not(td:first-child) { border-top-style: dotted; } +#Roster-days-container tr td:nth-child(2) {border-left: 0;} +#Roster-days-container tr td .td-name-hours-container { display: grid; grid-template-areas: "name top" "name bottom"; grid-template-columns: 1fr auto;} +#Roster-days-container tr td .td-name-container { display: grid; gap: 0 4px; grid-template-areas: "name overtime" "hours hours"; grid-template-columns: 1fr auto; height: 100%; } +#Roster-days-container tr td.td-sticky { position: -webkit-sticky; position: sticky; left: 0; z-index: 10;} +#Roster-days-container tr td.td-name { padding: 0; vertical-align: top; border-bottom: 0; border-left: 0; border-right: 0;} +#Roster-days-container tr td.td-name.active { background-color: var(--button-normal-active-background) !important; z-index: 100; } +#Roster-days-container tr td.td-name .name { padding: 4px 0 0 6px; white-space: nowrap; } + + + +#Roster-days-container tr td.td-name-hours-container { border-left: 1px solid var(--color-black);} +#Roster-days-container tr td.td-name-hours .td-top-bottom { border-left: 1px solid var(--color-black); } +#Roster-days-container tr td.td-name-hours .td-top { display: flex; grid-area: top; } +#Roster-days-container tr td.td-name-hours .td-bottom { display: flex; justify-content: space-between; } +#Roster-days-container tr td.td-name-hours .button-menu { grid-area: menu; margin: 0 0 0 auto; border-left: 1px solid var(--color-gray); border-bottom: 1px solid var(--color-gray); border-right: 1px solid black; border-radius: 0 0 0 8px; width: 26px; box-sizing: border-box; } +#Roster-days-container tr td.td-name-hours .button-menu[disabled="true"] { cursor: unset; opacity: 0; } +#Roster-days-container tr td.td-name-hours div.button-menu { opacity: 0;} +#Roster-days-container tr td.td-name-hours .menu { + background-color: white; + border: 1px solid var(--color-black); + display: none; + min-height: 36px; + min-width: 120px; + position: absolute; + right: 27px; + top: 0; + transform: translateX(100%); + white-space: nowrap; + z-index: 1; +} +#Roster-days-container tr td.td-name-hours .menu.active { display: inline-block; } +#Roster-days-container tr td.td-name-hours .menu > div { display: flex; flex-direction: column; } +#Roster-days-container tr td.td-name-hours .menu p { padding: 0 8px; } +#Roster-days-container tr td.td-name-hours .menu button.button-remove { border-radius: 0; border: 0; text-align: left; padding: 8px;} +#Roster-days-container tr td.td-name-hours .menu button:not(.button-remove) { all: unset; background: var(--color-orange); border-top: 1px solid var(--color-black); cursor: pointer; padding: 8px; } +#Roster-days-container tr td.td-name-hours .menu button:not(.button-remove):hover { background-color: var(--color-orange-hover); } +#Roster-days-container tr td.td-name-hours .menu button.prev-next {background: var(--color-darkorange)} +#Roster-days-container tr td.td-name-hours .menu button.prev-next:hover {background: var(--color-darkorange-hover)} +#Roster-days-container tr td.td-name-hours .menu .menu-extras .free:first-child { border-top: 3px solid var(--color-black); } +#Roster-days-container tr td.td-name-hours .menu >div *.free { background-color: var(--color-lightblue); border-top: 1px solid var(--color-black);} +#Roster-days-container tr td.td-name-hours .menu >div *.free:hover { background-color: var(--color-blue); } +#Roster-days-container tr td.td-name-hours .menu .menu-extras { display: flex; flex-direction: column;} +#Roster-days-container tr td.td-name-hours .menu .menu-extras >div { align-items: center; display: flex; justify-content: space-between; padding-left: 8px; } +#Roster-days-container tr td.td-name-hours .menu .menu-extras input { background: white; box-sizing: border-box; width: 72px; } + + +#Roster-days-container tr td.td-name-after { text-align: center; vertical-align: middle; padding: 0 4px;} +#Roster-days-container tr td.td-name .td-overtime { align-items: center; display: flex; font-size: 12px; grid-area: overtime; justify-content: center; margin-right: 6px; opacity: .7;} +#Roster-days-container tr td.td-name .td-overtime.red { color: var(--color-text-red); } +#Roster-days-container tr td.td-name .td-overtime.orange { color: var(--color-text-orange); } +#Roster-days-container tr td.td-name .td-overtime.green { color: var(--color-text-green); } +#Roster-days-container tr td.td-name-hours .td-info { grid-area: info; margin: 0 6px 0 0; position: relative; z-index: 1;} +#Roster-days-container tr td.td-name-hours .td-info button { border-color: var(--color-gray); border-radius: 0 0 28px 28px; border-top: 0; grid-area: info; } +#Roster-days-container tr td.td-name-hours .td-info button.set { background: var(--color-yellow); color: var(--color-blue); } +#Roster-days-container tr td.td-name-hours .td-info textarea { position: absolute; left: 0; top: 0; } + +#Roster-days-container td .hours-container { align-items: flex-end; display: flex; font-size: 14px; gap: 4px; grid-area: hours; justify-content: space-between; width: 100%; } +#Roster-days-container tr .hours-amount { padding: 4px 0 4px 6px; } +#Roster-days-container tr .hours-mpa { margin-left: auto; opacity: 0.7; padding: 2px 0 0; } +#Roster-days-container tr .hours-mpa >div { padding: 0 6px; width: 28px; } +#Roster-days-container tr .hours-mpa >div.title { font-size: 10px; } +#Roster-days-container tr .hours-given { opacity: .8; } +#Roster-days-container tr .hours-today { align-items: flex-end; display: flex; justify-content: flex-end; padding: 4px 6px 4px 0; } +#Roster-days-container tr .break-today { align-items: flex-end; display: flex; padding: 4px 6px; } +#Roster-days-container .td-day-time { + overflow: hidden; +} +#Roster-days-container .td-day-time .container { + display: grid; + grid-template-rows: 11px 1fr auto; + grid-template-areas: + "header" + "add" + "mod"; + height: 100%; + width: 100%; +} +#Roster-days-container .td-day-time.free .container { display: flex; justify-content: center; align-items: center; } +#Roster-days-container .assigned .container { background-color: green; } +#Roster-days-container .td-day-time .container > p{ margin: 4px auto; max-width: 68px; } + + + +#Roster-days-container .shift-split { + all: unset; + background-color: var(--color-lightred); + border-left: 1px solid var(--color-black); + cursor: pointer; + display: flex; + grid-area: header; + margin-left: auto; + opacity: .4; + width: 25px; +} +#Roster-days-container .shift-split:hover { background-color: var(--color-red); opacity: .8; } +#Roster-days-container .shift-split:after { font-size: 12px; line-height: 10px; } + +#Roster-days-container .shiftmodify-buttons-container { + display: flex; + grid-area: add; + height: 100%; + min-height: 50%; + width: 100%; +} +#Roster-days-container .shiftmodify-buttons-container button { + border-color: var(--color-lightgray); + border-radius: 0; + color: var(--color-lightgray); + height: 100%; + min-width: unset; + padding: 0 8px; +} +#Roster-days-container .roster-add-extra-shift { + all: unset; + color: gray; + cursor: pointer; + grid-area: header; + font-size: 11px; + line-height: 10px; + text-align: center; + background: var(--color-whiteblue); +} +#Roster-days-container .roster-add-extra-shift:hover { color: var(--color-black); background-color: var(--color-lightblue)} +#Roster-days-container .shiftmodify-buttons-container .roster-add-shift { + background-color: var(--color-whitegray); + border-bottom: 0; + border-left: 0; + border-right: 0; + border-radius: 0; + color: gray; + cursor: pointer; + height: 100%; + opacity: .8; + order: 2; + padding: 0; + position: relative; + margin: 0; + min-height: unset; + min-width: unset; + width: 100%; +} +#Roster-days-container .shiftmodify-buttons-container .roster-add-shift:hover { background-color: var(--button-normal-hover-background); opacity: 1; } +#Roster-days-container .shiftmodify-buttons-container .button-extend-shorten { + all: unset; + align-items: center; + background: var(--color-whitegray); + border-top: 1px solid gray; + box-sizing: border-box; + cursor: pointer; + display: flex; + height: 100%; + justify-content: center; + padding: 0 3px; + width: 50%; +} +#Roster-days-container .shiftmodify-buttons-container .button-extend-shorten:hover { background: var(--color-whiteblue); } +#Roster-days-container .shiftmodify-buttons-container .button-extend-shorten:before { + line-height: 0.5; +} + +#Roster-days-container .roster-extend-shift { margin-left: auto; background-color: var(--color-whitegray); border-bottom: 0; } +#Roster-days-container .roster-extend-shift:before { color: var(--color-gray); } +#Roster-days-container .roster-extend-shift:hover { background-color: var(--button-normal-hover-background); border-color: gray; color: gray; } +#Roster-days-container .roster-extend-shift.chevron-left { margin-left: auto; border-right: 0; order: 3;} +#Roster-days-container .roster-extend-shift.chevron-right { margin-right: auto; border-left: 0; order: 1;} + +#Roster-days-container .shiftmodify-buttons-container-inner { display: flex; grid-area: mod; } +#Roster-days-container .shiftmodify-buttons-container-inner button { + background-color: #bfd9bf; + border: 0; + border-top: 1px solid #80808075; + border-radius: 0; + color: #80808094; + min-height: unset; + min-width: unset; + padding-bottom: 0; + padding-top: 0; + width: 50%; +} +#Roster-days-container .shiftmodify-buttons-container-inner button:before { font-size: 23px; line-height: 16px; padding-bottom: 2px; } +#Roster-days-container .shiftmodify-buttons-container-inner button:hover { background-color: var(--button-normal-hover-background); border-color: gray; color: gray; } +#Roster-days-container .shiftmodify-buttons-container-inner .chevron-right { padding-right: 0; } +#Roster-days-container .shiftmodify-buttons-container-inner .chevron-left { padding-left: 0; } +#Roster-days-container .shiftmodify-buttons-container-inner .chevron-right:before { float: left; } +#Roster-days-container .shiftmodify-buttons-container-inner .chevron-left:before { float: right; } + + +#Roster-days-container .th-day-time { padding: 0; vertical-align: bottom; } +#Roster-days-container .th-day-time .time { font-size: 16px; margin-bottom: 4px; margin-top: 8px; transform: translateX(-50%);} +#Roster-days-container .th-day-time .time-amount { border-bottom: 1px solid var(--color-lightblue); display: flex; font-size: 12px; justify-content: center; line-height: 19px; opacity: .5;} +#Roster-days-container .th-day-time .time-amount:hover { opacity: .8; } +#Roster-days-container .th-day-time .time-amount p { margin: auto 0;} + + +#Roster-container-week { max-height: calc(100vh - 40px); overflow: auto;} + + +#Roster-week-view-settings-toggle-button {max-width: max-content; border-radius: 0; padding-left: 32px; padding-right: 18px; margin-bottom: -1px; } +#Roster-week-view-settings { display: flex; flex-direction: column; padding-top: 42px; position: relative; border-top: 4px double var(--button-normal-border); transition: all ease .25s; margin-left: -32px; } +#Roster-week-view-settings:not(.active) { max-height: 32px; overflow: hidden; } +#Roster-week-view-settings .settings { background: var(--color-lightblue-background); border: 1px solid var(--button-normal-border); display: flex; gap: 16px; flex-direction: column; max-width: max-content; padding: 16px 16px 16px 32px;; opacity: 1;} +#Roster-week-view-settings:not(.active) .settings { opacity: 0; } +#Roster-week-view-settings .settings .row { display: flex; gap: 16px; align-items: flex-end; } +#Roster-week-view-settings .settings .row > div { min-width: 228px; } +#Roster-week-view-settings label { display: block; margin-bottom: 4px; } +#Roster-week-view-settings button { text-align: center; } +#Roster-week-print-mode { display: flex; flex-direction: column;} +#Roster-week-print-zoom { display: flex; flex-direction: column;} +#Roster-week-print-zoom input {box-sizing: border-box; background-color: white; height: 10px; width: 100px;} +#Roster-week-print-zoom >div { display: flex; gap: 6px; align-items: center; } +#Roster-week-print-zoom button { all: unset; color: var(--color-lightblue); cursor: pointer; font-size: 18px; font-weight: bold; line-height: 32px;} +#Roster-week-print-zoom button:first-child { font-size: 28px; } +#Roster-week-print-zoom button:hover { color: #4d879b; } + +#Roster-week-display-overtime { width: 273px; } +#Roster-week-add-editable-row { display: flex; flex-direction: column; gap: 6px; margin-top: 8px;} +#Roster-week-add-editable-row button { width: 273px; } +#Roster-week-container { margin-bottom: 40px; } +#Roster-week-container h2 { display: inline-block; } +#Roster-week-container > button { margin: 0 20px; display: inline-block; transform: translateY(-4px); } +#Roster-week-container th, #Roster-week-container td { padding: 0 6px;} +#Roster-week-container th p {margin: 8px 0; } +#Roster-week-container td { vertical-align: top; height: 0; } +#Roster-week-container .tr-editable td, +#Roster-week-container .tr-editable th { padding: 8px 6px; font-weight: normal; text-align: left; vertical-align: top; } +#Roster-week-container .td-name { display: grid; grid-template-areas: "name overtime" "hours breaks"; ; gap: 8px; margin-bottom: 6px; margin-top: 6px; } +#Roster-week-container .td-name p:first-child { grid-area: name; } +#Roster-week-container .td-name p:nth-child(2) { font-size: 10px; grid-area: overtime; text-align: right;} +#Roster-week-container .td-name p:nth-child(3) { font-size: 14px; grid-area: hours; } +#Roster-week-container .td-name p:nth-child(4) { font-size: 14px; grid-area: breaks; text-align: right; } +#Roster-week-container .td-name p { margin: 0; } +#Roster-week-container .Roster-week-td.free { vertical-align: middle;} +#Roster-week-container .Roster-week-td.free p { margin: auto; font-size: 19px; } +#Roster-week-container .Roster-week-td.free p.time { max-width: 100px; overflow: hidden; } +.Roster-week-td .container { display: grid; font-family: Arial, Helvetica, monospace; min-width: max-content; grid-template-areas: "time time time" "break mpa duration"; grid-template-columns: 1fr auto 1fr; white-space: pre; } +.Roster-week-td .time { margin-top: 6px; min-height: 19px; grid-area: time; text-align: center; } +.Roster-week-td .time >div { display: flex; } +.Roster-week-td .time p { margin-bottom: 3px; margin-top: 0; } +.Roster-week-editable .Roster-week-td div.time:hover {background-color: var(--button-normal-hover-background)} +.Roster-week-editable .Roster-week-td .mpa { min-width: 14px; box-sizing: border-box;} +.Roster-week-editable .Roster-week-td:hover .mpa { min-width: 14px; border: 1px dotted lightgray; border-bottom: 0; background-color: var(--button-normal-hover-background);} +.Roster-week-editable .Roster-week-td:hover .mpa:hover {background-color: var(--color-orange)} +.Roster-week-editable .Roster-week-td input:hover {background-color: var(--color-orange)} +.Roster-week-td .mpa input, +.Roster-week-td .time input {all: unset; -webkit-appearance: none; font-family: Arial, Helvetica, monospace; } +.Roster-week-td .mpa input { max-width: 53px; margin-right: -12px; } +.Roster-week-td .time input { font-size: 14px;} +.Roster-week-td .mpa input[type="time"]::-webkit-calendar-picker-indicatorA, +.Roster-week-td .time input[type="time"]::-webkit-calendar-picker-indicator { display: none; } +.Roster-week-td .duration { grid-area: duration; margin: 6px 0; text-align: right; justify-content: flex-end;} +.Roster-week-td .label { grid-area: label; text-align: center; font-size: 19px; margin: auto; display: flex; padding: 0 4px 0 2px;} +.Roster-week-td .mpa { grid-area: mpa; margin: 0 0 2px 0; text-align: center; font-size: 11px; padding: 0 2px 0 4px;} +.Roster-week-td .break { grid-area: break; margin: 6px 0; text-align: left; } +.Roster-week-td .info { max-width: fit-content; font-size: 11px; white-space: break-spaces; } +.Roster-week-td .info >div { margin: 0 4px 4px;} +.Roster-week-td .break, .Roster-week-td .duration { display: flex; align-items: flex-end; } +#Roster-week-table { background: white; } +#Roster-week-table .td-editable-cell {border-left: 4px double var(--color-black); font-weight: normal; padding-top: 6px; padding-bottom: 6px; text-align: left; min-width: 60px; vertical-align: top;} + +#Roster-week-info { max-width: fit-content; } +#Roster-week-info > div { white-space: break-spaces; margin-top: 40px; } + +#Popup.request-remove #Popup-container button { border-bottom: 0; border-left: 0; border-radius: 0; text-align: center; width: 50%; } +#Popup.request-remove #Popup-container button:nth-last-child(1) { border-right: 0; } + +#Popup.help #Popup-container { padding: 20px; } +#Popup.help .container > button { width: 100%; border: 1px solid var(--button-normal-border); border-radius: 0;} +#Popup.help .container > p { display: none; cursor: unset; } +#Popup.help .container.active > p { display: inline-block; } + +#Closingtimes .container-add { margin-bottom: 20px; margin-left: -18px;} +#Closingtimes .container-add.active { background: var(--color-lightblue-background); padding: 0 8px 8px 18px; } +#Closingtimes .container-add >button { border-radius: 0; border-left: 0; padding-left: 18px;} +#Closingtimes .container-add.active >button { margin-left: -18px; margin-bottom: 8px; padding-left: 18px;} +#Closingtimes .container-add.active input {background: white; } +#Closingtimes #Set-closing-time { width: 100%; align-items: center; display: flex; } +#Closingtimes #Set-closing-time >* { margin-right: 6px;; } +#Closingtimes table {background: white; border-left: 0 !important; border-right: 0 !important;} +#Closingtimes table th:first-child, +#Closingtimes table td:first-child {border-left: 0 !important;} +#Closingtimes table td:last-child, +#Closingtimes table th:last-child {border-right: 0 !important;} +#Closingtimes table, #Closingtimes table th, #Closingtimes table td { border-color: black; border-right-color: lightgray; border-left-color: lightgray; text-align: left; } +#Closingtimes table th, #Closingtimes table td { padding: 0 6px;} +#Closingtimes table th { padding: 4px 6px;} +#Closingtimes table td:first-child:not(.year) { border: 0;} +#Closingtimes table td.year { border-bottom: 0;} +#Closingtimes .td-person { text-align: center; } +#Closingtimes .td-person .person button {min-width: auto; margin-bottom: 4px;} +#Closingtimes .td-person .person .container button {margin-right: 2px; } + +#Popup.reactivate-person #Popup-container {display: flex; justify-content: center; flex-direction: column; align-items: center; gap: 8px; padding: 20px; min-width: 248px;} + +#Vacations-overview table {border-left: 0; border-right: 0;} +#Vacations-overview table thead tr { position: sticky; top: 0; z-index: 1111; } +#Vacations-overview th {background-color: white; padding: 8px; min-width: 84px; border-right: 1px solid lightgray; border-left: 0;} +#Vacations-overview th:last-child {border-right: 0;} +#Vacations-overview td {position: relative; padding-top: 13px; border-right: 1px solid lightgray; border-left: 0;} +#Vacations-overview td:last-child {border-right: 0;} +#Vacations-overview .td-name {padding: 4px 8px; height: 39px; box-sizing: border-box; } +#Vacations-overview .view .td-name {height: auto; } +#Vacations-overview .table-container {overflow: auto; max-height: calc(100vh - 170px); padding-top: 20px;} +#Vacations-overview .table-container button {border-radius: 0; z-index: 2; padding: 0; min-height: 24px; min-width: 100%; background-color: #61a64d;} +#Vacations-overview .table-container button:hover { background-color: #9ed18f; } +#Vacations-overview .table-container button.isClosing:hover { background-color: #fdd3a7; } +#Vacations-overview .table-container .button-spacer { height: 24px;} +#Vacations-overview .table-container .button-new {background-color: var(--button-normal-border); opacity: .4; width: 100%; min-height: 13px; font-size: 10px; font-weight: bold; position: absolute; left: 0; top: 0; z-index: 1;} +#Vacations-overview .table-container .button-new:hover {opacity: .8;} +#Vacations-overview .table-container table tr:hover {background-color: var(--color-whiteblue);} +#Vacations-overview .table-container table tr.active { z-index: 1111; position: relative;} +#Vacations-overview .table-container table tr > *:first-child {background-color: white; position: sticky; left: 0; z-index: 1111} +#Vacations-overview .table-container table tr:hover > *:first-child {background-color: var(--color-whiteblue);} +#Vacations-overview .table-container .tr-x td {border-bottom: 4px double var(--color-black); height: auto;} +#Vacations-overview .table-container .tr-x td:not(.td-name) { padding-top: 0; } +#Vacations-overview .table-container .tr-x td > button {background-color: #ffaa4f; top: 0 !important;} +#Vacations-overview .table-container td > div.isclosing {background-color: #ffaa4f;} +#Vacations-overview .table-container.view td > button, +#Vacations-overview .table-container.view td > div { min-height: 100%; border: 0; border-left: 1px solid white; border-right: 1px solid white; overflow: hidden; font-size: 12px; white-space: nowrap;} +#Vacations-overview .table-container.view td > div { z-index: 200; } +#Vacations-overview .table-container.view td > div button { padding: 4px; } +#Vacations-overview .table-container.view td > div.isclosing button { background-color: #ffaa4f; } +#Vacations-overview .table-container.view td > button.button-new:hover { background-color: var(--button-normal-hover-background); opacity: .8; } +#Vacations-overview .table-container.view td > div:not(.button-new):hover { overflow: visible; width: auto !important; z-index: 300;} +#Vacations-overview .table-container.view td > div:not(.button-new):not(.vacations-overview-popup-edit):hover > button { background-color: #9ed18f; border: 1px solid white; } +#Vacations-overview .table-container.view td > div.isclosing:hover button { background-color: #fdd3a7 !important;} +#Vacations-overview .table-container.view .button-new { opacity: 0.2;} +#Vacations-overview .vacations-overview-popup-edit .button-x { position: absolute; top: 0; right: 0; left: unset; transform: unset; min-width: 20px; min-height: 20px; background: var(--button-normal-border); border-radius: 0 0 0 10px; } +#Vacations-overview .vacations-overview-popup-edit .button-x:hover { opacity: 1;} + +#Vacations-overview .table-container .vacations-overview-popup-edit { display: grid; grid-template-areas: "con con" "rem sav";} +#Vacations-overview .table-container .vacations-overview-popup-edit > button:not(.button-x) { margin: 0; min-width: 50%; } +#Vacations-overview .table-container .vacations-overview-popup-edit .button-remove {background: #f58186; } +#Vacations-overview .table-container .vacations-overview-popup-edit .button-remove:hover {background: #FF0D0D; } +.vacations-overview-popup-edit { position: absolute; background: white; z-index: 100; border: 2px solid var(--button-normal-border); } +#Vacations-overview .table-container .vacations-overview-popup-edit.add { grid-template-areas: "con con" "sav sav";} +#Vacations-overview .table-container .vacations-overview-popup-edit.add .button-save {grid-area: sav;} +.vacations-overview-popup-edit .container { padding: 8px; } +.vacations-overview-popup-edit h4 { margin: 0 0 8px; } + + +#Roster-copy-person-from { margin: 20px 0 40px; grid-area: week-copy;} +#Roster-auto-add-shifts {grid-area: auto-add} + +#Popup.roster-copy-person #Popup-container { padding: 20px; } +#Popup.roster-copy-person .box { display: flex; gap: 16px; } +#Popup.roster-copy-person .box .item { display: flex; flex-direction: column; } +#Popup.roster-copy-person .box .item button:not(.button-save) { border-radius: 0; } + +#Popup.roster-copy-person-table { padding: 0; } +#Popup.roster-copy-person-table #Popup-container { border-radius: 0; box-sizing: border-box; padding: 20px 20px 40px; min-width: unset; max-width: 100%; height: 100%; min-height: 100%; margin: 0; max-height: 100%; width: 100% !important;} +#Popup.roster-copy-person-table .box { display: flex; position: relative; } +#Popup.roster-copy-person-table .box .item-table { max-width: calc(50% - 16px); } +#Popup.roster-copy-person-table .box .item-table > .container { overflow: auto; position: relative; z-index: 2; max-height: calc(100vh - 176px); } +#Popup.roster-copy-person-table .box .item-table-to { max-width: calc(50% + 16px); position: relative; z-index: 2;} +#Popup.roster-copy-person-table .box .item-header { display: flex; position: sticky; left: 0; z-index: 3; margin-bottom: -1px; border-bottom: 1px solid var(--color-black);} +#Popup.roster-copy-person-table .box .item-table-to .item-header { justify-content: flex-end; max-width: calc(100% - 101px); margin-left: auto;} +#Popup.roster-copy-person-table .box .item-header .edit-shift { border-radius: 0; border-right: 0; border-bottom: 0;} +#Popup.roster-copy-person-table .box .item-header .change-date {line-height: 20px;} +#Popup.roster-copy-person-table .box .item-header .change-date button { min-width: unset; border-radius: 0; } +#Popup.roster-copy-person-table .box .item-header .change-date button:first-child { border-right: 0; } +#Popup.roster-copy-person-table .box .select-roster-label { background: #d3f0f9; border: 1px solid var(--color-black); border-bottom: 0; border-radius: 8px 0 0 0; display: flex; flex-direction: column; max-width: 110px; position: sticky; left: 0; } +#Popup.roster-copy-person-table .box .select-roster-label { height: 32px; } +#Popup.roster-copy-person-table .box .item-table-to > .container { margin-left: 32px; } +#Popup.roster-copy-person-table .box .item-table-to .select-roster-label { background: #fff2c5; border-radius: 0 8px 0 0; max-width: 110px; position: relative; left: unset; width: 100% !important; } +#Popup.roster-copy-person-table .box .select-roster { border-radius: 0; background: transparent; border: 0; padding: 0 18px; line-height: 32px;} +#Popup.roster-copy-person-table .box table { z-index: 1; position: relative; background: white; margin-bottom: 20px; } +#Popup.roster-copy-person-table .box table * { padding: 0 !important; margin: 0px !important;} +#Popup.roster-copy-person-table .box table thead { position: sticky; top: 0; z-index: 11;} +#Popup.roster-copy-person-table .box table th { padding: 4px 2px !important; background: white; z-index: 1;} +#Popup.roster-copy-person-table .box table th.inactive { background: #d5e3ca !important;} +#Popup.roster-copy-person-table .box table td.inactive { background: #f0ffeb !important;} +#Popup.roster-copy-person-table .box table th.hover, +#Popup.roster-copy-person-table .box table th:hover, +#Popup.roster-copy-person-table .box table td.hover, +#Popup.roster-copy-person-table .box table tr:hover .td-name, +#Popup.roster-copy-person-table .box table td:hover { outline: 1px solid lightcoral;} +#Popup.roster-copy-person-table .box table tr:hover .Roster-week-td-name {z-index: 111;} +#Popup.roster-copy-person-table .box table td >.container {padding: 4px !important; min-height: inherit; } +#Popup.roster-copy-person-table .box table td.free p{ display: flex; justify-content: center; align-items: center;} +#Popup.roster-copy-person-table .box table p { font-size: 12px; } +#Popup.roster-copy-person-table .box table .td-name p:first-child {} +#Popup.roster-copy-person-table .box table .td-name p.overtime {font-size: 10px; } +#Popup.roster-copy-person-table .box table .td-name p.hours { font-size: 10px; } +#Popup.roster-copy-person-table .box table tr .Roster-week-td-name {position: sticky; left: 0; background: white; z-index: 10; padding: 0 !important; } +#Popup.roster-copy-person-table .box table tr .Roster-week-td-name .td-name { padding: 4px 4px !important; box-sizing: border-box; } +#Popup.roster-copy-person-table .box table tbody tr:last-child .Roster-week-td-name .td-name {border-bottom: 0;} + + +#Popup.roster-copy-person-table .box table tr:nth-child(2n) td { background: #f1f0f0;} +#Popup.roster-copy-person-table .box table td:not(.Roster-week-td-name){ min-width: 99px; min-height: 42px; box-sizing: border-box; } +#Popup.roster-copy-person-table .box table .breaks, +#Popup.roster-copy-person-table .box table .mpa >div:first-child, +#Popup.roster-copy-person-table .box table .td-editable-cell, +#Popup.roster-copy-person-table .box table .td-editable-row, +#Popup.roster-copy-person-table .box table .td-editable-row, +#Popup.roster-copy-person-table .box table .tr-editable, +#Popup.roster-copy-person-table .box table .tr-empty:nth-last-child(2), +#Popup.roster-copy-person-table .box table .info { display: none; } +#Popup.roster-copy-person-table .box table .Roster-week-td { box-sizing: content-box; min-width: 80px; } + +#Popup.roster-copy-person-table .box .Roster-week-table-copy-person-container { position: relative; max-width: calc(50% - 16px); overflow: auto; } +#Popup.roster-copy-person-table .box .item:last-child .Roster-week-table-copy-person-container { padding: 33px 0 0 32px;} +#Popup.roster-copy-person-table .box table#Roster-week-table-from th:not(.inactive).hover, +#Popup.roster-copy-person-table .box table#Roster-week-table-from th:not(.inactive):hover { background-color: #c3e1eb !important;} +#Popup.roster-copy-person-table .box table#Roster-week-table-from td { cursor: pointer; } +#Popup.roster-copy-person-table .box table#Roster-week-table-from td:not(.no-shift).active { background-color: #d3f0f9;} +#Popup.roster-copy-person-table .box table#Roster-week-table-from tr:nth-child(2n) td:not(.no-shift).active { background-color: var(--button-normal-active-background);} +#Popup.roster-copy-person-table .box table#Roster-week-table-from td:not(.no-shift):not(.inactive).hover, +#Popup.roster-copy-person-table .box table#Roster-week-table-from td:NOT(.no-shift):not(.inactive):hover { background-color: #c3e1eb !important;} +#Popup.roster-copy-person-table .box table#Roster-week-table-from th { cursor: pointer; padding: 4px 2px !important; } +#Popup.roster-copy-person-table .box table#Roster-week-table-from th.active { background-color: var(--button-normal-active-background);} + +#Popup.roster-copy-person-table .box table#Roster-week-table-to th.active { background: #fbce50;} +#Popup.roster-copy-person-table .box table#Roster-week-table-to th:not(.inactive).hover, +#Popup.roster-copy-person-table .box table#Roster-week-table-to th:not(.inactive):hover { background-color: #f1de9d !important;} +#Popup.roster-copy-person-table .box table#Roster-week-table-to td.active { background: #fff2c5;} +#Popup.roster-copy-person-table .box table#Roster-week-table-to tr:nth-child(2n) td.active { background: #fbce50;} +#Popup.roster-copy-person-table .box table#Roster-week-table-to th.hover, +#Popup.roster-copy-person-table .box table#Roster-week-table-to td:not(.no-shift):not(.inactive).hover, +#Popup.roster-copy-person-table .box table#Roster-week-table-to td:not(.no-shift):not(.inactive):hover { background-color: #f1de9d !important;} +#Popup.roster-copy-person-table .box table#Roster-week-table-to td.Roster-week-td.no-shift:not(.inactive).hover, +#Popup.roster-copy-person-table .box table#Roster-week-table-to td.Roster-week-td.no-shift:not(.inactive):hover { background-color: #f1de9d !important;} +#Popup.roster-copy-person-table .box .button-save { border-radius: 0; border: 1px solid var(--color-black); line-height: 22px; display: flex; height: 100%; position:absolute; top: 0; left: 0; z-index: 1;} + +#Closingtimes #Popup-container.lawful {padding: 40px 20px 20px;} +.lawful-vacations >div { display: grid; grid-template-columns: auto auto 1fr;} +.lawful-vacations >div >* {display: flex; align-items: center;} + +#Add-closingtimes-closingtimes .td-person >div { display: flex; justify-content: center; padding: 4px 0; } +#Add-closingtimes-closingtimes .td-person .all { padding-right: 8px;} +#Add-closingtimes-closingtimes .td-person .all >button { height: 100%; } +#Add-closingtimes-closingtimes .td-person .container { display: flex !important; flex-wrap: wrap; justify-content: center; gap: 6px; min-width: unset !important; } +#Add-closingtimes-closingtimes .td-person button {padding: 4px 6px; min-width: unset; min-height: unset; border-radius: 6px;} + +.Footer { + display: flex; + gap: 8px; + justify-content: flex-end; + margin-top: 40px; +} +.Footer a { color: var(--color-blue) !important; cursor: pointer; } + +@keyframes loadingA { + 0% {opacity: 1;} + 25% {opacity: 1;} + 50% {opacity: 0;} + 100% {opacity: 0;} +} + +@keyframes loadingB { + 0% {opacity: 0;} + 25% {opacity: 1;} + 50% {opacity: 1;} + 100% {opacity: 0;} +} + +@keyframes loadingC { + 0% {opacity: 0;} + 25% {opacity: 0;} + 50% {opacity: 1;} + 100% {opacity: 1;} +} + + + +#Loading-screen.d-none { opacity: 0; display: flex !important; z-index: -1;} +#Loading-screen { + transition: opacity 1s; + align-items: center; + background: var(--color-lightblue); + display: flex; + font-size: 45px; + justify-content: center; + height: 100%; + left: 0; + opacity: .8; + position: fixed; + top: 0; + width: 100%; + z-index: 1000000; +} +#Loading-screen >div { animation-duration: 1s; animation-iteration-count: infinite;} +#Loading-screen >div:nth-child(1) { animation-name: loadingA; } +#Loading-screen >div:nth-child(2) { animation-name: loadingB; } +#Loading-screen >div:nth-child(3) { animation-name: loadingC; } + +#Console { all: unset; position: fixed; bottom: 0; left: 0; width: 100%; background: black; z-index: 1000000; color: white; } +#Console-input { display: flex; height: 18px; white-space: pre; } +#Console-input div.person {color: var(--color-whitegreen);} +#Console-input div.day {color: var(--color-whiteblue);} +#Console-input div.time {color: var(--color-whiteblue);} +#Console-input div.time {color: var(--color-whiteblue);} +#Console-help div.active{ background: white; color: black; } diff --git a/useradmin.php b/useradmin.php new file mode 100644 index 0000000..58a3a4f --- /dev/null +++ b/useradmin.php @@ -0,0 +1,118 @@ +<!DOCTYPE html> +<?php + +session_start(); + +require './api/config/db_inc.php'; +require './api/objects/account_class.php'; + +$account = new Account(); +if (!$account->sessionLogin()) { + if (!$account->isAuthenticated()) { + header('Location: login.php'); + die(); + } +} + +if ($_SESSION["user_role"] !== "admin" ) { + header('Location: /'); + die(); +} + +?> +<html> + <head> + <link rel="stylesheet" href="style-colors.css"> + <link rel="stylesheet" href="style-defaults.css"> + <link rel="stylesheet" href="style-useradmin.css"> + <script src="js/database/account-institution-admin.js" defer></script> + <script src="js/user-administration.js" defer></script> +<script> +Date.prototype.getWeek = function(){ + var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate())); + var dayNum = d.getUTCDay() || 7; + d.setUTCDate(d.getUTCDate() + 4 - dayNum); + var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1)); + return Math.ceil((((d - yearStart) / 86400000) + 1)/7) +} + let DATE = new Date(); + let DATE_YEAR = new Date().getFullYear().toString(); + let DATE_WEEK = new Date().getWeek().toString(); + DATE_WEEK.length === 1 && (DATE_WEEK = "0"+DATE_WEEK) + let DATE_YEAR_WEEK = `${DATE_YEAR}-${DATE_WEEK}` + let ROSTERS_YEARWEEK + let DATE_YEAR_WEEK_OLDEST + let USERS + let PERSONS +</script> + </head> + <body id="Administration" onload="renderUsers()"> + <button id="Back-button" onClick='window.location="/"'>Zurück</button> + <button id="Logout-button" onClick="logout()">Logout</button> + <h1>Administration</h1> + <div class="container"> + <div class="container-users"> + <h2>Benutzer</h2> + <div class="role-hints"> + <div>Benutzer:</div><div>Kann den Schichtplan einsehen aber nicht bearbeiten.</div> + <div>Einrichtungs-Administrator:</div><div>Kann einen Schichtplan erstellen/ bearbeiten.</div> + </div> + <div id="Users"></div> + </div> + </div> + <div class="Popup Popup-add-new-user"> + <div class="Popup-container"> + <h2 class="title">Benutzer hinzufügen</h2> + <div class="container"> + <p class="hint hint-user"></p> + <label class="connect-label d-none">Varküpft: </label> + <input class="connect d-none" type="checkbox" checked onchange="changeConnected(this.checked)"/> + <label>Name: </label> + <div class="container-name"> </div> + <label>Rolle: </label> + <label class="chevron-select chevron-down"> + <select class="select-role" onchange="changeRoleSelect(this.value)"> + <option value="user" selected="selected">Benutzer</option> + <option value="admin">Einrichtungs-Administrator</option> + </select> + </label> + <label>Passwort: </label><input class="password" type="password"> + <label>Passwort wiederholung: </label><input class="password-confirm"type="password"> + <div class="container-buttons"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="confirm" onClick="addNewUser()">Hinzufügen</button> + </div> + <p class="hint"></p> + </div> + </div> + </div> + <div class="Popup Popup-edit-user"> + <div class="Popup-container"> + <div class="container-title"> + <h2 class="title">Benuter </h2> + <h2 class="name"></h2> + <h2 class="title"> bearbeiten</h2> + </div> + <div class="container"> + <div class="container-name"> + <h3>Name ändern</h3> + <input class="name"/> + <div class="container-buttons"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="confirm" onClick="changeName()">Ändern</button> + </div> + </div> + <p class="hint hint-name"></p> + <div class="container-password"> + <h3>Neues Passwort</h3> + <label>Passwort: </label><input class="password_1" type="password"> + <label>Passwort wiederholung: </label><input class="password_2" type="password"> + <button class="abort" onClick="closePopup()">Abbrechen</button> + <button class="confirm" onClick="changePassword()">Ändern</button> + </div> + <p class="hint hint-password"></p> + </div> + </div> + </div> + </body> +</html>