dumb bithcc penis dick negro jews in ukraine
This commit is contained in:
parent
140e40e79a
commit
2c9da15059
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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 = [<<<javascript
|
||||
$this->view->javascript = [
|
||||
sprintf(
|
||||
<<<javascript
|
||||
if (typeof _window === 'undefined') {
|
||||
_window = setTimeout(() => core.catalog.product_system('$product'), 500);
|
||||
_window = setTimeout(() => core.catalog.product_system('%s'), 500);
|
||||
}
|
||||
javascript] + ($this->view->javascript ?? []);
|
||||
javascript,
|
||||
$this->view->product['identifier']
|
||||
)
|
||||
] + ($this->view->javascript ?? []);
|
||||
}
|
||||
|
||||
// Exit (success)
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
} else throw new exception('Failed to initialize ' . static::TYPE . ' collection: ' . static::COLLECTION);
|
||||
} catch (exception $e) {
|
||||
// Writing to the registry of errors
|
||||
|
|
|
@ -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,17 +127,26 @@ import("/js/core.js").then(() =>
|
|||
);
|
||||
|
||||
// Initializing the amount <span> 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 <span> element
|
||||
for (const amount of amounts) {
|
||||
// Iterating over an amount elements
|
||||
|
||||
if (amount instanceof HTMLInputElement) {
|
||||
// The <input> element
|
||||
|
||||
// Writing amount of the product in the cart
|
||||
amount.value = json.amount;
|
||||
} else {
|
||||
// Not the <input> 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,17 +251,26 @@ import("/js/core.js").then(() =>
|
|||
);
|
||||
|
||||
// Initializing the amount <span> 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 <span> element
|
||||
for (const amount of amounts) {
|
||||
// Iterating over an amount elements
|
||||
|
||||
if (amount instanceof HTMLInputElement) {
|
||||
// The <input> element
|
||||
|
||||
// Writing amount of the product in the cart
|
||||
amount.value = json.amount;
|
||||
} else {
|
||||
// Not the <input> 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,17 +375,26 @@ import("/js/core.js").then(() =>
|
|||
);
|
||||
|
||||
// Initializing the amount <span> 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 <span> element
|
||||
for (const amount of amounts) {
|
||||
// Iterating over an amount elements
|
||||
|
||||
if (amount instanceof HTMLInputElement) {
|
||||
// The <input> element
|
||||
|
||||
// Writing amount of the product in the cart
|
||||
amount.value = json.amount;
|
||||
} else {
|
||||
// Not the <input> 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,17 +499,26 @@ import("/js/core.js").then(() =>
|
|||
);
|
||||
|
||||
// Initializing the amount <span> 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 <span> element
|
||||
for (const amount of amounts) {
|
||||
// Iterating over an amount elements
|
||||
|
||||
if (amount instanceof HTMLInputElement) {
|
||||
// The <input> element
|
||||
|
||||
// Writing amount of the product in the cart
|
||||
amount.value = json.amount;
|
||||
} else {
|
||||
// Not the <input> element
|
||||
|
||||
// Writing amount of the product in the cart
|
||||
amount.innerText = json.amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,9 @@ import("/js/core.js").then(() =>
|
|||
this.element_search.getElementsByTagName("input")[0];
|
||||
|
||||
// Categories <section>
|
||||
static element_categories =
|
||||
document.getElementById("categories");
|
||||
static element_categories = document.getElementById(
|
||||
"categories",
|
||||
);
|
||||
|
||||
// Filters <section>
|
||||
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 <input> 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 <input> 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 <h2> element before the first element in the <main> 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 <search> element
|
||||
this.element_search =
|
||||
document.getElementById("search");
|
||||
this.element_search = document.getElementById(
|
||||
"search",
|
||||
);
|
||||
} else {
|
||||
// Not found the search <search> element
|
||||
|
||||
// Initialize the search <search> element
|
||||
this.element_search =
|
||||
document.createElement("search");
|
||||
this.element_search = document.createElement(
|
||||
"search",
|
||||
);
|
||||
|
||||
if (core.main instanceof HTMLElement) {
|
||||
// Found the <main> element
|
||||
|
@ -307,7 +313,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the search <search> element after the title <h2> element in the <main> element
|
||||
core.main.insertBefore(
|
||||
this.element_search,
|
||||
this.element_title.nextSibling
|
||||
this.element_title.nextSibling,
|
||||
);
|
||||
} else {
|
||||
// Not initialized the title <h2> element in the <main> element
|
||||
|
@ -321,7 +327,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the search <search> element before the first element in the <main> 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 <search> element
|
||||
this.element_search =
|
||||
document.getElementById("search");
|
||||
this.element_search = document.getElementById(
|
||||
"search",
|
||||
);
|
||||
|
||||
// Reinitializing the parameter with the search <input> 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 <section> element
|
||||
this.element_categories =
|
||||
document.getElementById("categories");
|
||||
this.element_categories = document.getElementById(
|
||||
"categories",
|
||||
);
|
||||
} else {
|
||||
// Not found the categories <section> element
|
||||
|
||||
// Initialize the categories <section> element
|
||||
this.element_categories =
|
||||
document.createElement("section");
|
||||
this.element_categories = document.createElement(
|
||||
"section",
|
||||
);
|
||||
|
||||
if (core.main instanceof HTMLElement) {
|
||||
// Found the <main> element
|
||||
|
@ -389,7 +398,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the categories <section> element after the search <search> element in the <main> 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 <section> element after the title <h2> element in the <main> element
|
||||
core.main.insertBefore(
|
||||
this.element_categories,
|
||||
this.element_title.nextSibling
|
||||
this.element_title.nextSibling,
|
||||
);
|
||||
} else {
|
||||
// Not initialized the title <h2> element in the <main> element
|
||||
|
@ -413,7 +422,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the categories <section> before the first element in the <main> 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 <section> 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 <section> element
|
||||
this.element_filters =
|
||||
document.getElementById("filters");
|
||||
this.element_filters = document.getElementById(
|
||||
"filters",
|
||||
);
|
||||
} else {
|
||||
// Not found the filters <section> element
|
||||
|
||||
// Initialize the filters <section> element
|
||||
this.element_filters =
|
||||
document.createElement("section");
|
||||
this.element_filters = document.createElement(
|
||||
"section",
|
||||
);
|
||||
|
||||
if (core.main instanceof HTMLElement) {
|
||||
// Found the <main> element
|
||||
|
@ -474,7 +486,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the filters <section> element after the categories <section> element in the <main> 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 <section> element after the search <search> element in the <main> 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 <section> element after the title <h2> element in the <main> element
|
||||
core.main.insertBefore(
|
||||
this.element_filters,
|
||||
this.element_title.nextSibling
|
||||
this.element_title.nextSibling,
|
||||
);
|
||||
} else {
|
||||
// Not initialized the title <h2> element in the <main> element
|
||||
|
@ -508,7 +520,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the filters <section> before the first element in the <main> 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 <section> 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 <section> element
|
||||
this.element_sorting =
|
||||
document.getElementById("sorting");
|
||||
this.element_sorting = document.getElementById(
|
||||
"sorting",
|
||||
);
|
||||
} else {
|
||||
// Not found the sorting <section> element
|
||||
|
||||
// Initialize the sorting <section> element
|
||||
this.element_sorting =
|
||||
document.createElement("section");
|
||||
this.element_sorting = document.createElement(
|
||||
"section",
|
||||
);
|
||||
|
||||
if (core.main instanceof HTMLElement) {
|
||||
// Found the <main> element
|
||||
|
@ -566,7 +581,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the sorting <section> element after the filters <section> element in the <main> 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 <section> element after the categories <section> element in the <main> 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 <section> element after the search <search> element in the <main> 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 <section> element after the title <h2> element in the <main> element
|
||||
core.main.insertBefore(
|
||||
this.element_sorting,
|
||||
this.element_title.nextSibling
|
||||
this.element_title.nextSibling,
|
||||
);
|
||||
} else {
|
||||
// Not initialized the title <h2> element in the <main> element
|
||||
|
@ -610,7 +625,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the sorting <section> before the first element in the <main> 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 <section> 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 <section> element
|
||||
this.element_products =
|
||||
document.getElementById("products");
|
||||
this.element_products = document.getElementById(
|
||||
"products",
|
||||
);
|
||||
} else {
|
||||
// Not found the products <section> element element
|
||||
|
||||
// Initialize the products <section> element
|
||||
this.element_products =
|
||||
document.createElement("section");
|
||||
this.element_products = document.createElement(
|
||||
"section",
|
||||
);
|
||||
|
||||
if (core.main instanceof HTMLElement) {
|
||||
// Found the <main> element
|
||||
|
@ -668,7 +686,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the products <section> element after the sorting <section> element in the <main> 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 <section> element after the filters <section> element in the <main> 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 <section> element after the categories <section> element in the <main> 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 <section> element after the search <search> element in the <main> 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 <section> element after the title <h2> element in the <main> element
|
||||
core.main.insertBefore(
|
||||
this.element_products,
|
||||
this.element_title.nextSibling
|
||||
this.element_title.nextSibling,
|
||||
);
|
||||
} else {
|
||||
// Not initialized the title <h2> element in the <main> element
|
||||
|
@ -722,7 +740,7 @@ import("/js/core.js").then(() =>
|
|||
// Writing the products <section> before the first element in the <main> 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 <section> 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 +
|
||||
(child) => (width += child.offsetWidth +
|
||||
(isNaN(
|
||||
(buffer = parseFloat(
|
||||
getComputedStyle(child).marginRight
|
||||
))
|
||||
buffer = parseFloat(
|
||||
getComputedStyle(child).marginRight,
|
||||
),
|
||||
)
|
||||
? 0
|
||||
: buffer))
|
||||
: 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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -10,3 +10,6 @@ i.icon.minus {
|
|||
border-radius: 10px;
|
||||
}
|
||||
|
||||
i.icon.minus.small {
|
||||
width: 10px;
|
||||
}
|
||||
|
|
|
@ -7,12 +7,18 @@ i.icon.plus::after {
|
|||
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;
|
||||
|
@ -22,3 +28,8 @@ i.icon.plus::after {
|
|||
left: 7px;
|
||||
}
|
||||
|
||||
i.icon.plus.small::after {
|
||||
height: 10px;
|
||||
top: -4px;
|
||||
left: 4px;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{% if ASDASDASDASDASDASDSD is not empty %}
|
||||
<section id="" class="unselectable">
|
||||
|
||||
</section>
|
||||
{% endif %}
|
|
@ -0,0 +1,44 @@
|
|||
{% macro card(product, amount) %}
|
||||
<article id="{{ product._id }}" class="product unselectable" data-product-identifier="{{ product.identifier }}"
|
||||
data-product-amount="{{ amount }}">
|
||||
<a data-product="cover" href="?product={{ product.identifier }}" onclick="return core.catalog.product(this);"
|
||||
onkeydown="event.keyCode === 13 && core.catalog.product(this)" tabindex="10">
|
||||
<img src="{{ product.images.0.storage }}" alt="{{ product.name }}" ondrugstart="return false;">
|
||||
</a>
|
||||
<div data-product="body">
|
||||
<p class="title" title="{{ product.name }}">
|
||||
{{ product.name | length > 65 ? product.name | slice(0, 65) ~ '...' : product.name }}
|
||||
</p>
|
||||
<p class="characteristics">
|
||||
{% for characteristic in [product.brand, format_dimensions(product.dimensions.x,
|
||||
product.dimensions.y, product.dimensions.z, ' '), product.weight ~ (language.name == 'ru' ? 'г' : 'g')] %}
|
||||
<span>
|
||||
{{ characteristic | length > 30 ? characteristic | slice(0, 30) ~ '...' : characteristic }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
<p class="cost">
|
||||
<span data-product-parameter="cost">{{ product.cost }}</span>
|
||||
<span data-product-parameter="currency">{{ currency.symbol }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div data-product="buttons">
|
||||
<div class="row">
|
||||
<button data-product-button="list" onclick="core.cart.list(this, document.getElementById('{{ product._id }}'))" title="{{ language.name == 'ru' ? 'Добавить в список' : 'Add to a list' }}"><i class="icon small list add"></i></button>
|
||||
<button data-product-button="toggle" onclick="core.cart.toggle(this, document.getElementById('{{ product._id }}'))" title="{{ language.name == 'ru' ? 'Удалить' : 'Delete' }}"><i class="icon small trash"></i></button>
|
||||
</div>
|
||||
<div class="row" {% if amount> 0 %} style="--hue-rotate-offset: {{ amount }}0deg;"{% endif %}>
|
||||
<button data-product-button="delete" onclick="core.cart.delete(this, document.getElementById('{{ product._id }}'), 1)" title="{{ language.name == 'ru' ? 'Уменьшить' : 'Decrease' }}"><i class="icon small minus"></i></button>
|
||||
<input type="text" value="{{ amount ?? 1 }}" title="{{ language.name == 'ru' ? 'Количество' : 'Amount' }}" data-product-parameter="amount" oninput="core.cart.set(this, document.getElementById('{{ product._id }}'), this.value)"></input>
|
||||
<button data-product-button="write" onclick="core.cart.write(this, document.getElementById('{{ product._id }}'), 1)" title="{{ language.name == 'ru' ? 'Увеличить' : 'Increase' }}"><i class="icon small plus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{% endmacro %}
|
||||
{% if cart is not empty %}
|
||||
<section id="products" class="unselectable">
|
||||
{% for entry in cart %}
|
||||
{{ _self.card(entry.product, amount) }}
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "/themes/default/index.html" %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/cart.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/trash.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/list_add.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/shopping_cart.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/plus.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/icons/minus.css" />
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<h2 class="unselectable">{{ h2 }}</h2>
|
||||
{% include "/themes/default/cart/elements/products.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script src="/js/cart.js"></script>
|
||||
<script src="/js/hotline.js"></script>
|
||||
{% endblock %}
|
|
@ -12,13 +12,13 @@ product.dimensions.y, product.dimensions.z, ' ') ~ ' ' ~ product.weight ~ 'г' %
|
|||
</p>
|
||||
</a>
|
||||
<div data-product="buttons"{% if amount > 0 %} style="--hue-rotate-offset: {{ amount }}0deg;"{% endif %}>
|
||||
<button data-product-button="delete" onclick="core.cart.delete(this, 1)"><i class="icon minus"></i></button>
|
||||
<button data-product-button="toggle" onclick="core.cart.toggle(this)" tabindex="15">
|
||||
<span data-product-button-text="amount">{{ amount }}</span>
|
||||
<span data-product-button-text="cost">{{ product.cost }}</span>
|
||||
<span data-product-button-text="currency">{{ currency.symbol }}</span>
|
||||
<button data-product-button="delete" onclick="core.cart.delete(this, document.getElementById('{{ product.getId() }}'), 1)" title="{{ language.name == 'ru' ? 'Уменьшить' : 'Decrease' }}"><i class="icon small minus"></i></button>
|
||||
<button data-product-button="toggle" onclick="core.cart.toggle(this, document.getElementById('{{ product.getId() }}'))" tabindex="15">
|
||||
<span data-product-parameter="amount">{{ amount }}</span>
|
||||
<span data-product-parameter="cost">{{ product.cost }}</span>
|
||||
<span data-product-parameter="currency">{{ currency.symbol }}</span>
|
||||
</button>
|
||||
<button data-product-button="write" onclick="core.cart.write(this, 1)"><i class="icon plus"></i></button>
|
||||
<button data-product-button="write" onclick="core.cart.write(this, document.getElementById('{{ product.getId() }}'), 1)" title="{{ language.name == 'ru' ? 'Увеличить' : 'Increase' }}"><i class="icon small plus"></i></button>
|
||||
</div>
|
||||
</article>
|
||||
{% endmacro %}
|
||||
|
|
|
@ -16,4 +16,5 @@
|
|||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/loading.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/window.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/fonts/dejavu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/{{ theme }}/css/fonts/kabrio.css" />
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in New Issue