diff --git a/src/Praktikum/Prak5/Baecker.php b/src/Praktikum/Prak5/Baecker.php index 22a2720d8147fe5ff24b2e3ca0100465bcd438d9..14d2fd6fdc6dfb13d64d20f14b5241726abd0099 100644 --- a/src/Praktikum/Prak5/Baecker.php +++ b/src/Praktikum/Prak5/Baecker.php @@ -131,16 +131,16 @@ HTML; echo <<< HTML <fieldset> <legend>Bestellung {$order->getOrderingId()} Pizza {$pizzaName}</legend> - Status: <br> + Status: <label> <input type="radio" name="{$orderedArticleId}" value="0" {$statusArray[0]} onclick="document.forms['formBaecker'].submit();"> Bestellt - </label> <br> + </label> <label> <input type="radio" name="{$orderedArticleId}" value="1" {$statusArray[1]} onclick="document.forms['formBaecker'].submit();"> Im Ofen - </label> <br> + </label> <label> <input type="radio" name="{$orderedArticleId}" value="2" {$statusArray[2]} onclick="document.forms['formBaecker'].submit();"> diff --git a/src/Praktikum/Prak5/Kundenstatus.php b/src/Praktikum/Prak5/Kundenstatus.php index 743f34fb91eac9470d83771d74cf1b2bfd2b75b7..f0f0b0b9fea07ee47861679b4f7593d8e9f863d5 100644 --- a/src/Praktikum/Prak5/Kundenstatus.php +++ b/src/Praktikum/Prak5/Kundenstatus.php @@ -63,6 +63,7 @@ class Kundenstatus extends Page */ protected function getViewData() :array { + header("Refresh: 5;"); if (isset($_SESSION["orders"])) { $customerOrders = $_SESSION["orders"]; @@ -155,7 +156,6 @@ class Kundenstatus extends Page $page->processReceivedData(); $page->generateView(); } catch (Exception $e) { - //header("Content-type: text/plain; charset=UTF-8"); header("Content-type: text/html; charset=UTF-8"); echo $e->getMessage(); } diff --git a/src/Praktikum/Prak5/baeckerAjax/Baecker.js b/src/Praktikum/Prak5/baeckerAjax/Baecker.js new file mode 100644 index 0000000000000000000000000000000000000000..0c77698667c3c512dfea9592a394bb2c3d812dae --- /dev/null +++ b/src/Praktikum/Prak5/baeckerAjax/Baecker.js @@ -0,0 +1,145 @@ +function loadData() { + "use strict"; + var url = "./Kundenstatus.php"; + var request = new XMLHttpRequest(); + + request.open("GET", url, true); + + request.onload = function () { + + if (request.readyState === 4 && + request.status >= 200 && + request.status < 300) { + + if (request.responseText != null) { + + var responseData = JSON.parse(request.responseText); + console.log(responseData); + process(responseData); + } else { + console.error ("Dokument ist leer"); + } + } else { + console.error("Statuscode: " + request.status); + } + }; + + request.onerror = function () { + "use strict"; + console.error("Netzwerkfehler"); + }; + + //request.onreadystatechange = processData; + + request.send(); +} + + +function process(data) { + + "use strict"; + + const orderForm = document.getElementById("formBaecker"); + if (orderForm != null) { + + while (orderForm.lastElementChild) { + orderForm.removeChild(orderForm.lastElementChild); + } + + + for (let [orderingID, order] of Object.entries(data)) { + + let pizzaObj = { + pizzaList: [] + }; + + + let orderList = order["OrderList"] + for (let [orderedArticleID, pizza] of Object.entries(orderList)) { + + let name = pizza["Name"]; + let price = parseFloat(pizza["Price"]); + let status = parseInt(pizza["Status"]); + + if (status <= 2) { + let newPizza = { + orderedArticleID: orderedArticleID, + name: name, + price: price, + status: status + }; + pizzaObj.pizzaList.push(newPizza); + } + } + buildOrder(orderForm, orderingID, pizzaObj); + } + + } +} + + +window.onload = function () { + + "use strict"; + loadData(); +} + +window.setInterval (loadData, 2000); + + + +function buildOrder(parentNode, id, pizzaObj) { + + "use strict"; + let pizzaList = pizzaObj.pizzaList; + + for (let pizza of pizzaList) { + + let pizzaName = pizza.name; + let orderedArticleID = pizza.orderedArticleID; + let pizzaStatus = pizza.status; + + let orderMainNode = document.createElement("fieldset"); + orderMainNode.id = id; + orderMainNode.className = "orderFieldset"; + + let orderLegend = document.createElement("legend"); + orderLegend.id = id + ".legend"; + orderLegend.innerText = "Bestellung " + id + " Pizza " + pizzaName; + orderLegend.className = "orderLegend"; + + orderMainNode.append(orderLegend); + + buildInputs(orderMainNode, orderedArticleID, pizzaStatus); + + parentNode.append(orderMainNode); + } +} + + +function buildInputs(orderMainNode, orderedArticleID, status) { + "use strict"; + let statusArray = ["Bestellt", "Im Ofen", "Fertig"]; + for (let value = 0; value < statusArray.length; value++) { + let inputLabel = document.createElement("label"); + let inputRadio = document.createElement("input"); + + inputLabel.innerText = statusArray[value]; + inputLabel.className = "pizzaRadioLabel"; + inputRadio.type = "radio"; + inputRadio.className = "pizzaRadio"; + inputRadio.name = orderedArticleID; + inputRadio.value = value.toString(); + + inputRadio.onclick = function () { + document.forms["formBaecker"].submit(); + } + + if (value === status) { + inputRadio.checked = true; + } + + inputLabel.prepend(inputRadio); + orderMainNode.append(inputLabel); + } +} diff --git a/src/Praktikum/Prak5/baeckerAjax/Baeckerajax.php b/src/Praktikum/Prak5/baeckerAjax/Baeckerajax.php new file mode 100644 index 0000000000000000000000000000000000000000..2c3969a591bf73d75dc6bdb92717e4d5d46edd36 --- /dev/null +++ b/src/Praktikum/Prak5/baeckerAjax/Baeckerajax.php @@ -0,0 +1,217 @@ +<?php declare(strict_types=1); +// UTF-8 marker äöüÄÖÜ߀ +/** + * Class baecker for the exercises of the EWA lecture + * Demonstrates use of PHP including class and OO. + * Implements Zend coding standards. + * Generate documentation with Doxygen or phpdoc + * + * PHP Version 7.4 + * + * @file baecker.php + * @package Page Templates + * @author Bernhard Kreling, <bernhard.kreling@h-da.de> + * @author Ralf Hahn, <ralf.hahn@h-da.de> + * @version 3.1 + */ + +// to do: change name 'baecker' throughout this file +namespace baeckerAjax; +use OrderedArticle; +use Page; + +require_once '../Page.php'; +require_once '../DB_Classes/OrderedArticle.php'; +require_once '../navbar.php'; + +/** + * This is a template for top level classes, which represent + * a complete web page and which are called directly by the user. + * Usually there will only be a single instance of such a class. + * The name of the template is supposed + * to be replaced by the name of the specific HTML page e.g. baker. + * The order of methods might correspond to the order of thinking + * during implementation. + * @author Bernhard Kreling, <bernhard.kreling@h-da.de> + * @author Ralf Hahn, <ralf.hahn@h-da.de> + */ +class Baeckerajax extends Page +{ + // to do: declare reference variables for members + // representing substructures/blocks + + /** + * Instantiates members (to be defined above). + * Calls the constructor of the parent i.e. page class. + * So, the database connection is established. + * @throws Exception + */ + protected function __construct() + { + parent::__construct(); + // to do: instantiate members representing substructures/blocks + } + + /** + * Cleans up whatever is needed. + * Calls the destructor of the parent i.e. page class. + * So, the database connection is closed. + */ + public function __destruct() + { + parent::__destruct(); + } + + /** + * Fetch all data that is necessary for later output. + * Data is returned in an array e.g. as associative array. + * @return array An array containing the requested data. + * This may be a normal array, an empty array or an associative array. + */ + protected function getViewData(): array + { + $query = "SELECT * FROM ordered_article;"; + $resultSet = $this->_database->query($query); + $orderedArticleList = array(); + + while ($row = $resultSet->fetch_assoc()) { + + $orderedArticle = new OrderedArticle( + (int)$row["ordered_article_id"], (int)$row["ordering_id"], (int)$row["article_id"], (int)$row["status"] + ); + + $orderedArticleList[$orderedArticle->getOrderedArticleId()] = $orderedArticle; + } + $resultSet->free_result(); + return $orderedArticleList; + } + + /** + * First the required data is fetched and then the HTML is + * assembled for output. i.e. the header is generated, the content + * of the page ("view") is inserted and -if available- the content of + * all views contained is generated. + * Finally, the footer is added. + * @return void + */ + protected function generateView(): void + { + $data = $this->getViewData(); //NOSONAR ignore unused $data + $this->generatePageHeader('Bäcker', "./Baecker.js", false, "../CSS/Baecker.css"); + echo "\n<header class='flex-container flex-direction-column justify-content-center'>\n"; + buildNavbar(null, false); + echo "<img src='../img/Header.png' alt='Header Image'>\n"; + echo "</header>\n"; + + echo <<< HTML + <main> + <section id="baecker"> + <h2>Bestellungen</h2> + + <form class="flex-container flex-direction-row justify-content-center wrap" id="formBaecker" accept-charset="UTF-8" action="#" method="post">\n +HTML; + + $noOrders = true; + foreach ($data as $order) { + $query = "SELECT UNIQUE name FROM article, ordered_article + WHERE article.article_id = {$order->getArticleId()};"; + $resultSet = $this->_database->query($query); + $resultArray = $resultSet->fetch_assoc(); + $resultSet->free_result(); + + $pizzaName = htmlspecialchars($resultArray["name"]); + $orderedArticleId = $order->getOrderedArticleId(); + + $status = $order->getStatus(); + if ($status > 2) { + continue; + } else { + $noOrders = false; + } + + $statusArray = array_fill(0, 5, ""); + $statusArray[$status] = "checked"; + + + } + + if ($noOrders) { + + echo <<< HTML + \n<p>Es gibt keine Bestellungen</p> +HTML; + } + + echo <<< HTML + </form> + </section> + </main>\n +HTML; + + $this->generatePageFooter(); + } + + /** + * Processes the data that comes via GET or POST. + * If this page is supposed to do something with submitted + * data do it here. + * @return void + */ + protected function processReceivedData(): void + { + parent::processReceivedData(); + // to do: call processReceivedData() for all members + $data = $this->getViewData(); + foreach ($data as $order) { + $orderedArticleId = $order->getOrderedArticleId(); + if (isset($_POST["{$orderedArticleId}"]) && is_numeric($_POST["{$orderedArticleId}"])) { + $status = $this->_database->real_escape_string($_POST["{$orderedArticleId}"]); + $query = "UPDATE ordered_article SET status = {$status} + WHERE ordered_article.ordered_article_id = {$orderedArticleId};"; + $this->_database->query($query); + } + } + + // On Post => Reload + if (isset($_POST["save"])) { + header("HTTP/1.1 303 See Other"); + header('Location: ' . $_SERVER['REQUEST_URI']); + die; + } + } + + /** + * This main-function has the only purpose to create an instance + * of the class and to get all the things going. + * I.e. the operations of the class are called to produce + * the output of the HTML-file. + * The name "main" is no keyword for php. It is just used to + * indicate that function as the central starting point. + * To make it simpler this is a static function. That is you can simply + * call it without first creating an instance of the class. + * @return void + */ + public static function main(): void + { + try { + $page = new Baeckerajax(); + $page->processReceivedData(); + $page->generateView(); + } catch (Exception $e) { + //header("Content-type: text/plain; charset=UTF-8"); + header("Content-type: text/html; charset=UTF-8"); + echo $e->getMessage(); + } + } +} + +// This call is starting the creation of the page. +// That is input is processed and output is created. +Baecker::main(); + +// Zend standard does not like closing php-tag! +// PHP doesn't require the closing tag (it is assumed when the file ends). +// Not specifying the closing ? > helps to prevent accidents +// like additional whitespace which will cause session +// initialization to fail ("headers already sent"). +//? >