From 3909f878cb7eef0a5268bc78da7bbb6003b2192f Mon Sep 17 00:00:00 2001 From: fet1sov Date: Thu, 30 May 2024 22:07:59 +0500 Subject: [PATCH] Applications logic Backend: - Added the application logic - Added the update process of application data Frontend: - Added form for application information serving - Added form of application edit process for the admins --- .gitignore | 3 +- database.sql | 10 +- docker-compose.yml | 1 + www/_styles/_css/styles.css | 49 +++++++- www/backend/models/application.mdl.php | 125 ++++++++++++++++-- www/backend/models/user.mdl.php | 20 ++- www/backend/routes/admin/admin.ctrl.php | 77 ++++++++++-- www/backend/routes/admin/admin.view.php | 153 ++++++++++++++++++++--- www/backend/routes/index/index.view.php | 4 + www/backend/routes/user/user.ctrl.php | 44 +++++-- www/backend/routes/user/user.view.php | 111 +++++++++++++++- www/data/locales/en-US.json | 41 +++++- www/data/locales/ru-RU.json | 39 +++++- www/frontend/components/elems/footer.php | 4 +- www/frontend/components/elems/header.php | 3 +- www/index.php | 2 +- 16 files changed, 608 insertions(+), 78 deletions(-) diff --git a/.gitignore b/.gitignore index 5ee3815..f1677fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # Ignoring all uploads on the website www/uploads/avatars/*.png -!www/uploads/avatars/no_avatar.png \ No newline at end of file +!www/uploads/avatars/no_avatar.png +.vscode \ No newline at end of file diff --git a/database.sql b/database.sql index 01a8c65..7dcf9df 100644 --- a/database.sql +++ b/database.sql @@ -43,8 +43,8 @@ CREATE TABLE IF NOT EXISTS `applications` ( PRIMARY KEY (`id`) ); -INSERT INTO `role`(`name`, `admin_right`, `applications_list`) VALUES('administrator', '1', '1'); -INSERT INTO `role`(`name`, `admin_right`, `applications_list`) VALUES('manager', '0', '1'); -INSERT INTO `applications_statuses`(`name`, `color`) VALUES('waiting', '#ffd500'); -INSERT INTO `applications_statuses`(`name`, `color`) VALUES('desclined', '#FF0000'); -INSERT INTO `applications_statuses`(`name`, `color`) VALUES('success', '#00FF00') \ No newline at end of file +INSERT INTO `role`(`name`, `admin_rights`, `applications_list`) VALUES('administrator', '1', '1'); +INSERT INTO `role`(`name`, `admin_rights`, `applications_list`) VALUES('manager', '0', '1'); +INSERT INTO `application_statuses`(`name`, `color`) VALUES('waiting', '#ffd500'); +INSERT INTO `application_statuses`(`name`, `color`) VALUES('desclined', '#FF0000'); +INSERT INTO `application_statuses`(`name`, `color`) VALUES('success', '#00FF00'); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index f5b676e..6e506d9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,7 @@ services: volumes: - ./www:/var/www/html - ./apache-conf.conf:/etc/apache2/sites-enabled/000-default.conf + - ./www/data/uploads:/var/www/html/data/uploads/ develop: watch: - path: www/ diff --git a/www/_styles/_css/styles.css b/www/_styles/_css/styles.css index 5c58d67..c3b110d 100644 --- a/www/_styles/_css/styles.css +++ b/www/_styles/_css/styles.css @@ -89,6 +89,31 @@ span.red-text { background-color: var(--secondary-color-02); } +textarea { + outline: none; + border: none; + + width: 100%; + resize: none; + + margin-top: 20px; + margin-bottom: 20px; + + background-color: var(--secondary-color-04); + border-radius: 10px; + + padding: 10px; +} + +select { + background-color: var(--secondary-color-04); + border: none; + border-radius: 10px; + + outline: none; + padding: 10px; +} + body { background-color: var(--secondary-color-01); @@ -109,6 +134,27 @@ header { animation-duration: 0.5s; } +table, th, td { + text-align: center; + border: 10px transparent; + + text-align: center; +} + +tr td { + display: flex; + align-items: center; + + text-align: center; +} + +td, th { + text-align: center; + vertical-align: middle; + + padding: 10px; +} + header nav.navigation { position: fixed; @@ -242,9 +288,6 @@ table tbody tr { table tbody :first-child th { font-weight: bold; - margin-right: 10px; - margin-left: 10px; - border-bottom: 2px #000000; } diff --git a/www/backend/models/application.mdl.php b/www/backend/models/application.mdl.php index 968fb93..e49d264 100644 --- a/www/backend/models/application.mdl.php +++ b/www/backend/models/application.mdl.php @@ -2,33 +2,38 @@ class Application extends DatabaseEntity { public $id = 0; - public $authorName = ""; - public $managerName = ""; + public $authorId = 0; + public $managerId = 0; + public $text = ""; + public $status = 0; public function __construct($id = 0, $applicationData = array()) { $this->id = $id; + $createRowFlag = false; if ($id >= 1) { - $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT COUNT(`id`) FROM `application` WHERE `id`=?"); + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT COUNT(`id`) FROM `applications` WHERE `id`=?"); $stmt->bind_param('i', $id); $stmt->execute(); $stmt->store_result(); if ($stmt->num_rows() >= 1) { - $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT * FROM `user` WHERE `id`=?"); + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT * FROM `applications` WHERE `applications`.`id`=?"); $stmt->bind_param('i', $id); $stmt->execute(); $applicationRes = $stmt->get_result(); $applicationRow = $applicationRes->fetch_array(MYSQLI_ASSOC); + $this->id = $applicationRow["id"]; + $this->authorId = $applicationRow["author_id"]; + $this->managerId = $applicationRow["manager_id"]; + $this->text = $applicationRow["text"]; + $this->status = $applicationRow["status"]; } else { - //if (!count($userData)) - //{ - $createRowFlag = true; - //} + $createRowFlag = true; } } else { $createRowFlag = true; @@ -36,22 +41,118 @@ public function __construct($id = 0, $applicationData = array()) { if ($createRowFlag) { - + $stmt = $GLOBALS["dbAdapter"]->prepare("INSERT INTO `applications`(`author_id`, `creation_date`, `text`) VALUES (?, ?, ?)"); + $stmt->bind_param( + 'iis', + $applicationData["author_id"], + $applicationData["creation_date"], + $applicationData["text"] + ); + $stmt->execute(); $this->id = $GLOBALS["dbAdapter"]->insert_id; + $this->authorId = $applicationData["author_id"]; + $this->text = $applicationData["text"]; } } public static function getFullList() { - $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT `applications`.*, `user`.`username` AS `user_author`, `user`.`username` AS `user_manager`, `application_statuses`.`name` FROM `applications` INNER JOIN `application_statuses` ON `applications`.`status` = `application_statuses`.`id` INNER JOIN `user` ON `applications`.`author_id` = `user`.`id` LEFT JOIN `user` manager_user ON `applications`.`manager_id`=`user`.`id`"); + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT `applications`.*, `user`.`username` AS `user_author`, `manager_user`.`username` AS `user_manager`, `application_statuses`.`name` AS `status_name` FROM `applications` LEFT JOIN `application_statuses` ON `applications`.`status` = `application_statuses`.`id` LEFT JOIN `user` ON `applications`.`author_id` = `user`.`id` LEFT JOIN `user` manager_user ON `applications`.`manager_id`=`user`.`id`"); $stmt->execute(); + $applicationsList = array(); + $applicationsResult = $stmt->get_result(); - return $applicationsResult->fetch_array(MYSQLI_ASSOC); + while ($row = $applicationsResult->fetch_array(MYSQLI_ASSOC)) { + array_push($applicationsList, $row); + } + + return $applicationsList; } - public function saveData() : void + public static function fetchByUserId($userID) { + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT `applications`.*, `user`.`username` AS `user_author`, `manager_user`.`username` AS `user_manager`, `application_statuses`.`name` AS `status_name` FROM `applications` LEFT JOIN `application_statuses` ON `applications`.`status` = `application_statuses`.`id` LEFT JOIN `user` ON `applications`.`author_id` = `user`.`id` LEFT JOIN `user` manager_user ON `applications`.`manager_id`=`user`.`id` WHERE `applications`.`author_id`=?"); + $stmt->bind_param('i', $userID); + $stmt->execute(); + + $applicationsList = array(); + + $applicationsResult = $stmt->get_result(); + while ($row = $applicationsResult->fetch_array(MYSQLI_ASSOC)) { + array_push($applicationsList, $row); + } + + return $applicationsList; + } + + public function setStatus($statusID) : void { } + + public function getStatus() : ?array { + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT * FROM `application_statuses` WHERE `id`=?"); + $stmt->bind_param('i', $this->status); + $stmt->execute(); + + $statusResult = $stmt->get_result(); + return $statusResult->fetch_array(MYSQLI_ASSOC); + } + + public static function getStatusList() : ?array + { + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT * FROM `application_statuses`"); + $stmt->execute(); + + $statusesList = array(); + + $statusResult = $stmt->get_result(); + while ($row = $statusResult->fetch_array(MYSQLI_ASSOC)) { + array_push($statusesList, $row); + } + + return $statusesList; + } + + public function getAuthorInfo() : ?array { + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT * FROM `user` WHERE `id`=?"); + $stmt->bind_param('i', $this->authorId); + $stmt->execute(); + + $userResult = $stmt->get_result(); + return $userResult->fetch_array(MYSQLI_ASSOC); + } + + public function getManagerInfo() : ?array { + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT * FROM `user` WHERE `id`=?"); + $stmt->bind_param('i', $this->managerId); + $stmt->execute(); + + $userResult = $stmt->get_result(); + return $userResult->fetch_array(MYSQLI_ASSOC); + } + + public function saveData() : void + { + $stmt = $GLOBALS["dbAdapter"]->prepare("UPDATE `applications` SET `author_id`=?, `manager_id`=?, `status`=?, `text`=? WHERE `id`=?"); + $stmt->bind_param( + 'iiisi', + $this->authorId, + $this->managerId, + $this->status, + $this->text, + $this->id + ); + $stmt->execute(); + } + + public function remove() : void + { + $stmt = $GLOBALS["dbAdapter"]->prepare("DELETE FROM `applications` WHERE `id`=?"); + $stmt->bind_param( + 'i', + $this->id + ); + $stmt->execute(); + } } \ No newline at end of file diff --git a/www/backend/models/user.mdl.php b/www/backend/models/user.mdl.php index ea97a2c..55c8c78 100644 --- a/www/backend/models/user.mdl.php +++ b/www/backend/models/user.mdl.php @@ -39,7 +39,7 @@ public function __construct($id = 0, $userData = array()) { $this->password = $row["password"]; $this->company = $row["company"]; $this->email = $row["email"]; - $this->roleid = $row["role_id"] ? $row["role_id"] : 0; + $this->roleid = $row["role_id"]; } else { if (!count($userData)) { @@ -73,15 +73,29 @@ public function __construct($id = 0, $userData = array()) { } } - public function getPermissions() : array { + public function getPermissions() : ?array { $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT `role`.`admin_rights`, `role`.`applications_list` FROM `user` INNER JOIN `role` ON `user`.`role_id` = `role`.`id` WHERE `user`.`id`=?"); - $stmt->bind_param('i', $this->id); + $stmt->bind_param('i', $this->roleid); $stmt->execute(); $rightResult = $stmt->get_result(); return $rightResult->fetch_array(MYSQLI_ASSOC); } + public static function getFullList($condition = "") { + $stmt = $GLOBALS["dbAdapter"]->prepare("SELECT `role`.`admin_rights`, `role`.`applications_list`, `user`.* FROM `user` LEFT JOIN `role` ON `user`.`role_id` = `role`.`id` " . $condition); + $stmt->execute(); + + $userList = array(); + + $userResult = $stmt->get_result(); + while ($row = $userResult->fetch_array(MYSQLI_ASSOC)) { + array_push($userList, $row); + } + + return $userList; + } + public function saveData() : void { $stmt = $GLOBALS["dbAdapter"]->prepare("UPDATE `user` SET `username`=?, `password`=?, `company`=?, `email`=? WHERE `id`=?"); diff --git a/www/backend/routes/admin/admin.ctrl.php b/www/backend/routes/admin/admin.ctrl.php index f73d46f..c3e4f9e 100644 --- a/www/backend/routes/admin/admin.ctrl.php +++ b/www/backend/routes/admin/admin.ctrl.php @@ -1,11 +1,70 @@ ROUTE_ROOT . "admin/admin.view.php", - "layout_data" => [ - "footerShow" => false, - "applications" => $applications ? $applications : [] - ] -]); \ No newline at end of file +if (!isset($_SESSION["userData"])) { + header('Location: /'); +} + +$userData = unserialize($_SESSION["userData"]); + +if($userData->roleid == NULL +&& !$userData->getPermissions()["admin_rights"]) +{ + header('Location: /'); + die(); +} + +if (isset($params['category'])) { + switch ($params['category']) { + case "application": { + if ($_SERVER['REQUEST_METHOD'] == 'GET') + { + $application = new Application(intval($_GET["id"])); + + Renderer::includeTemplate("frontend/components/layout.php", [ + "layout_path" => ROUTE_ROOT . "admin/admin.view.php", + "layout_data" => [ + "footerShow" => false, + "category" => $params['category'], + "applicationData" => $application, + "authorData" => $application->getAuthorInfo(), + "managerList" => User::getFullList("WHERE `role`.`admin_rights`=1"), + "statusList" => Application::getStatusList(), + ] + ]); + } else { + $application = new Application(intval($_POST["id"])); + + if ($_POST["action"] == "update") + { + $application->status = intval($_POST["statuses"]); + $application->managerId = intval($_POST["manager"]); + + $application->saveData(); + } else { + $application->remove(); + } + + + Renderer::includeTemplate("frontend/components/layout.php", [ + "layout_path" => ROUTE_ROOT . "admin/admin.view.php", + "layout_data" => [ + "footerShow" => false, + "category" => $params['category'], + "applicationData" => $application, + "authorData" => $application->getAuthorInfo(), + "managerList" => User::getFullList("WHERE `role`.`admin_rights`=1"), + "statusList" => Application::getStatusList(), + ] + ]); + } + } + } +} else { + Renderer::includeTemplate("frontend/components/layout.php", [ + "layout_path" => ROUTE_ROOT . "admin/admin.view.php", + "layout_data" => [ + "footerShow" => false, + "applications" => Application::getFullList() + ] + ]); +} \ No newline at end of file diff --git a/www/backend/routes/admin/admin.view.php b/www/backend/routes/admin/admin.view.php index 7794390..7ee0585 100644 --- a/www/backend/routes/admin/admin.view.php +++ b/www/backend/routes/admin/admin.view.php @@ -1,22 +1,137 @@
- - - - - - - - - - - - - - + + +
+ + + + + + + + + + + + +
"> " class="small-primary-button">
+ + + +
+ + arrow-left Created with Sketch Beta. + + +
+ + +
+ +
+ +
+ +

+
+
+ +
+ +

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

text ?>

+
+ +
+ + +
+
+
+ + + +
\ No newline at end of file diff --git a/www/backend/routes/index/index.view.php b/www/backend/routes/index/index.view.php index 9d499c6..0c59c17 100644 --- a/www/backend/routes/index/index.view.php +++ b/www/backend/routes/index/index.view.php @@ -3,6 +3,10 @@ ?> +

-

+
- + +
+
+ + + +
+ + arrow-left Created with Sketch Beta. + + +
+
+ +
+ + + +

+
+ + +
+ getStatus(); + if ($statusInfo) { ?> +

;">

+ +

+ +
+ +
+ +

text ?>

+
+
+
+
+ + +
+ + +

+ +
+
- - -
@@ -233,7 +317,22 @@ + + + + + + + + + + "> + diff --git a/www/data/locales/en-US.json b/www/data/locales/en-US.json index 4711838..29bb5e4 100644 --- a/www/data/locales/en-US.json +++ b/www/data/locales/en-US.json @@ -1,4 +1,5 @@ { + "locale_name": "English", "moreButton": "More", "placeholders": { "login": "Login", @@ -20,7 +21,9 @@ "message": " we didn't found this place :(", "description": "Page not found or not avaible anymore" } - } + }, + "nullField": "Not clarified", + "noStatus": "In process" }, "success": { "settings": { @@ -34,6 +37,11 @@ "applicationsTitle": "Your applications" }, "userPage": { + "statuses": { + "waiting": "Observing", + "desclined": "Desclined", + "success": "Accepted" + }, "greetings": { "goodmorning": "Good morning, ", "goodday": "Have nice day, ", @@ -44,6 +52,7 @@ "appTable": { "id": "№ number", "manager": "Manager", + "author": "Author", "status": "Status", "date": "Creation date" } @@ -66,6 +75,17 @@ "placeholder": "Company name" } } + }, + "applicationInfo": { + "author": "Author:", + "manager": "Assigned manager:", + "status": "Current status:", + "text": "Application description:", + + "contact": "Contact information:", + + "assignManager": "Assign manager:", + "changeStatus": "Change status:" } }, "navigationBar": { @@ -98,21 +118,32 @@ "sections": { "companiestrustus": "THEY TRUST US", "applicationconfirm": { - "title": "Are you sure you want create a application?", - "text": "Your application will be sent to the management team" + "title": "Fill all blanks to send a request", + "text": "Enter the description of your request", + "success_message": "Application was sent to management team" } }, "userMenu": { - "personalCabinet": "Personal cabinet", + "personalCabinet": "Personal", "admin": "Admin", "settings": "Settings", "logout": "Log out" }, "buttons": { + "continue": "Continue", "confirm": "Confirm", "cancel": "Cancel", "upload": "Upload", "saveButton": "Save changes", - "discardButton": "Discard changes" + "discardButton": "Discard changes", + "view": "View", + "backtolist": "Back to list", + "update": "Update", + + "delete": "Delete" + }, + "footer": { + "phone": "Phone", + "contacts": "Contacts" } } \ No newline at end of file diff --git a/www/data/locales/ru-RU.json b/www/data/locales/ru-RU.json index 066a9f7..de08a68 100644 --- a/www/data/locales/ru-RU.json +++ b/www/data/locales/ru-RU.json @@ -1,4 +1,5 @@ { + "locale_name": "Русский", "moreButton": "Подробнее", "placeholders": { "login": "Имя пользователя", @@ -20,7 +21,9 @@ "message": " мы не нашли этого места", "description": "Страница не найдена и стала недоступна" } - } + }, + "nullField": "Не назначено", + "noStatus": "В процессе" }, "success": { "settings": { @@ -34,6 +37,11 @@ "applicationsTitle": "Ваши заявки" }, "userPage": { + "statuses": { + "waiting": "На рассмотрении", + "desclined": "Отказано", + "success": "Принята" + }, "greetings": { "goodmorning": "Доброе утро, ", "goodday": "Хорошего дня, ", @@ -44,6 +52,7 @@ "appTable": { "id": "№ номер", "manager": "Менеджер", + "author": "Автор", "status": "Статус", "date": "Дата создания" } @@ -66,6 +75,17 @@ "placeholder": "Название компании" } } + }, + "applicationInfo": { + "author": "Автор:", + "manager": "Назначенный менеджер:", + "status": "Текущий статус:", + "text": "Описание заявки:", + + "contact": "Контактная информация:", + + "assignManager": "Назначить менеджера:", + "changeStatus": "Установить статус:" } }, "navigationBar": { @@ -98,8 +118,9 @@ "sections": { "companiestrustus": "НАМ ДОВЕРЯЮТ", "applicationconfirm": { - "title": "Вы уверены что хотите создать заявку?", - "text": "Заявка будет отправлена на рассмотрение отделу менеджмента" + "title": "Заполните все поля для отправки заявки", + "text": "Введите описание вашей заявки", + "success_message": "Заявка была отправлена отделу менеджемента" } }, "userMenu": { @@ -109,10 +130,20 @@ "logout": "Выйти" }, "buttons": { + "continue": "Продолжить", "confirm": "Подтвердить", "cancel": "Отмена", "upload": "Загрузить", "saveButton": "Сохранить изменения", - "discardButton": "Отменить изменения" + "discardButton": "Отменить изменения", + "view": "Просмотреть", + "backtolist": "Назад к списку", + "update": "Обновить", + + "delete": "Удалить" + }, + "footer": { + "phone": "Телефон", + "contacts": "Контакты" } } \ No newline at end of file diff --git a/www/frontend/components/elems/footer.php b/www/frontend/components/elems/footer.php index 34b6c05..32fdf83 100644 --- a/www/frontend/components/elems/footer.php +++ b/www/frontend/components/elems/footer.php @@ -6,8 +6,8 @@ \ No newline at end of file diff --git a/www/frontend/components/elems/header.php b/www/frontend/components/elems/header.php index 7e2a79b..982694b 100644 --- a/www/frontend/components/elems/header.php +++ b/www/frontend/components/elems/header.php @@ -46,7 +46,8 @@ getPermissions()["admin_rights"]) { ?> + if($userData->roleid != NULL + && $userData->getPermissions()["admin_rights"]) { ?>
  • diff --git a/www/index.php b/www/index.php index a38b78d..c69c953 100644 --- a/www/index.php +++ b/www/index.php @@ -32,7 +32,7 @@ * Admin routes */ $router->add("/admin/", ROUTE_ROOT . "admin/admin.ctrl.php"); -$router->add("/admin/{category}/", ROUTE_ROOT . "admin/admin.ctrl.php"); +$router->add("/admin/{category}", ROUTE_ROOT . "admin/admin.ctrl.php"); /* * 404 NOT FOUND p_p