diff --git a/public/assets/scripts.js b/public/assets/scripts.js index 6bdd69b..013aa7d 100644 --- a/public/assets/scripts.js +++ b/public/assets/scripts.js @@ -3,14 +3,19 @@ function checkboxHelper(checkbox) checkbox.value = checkbox.checked; } -function fileHelper(inputId, imgType, e) +function fileHelper(inputId, e) { if(e.target.files && e.target.files[0] && e.target.files[0].size < 5242880) { - const reader = new FileReader(); - reader.onload = evt => { - resizeImage(evt.target.result, imgType, 512, 1024, (r) => document.getElementById(inputId).value = r) + const file = e.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = function(event) { + const base64String = event.target.result; + //resizeImage(base64String, 512, 768, img => document.getElementById(inputId).value = img); + document.getElementById(inputId).value = base64String; + }; + reader.readAsDataURL(file); } - reader.readAsText(e.target.files[0]); } else { @@ -18,17 +23,11 @@ function fileHelper(inputId, imgType, e) } } -function resizeImage(imgBytes, imgType, maxWidth, maxHeight, cb) +function resizeImage(base64, maxWidth, maxHeight, callback) { - const blob = new Blob([byteArray]); - const img = new Image(); - const url = URL.createObjectURL(blob); - + img.src = base64; img.onload = () => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - let width = img.width; let height = img.height; @@ -44,20 +43,15 @@ function resizeImage(imgBytes, imgType, maxWidth, maxHeight, cb) } } + const canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; + const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, width, height); - canvas.toBlob((resizedBlob) => { - const reader = new FileReader(); - reader.onload = function(event) { - const resizedByteArray = new Uint8Array(event.target.result); - cb(resizedByteArray); - }; - reader.readAsArrayBuffer(resizedBlob); - }, imgType); - - URL.revokeObjectURL(url); + const resizedBase64 = canvas.toDataURL(); + console.log(resizedBase64) + callback(resizedBase64); }; } \ No newline at end of file diff --git a/src/Controllers/Home/HomeController.php b/src/Controllers/Home/HomeController.php index 32f95bb..f7e933a 100644 --- a/src/Controllers/Home/HomeController.php +++ b/src/Controllers/Home/HomeController.php @@ -3,13 +3,38 @@ { use Controllers\BaseController; + use Models\QueryModel\DVDQueryModel; + use Models\QueryModel\HomeQueryModel; use Models\ViewModels\HomeViewModel; + use Services\DVDService; use Views\Home\HomeView; class HomeController extends BaseController { public function get(): void { $data = new HomeViewModel(); + $service = DVDService::getInstance(); + + $queryModel = new DVDQueryModel(); + if(!empty($_GET)) + { + $queryModel->setFromQueryString($_GET); + } + else + { + header('Location: ' . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH)."?".$queryModel->getQueryString(), true, 303); + die(); + } + + // override to prevent customers to see not-in-offer DVDs + $queryModel->IsOffered = 1; + + $data->Query = $queryModel; + $data->FilteredCount = $service->getCount($queryModel); + $data->DVDs = $service->getAll($queryModel); + $data->TotalPages = ceil($data->FilteredCount / $queryModel->Limit); + $data->CurrentPage = ($queryModel->Offset / $queryModel->Limit) + 1; + $view = new HomeView($data); $view->render(); } diff --git a/src/Controllers/Manage/ManageDVDController.php b/src/Controllers/Manage/ManageDVDController.php index 8807a2e..6e2c3c6 100644 --- a/src/Controllers/Manage/ManageDVDController.php +++ b/src/Controllers/Manage/ManageDVDController.php @@ -64,10 +64,34 @@ private function getById($id): void $viewModel = new ManageDVDDetailViewModel(); $service = DVDService::getInstance(); - $viewModel->DVD = $service->getById($id); - //$viewModel->DVD->ImageBase64 = base64_encode($viewModel->DVD->Image); - //$viewModel->DVD->ImageSignature = ImageUtils::getImageTypeFromSignature($viewModel->DVD->Image); - $viewModel->state = ManageDVDDetailViewStateEnum::Update; + if($id === -1) + { + $viewModel->state = ManageDVDDetailViewStateEnum::Create; + $model = new DVDModel(); + $model->Title = ""; + $model->LocalTitle = ""; + $model->Synopsis = ""; + $model->Notation = 0; + $model->Certification = ""; + $model->Note = ""; + $model->IsOffered = true; + $model->Quantity = 0; + $model->Price = 0; + $model->Year = 0; + $model->TypeId = null; + $model->Image = null; + $model->Genres = []; + + $viewModel->DVD = $model; + + } + else + { + $viewModel->DVD = $service->getById($id); + //$viewModel->DVD->ImageBase64 = base64_encode($viewModel->DVD->Image); + //$viewModel->DVD->ImageSignature = ImageUtils::getImageTypeFromSignature($viewModel->DVD->Image); + $viewModel->state = ManageDVDDetailViewStateEnum::Update; + } $controller = new ManageDVDDetailView($viewModel); $controller->render(); @@ -84,6 +108,31 @@ public function put($id): void $service = DVDService::getInstance(); $model->Id = $id; + $this->postToDvdModel($model); + + $service->update($model); + + header("Location: /manage/dvd/$id"); + die(); + } + + public function post(): void + { + + $model = new DVDModel(); + $service = DVDService::getInstance(); + + $this->postToDvdModel($model); + //$model->Image = $_POST["Image"]; + + $newId = $service->insert($model); + + header("Location: /manage/dvd/$newId"); + die(); + } + + private function postToDvdModel(DVDModel $model) + { $model->Title = $_POST["Title"]; $model->LocalTitle = $_POST["LocalTitle"]; $model->Synopsis = $_POST["Synopsis"]; @@ -96,12 +145,7 @@ public function put($id): void $model->Year = $_POST["Year"]; $model->TypeId = !is_null($_POST["TypeId"]) ? intval($_POST["TypeId"]) : null; $model->Genres = $_POST["Genres"] && is_array($_POST["Genres"]) ? $_POST["Genres"] : null; - //$model->Image = $_POST["Image"]; - - $service->update($model); - - header("Location: /manage/dvd/$id"); - die(); + $model->Image = $_POST["Image"]; } } } diff --git a/src/Controllers/Manage/ManageRouter.php b/src/Controllers/Manage/ManageRouter.php deleted file mode 100644 index 7e9f0ce..0000000 --- a/src/Controllers/Manage/ManageRouter.php +++ /dev/null @@ -1,49 +0,0 @@ -handle(); - exit; - } - - switch (strtolower($requestedController[2])) { - case '/' : - case 'dashboard' : - $controller = new ManageDashboardController(); - $controller->handle(); - break; - case 'dvd' : - $controller = new ManageDVDController(); - $controller->handle(); - break; - default: - throw new RouteNotFoundException("Manage"); - break; - } - } - } -} - diff --git a/src/Models/DVDLightModel.php b/src/Models/DVDLightModel.php new file mode 100644 index 0000000..4825c0a --- /dev/null +++ b/src/Models/DVDLightModel.php @@ -0,0 +1,19 @@ +OrderBy = $param['OrderBy'] ?? ''; + $this->OrderDesc = $param['OrderDesc'] ?? ''; + $this->Search = $param['Search'] ?? ''; + $this->Limit = isset($param['Limit']) ? (int)$param['Limit'] : 10; + $this->Offset = isset($param['Offset']) ? (int)$param['Offset'] : 0; + } } } diff --git a/src/Models/QueryModel/DVDQueryModel.php b/src/Models/QueryModel/DVDQueryModel.php index 537a691..fccf2d2 100644 --- a/src/Models/QueryModel/DVDQueryModel.php +++ b/src/Models/QueryModel/DVDQueryModel.php @@ -5,9 +5,6 @@ class DVDQueryModel extends BaseQueryModel { public bool|null $IsOffered = null; - public string|null $OrderBy = null; - public string|null $OrderDesc = null; - public string|null $Search = null; public function getQueryString(): string { @@ -25,11 +22,8 @@ public function setFromQueryString(array $param): void $this->IsOffered = array_key_exists('IsOffered', $param) && $param['IsOffered'] !== '' ? filter_var($param['IsOffered'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : null; - $this->OrderBy = $param['OrderBy'] ?? ''; - $this->OrderDesc = $param['OrderDesc'] ?? ''; - $this->Search = $param['Search'] ?? ''; - $this->Limit = isset($param['Limit']) ? (int)$param['Limit'] : 10; - $this->Offset = isset($param['Offset']) ? (int)$param['Offset'] : 0; + + parent::setFromListingQueryString($param); } } } diff --git a/src/Models/ViewModels/HomeViewModel.php b/src/Models/ViewModels/HomeViewModel.php index 3beb7c6..99f507f 100644 --- a/src/Models/ViewModels/HomeViewModel.php +++ b/src/Models/ViewModels/HomeViewModel.php @@ -4,9 +4,15 @@ { use Interfaces\IViewModel; + use Models\QueryModel\DVDQueryModel; class HomeViewModel implements IViewModel { + public array $DVDs; + public int $FilteredCount; + public DVDQueryModel $Query; + public int $TotalPages; + public int $CurrentPage; } } \ No newline at end of file diff --git a/src/Services/DVDService.php b/src/Services/DVDService.php index a41f8ad..ebe683b 100644 --- a/src/Services/DVDService.php +++ b/src/Services/DVDService.php @@ -6,6 +6,7 @@ use Exception; use Models\DVDModel; use Models\QueryModel\DVDQueryModel; + use Utils\Query\InsertQueryBuilder; use Utils\Query\QueryBuilder; use Utils\Query\UpdateQueryBuilder; @@ -51,7 +52,7 @@ public function getAll(DVDQueryModel $queryModel): array { $result = array(); $queryBuilder = (new QueryBuilder()) - ->select(["Id", "Title", "LocalTitle", "Synopsis", "Notation", "Note", "Certification", "IsOffered", "Quantity", "Price", "Year"]) + ->select(["Id", "LocalTitle", "Notation", "Certification", "IsOffered", "Quantity", "Price", "Year", "Image", "TypeId"]) ->from("dvds") ->limit($queryModel->Offset, $queryModel->Limit); @@ -122,7 +123,7 @@ public function update(DVDModel $dvd) ->set("Quantity", $dvd->Quantity) ->set("Price", $dvd->Price) ->set("Year", $dvd->Year) - //->set("Image", $dvd->Image) + ->set("Image", $dvd->Image) ->set("TypeId", $dvd->TypeId) ->where("Id", "=", $dvd->Id); @@ -132,6 +133,28 @@ public function update(DVDModel $dvd) $queryResult = $this->fetchStatement($query->sql, $query->params, DVDModel::class); } + public function insert(DVDModel $dvd) + { + $queryBuilder = (new InsertQueryBuilder()) + ->insert("dvds") + ->value("Title", $dvd->Title) + ->value("LocalTitle", $dvd->LocalTitle) + ->value("Synopsis", $dvd->Synopsis) + ->value("Notation", $dvd->Notation) + ->value("Certification", $dvd->Certification) + ->value("Note", $dvd->Note) + ->value("IsOffered", $dvd->IsOffered) + ->value("Quantity", $dvd->Quantity) + ->value("Price", $dvd->Price) + ->value("Year", $dvd->Year) + ->value("Image", $dvd->Image) + ->value("TypeId", $dvd->TypeId); + + $query = $queryBuilder->getQuery(); + + return $this->insertStatement($query->sql, $query->params); + } + function isAllowedOrderColumn(string $column): bool { $allowedOrderColumns = array("Quantity", "Year", "Title", "IsOffered", "Price"); diff --git a/src/Services/DataService.php b/src/Services/DataService.php index 484a157..6a8628e 100644 --- a/src/Services/DataService.php +++ b/src/Services/DataService.php @@ -94,6 +94,15 @@ protected function executeStatement($statement, $parameters) return $query->execute($parameters); } + protected function insertStatement($statement, $parameters) + { + $this->validateStatementAndParameters($statement, $parameters); + + $query = $this->GetDBContext()->prepare($statement); + $query->execute($parameters); + return $this->GetDBContext()->lastInsertId(); + } + protected function fetchValue($statement, $parameters) { $this->validateStatementAndParameters($statement, $parameters); diff --git a/src/Utils/Components/FormImageComponent/FormImageComponent.php b/src/Utils/Components/FormImageComponent/FormImageComponent.php index e3db69d..1d0694a 100644 --- a/src/Utils/Components/FormImageComponent/FormImageComponent.php +++ b/src/Utils/Components/FormImageComponent/FormImageComponent.php @@ -12,13 +12,11 @@ class FormImageComponent public bool $required; public bool $readOnly; - public function __construct(string $name, string $label, ?string $value, ?string $base64Value, ?string $imgType, bool $required = true, bool $readOnly = true) + public function __construct(string $name, string $label, ?string $base64Value, bool $required = true, bool $readOnly = true) { $this->name = $name; $this->label = $label; - $this->value = $value; $this->base64Value = $base64Value; - $this->imgType = $imgType; $this->required = $required; $this->readOnly = $readOnly; } diff --git a/src/Utils/Components/FormImageComponent/FormImageComponent.template.php b/src/Utils/Components/FormImageComponent/FormImageComponent.template.php index 5a43a1c..fcda37b 100644 --- a/src/Utils/Components/FormImageComponent/FormImageComponent.template.php +++ b/src/Utils/Components/FormImageComponent/FormImageComponent.template.php @@ -1,11 +1,11 @@ \ No newline at end of file diff --git a/src/Utils/ComponentsUtils.php b/src/Utils/ComponentsUtils.php index e42aa29..b9120dc 100644 --- a/src/Utils/ComponentsUtils.php +++ b/src/Utils/ComponentsUtils.php @@ -33,9 +33,9 @@ public static function getNumberComponent($name, $label, $value, $min, $max, $st $comp = new FormNumberComponent($name, $label, $value, $min, $max, $step, $required, $readOnly); return $comp->getRenderedComponent(); } - public static function getImageComponent($name, $label, $value, $valueBase64, $imgType, $required, $readOnly):string + public static function getImageComponent($name, $label, $valueBase64, $required, $readOnly):string { - $comp = new FormImageComponent($name, $label, $value, $valueBase64, $imgType, $required, $readOnly); + $comp = new FormImageComponent($name, $label, $valueBase64, $required, $readOnly); return $comp->getRenderedComponent(); } diff --git a/src/Utils/Query/InsertQueryBuilder.php b/src/Utils/Query/InsertQueryBuilder.php new file mode 100644 index 0000000..4ea80c0 --- /dev/null +++ b/src/Utils/Query/InsertQueryBuilder.php @@ -0,0 +1,56 @@ +params = []; + } + + public function insert($table) { + $this->table = $table; + return $this; + } + + public function value($column, $value) { + $this->col[] = $column; + $this->params[] = $value; + return $this; + } + + public function getQuery():QueryModel { + $sql = "INSERT INTO " . $this->table; + $sql .= " ( " . implode(', ', $this->col) . ") "; + + $sql .= " VALUES ("; + $firstParam = true; + foreach ($this->params as $param) { + if($firstParam) + { + $firstParam = false; + $sql .= "?"; + } + else + { + $sql .= ", ?"; + } + } + + $sql .= " )"; + $sql .= ";"; + $result = new QueryModel(); + $result->sql = $sql; + $result->params = $this->params; + + return $result; + } + } +} + diff --git a/src/Views/Home/HomeView.js b/src/Views/Home/HomeView.js new file mode 100644 index 0000000..5f29ffc --- /dev/null +++ b/src/Views/Home/HomeView.js @@ -0,0 +1,8 @@ +function search() { + let url = new URL(window.location.href); + const query = document.querySelector('#dvd-search-input').value.trim(); + if (query) { + url.searchParams.set("Search", query); + } + window.location.href = url.toString(); +} \ No newline at end of file diff --git a/src/Views/Home/HomeView.style.css b/src/Views/Home/HomeView.style.css index e69de29..6cd0346 100644 --- a/src/Views/Home/HomeView.style.css +++ b/src/Views/Home/HomeView.style.css @@ -0,0 +1,85 @@ +.search-bar { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + +.search-input { + padding: 10px; + border: none; + border-radius: 4px 0 0 4px; + width: 70%; + background-color: #3B4252; + color: #D8DEE9; + font-size: 16px; +} + +.search-button { + padding: 10px 20px; + border: none; + border-radius: 0 4px 4px 0; + background-color: #81A1C1; + color: white; + cursor: pointer; +} + +.search-button:hover { + background-color: #88C0D0; +} + +.card-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 20px; + justify-content: space-around; +} + +.card { + background-color: #2E3440; + flex-basis: 15%; + border-radius: 8px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + position: relative; + overflow: hidden; + max-width: 512px; +} + +.card-content { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + width: 100%; + height: 100%; + padding: 20px; +} + +.no-preview { + text-align: center; + color: #D8DEE9; + font-size: 18px; + font-weight: bold; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + aspect-ratio: 1 / 1.5; + position: relative; + background-color: #3B4252; + border-radius: 4px; +} + +.no-preview span { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border: 2px solid #D8DEE9; + padding: 10px 20px; + border-radius: 4px; +} diff --git a/src/Views/Home/HomeView.template.php b/src/Views/Home/HomeView.template.php index 6ffcaa2..5c4cd23 100644 --- a/src/Views/Home/HomeView.template.php +++ b/src/Views/Home/HomeView.template.php @@ -1,3 +1,17 @@ -
- Welcome! -
\ No newline at end of file + + +