From 2c9da150591769be34bf944321c74cb823c017ad Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Thu, 24 Oct 2024 01:14:55 +0300 Subject: [PATCH] dumb bithcc penis dick negro jews in ukraine --- .../arming_bot/system/controllers/cart.php | 71 ++++++- .../arming_bot/system/controllers/catalog.php | 33 +-- mirzaev/arming_bot/system/models/product.php | 14 +- mirzaev/arming_bot/system/public/js/cart.js | 150 +++++++------ .../arming_bot/system/public/js/catalog.js | 199 ++++++++++-------- .../system/public/themes/default/css/cart.css | 115 ++++++++++ .../public/themes/default/css/catalog.css | 11 +- .../themes/default/css/icons/corner.css | 61 ++++++ .../themes/default/css/icons/list_add.css | 55 +++++ .../public/themes/default/css/icons/minus.css | 3 + .../public/themes/default/css/icons/plus.css | 47 +++-- .../public/themes/default/css/icons/trash.css | 49 +++++ .../system/public/themes/default/css/main.css | 15 +- .../public/themes/default/css/window.css | 1 + .../default/cart/elements/categories.html | 5 + .../default/cart/elements/products.html | 44 ++++ .../views/themes/default/cart/page.html | 22 ++ .../default/catalog/elements/products.html | 12 +- .../system/views/themes/default/head.html | 1 + 19 files changed, 702 insertions(+), 206 deletions(-) create mode 100644 mirzaev/arming_bot/system/public/themes/default/css/cart.css create mode 100755 mirzaev/arming_bot/system/public/themes/default/css/icons/corner.css create mode 100755 mirzaev/arming_bot/system/public/themes/default/css/icons/list_add.css create mode 100755 mirzaev/arming_bot/system/public/themes/default/css/icons/trash.css create mode 100755 mirzaev/arming_bot/system/views/themes/default/cart/elements/categories.html create mode 100755 mirzaev/arming_bot/system/views/themes/default/cart/elements/products.html create mode 100755 mirzaev/arming_bot/system/views/themes/default/cart/page.html diff --git a/mirzaev/arming_bot/system/controllers/cart.php b/mirzaev/arming_bot/system/controllers/cart.php index a166020..ad2ad21 100755 --- a/mirzaev/arming_bot/system/controllers/cart.php +++ b/mirzaev/arming_bot/system/controllers/cart.php @@ -6,8 +6,10 @@ namespace mirzaev\arming_bot\controllers; // Files of the project use mirzaev\arming_bot\controllers\core, + mirzaev\arming_bot\models\cart as model, mirzaev\arming_bot\models\product, - mirzaev\arming_bot\models\cart as model; + mirzaev\arming_bot\models\menu, + mirzaev\arming_bot\models\enumerations\language; // Framework for ArangoDB use mirzaev\arangodb\document; @@ -28,9 +30,74 @@ final class cart extends core protected array $errors = [ 'session' => [], 'account' => [], - 'cart' => [] + 'cart' => [], + 'menu' => [], ]; + /** + * Cart + * + * @param array $parameters Parameters of the request (POST + GET) + */ + public function index(array $parameters = []): ?string + { + if (isset($menu)) { + // + + } else { + // Not received ... menu + + // Search for filters and write to the buffer of global variables of view templater + $this->view->menu = menu::_read( + return: 'MERGE(d, { name: d.name.@language })', + sort: 'd.position ASC, d.created DESC, d._key DESC', + amount: 4, + parameters: ['language' => $this->language->name], + errors: $this->errors['menu'] + ); + } + + if ($_SERVER['REQUEST_METHOD'] === 'GET') { + // GET request + + // Exit (success) + return $this->view->render('cart/page.html', [ + 'h2' => $this->language === language::ru ? 'Корзина' : 'Cart' // @see https://git.mirzaev.sexy/mirzaev/huesos/issues/1 + ]); + } else if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // POST request + + // Initializing a response headers + header('Content-Type: application/json'); + header('Content-Encoding: none'); + header('X-Accel-Buffering: no'); + + // Initializing of the output buffer + ob_start(); + + // Generating the reponse + echo json_encode( + [ + 'main' => '', + 'errors' => $this->errors + ] + ); + + // Initializing a response headers + header('Content-Length: ' . ob_get_length()); + + // Sending and deinitializing of the output buffer + ob_end_flush(); + flush(); + + // Exit (success) + return null; + } + + // Exit (fail) + return null; + } + /** * Product * diff --git a/mirzaev/arming_bot/system/controllers/catalog.php b/mirzaev/arming_bot/system/controllers/catalog.php index 8f6f5e7..194cbef 100755 --- a/mirzaev/arming_bot/system/controllers/catalog.php +++ b/mirzaev/arming_bot/system/controllers/catalog.php @@ -46,19 +46,19 @@ final class catalog extends core if (!empty($parameters['product']) && preg_match('/[\d]+/', $parameters['product'], $matches)) $product = (int) $matches[0]; if (isset($product)) { - // received and validated identifier of the product + // Received and validated identifier of the product // Search for the product data and write to the buffer of global variables of view templater $this->view->product = product::read( filter: "d.identifier == @identifier && d.deleted != true && d.hidden != true", sort: 'd.created DESC', amount: 1, - return: '{name: d.name.@language, description: d.description.@language, cost: d.cost, weight: d.weight, dimensions: d.dimensions, brand: d.brand.@language, compatibility: d.compatibility.@language, cost: d.cost.@currency, images: d.images[*].storage}', + return: '{identifier: d.identifier, name: d.name.@language, description: d.description.@language, cost: d.cost, weight: d.weight, dimensions: d.dimensions, brand: d.brand.@language, compatibility: d.compatibility.@language, cost: d.cost.@currency, images: d.images[*].storage}', language: $this->language, currency: $this->currency, parameters: ['identifier' => $product], errors: $this->errors['catalog'] - )[0]?->getAll() ?? null; + )?->getAll(); } // Intializing buffer of query parameters @@ -296,19 +296,23 @@ final class catalog extends core ) ?? null; } - // Search among products in the $category - if (isset($this->view->products) && count($this->view->products) > 0) { - // Amount of rendered products is more than 0 + if (isset($brand) || (isset($this->view->products) && count($this->view->products) > 0)) { + // Received and validated at least one of filters or amount of rendered products is more than 0 // Search for filters and write to the buffer of global variables of view templater $this->view->filters = [ 'brands' => product::collect( return: 'd.brand.@language', - products: array_map(fn(_document $document): string => $document->getId(), $this->view->products), + products: array_map(fn(_document $document): string => $document->getId(), $this->view->products ?? []), language: $this->language, errors: $this->errors['catalog'] ) ]; + } + + // Search among products in the $category + if (isset($text) || isset($this->view->products) && count($this->view->products) > 0) { + // Amount of rendered products is more than 0 // Search for products and write to the buffer of global variables of view templater $this->view->products = product::read( @@ -347,11 +351,16 @@ final class catalog extends core // Initialized the product data // Writing javascript code that has been executed after core and damper has been loaded - $this->view->javascript = [<< core.catalog.product_system('$product'), 500); - } - javascript] + ($this->view->javascript ?? []); + $this->view->javascript = [ + sprintf( + << core.catalog.product_system('%s'), 500); + } + javascript, + $this->view->product['identifier'] + ) + ] + ($this->view->javascript ?? []); } // Exit (success) diff --git a/mirzaev/arming_bot/system/models/product.php b/mirzaev/arming_bot/system/models/product.php index abae9ed..0ed3aa9 100755 --- a/mirzaev/arming_bot/system/models/product.php +++ b/mirzaev/arming_bot/system/models/product.php @@ -130,8 +130,8 @@ final class product extends core implements document_interface, collection_inter * @param array &$errors Registry of errors * * @return array|static Found products or instance of the product from ArangoDB (can be empty) - * - * @todo убрать language и currency + * + * @todo убрать language и currency */ public static function read( ?string $search = null, @@ -205,7 +205,7 @@ final class product extends core implements document_interface, collection_inter ); if ($amount === 1 && $result instanceof _document) { - // Found product @todo need to rebuild this + // Found the product @todo need to rebuild this // Initializing the object $product = new static; @@ -219,10 +219,12 @@ final class product extends core implements document_interface, collection_inter // Exit (success) return $product; } else throw new exception('Class ' . static::class . ' does not implement a document from ArangoDB'); - } + } else if (!empty($result)) { + // Found products - // Exit (success) - return is_array($result) ? $result : [$result]; + // Exit (success) + return is_array($result) ? $result : [$result]; + } } else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION); } catch (exception $e) { // Writing to the registry of errors diff --git a/mirzaev/arming_bot/system/public/js/cart.js b/mirzaev/arming_bot/system/public/js/cart.js index 2701fa1..8166060 100755 --- a/mirzaev/arming_bot/system/public/js/cart.js +++ b/mirzaev/arming_bot/system/public/js/cart.js @@ -44,12 +44,12 @@ import("/js/core.js").then(() => * * @return {bool} True if an error occurs to continue the event execution */ - static toggle(button, force = false) { + static toggle(button, product, force = false) { // Blocking the button button.setAttribute("disabled", "true"); // Execute under damper - this.toggle_damper(button, force); + this.toggle_damper(button, product, force); // Exit (success) return false; @@ -82,16 +82,13 @@ import("/js/core.js").then(() => * * @todo add unblocking button by timer + everywhere */ - static async toggle_system(button) { - if (button instanceof HTMLElement) { + static async toggle_system(button, product) { + if ( + product instanceof HTMLElement && + button instanceof HTMLElement + ) { // Validated - // Initializing of the wrap of buttons - const wrap = button.parentElement; - - // Initializing of the product - const product = wrap.parentElement; - // Initializing of identifier of the product const identifier = product.getAttribute( "data-product-identifier", @@ -118,9 +115,9 @@ import("/js/core.js").then(() => button.removeAttribute("disabled"); // Writing offset of hue-rotate to indicate that the product is in the cart - wrap.style.setProperty( + product.style.setProperty( "--hue-rotate-offset", - json.amount + '0deg', + json.amount + "0deg", ); // Writing attribute with amount of the product in the cart @@ -130,15 +127,24 @@ import("/js/core.js").then(() => ); // Initializing the amount element - const amount = wrap.querySelector( - 'span[data-product-button-text="amount"]', + const amounts = product.querySelectorAll( + 'span[data-product-parameter="amount"]', ); - if (amount instanceof HTMLElement) { - // Initialized the amount element + for (const amount of amounts) { + // Iterating over an amount elements - // Writing amount of the product in the cart - amount.innerText = json.amount; + if (amount instanceof HTMLInputElement) { + // The element + + // Writing amount of the product in the cart + amount.value = json.amount; + } else { + // Not the element + + // Writing amount of the product in the cart + amount.innerText = json.amount; + } } } }); @@ -157,7 +163,7 @@ import("/js/core.js").then(() => * * @return {bool} True if an error occurs to continue the event execution */ - static write(button, amount = 1, force = false) { + static write(button, product, amount = 1, force = false) { // Blocking the button button.setAttribute("disabled", "true"); @@ -197,8 +203,9 @@ import("/js/core.js").then(() => * * @todo add unblocking button by timer + everywhere */ - static async write_system(button, amount = 1) { + static async write_system(button, product, amount = 1) { if ( + product instanceof HTMLElement && button instanceof HTMLElement && typeof amount === "number" && amount > -1 && @@ -206,12 +213,6 @@ import("/js/core.js").then(() => ) { // Validated - // Initializing of the wrap of buttons - const wrap = button.parentElement; - - // Initializing of the product - const product = wrap.parentElement; - // Initializing of identifier of the product const identifier = product.getAttribute( "data-product-identifier", @@ -238,9 +239,9 @@ import("/js/core.js").then(() => button.removeAttribute("disabled"); // Writing offset of hue-rotate to indicate that the product is in the cart - wrap.style.setProperty( + product.style.setProperty( "--hue-rotate-offset", - json.amount + '0deg', + json.amount + "0deg", ); // Writing attribute with amount of the product in the cart @@ -250,15 +251,24 @@ import("/js/core.js").then(() => ); // Initializing the amount element - const amount = wrap.querySelector( - 'span[data-product-button-text="amount"]', + const amounts = product.querySelectorAll( + 'span[data-product-parameter="amount"]', ); - if (amount instanceof HTMLElement) { - // Initialized the amount element + for (const amount of amounts) { + // Iterating over an amount elements - // Writing amount of the product in the cart - amount.innerText = json.amount; + if (amount instanceof HTMLInputElement) { + // The element + + // Writing amount of the product in the cart + amount.value = json.amount; + } else { + // Not the element + + // Writing amount of the product in the cart + amount.innerText = json.amount; + } } } }); @@ -277,7 +287,7 @@ import("/js/core.js").then(() => * * @return {bool} True if an error occurs to continue the event execution */ - static delete(button, amount = 1, force = false) { + static delete(button, product, amount = 1, force = false) { // Blocking the button button.setAttribute("disabled", "true"); @@ -317,8 +327,9 @@ import("/js/core.js").then(() => * * @todo add unblocking button by timer + everywhere */ - static async delete_system(button, amount = 1) { + static async delete_system(button, product, amount = 1) { if ( + product instanceof HTMLElement && button instanceof HTMLElement && typeof amount === "number" && amount > 0 && @@ -326,12 +337,6 @@ import("/js/core.js").then(() => ) { // Validated - // Initializing of the wrap of buttons - const wrap = button.parentElement; - - // Initializing of the product - const product = wrap.parentElement; - // Initializing of identifier of the product const identifier = product.getAttribute( "data-product-identifier", @@ -358,9 +363,9 @@ import("/js/core.js").then(() => button.removeAttribute("disabled"); // Writing offset of hue-rotate to indicate that the product is in the cart - wrap.style.setProperty( + product.style.setProperty( "--hue-rotate-offset", - json.amount + '0deg', + json.amount + "0deg", ); // Writing attribute with amount of the product in the cart @@ -370,15 +375,24 @@ import("/js/core.js").then(() => ); // Initializing the amount element - const amount = wrap.querySelector( - 'span[data-product-button-text="amount"]', + const amounts = product.querySelectorAll( + 'span[data-product-parameter="amount"]', ); - if (amount instanceof HTMLElement) { - // Initialized the amount element + for (const amount of amounts) { + // Iterating over an amount elements - // Writing amount of the product in the cart - amount.innerText = json.amount; + if (amount instanceof HTMLInputElement) { + // The element + + // Writing amount of the product in the cart + amount.value = json.amount; + } else { + // Not the element + + // Writing amount of the product in the cart + amount.innerText = json.amount; + } } } }); @@ -397,7 +411,7 @@ import("/js/core.js").then(() => * * @return {bool} True if an error occurs to continue the event execution */ - static set(button, amount = 1, force = false) { + static set(button, product, amount = 1, force = false) { // Blocking the button button.setAttribute("disabled", "true"); @@ -437,8 +451,9 @@ import("/js/core.js").then(() => * * @todo add unblocking button by timer + everywhere */ - static async set_system(button, amount = 1) { + static async set_system(button, product, amount = 1) { if ( + product instanceof HTMLElement && button instanceof HTMLElement && typeof amount === "number" && amount > -1 && @@ -446,12 +461,6 @@ import("/js/core.js").then(() => ) { // Validated - // Initializing of the wrap of buttons - const wrap = button.parentElement; - - // Initializing of the product - const product = wrap.parentElement; - // Initializing of identifier of the product const identifier = product.getAttribute( "data-product-identifier", @@ -478,9 +487,9 @@ import("/js/core.js").then(() => button.removeAttribute("disabled"); // Writing offset of hue-rotate to indicate that the product is in the cart - wrap.style.setProperty( + product.style.setProperty( "--hue-rotate-offset", - json.amount + '0deg', + json.amount + "0deg", ); // Writing attribute with amount of the product in the cart @@ -490,15 +499,24 @@ import("/js/core.js").then(() => ); // Initializing the amount element - const amount = wrap.querySelector( - 'span[data-product-button-text="amount"]', + const amounts = product.querySelectorAll( + 'span[data-product-parameter="amount"]', ); - if (amount instanceof HTMLElement) { - // Initialized the amount element + for (const amount of amounts) { + // Iterating over an amount elements - // Writing amount of the product in the cart - amount.innerText = json.amount; + if (amount instanceof HTMLInputElement) { + // The element + + // Writing amount of the product in the cart + amount.value = json.amount; + } else { + // Not the element + + // Writing amount of the product in the cart + amount.innerText = json.amount; + } } } }); diff --git a/mirzaev/arming_bot/system/public/js/catalog.js b/mirzaev/arming_bot/system/public/js/catalog.js index 42d4899..bc7d58a 100755 --- a/mirzaev/arming_bot/system/public/js/catalog.js +++ b/mirzaev/arming_bot/system/public/js/catalog.js @@ -50,8 +50,9 @@ import("/js/core.js").then(() => this.element_search.getElementsByTagName("input")[0]; // Categories
- static element_categories = - document.getElementById("categories"); + static element_categories = document.getElementById( + "categories", + ); // Filters
static element_filters = document.getElementById("filters"); @@ -75,7 +76,7 @@ import("/js/core.js").then(() => [ "category", new URLSearchParams(document.location.search).get( - "category" + "category", ), ], [ @@ -128,6 +129,12 @@ import("/js/core.js").then(() => if (event.keyCode === 13) { // Executed by "enter" button + // Blocking the search element + this.element_search_input.setAttribute( + "disabled", + true, + ); + // Execute this.search_system(); } else if (this.element_search_input.value.length < 3) { @@ -169,7 +176,7 @@ import("/js/core.js").then(() => static search_damper = core.damper( (...variables) => this.search_system(...variables), 1400, - 1 + 1, ); /** @@ -182,14 +189,11 @@ import("/js/core.js").then(() => * @todo add animations of errors */ static async search_system() { - // Blocking the search element - this.element_search_input.setAttribute("disabled", true); - // @todo add timeout to unblock // Initialize the buffer of URN parameters const parameters = new URLSearchParams( - window.location.search + window.location.search, ); // Iterate parameters @@ -250,7 +254,7 @@ import("/js/core.js").then(() => // Writing the title

element before the first element in the
element core.main.insertBefore( this.element_title, - first + first, ); } } @@ -289,14 +293,16 @@ import("/js/core.js").then(() => this.element_search.outerHTML = json.search; // Reinitializing the parameter with the search element - this.element_search = - document.getElementById("search"); + this.element_search = document.getElementById( + "search", + ); } else { // Not found the search element // Initialize the search element - this.element_search = - document.createElement("search"); + this.element_search = document.createElement( + "search", + ); if (core.main instanceof HTMLElement) { // Found the
element @@ -307,7 +313,7 @@ import("/js/core.js").then(() => // Writing the search element after the title

element in the
element core.main.insertBefore( this.element_search, - this.element_title.nextSibling + this.element_title.nextSibling, ); } else { // Not initialized the title

element in the
element @@ -321,7 +327,7 @@ import("/js/core.js").then(() => // Writing the search element before the first element in the
element core.main.insertBefore( this.element_search, - first + first, ); } } @@ -330,13 +336,14 @@ import("/js/core.js").then(() => this.element_search.outerHTML = json.search; // Reinitializing the parameter with the search element - this.element_search = - document.getElementById("search"); + this.element_search = document.getElementById( + "search", + ); // Reinitializing the parameter with the search element this.element_search_input = this.element_search.getElementsByTagName( - "input" + "input", )[0]; } } @@ -371,14 +378,16 @@ import("/js/core.js").then(() => this.element_categories.outerHTML = json.categories; // Reinitializing the parameter with the categories
element - this.element_categories = - document.getElementById("categories"); + this.element_categories = document.getElementById( + "categories", + ); } else { // Not found the categories
element // Initialize the categories
element - this.element_categories = - document.createElement("section"); + this.element_categories = document.createElement( + "section", + ); if (core.main instanceof HTMLElement) { // Found the
element @@ -389,7 +398,7 @@ import("/js/core.js").then(() => // Writing the categories
element after the search element in the
element core.main.insertBefore( this.element_categories, - this.element_search.nextSibling + this.element_search.nextSibling, ); } else if ( this.element_title instanceof HTMLElement @@ -399,7 +408,7 @@ import("/js/core.js").then(() => // Writing the categories
element after the title

element in the
element core.main.insertBefore( this.element_categories, - this.element_title.nextSibling + this.element_title.nextSibling, ); } else { // Not initialized the title

element in the
element @@ -413,7 +422,7 @@ import("/js/core.js").then(() => // Writing the categories
before the first element in the
element core.main.insertBefore( this.element_categories, - first + first, ); } } @@ -423,8 +432,9 @@ import("/js/core.js").then(() => json.categories; // Reinitializing the parameter with the categories
element - this.element_categories = - document.getElementById("categories"); + this.element_categories = document.getElementById( + "categories", + ); } } } else { @@ -454,14 +464,16 @@ import("/js/core.js").then(() => this.element_filters.outerHTML = json.filters; // Reinitializing the parameter with the filters
element - this.element_filters = - document.getElementById("filters"); + this.element_filters = document.getElementById( + "filters", + ); } else { // Not found the filters
element // Initialize the filters
element - this.element_filters = - document.createElement("section"); + this.element_filters = document.createElement( + "section", + ); if (core.main instanceof HTMLElement) { // Found the
element @@ -474,7 +486,7 @@ import("/js/core.js").then(() => // Writing the filters
element after the categories
element in the
element core.main.insertBefore( this.element_filters, - this.element_categories.nextSibling + this.element_categories.nextSibling, ); } else if ( this.element_search instanceof HTMLElement @@ -484,7 +496,7 @@ import("/js/core.js").then(() => // Writing the filters
element after the search element in the
element core.main.insertBefore( this.element_filters, - this.element_search.nextSibling + this.element_search.nextSibling, ); } else if ( this.element_title instanceof HTMLElement @@ -494,7 +506,7 @@ import("/js/core.js").then(() => // Writing the filters
element after the title

element in the
element core.main.insertBefore( this.element_filters, - this.element_title.nextSibling + this.element_title.nextSibling, ); } else { // Not initialized the title

element in the
element @@ -508,7 +520,7 @@ import("/js/core.js").then(() => // Writing the filters
before the first element in the
element core.main.insertBefore( this.element_filters, - first + first, ); } } @@ -517,8 +529,9 @@ import("/js/core.js").then(() => this.element_filters.outerHTML = json.filters; // Reinitializing the parameter with the filters
element - this.element_filters = - document.getElementById("filters"); + this.element_filters = document.getElementById( + "filters", + ); } } } else { @@ -548,14 +561,16 @@ import("/js/core.js").then(() => this.element_sorting.outerHTML = json.sorting; // Reinitializing the parameter with the sorting
element - this.element_sorting = - document.getElementById("sorting"); + this.element_sorting = document.getElementById( + "sorting", + ); } else { // Not found the sorting
element // Initialize the sorting
element - this.element_sorting = - document.createElement("section"); + this.element_sorting = document.createElement( + "section", + ); if (core.main instanceof HTMLElement) { // Found the
element @@ -566,7 +581,7 @@ import("/js/core.js").then(() => // Writing the sorting
element after the filters
element in the
element core.main.insertBefore( this.element_sorting, - this.element_filters.nextSibling + this.element_filters.nextSibling, ); } else if ( this.element_categories instanceof HTMLElement @@ -576,7 +591,7 @@ import("/js/core.js").then(() => // Writing the sorting
element after the categories
element in the
element core.main.insertBefore( this.element_sorting, - this.element_categories.nextSibling + this.element_categories.nextSibling, ); } else if ( this.element_search instanceof HTMLElement @@ -586,7 +601,7 @@ import("/js/core.js").then(() => // Writing the sorting
element after the search element in the
element core.main.insertBefore( this.element_sorting, - this.element_search.nextSibling + this.element_search.nextSibling, ); } else if ( this.element_title instanceof HTMLElement @@ -596,7 +611,7 @@ import("/js/core.js").then(() => // Writing the sorting
element after the title

element in the
element core.main.insertBefore( this.element_sorting, - this.element_title.nextSibling + this.element_title.nextSibling, ); } else { // Not initialized the title

element in the
element @@ -610,7 +625,7 @@ import("/js/core.js").then(() => // Writing the sorting
before the first element in the
element core.main.insertBefore( this.element_sorting, - first + first, ); } } @@ -619,8 +634,9 @@ import("/js/core.js").then(() => this.element_sorting.outerHTML = json.sorting; // Reinitializing the parameter with the sorting
element - this.element_sorting = - document.getElementById("sorting"); + this.element_sorting = document.getElementById( + "sorting", + ); } } } else { @@ -650,14 +666,16 @@ import("/js/core.js").then(() => this.element_products.outerHTML = json.products; // Reinitializing the parameter with the products
element - this.element_products = - document.getElementById("products"); + this.element_products = document.getElementById( + "products", + ); } else { // Not found the products
element element // Initialize the products
element - this.element_products = - document.createElement("section"); + this.element_products = document.createElement( + "section", + ); if (core.main instanceof HTMLElement) { // Found the
element @@ -668,7 +686,7 @@ import("/js/core.js").then(() => // Writing the products
element after the sorting
element in the
element core.main.insertBefore( this.element_products, - this.element_sorting.nextSibling + this.element_sorting.nextSibling, ); } else if ( this.element_filters instanceof HTMLElement @@ -678,7 +696,7 @@ import("/js/core.js").then(() => // Writing the products
element after the filters
element in the
element core.main.insertBefore( this.element_products, - this.element_filters.nextSibling + this.element_filters.nextSibling, ); } else if ( this.element_categories instanceof HTMLElement @@ -688,7 +706,7 @@ import("/js/core.js").then(() => // Writing the products
element after the categories
element in the
element core.main.insertBefore( this.element_products, - this.element_categories.nextSibling + this.element_categories.nextSibling, ); } else if ( this.element_search instanceof HTMLElement @@ -698,7 +716,7 @@ import("/js/core.js").then(() => // Writing the products
element after the search element in the
element core.main.insertBefore( this.element_products, - this.element_search.nextSibling + this.element_search.nextSibling, ); } else if ( this.element_title instanceof HTMLElement @@ -708,7 +726,7 @@ import("/js/core.js").then(() => // Writing the products
element after the title

element in the
element core.main.insertBefore( this.element_products, - this.element_title.nextSibling + this.element_title.nextSibling, ); } else { // Not initialized the title

element in the
element @@ -722,7 +740,7 @@ import("/js/core.js").then(() => // Writing the products
before the first element in the
element core.main.insertBefore( this.element_products, - first + first, ); } } @@ -731,8 +749,9 @@ import("/js/core.js").then(() => this.element_products.outerHTML = json.products; // Reinitializing the parameter with the products
element - this.element_products = - document.getElementById("products"); + this.element_products = document.getElementById( + "products", + ); } } } else { @@ -761,8 +780,8 @@ import("/js/core.js").then(() => */ static product(button, force = false) { // Initializing identifier of the category - const identifier = button.getAttribute( - "data-product-identifier" + const identifier = button.parentElement.getAttribute( + "data-product-identifier", ); // Execute under damper @@ -785,7 +804,7 @@ import("/js/core.js").then(() => static product_damper = core.damper( (...variables) => this.product_system(...variables), 400, - 1 + 1, ); /** @@ -802,12 +821,17 @@ import("/js/core.js").then(() => // Validated identifier // Initialize the buffer of URN parameters @todo after opening window add to document.location.search - const parameters = new URLSearchParams(); + const parameters = new URLSearchParams( + document.location.search, + ); // Write parameter to the buffer of URN parameters parameters.set("product", identifier); - return await core.request("?" + parameters).then((json) => { + // Intializing URI of the request + const uri = "?" + parameters; + + return await core.request(uri).then((json) => { if ( json.errors !== null && typeof json.errors === "object" && @@ -830,6 +854,9 @@ import("/js/core.js").then(() => ) { // Received data of the product + // Writing to the browser history + history.pushState({}, json.product.name, uri); + // Deinitializing of the old winow const old = document.getElementById("window"); if (old instanceof HTMLElement) old.remove(); @@ -874,11 +901,9 @@ import("/js/core.js").then(() => { let x = event.pageX || event.touches[0].pageX; let y = event.pageY || event.touches[0].pageY; - let _x = - images_from.pageX || + let _x = images_from.pageX || images_from.touches[0].pageX; - let _y = - images_from.pageY || + let _y = images_from.pageY || images_from.touches[0].pageY; if ( @@ -910,10 +935,10 @@ import("/js/core.js").then(() => const _close = (event) => { let x = event.pageX || event.touches[0].pageX; let y = event.pageY || event.touches[0].pageY; - let _x = - images_from.pageX || images_from.touches[0].pageX; - let _y = - images_from.pageY || images_from.touches[0].pageY; + let _x = images_from.pageX || + images_from.touches[0].pageX; + let _y = images_from.pageY || + images_from.touches[0].pageY; if ( event.type === "touchstart" || @@ -1019,6 +1044,7 @@ import("/js/core.js").then(() => const cost = document.createElement("p"); cost.classList.add("cost"); cost.innerText = json.product.cost + "р"; + console.log(json.product.cost); h3.append(name); exit.append(exit_icon); @@ -1037,21 +1063,19 @@ import("/js/core.js").then(() => document.body.append(wrap); // Reinitialize parameter - core.window = document.getElementById('window'); + core.window = document.getElementById("window"); let width = 0; let buffer; [...images.children].forEach( - (child) => - (width += - child.offsetWidth + - (isNaN( - (buffer = parseFloat( - getComputedStyle(child).marginRight - )) + (child) => (width += child.offsetWidth + + (isNaN( + buffer = parseFloat( + getComputedStyle(child).marginRight, + ), ) - ? 0 - : buffer)) + ? 0 + : buffer)), ); // блокировка закрытия карточки @@ -1064,17 +1088,18 @@ import("/js/core.js").then(() => if ( typeof event === "undefined" || event.type !== "popstate" - ) + ) { history.back(); + } wrap.remove(); images.removeEventListener( "mousedown", - _images_from + _images_from, ); images.removeEventListener( "touchstart", - _images_from + _images_from, ); wrap.removeEventListener("mousedown", _from); wrap.removeEventListener("touchstart", _from); @@ -1110,7 +1135,7 @@ import("/js/core.js").then(() => images.hotline = new core.hotline( json.product.identfier, - images + images, ); images.hotline.step = -0.3; images.hotline.wheel = true; diff --git a/mirzaev/arming_bot/system/public/themes/default/css/cart.css b/mirzaev/arming_bot/system/public/themes/default/css/cart.css new file mode 100644 index 0000000..f17f79f --- /dev/null +++ b/mirzaev/arming_bot/system/public/themes/default/css/cart.css @@ -0,0 +1,115 @@ +@charset "UTF-8"; + +main>section#products { + width: var(--width); + display: flex; + flex-direction: column; + gap: var(--gap); +} + +main>section#products>article.product { + position: relative; + width: 100%; + min-height: 5rem; + max-height: 8rem; + display: flex; + border-radius: 0.75rem; + overflow: hidden; + backdrop-filter: brightness(0.7); +} + +main>section#products>article.product:is(:hover, :focus)>* { + transition: 0s; +} + +main>section#products>article.product:not(:is(:hover, :focus))>* { + transition: 0.2s ease-out; +} + +main>section#products>article.product>a { + display: contents; +} + +main>section#products>article.product>a>img:first-of-type { + width: 5rem; + min-width: 5rem; + min-height: 100%; + object-fit: cover; + image-rendering: auto; +} + +main>section#products>article.product>div[data-product="body"] { + width: 100%; + padding: 0.5rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + overflow: hidden; +} + +main>section#products>article.product>div[data-product="body"]>p { + margin: unset; +} + +main>section#products>article.product>div[data-product="body"]>p.title { + z-index: 50; + padding: 0 0.4rem; + font-size: 0.8rem; + hyphens: auto; + overflow-wrap: anywhere; +} + +main>section#products>article.product>div[data-product="body"]>p.characteristics { + z-index: 30; + display: inline-flex; + flex-flow: row wrap; + gap: 0.3rem; + font-size: 0.6rem; + overflow: hidden; +} + +main>section#products>article.product>div[data-product="body"]>p.characteristics>span { + padding: 0.2rem 0.4rem; + border-radius: 0.75rem; + color: var(--tg-theme-accent_text_color); + background-color: var(--tg-theme-secondary-bg-color); +} + +main>section#products>article.product>div[data-product="body"]>p.cost { + z-index: 20; + margin-top: auto; + padding: 0 0.4rem; + font-size: 0.8rem; +} + +main>section#products>article.product>div[data-product="buttons"]:last-of-type { + z-index: 100; + flex-shrink: 0; + padding: 0.2rem 0rem; + display: flex; + flex-direction: column; + justify-content: space-between; + overflow: hidden; +} + +main>section#products>article.product>div[data-product="buttons"]:last-of-type>div.row { + padding: 0 0.6rem; + display: flex; + gap: 0.2rem; + justify-content: end; +} + +main>section#products>article.product>div[data-product="buttons"]:last-of-type>div.row>button { + padding: 0.4rem; + background: unset; +} + +main>section#products>article.product>div[data-product="buttons"]:last-of-type>div.row>button + button { + margin-left: 0.4rem; +} + +main>section#products>article.product>div[data-product="buttons"]:last-of-type>div.row>input { + width: 2rem; + padding: 0 0.3rem; + text-align: center; +} diff --git a/mirzaev/arming_bot/system/public/themes/default/css/catalog.css b/mirzaev/arming_bot/system/public/themes/default/css/catalog.css index 0101d40..a5b997f 100644 --- a/mirzaev/arming_bot/system/public/themes/default/css/catalog.css +++ b/mirzaev/arming_bot/system/public/themes/default/css/catalog.css @@ -1,6 +1,6 @@ @charset "UTF-8"; -main>section:is(#products, #categories) { +main>section#categories { width: var(--width); display: flex; flex-flow: row wrap; @@ -119,6 +119,7 @@ main>section#products>div.column>article.product>a { main>section#products>div.column>article.product>a>img:first-of-type { width: 100%; height: 100%; + image-rendering: auto; } main>section#products>div.column>article.product>a>img:first-of-type+* { @@ -155,12 +156,12 @@ main>section#products>div.column>article.product>div[data-product="buttons"]>but flex-grow: 1; } -main>section#products>div.column>article.product:is([data-product-amount="0"], [data-product-amount="1"])>div[data-product="buttons"]>button[data-product-button="toggle"]>span[data-product-button-text="amount"], +main>section#products>div.column>article.product:is([data-product-amount="0"], [data-product-amount="1"])>div[data-product="buttons"]>button[data-product-button="toggle"]>span[data-product-parametert="amount"], main>section#products>div.column>article.product[data-product-amount="0"]>div[data-product="buttons"]>button:is([data-product-button="write"], [data-product-button="delete"]) { display: none; } -main>section#products>div.column>article.product>div[data-product="buttons"]>button[data-product-button="toggle"]>span[data-product-button-text="amount"]:after { +main>section#products>div.column>article.product>div[data-product="buttons"]>button[data-product-button="toggle"]>span[data-product-parametert="amount"]:after { content: '*'; margin: 0 0.2rem; } @@ -170,11 +171,11 @@ main>section#products>div.column>article.product[data-product-amount]:not([data- } @container product-buttons (max-width: 200px) { - main>section#products>div.column>article.product>div[data-product="buttons"]>button[data-product-button="toggle"]>span:is([data-product-button-text="cost"], [data-product-button-text="currency"]) { + main>section#products>div.column>article.product>div[data-product="buttons"]>button[data-product-button="toggle"]>span:is([data-product-parametert="cost"], [data-product-parametert="currency"]) { display: none; } - main>section#products>div.column>article.product>div[data-product="buttons"]>button[data-product-button="toggle"]>span[data-product-button-text="amount"]:after { + main>section#products>div.column>article.product>div[data-product="buttons"]>button[data-product-button="toggle"]>span[data-product-parametert="amount"]:after { content: unset; } } diff --git a/mirzaev/arming_bot/system/public/themes/default/css/icons/corner.css b/mirzaev/arming_bot/system/public/themes/default/css/icons/corner.css new file mode 100755 index 0000000..15c907c --- /dev/null +++ b/mirzaev/arming_bot/system/public/themes/default/css/icons/corner.css @@ -0,0 +1,61 @@ +@charset "UTF-8"; + +i.icon.corner { + position: relative; + width: 22px; + height: 22px; + display: block; + box-sizing: border-box; +} + +i.icon.corner::after, +i.icon.corner::before { + content: ""; + position: absolute; + display: block; + box-sizing: border-box; +} + +i.icon.corner.left::after, +i.icon.corner.left::before { + left: 3px; +} + +i.icon.corner.right::after, +i.icon.corner.right::before { + right: 3px; +} + +i.icon.corner::after { + bottom: 3px; + width: 8px; + height: 8px; + transform: rotate(45deg); +} + +i.icon.corner.left::after { + border-left: 2px solid; + border-bottom: 2px solid; +} + +i.icon.corner.right::after { + border-top: 2px solid; + border-right: 2px solid; +} + +i.icon.corner::before { + bottom: 6px; + width: 16px; + height: 12px; + border-bottom: 2px solid; +} + +i.icon.corner.left::before { + border-bottom-right-radius: 4px; + border-right: 2px solid; +} + +i.icon.corner.right::before { + border-bottom-left-radius: 4px; + border-left: 2px solid; +} diff --git a/mirzaev/arming_bot/system/public/themes/default/css/icons/list_add.css b/mirzaev/arming_bot/system/public/themes/default/css/icons/list_add.css new file mode 100755 index 0000000..d131b98 --- /dev/null +++ b/mirzaev/arming_bot/system/public/themes/default/css/icons/list_add.css @@ -0,0 +1,55 @@ +@charset "UTF-8"; + +i.icon.list.add { + box-sizing: border-box; + position: relative; + display: block; + width: 12px; + height: 6px; + border-top: 0 solid transparent; + border-bottom: 2px solid transparent; + box-shadow: + inset 0 -2px 0, + -2px 4px 0 -2px, + 0 -2px 0 0; +} + +i.icon.list.add.small { + width: 10px; + box-shadow: + inset 0 -2px 0, + -1px 3px 0 -1px, + 0 -2px 0 0; +} + +i.icon.list.add::after, +i.icon.list.add::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 10px; + height: 2px; + background: currentColor; + top: 6px; + right: -8px; +} + +i.icon.list.add.small::after, +i.icon.list.add.small::before { + width: 8px; +} + +i.icon.list.add::before { + width: 2px; + height: 10px; + top: 2px; + right: -4px; +} + +i.icon.list.add.small::before { + width: 2px; + height: 8px; + top: 3px; + right: -5px; +} diff --git a/mirzaev/arming_bot/system/public/themes/default/css/icons/minus.css b/mirzaev/arming_bot/system/public/themes/default/css/icons/minus.css index 9e07218..726f3d7 100755 --- a/mirzaev/arming_bot/system/public/themes/default/css/icons/minus.css +++ b/mirzaev/arming_bot/system/public/themes/default/css/icons/minus.css @@ -10,3 +10,6 @@ i.icon.minus { border-radius: 10px; } +i.icon.minus.small { + width: 10px; +} diff --git a/mirzaev/arming_bot/system/public/themes/default/css/icons/plus.css b/mirzaev/arming_bot/system/public/themes/default/css/icons/plus.css index 88320aa..0919115 100755 --- a/mirzaev/arming_bot/system/public/themes/default/css/icons/plus.css +++ b/mirzaev/arming_bot/system/public/themes/default/css/icons/plus.css @@ -2,23 +2,34 @@ i.icon.plus, i.icon.plus::after { - display: block; - box-sizing: border-box; - background: currentColor; - border-radius: 10px; -} -i.icon.plus { - margin-top: -2px; - position: relative; - width: 16px; - height: 2px; -} -i.icon.plus::after { - content: ""; - position: absolute; - width: 2px; - height: 16px; - top: -7px; - left: 7px; + display: block; + box-sizing: border-box; + background: currentColor; + border-radius: 10px; } +i.icon.plus { + margin-top: -2px; + position: relative; + width: 16px; + height: 2px; +} + +i.icon.plus.small { + width: 10px; +} + +i.icon.plus::after { + content: ""; + position: absolute; + width: 2px; + height: 16px; + top: -7px; + left: 7px; +} + +i.icon.plus.small::after { + height: 10px; + top: -4px; + left: 4px; +} diff --git a/mirzaev/arming_bot/system/public/themes/default/css/icons/trash.css b/mirzaev/arming_bot/system/public/themes/default/css/icons/trash.css new file mode 100755 index 0000000..750c1f2 --- /dev/null +++ b/mirzaev/arming_bot/system/public/themes/default/css/icons/trash.css @@ -0,0 +1,49 @@ +@charset "UTF-8"; + +i.icon.trash { + box-sizing: border-box; + position: relative; + display: block; + width: 10px; + height: 12px; + border: 2px solid transparent; + box-shadow: + 0 0 0 2px, + inset -2px 0 0, + inset 2px 0 0; + border-bottom-left-radius: 1px; + border-bottom-right-radius: 1px; + margin-top: 4px; +} + +i.icon.trash.small { + height: 9px; +} + +i.icon.trash::after, +i.icon.trash::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; +} + +i.icon.trash::after { + background: currentColor; + border-radius: 3px; + width: 16px; + height: 2px; + top: -4px; + left: -5px; +} + +i.icon.trash::before { + width: 10px; + height: 4px; + border: 2px solid; + border-bottom: transparent; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + top: -7px; + left: -2px; +} diff --git a/mirzaev/arming_bot/system/public/themes/default/css/main.css b/mirzaev/arming_bot/system/public/themes/default/css/main.css index 7b0626d..aca3222 100755 --- a/mirzaev/arming_bot/system/public/themes/default/css/main.css +++ b/mirzaev/arming_bot/system/public/themes/default/css/main.css @@ -8,8 +8,6 @@ --socket-text: #b09999; } - - * { text-decoration: none; outline: none; @@ -88,6 +86,8 @@ main>search { overflow: clip; } +footer {} + search:has(input:is(:focus, :active)) { border-color: var(--tg-theme-accent-text-color); transition: unset; @@ -129,7 +129,8 @@ search:has(input:disabled) { backdrop-filter: contrast(0.5); } -button, *[type="button"] { +button, +*[type="button"] { cursor: pointer; } @@ -166,7 +167,13 @@ h2 { margin: 1rem 0 0; } -footer {} +input { + background: unset; +} + +.kabrio { + font-family: "Kabrio"; +} .unselectable { -webkit-touch-callout: none; diff --git a/mirzaev/arming_bot/system/public/themes/default/css/window.css b/mirzaev/arming_bot/system/public/themes/default/css/window.css index 71f66fd..9a375e5 100755 --- a/mirzaev/arming_bot/system/public/themes/default/css/window.css +++ b/mirzaev/arming_bot/system/public/themes/default/css/window.css @@ -89,6 +89,7 @@ section#window>div.card>div.images>img { flex-shrink: 0; flex-grow: 0; object-fit: cover; + image-rendering: auto; border-radius: 0.5rem; transition: 0s; } diff --git a/mirzaev/arming_bot/system/views/themes/default/cart/elements/categories.html b/mirzaev/arming_bot/system/views/themes/default/cart/elements/categories.html new file mode 100755 index 0000000..cb40127 --- /dev/null +++ b/mirzaev/arming_bot/system/views/themes/default/cart/elements/categories.html @@ -0,0 +1,5 @@ +{% if ASDASDASDASDASDASDSD is not empty %} +
+ +
+{% endif %} diff --git a/mirzaev/arming_bot/system/views/themes/default/cart/elements/products.html b/mirzaev/arming_bot/system/views/themes/default/cart/elements/products.html new file mode 100755 index 0000000..91296e0 --- /dev/null +++ b/mirzaev/arming_bot/system/views/themes/default/cart/elements/products.html @@ -0,0 +1,44 @@ +{% macro card(product, amount) %} +
+ + {{ product.name }} + +
+

+ {{ product.name | length > 65 ? product.name | slice(0, 65) ~ '...' : product.name }} +

+

+ {% for characteristic in [product.brand, format_dimensions(product.dimensions.x, + product.dimensions.y, product.dimensions.z, ' '), product.weight ~ (language.name == 'ru' ? 'г' : 'g')] %} + + {{ characteristic | length > 30 ? characteristic | slice(0, 30) ~ '...' : characteristic }} + + {% endfor %} +

+

+ {{ product.cost }} + {{ currency.symbol }} +

+
+
+
+ + +
+
0 %} style="--hue-rotate-offset: {{ amount }}0deg;"{% endif %}> + + + +
+
+
+{% endmacro %} +{% if cart is not empty %} +
+ {% for entry in cart %} + {{ _self.card(entry.product, amount) }} + {% endfor %} +
+{% endif %} diff --git a/mirzaev/arming_bot/system/views/themes/default/cart/page.html b/mirzaev/arming_bot/system/views/themes/default/cart/page.html new file mode 100755 index 0000000..7d2e197 --- /dev/null +++ b/mirzaev/arming_bot/system/views/themes/default/cart/page.html @@ -0,0 +1,22 @@ +{% extends "/themes/default/index.html" %} + +{% block css %} +{{ parent() }} + + + + + + +{% endblock %} + +{% block main %} +

{{ h2 }}

+{% include "/themes/default/cart/elements/products.html" %} +{% endblock %} + +{% block js %} +{{ parent() }} + + +{% endblock %} diff --git a/mirzaev/arming_bot/system/views/themes/default/catalog/elements/products.html b/mirzaev/arming_bot/system/views/themes/default/catalog/elements/products.html index e35d076..ecd08ad 100755 --- a/mirzaev/arming_bot/system/views/themes/default/catalog/elements/products.html +++ b/mirzaev/arming_bot/system/views/themes/default/catalog/elements/products.html @@ -12,13 +12,13 @@ product.dimensions.y, product.dimensions.z, ' ') ~ ' ' ~ product.weight ~ 'г' %

0 %} style="--hue-rotate-offset: {{ amount }}0deg;"{% endif %}> - - + - +
{% endmacro %} diff --git a/mirzaev/arming_bot/system/views/themes/default/head.html b/mirzaev/arming_bot/system/views/themes/default/head.html index e1d1085..ff7af2e 100755 --- a/mirzaev/arming_bot/system/views/themes/default/head.html +++ b/mirzaev/arming_bot/system/views/themes/default/head.html @@ -16,4 +16,5 @@ + {% endblock %}