(() => { // application/scripts/height_equaler.js var height_equaler = class { #to; #from; constructor(from, to) { this.#from = from; this.#to = to; this.#set_styles(); new ResizeObserver(() => { this.#update(); }).observe(from); setTimeout(() => { this.#update(); }, 100); } get height() { return this.#from.offsetHeight; } #set_styles() { this.#to.style.height = "0px"; this.#to.style.transition = "height 0.5s"; } #update() { this.#to.style.height = this.height + "px"; } }; // application/scripts/product.js var product = class _product { name; description; author; image; stock_count; barcode; thumbnail; on_stock; constructor(target) { this.name = null; this.description = null; this.author = null; this.image = null; this.stock_count = null; this.barcode = null; this.thumbnail = null; this.on_stock = null; if ("name" in target) this.name = target["name"]; if ("description" in target) this.description = target["description"]; if ("author" in target) this.author = target["author"]; if ("image" in target) this.image = target["image"]; if ("stock_count" in target) this.stock_count = target["stock_count"]; if ("barcode" in target) this.barcode = target["barcode"]; if ("thumbnail" in target) this.thumbnail = target["thumbnail"]; if ("on_stock" in target) this.on_stock = target["on_stock"]; } get dump() { const dumped = { "name": this.name, "description": this.description, "author": this.author, "image": this.image, "stock_count": this.stock_count, "barcode": this.barcode, "thumbnail": this.thumbnail }; if (this.on_stock !== null) { dumped["on_stock"] = this.on_stock; } return dumped; } get ready() { if (this.name === null || this.description === null) return false; if (this.author === null || this.image === null) return false; if (this.stock_count === null || this.barcode === null) return false; if (this.thumbnail === null) return false; return true; } copy() { return new _product(this.dump); } }; // application/scripts/products_loader.js var products_loader = class _products_loader { static async all() { const request2 = await fetch("/products/"); const response = await request2.json(); return _products_loader.#response_to_collection(response); } static #response_to_collection(response) { const result = new Array(); if (response.result !== "success") { return result; } response.collection.forEach((serialized) => { result.push(new product(serialized)); }); return result; } static async search_name(name) { return await _products_loader.#search( "/product/search/name", name ); } static async search_author(author) { return await _products_loader.#search( "/product/search/author", author ); } static async #search(path, parameter) { const coded = encodeURI(parameter); const request2 = await fetch(path + "/" + coded); const response = await request2.json(); return _products_loader.#response_to_collection(response); } }; // application/scripts/fullscreen.js var fullscreen = class { #node; constructor() { this.#node = null; } get visible() { return this.#node !== null; } _build_node() { throw new TypeError("This is virtual method!"); } get #opacity() { if (!this.visible) { throw new TypeError("Can not change opacity of not existed."); } return Number(this.#node.style.opacity); } set #opacity(target) { if (!this.visible) { throw new TypeError("Can not change opacity of not existed."); } this.#node.style.opacity = String(target); } get_query(selector) { if (!this.visible) { throw new TypeError("Can not get item from not visible."); } return this.#node.querySelector(selector); } #prepare() { const container = document.createElement("div"); container.classList.add("fullscreen-viewer"); container.style.transition = "opacity 0.5s"; container.appendChild(this._build_node()); return container; } hide() { if (!this.visible) { return; } this.#opacity = 0; setTimeout(() => { if (!this.visible) { return; } this.#node.remove(); this.#node = null; }, 500); } show() { if (this.visible) { return; } this.#node = this.#prepare(); this.#opacity = 0; document.querySelector("body").appendChild(this.#node); setTimeout(() => { this.#opacity = 1; }, 100); } }; // application/scripts/product_fullscreen.js var product_fullscreen = class extends fullscreen { #target; constructor(target) { super(); this.#target = target; } get target() { return this.#target; } _build_node() { const container = document.createElement("div"); container.classList.add("product-fullscreen-viewer"); const image = document.createElement("div"); image.style.backgroundImage = 'url("' + this.target.image + '")'; image.classList.add("image"); container.appendChild(image); const title = document.createElement("div"); title.classList.add("title"); container.appendChild(title); const title_content = document.createElement("h1"); title_content.innerText = this.target.name; title.appendChild(title_content); const bottom = document.createElement("div"); bottom.classList.add("bottom-side"); container.appendChild(bottom); const bottom_header = document.createElement("div"); bottom_header.classList.add("bottom-header"); bottom.appendChild(bottom_header); const barcode_icon = document.createElement("span"); barcode_icon.classList.add("material-icons"); barcode_icon.innerText = "qr_code_scanner"; const barcode_content = document.createElement("span"); barcode_content.innerText = this.target.barcode; barcode_content.classList.add("numbers"); const barcode = document.createElement("p"); barcode.appendChild(barcode_icon); barcode.appendChild(barcode_content); bottom_header.appendChild(barcode); const author_icon = document.createElement("span"); author_icon.classList.add("material-icons"); author_icon.innerText = "attribution"; const author_content = document.createElement("span"); author_content.innerText = this.target.author; const author = document.createElement("p"); author.appendChild(author_icon); author.appendChild(author_content); bottom_header.appendChild(author); const description = document.createElement("div"); description.classList.add("description"); bottom.appendChild(description); const description_content = document.createElement("p"); description_content.innerText = this.target.description; description.appendChild(description_content); const close_button = document.createElement("button"); close_button.classList.add("material-icons"); close_button.classList.add("close"); close_button.innerText = "close"; container.appendChild(close_button); close_button.addEventListener("click", () => { this.hide(); }); return container; } }; // application/scripts/user.js var user = class { #nick; #apikey; constructor(nick, apikey) { this.#nick = nick; this.#apikey = apikey; } get nick() { return this.#nick; } get apikey() { return this.#apikey; } }; // application/scripts/login_manager.js var login_manager = class { get apikey() { return localStorage.getItem("apikey"); } get logged_in() { return localStorage.getItem("apikey") !== null; } #create_request(data) { return { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" } }; } async get_user() { if (!this.logged_in) { return null; } const request_data = this.#create_request({ apikey: this.apikey }); const request2 = await fetch("/user", request_data); const response = await request2.json(); if (response.result !== "success") { return null; } return new user( response.nick, response.apikey ); } async login(nick, password) { const request_data = this.#create_request({ nick, password }); const request2 = await fetch("/user/login", request_data); const response = await request2.json(); if (response.result !== "success") { return false; } localStorage.setItem("apikey", response.apikey); return true; } logout() { localStorage.removeItem("apikey"); } }; // application/scripts/confirm_action.js var confirm_action = class { #node; #action; constructor() { this.#node = null; this.#action = true; } get _description() { throw new TypeError("It must be overwriten."); } get _title() { return "You must confirm it."; } _action() { throw new TypeError("It must be overwriten."); } get _info() { return false; } show() { if (this.#node !== null) { return; } this.#action = true; this.#node = this.#create_window(); document.querySelector("body").appendChild(this.#node); setTimeout(() => { this.#node.style.opacity = "1"; }, 100); } hide() { if (this.#node === null) { return; } this.#action = false; this.#node.style.opacity = "0"; setTimeout(() => { if (this.#node === null) { return; } this.#node.remove(); this.#node = null; }, 500); } #create_window() { const container = document.createElement("div"); container.classList.add("confirm-window"); container.style.transition = "opacity 0.5s"; container.style.opacity = "0"; const center = document.createElement("div"); center.classList.add("center"); container.appendChild(center); const title = document.createElement("div"); title.classList.add("title"); center.appendChild(title); const title_text = document.createElement("h3"); title_text.innerText = this._title; title.appendChild(title_text); const description = document.createElement("div"); description.classList.add("description"); center.appendChild(description); const description_text = document.createElement("p"); description_text.innerText = this._description; description.appendChild(description_text); const buttons = document.createElement("div"); buttons.classList.add("buttons"); center.appendChild(buttons); const cancel_button = document.createElement("button"); cancel_button.classList.add("cancel"); cancel_button.classList.add("material-icons"); cancel_button.innerText = "clear"; buttons.appendChild(cancel_button); cancel_button.addEventListener("click", () => { this.hide(); }); if (!this._info) { const confirm_button = document.createElement("button"); confirm_button.classList.add("confirm"); confirm_button.classList.add("material-icons"); confirm_button.innerText = "send"; buttons.appendChild(confirm_button); confirm_button.addEventListener("click", () => { if (this.#action === false) { return; } this._action(); this.hide(); }); } return container; } }; // application/scripts/request.js var request = class { get settings() { return { "method": this.method, "headers": this.headers, "body": this.body }; } get _apikey() { const manager = new login_manager(); if (manager.logged_in) { return manager.apikey; } throw new Error("User must be logged in."); } get method() { throw new TypeError("It must be overwrite."); } get url() { throw new TypeError("It must be overwrite."); } get headers() { if (this.method === "GET") { return {}; } return { "Content-Type": "application/json" }; } get body() { if (this.data === null) { return ""; } return JSON.stringify(this.data); } get _response() { throw new TypeError("It must be overwrite."); } async connect() { const request2 = await fetch(this.url, this.settings); if (!request2.ok) { throw new Error('Fail when requested: "' + this.url + '".'); } const response = await request2.json(); if (!("result" in response)) { throw new Error("Bad response, not contain result."); } return new this._response(response); } get data() { throw new TypeError("This must be overwrite."); } }; // application/scripts/bool_response.js var bool_response = class { #result; #cause; constructor(target) { this.#result = target.result === "success"; this.#cause = null; if (!this.result) { this.#cause = target.cause; } } get cause() { return this.#cause; } get result() { return this.#result; } }; // application/scripts/delete_request.js var delete_request = class extends request { #product; constructor(product2) { super(); this.#product = product2; } get _response() { return bool_response; } get data() { return { "apikey": this._apikey }; } get url() { return "/product/barcode/" + this.#product.barcode; } get method() { return "DELETE"; } }; // application/scripts/product_containers.js var product_containers = class { #content; #where; #inserted; constructor(where) { this.#where = where; this.#content = new Array(); this.#inserted = new Array(); } add_list(target) { target.forEach((count) => { this.add(count); }); return this; } add(target) { const current = new product_container(target); this.#content.push(current); return this; } clean() { this.#content = new Array(); return this; } update() { this.#hide(); setTimeout(() => { this.#content.forEach((count) => { this.#inserted.push(count); count.add(this.#where); }); }, 500); return this; } #hide() { this.#inserted.forEach((count) => { if (!this.#content.includes(count)) { count.drop(); } }); this.#inserted = new Array(); return this; } }; // application/scripts/searcher.js var searcher = class _searcher { #input; #category; #manager; #result; static #instances; static #add(instance) { if (typeof _searcher.#instances !== "object") { _searcher.#instances = new Array(); } _searcher.#instances.push(instance); } static reload() { if (typeof _searcher.#instances !== "object") { return; } _searcher.#instances.forEach((instance) => { instance.update(); }); } constructor(search_form, manager, result) { this.#input = search_form.querySelector('input[type="text"]'); this.#category = search_form.querySelector("select"); this.#manager = manager; this.#result = result; this.#selector_complete(); search_form.addEventListener("submit", (target) => { target.preventDefault(); this.update(); }); _searcher.#add(this); } get categories() { return { "name": "Name", "author": "Author" }; } #selector_complete() { const category = this.#category; const categories = this.categories; Object.keys(categories).forEach((name) => { const option = document.createElement("option"); option.value = name; option.innerText = categories[name]; category.appendChild(option); }); } get #loader() { return { "name": products_loader.search_name, "author": products_loader.search_author }[this.category]; } get category() { return this.#category.value; } get phrase() { return this.#input.value.trim(); } get #result_title() { return this.#result.innerText; } set #result_title(target) { this.#result.innerText = target; } async update() { if (this.phrase.length === 0) { this.show_all(); return; } this.#insert(await this.#loader(this.phrase)); } #insert(list) { if (list.length === 0) { this.#result_title = "Not found anything."; } else { this.#result_title = "Browse our products!"; } this.#manager.clean().add_list(list).update(); } async show_all() { this.#insert(await products_loader.all()); } }; // application/scripts/delete_product_window.js var delete_product_window = class extends confirm_action { #target; constructor(target) { super(); this.#target = target; } get _title() { return "Do you want remove it?"; } get _description() { let content = "You try to remove " + this.#target.name + ". "; content += "You can not restore it, when confirm."; return content; } async _action() { new delete_request(this.#target).connect(); searcher.reload(); } }; // application/scripts/formscreen.js var formscreen = class extends fullscreen { #form; #result; constructor() { super(); this.#form = null; this.#result = null; } get _name() { throw new TypeError("This is virtual getter!"); } _process() { this._error = "This is abstract, and must be overwriten."; } _build_form() { throw new TypeError("This is virtual method!"); } _get_input(name) { return this.get_query('input[name="' + name + '"]'); } get _has_submit() { return true; } _build_node() { const center = document.createElement("div"); center.classList.add("center"); const title = document.createElement("div"); title.classList.add("title"); center.appendChild(title); const title_content = document.createElement("h3"); title_content.innerText = this._name; title.appendChild(title_content); const form = document.createElement("form"); center.appendChild(form); form.addEventListener("click", () => { this._clear_results(); }); this.#form = document.createElement("div"); this.#form.classList.add("content"); form.appendChild(this.#form); this.#result = document.createElement("div"); this.#result.classList.add("result"); form.appendChild(this.#result); const bottom = document.createElement("div"); bottom.classList.add("bottom"); form.appendChild(bottom); const close_button = document.createElement("button"); close_button.classList.add("close"); close_button.classList.add("material-icons"); close_button.innerText = "close"; close_button.type = "button"; bottom.appendChild(close_button); if (this._has_submit) { const send_button = document.createElement("button"); send_button.classList.add("send"); send_button.classList.add("material-icons"); send_button.innerText = "send"; send_button.type = "submit"; bottom.appendChild(send_button); } close_button.addEventListener("click", () => { this.hide(); }); form.addEventListener("submit", (target) => { target.preventDefault(); this._process(); }); this._refresh(); return center; } _refresh() { while (this.#form.lastChild) { this.#form.lastChild.remove(); } this._build_form(); } _create_input(name, label_text, placeholder, worker = null) { const container = document.createElement("div"); container.classList.add("input-container"); container.classList.add("input-" + name); const label = document.createElement("label"); label.htmlFor = name; label.innerText = label_text; container.appendChild(label); const input = document.createElement("input"); input.type = "text"; input.placeholder = placeholder; input.name = name; input.id = name; container.appendChild(input); if (worker !== null) { worker(input); } if (!this.#form) { throw new Error("Screen is not visible yet!"); } this._append_child(container); return () => { return input.value; }; } _append_child(target) { this.#form.appendChild(target); } _clear_results() { if (!this.#result) { return; } while (this.#result.lastChild) { this.#result.lastChild.remove(); } } set _info(target) { this._clear_results(); const info = document.createElement("p"); info.classList.add("info"); info.innerText = target; if (this.#result) { this.#result.appendChild(info); } } set _error(target) { this._clear_results(); const info = document.createElement("p"); info.classList.add("error"); info.innerText = target; if (this.#result) { this.#result.appendChild(info); } } set _success(target) { this._clear_results(); const info = document.createElement("p"); info.classList.add("success"); info.innerText = target; if (this.#result) { this.#result.appendChild(info); } } }; // application/scripts/product_base.js var product_base = class { name; description; author; barcode; stock_count; constructor(target = null) { this.name = this._extract(target, "name"); this.description = this._extract(target, "description"); this.author = this._extract(target, "author"); this.barcode = this._extract(target, "barcode"); this.stock_count = this._extract(target, "stock_count"); if (this.stock_count !== null) { this.stock_count = Number(this.stock_count); } } get dump() { return { "name": this.name, "description": this.description, "author": this.author, "barcode": this.barcode, "stock_count": this.stock_count }; } _extract(dict, name) { if (dict === null) { return null; } if (name in dict) { return dict[name]; } return null; } get avairable() { return this.stock_count > 0; } }; // application/scripts/edit_request.js var edit_request = class extends request { #target; #updated; constructor(target, updated) { super(); this.#target = target; this.#updated = updated; } get _response() { return bool_response; } get data() { return Object.assign(this.#updated.dump, { "apikey": this._apikey }); } get method() { return "POST"; } get url() { return "/product/update/barcode/" + this.#target.barcode; } }; // application/scripts/edit_image_request.js var edit_image_request = class extends request { #image; #target; constructor(target, image) { super(); this.#target = target; this.#image = image; } get _response() { return bool_response; } get data() { return { "image": this.#image, "apikey": this._apikey }; } get method() { return "POST"; } get url() { return "/product/update/image/barcode/" + this.#target.barcode; } }; // application/scripts/product_editor.js var product_editor = class extends formscreen { #target; #name; #description; #author; #barcode; #stock_count; #image; constructor(target) { super(); this.#target = target; } get target() { return this.#target; } get _name() { return "Product editor"; } _build_form() { this.#name = this._create_input( "name", "Name:", "Sample...", (input) => { input.value = this.#target.name; } ); this.#description = this._create_input( "description", "Description:", "This is sample product...", (input) => { input.value = this.#target.description; } ); this.#author = this._create_input( "author", "Author:", "Jack Black", (input) => { input.value = this.#target.author; } ); this.#barcode = this._create_input( "barcode", "Barcode (EAN):", "123456789012...", (input) => { input.type = "number"; input.value = this.#target.barcode; } ); this.#stock_count = this._create_input( "stock_count", "Stock count:", "10...", (input) => { input.type = "number"; input.value = this.#target.stock_count; } ); this._create_input( "image", "Change product image:", "", (input) => { this.#image = input; input.type = "file"; input.accept = "image/*"; } ); } async #code_image() { if (this.#image.files.length === 0) { return null; } const file = this.#image.files.item(0); const buffer = await file.arrayBuffer(); const list = new Uint8Array(buffer); let content = new String(); list.forEach((code) => { content += String.fromCharCode(code); }); return btoa(content); } async #submit() { const copy = this.#target.copy(); copy.name = this.#name(); copy.description = this.#description(); copy.author = this.#author(); copy.barcode = this.#barcode(); copy.stock_count = this.#stock_count(); const request2 = new edit_request(this.#target, copy); const response = await request2.connect(); if (!response.result) { throw new Error(response.cause); } this.#target = copy; } async #image_submit() { const image = await this.#code_image(); if (image === null) { return; } const request2 = new edit_image_request(this.#target, image); const response = await request2.connect(); if (!response.result) { throw new Error(response.cause); } } async _process() { try { this._info = "Uploading..."; await this.#submit(); this._info = "Processing image..."; await this.#image_submit(); this._success = "Updated success!"; searcher.reload(); setTimeout(() => { this.hide(); }, 500); } catch (error) { this._error = new String(error); } } }; // application/scripts/rents_screen.js var rents_screen = class extends formscreen { #target; #email; #phone; get _email() { return this.#email(); } get _phone() { return this.#phone(); } constructor(target) { super(); this.#target = target; } get _target() { return this.#target; } _build_form() { this.#email = this._create_input( "email", "E-mail:", "sample@example.com", (input) => { input.type = "email"; } ); this.#phone = this._create_input( "phone", "Phone number:", "+1 123-456-789", (input) => { input.type = "tel"; const add_prefix = () => { if (input.value.length === 0) { input.value = "+48 "; } }; input.addEventListener("click", add_prefix); input.addEventListener("focus", add_prefix); } ); } }; // application/scripts/reservation.js var reservation = class _reservation { email; phone_number; product_barcode; constructor(target = null) { this.email = null; this.phone_number = null; this.product_barcode = null; if (target === null) { return; } if ("email" in target) { this.email = target["email"]; } if ("target_barcode" in target) { this.product_barcode = target["target_barcode"]; } if ("phone_number" in target) { this.phone_number = target["phone_number"]; } } get dump() { const dumped = { "target_barcode": this.product_barcode }; if (this.email !== null) { dumped["email"] = this.email; } if (this.phone_number !== null) { dumped["phone_number"] = this.phone_number; } return dumped; } get ready() { if (this.product_barcode === null) return false; if (this.email === null && this.phone_number === null) return false; return true; } copy() { return new _reservation(this.dump); } }; // application/scripts/product_rent_request.js var product_rent_request = class extends request { #reservation; constructor(reservation2) { super(); this.#reservation = reservation2; } get data() { return Object.assign(this.#reservation.dump, { "apikey": this._apikey }); } get _response() { return bool_response; } get method() { return "POST"; } get url() { return "/rent/product/barcode/" + this.#reservation.product_barcode; } }; // application/scripts/reservation_factory.js var reservation_factory = class { #target; constructor() { this.#target = new reservation(); } phone_number(target) { target = target.trim().replaceAll("-", ""); if (target.length === 0) { target = null; } this.#target.phone_number = target; return this; } email(target) { target = target.trim(); if (target.length === 0) { target = null; } this.#target.email = target; return this; } product(target) { this.#target.product_barcode = target.barcode; return this; } result() { if (this.#target.ready) { return this.#target; } throw new Error("Target reservation is not ready yet."); } }; // application/scripts/product_rent.js var product_rent = class extends rents_screen { get _name() { return "Product rent"; } async _process() { try { this._info = "Processing..."; const target = new reservation_factory().email(this._email).phone_number(this._phone).product(this._target).result(); const request2 = new product_rent_request(target); const response = await request2.connect(); if (!response.result) { throw new Error(response.cause); } this._success = "New rent added."; searcher.reload(); setTimeout(() => { this.hide(); }, 500); } catch (error) { this._error = String(error); } } }; // application/scripts/product_give_back_request.js var product_give_back_request = class extends request { #reservation; constructor(reservation2) { super(); this.#reservation = reservation2; } get data() { return Object.assign(this.#reservation.dump, { "apikey": this._apikey }); } get _response() { return bool_response; } get method() { return "POST"; } get url() { return "/give_back/product/barcode/" + this.#reservation.product_barcode; } }; // application/scripts/product_give_back.js var product_give_back = class extends rents_screen { get _name() { return "Product give back"; } async _process() { try { this._info = "Processing..."; const target = new reservation_factory().email(this._email).phone_number(this._phone).product(this._target).result(); const request2 = new product_give_back_request(target); const response = await request2.connect(); if (!response.result) { throw new Error(response.cause); } this._success = "Success!"; searcher.reload(); setTimeout(() => { this.hide(); }, 500); } catch (error) { this._error = String(error); } } }; // application/scripts/reservations_response.js var reservations_response = class extends bool_response { #collection; constructor(target) { super(target); if (!this.result) { return; } this.#collection = new Array(); target["reservations"].forEach((count) => { this.#collection.push(new reservation(count)); }); } get collection() { if (!this.result) { throw new Error(this.cause); } return this.#collection; } }; // application/scripts/product_reservations_request.js var product_reservations_request = class extends request { #target; constructor(target) { super(); this.#target = target; } get _response() { return reservations_response; } get data() { return { "apikey": this._apikey }; } get method() { return "POST"; } get url() { return "/reservations/product/barcode/" + this.#target.barcode; } }; // application/scripts/product_all_rents.js var product_all_rents = class extends formscreen { #target; constructor(target) { super(); this.#target = target; } get _name() { return "All rents"; } get _has_submit() { return false; } #create_single(target) { const container = document.createElement("div"); container.classList.add("reservation-info"); if (target.phone_number !== null) { const phone_icon = document.createElement("span"); phone_icon.classList.add("material-icons"); phone_icon.innerText = "phone"; const phone_number = document.createElement("span"); phone_number.classList.add("numbers"); phone_number.innerText = target.phone_number; const phone_number_container = document.createElement("p"); phone_number_container.appendChild(phone_icon); phone_number_container.appendChild(phone_number); container.appendChild(phone_number_container); } if (target.email !== null) { const email_icon = document.createElement("span"); email_icon.classList.add("material-icons"); email_icon.innerText = "mail"; const email = document.createElement("span"); email.innerText = target.email; const email_container = document.createElement("p"); email_container.appendChild(email_icon); email_container.appendChild(email); container.appendChild(email_container); } return container; } #create_single_button(target) { const button = document.createElement("button"); button.classList.add("material-icons"); button.classList.add("give-back-button"); button.innerText = "save_alt"; button.addEventListener("click", async () => { try { this._info = "Processing..."; const request2 = new product_give_back_request(target); const response = await request2.connect(); if (!response.result) { throw new Error(response.cause); } this._refresh(); searcher.reload(); } catch (error) { this._error = String(error); } }); return button; } _process() { return; } async _build_form() { try { this._info = "Loading..."; const request2 = new product_reservations_request(this.#target); const response = await request2.connect(); const list = document.createElement("div"); list.classList.add("reservations-list"); let empty = true; response.collection.forEach((count) => { const item = document.createElement("div"); item.classList.add("reservation"); const left = this.#create_single(count); const right = this.#create_single_button(count); empty = false; item.appendChild(left); item.appendChild(right); list.appendChild(item); }); this._append_child(list); if (empty) { this._success = "Not found any reservations."; } else { this._clear_results(); } } catch (error) { this._error = String(error); } } }; // application/scripts/product_not_avairable.js var product_not_avairable = class extends confirm_action { get _title() { return "Error"; } get _description() { return "This product is not avairable. Anybody can not rent it."; } get _info() { return true; } }; // application/scripts/product_container.js var product_container = class { #target; #node; #login; constructor(target) { this.#target = new product(target.dump); this.#node = null; this.#login = new login_manager().logged_in; } get #header() { const header = document.createElement("div"); header.classList.add("header"); const title = document.createElement("h3"); title.innerText = this.#target.name; header.appendChild(title); if (this.#login) { header.appendChild(this.#manage); } return header; } get #manage() { const manage = document.createElement("div"); manage.classList.add("manage"); const all_rents_button = document.createElement("button"); all_rents_button.classList.add("material-icons"); all_rents_button.classList.add("all-rents-button"); all_rents_button.innerText = "list"; manage.appendChild(all_rents_button); const rent_button = document.createElement("button"); rent_button.classList.add("material-icons"); rent_button.classList.add("rent-button"); rent_button.innerText = "backpack"; manage.appendChild(rent_button); const give_back_button = document.createElement("button"); give_back_button.classList.add("material-icons"); give_back_button.classList.add("give-back-button"); give_back_button.innerText = "save_alt"; manage.appendChild(give_back_button); const edit_button = document.createElement("button"); edit_button.classList.add("material-icons"); edit_button.classList.add("edit-button"); edit_button.innerText = "edit"; manage.appendChild(edit_button); const delete_button = document.createElement("button"); delete_button.classList.add("material-icons"); delete_button.classList.add("delete-button"); delete_button.innerText = "remove_circle_outline"; manage.appendChild(delete_button); all_rents_button.addEventListener("click", () => { new product_all_rents(this.#target).show(); }); rent_button.addEventListener("click", () => { if (this.#target.on_stock > 0) { new product_rent(this.#target).show(); } else { new product_not_avairable().show(); } }); give_back_button.addEventListener("click", () => { new product_give_back(this.#target).show(); }); edit_button.addEventListener("click", () => { new product_editor(this.#target).show(); }); delete_button.addEventListener("click", () => { new delete_product_window(this.#target).show(); }); return manage; } get #description() { const container = document.createElement("div"); container.classList.add("description"); const description = document.createElement("p"); description.innerText = this.#target.description; description.classList.add("content"); const author_container = document.createElement("div"); author_container.classList.add("author"); const author = document.createElement("span"); author.innerText = this.#target.author; const author_icon = document.createElement("span"); author_icon.classList.add("material-icons"); author_icon.innerText = "attribution"; author_container.appendChild(author_icon); author_container.appendChild(author); const stock_count = document.createElement("p"); stock_count.classList.add("stock-count"); stock_count.classList.add("material-icons"); if (this.#target.on_stock > 0) { stock_count.innerText = "check_circle"; stock_count.classList.add("avairable"); } else { stock_count.innerText = "cancel"; stock_count.classList.add("unavairable"); } const barcode_container = document.createElement("p"); barcode_container.classList.add("barcode"); const barcode = document.createElement("span"); barcode.innerText = this.#target.barcode; barcode.classList.add("numbers"); const barcode_icon = document.createElement("span"); barcode_icon.classList.add("material-icons"); barcode_icon.innerText = "qr_code_scanner"; barcode_container.appendChild(barcode_icon); barcode_container.appendChild(barcode); container.appendChild(description); container.appendChild(author_container); container.appendChild(barcode_container); container.appendChild(stock_count); return container; } get #cache_bypass() { return "?cache=" + new String(Math.floor(Math.random() * 100)); } get #image() { const image = document.createElement("img"); image.classList.add("image"); image.src = this.#target.thumbnail + this.#cache_bypass; image.alt = this.#target.name; image.addEventListener("click", () => { new product_fullscreen(this.#target).show(); }); return image; } get node() { if (this.#node !== null) { return this.#node; } const bottom_container = document.createElement("div"); bottom_container.classList.add("bottom-container"); bottom_container.appendChild(this.#description); bottom_container.appendChild(this.#image); const container = document.createElement("div"); container.classList.add("product"); container.appendChild(this.#header); container.appendChild(bottom_container); return this.#node = container; } add(target) { const node = this.node; node.style.opacity = "0"; node.style.transition = "opacity 0.5s"; target.appendChild(node); setTimeout(() => { node.style.opacity = "1"; }, 50); } drop() { const container = this.#node; if (container === null) { throw new TypeError("It is not showed yet."); } container.style.opacity = "1"; container.style.transition = "opacity 0.5s"; setTimeout(() => { container.style.opacity = "0"; }, 50); setTimeout(() => { this.#node = null; container.remove(); }, 550); } }; // application/scripts/login_prompt.js var login_prompt = class extends formscreen { #nick; #password; constructor(target) { super(); target.addEventListener("click", () => { this.show(); }); } get _name() { return "Login"; } async _process() { try { this._info = "Processing..."; await this.#login(); this._success = "Logged in!"; setTimeout(() => { location.reload(); }, 250); } catch (error) { this._error = new String(error); } } async #login() { const manager = new login_manager(); const result = await manager.login( this.#nick(), this.#password() ); if (result) { return; } throw new Error("Can not login. Check nick and password."); } _build_form() { this.#nick = this._create_input( "nick", "Nick:", "Sample..." ); this.#password = this._create_input( "password", "Password:", "ABCDEFGH", (input) => { input.type = "password"; } ); } }; // application/scripts/create_request.js var create_request = class extends request { #image; #product; constructor(product2, image) { super(); this.#image = image; this.#product = product2; } get _response() { return bool_response; } get data() { return Object.assign(this.#product.dump, { "image": this.#image, "apikey": this._apikey }); } get method() { return "POST"; } get url() { return "/product/create"; } }; // application/scripts/product_adder.js var product_adder = class extends formscreen { #name; #description; #author; #barcode; #stock_count; #image; get _name() { return "Add product"; } _build_form() { this.#name = this._create_input( "name", "Name:", "Sample..." ); this.#description = this._create_input( "description", "Description:", "This is sample product..." ); this.#author = this._create_input( "author", "Author:", "Jack Black" ); this.#barcode = this._create_input( "barcode", "Barcode (EAN):", "123456789012...", (input) => { input.type = "number"; } ); this.#stock_count = this._create_input( "stock_count", "Stock count:", "10...", (input) => { input.type = "number"; } ); this._create_input( "image", "Product image:", "", (input) => { this.#image = input; input.type = "file"; input.accept = "image/*"; } ); } async #code_image() { if (this.#image.files.length === 0) { throw new Error("Upload image for product."); } const file = this.#image.files.item(0); const buffer = await file.arrayBuffer(); const list = new Uint8Array(buffer); let content = new String(); list.forEach((code) => { content += String.fromCharCode(code); }); return btoa(content); } async #submit() { const product2 = new product_base(); product2.name = this.#name(); product2.description = this.#description(); product2.author = this.#author(); product2.stock_count = this.#stock_count(); product2.barcode = this.#barcode(); const image = await this.#code_image(); const request2 = new create_request(product2, image); const response = await request2.connect(); if (!response.result) { throw new Error(response.cause); } } async _process() { try { this._info = "Uploading..."; await this.#submit(); this._success = "Created success!"; searcher.reload(); setTimeout(() => { this.hide(); }, 500); } catch (error) { this._error = new String(error); } } }; // application/scripts/login_bar.js var login_bar = class { #manager; constructor(target) { this.#manager = new login_manager(); if (!this.#manager.logged_in) { this.#not_logged(target); return; } this.#logged(target); } #not_login_propertly() { this.#manager.logout(); location.reload(); } async #logged(target) { const user2 = await this.#manager.get_user(); if (user2 === null) { this.#not_login_propertly(); } const info_icon = document.createElement("span"); info_icon.classList.add("icon"); info_icon.classList.add("material-icons"); info_icon.innerText = "account_circle"; const info_content = document.createElement("span"); info_content.innerText = user2.nick; const info = document.createElement("p"); info.classList.add("login-info"); info.appendChild(info_icon); info.appendChild(info_content); target.appendChild(info); const logout_button = document.createElement("button"); logout_button.innerText = "logout"; logout_button.classList.add("logout-button"); logout_button.classList.add("material-icons"); target.appendChild(logout_button); const add_product_button = document.createElement("button"); add_product_button.innerText = "add"; add_product_button.classList.add("add-product-button"); add_product_button.classList.add("material-icons"); target.appendChild(add_product_button); add_product_button.addEventListener("click", () => { new product_adder().show(); }); logout_button.addEventListener("click", () => { this.#manager.logout(); location.reload(); }); } #not_logged(target) { const login_button = document.createElement("button"); login_button.innerText = "account_circle"; login_button.classList.add("login-button"); login_button.classList.add("material-icons"); target.appendChild(login_button); new login_prompt(login_button); } }; // application/scripts/scroll_up.js var scroll_up = class { #button; constructor(button) { this.#button = button; this.#update(); document.addEventListener("scroll", () => { this.#update(); }); this.#button.addEventListener("click", () => { this.scroll(); }); } scroll() { this.#position = 0; } get #position() { return document.scrollingElement.scrollTop; } set #position(target) { document.scrollingElement.scrollTop = target; } get #visible() { return Number(this.#button.style.opacity) === 1; } set #visible(target) { this.#button.style.opacity = target ? "1" : "0"; } get #margin() { return 20; } #update() { this.#visible = this.#position > this.#margin; } }; // application/scripts/color_theme.js var color_theme = class { #button; #themes; get themes() { return Object.keys(this.#themes); } theme_name(target) { return this.#themes[target]; } constructor(button, themes = null) { this.#button = button; this.#themes = themes; if (this.#themes === null) { this.#themes = { "dark-theme": "Dark", "white-theme": "White" }; } this.#load(); this.#button.addEventListener("click", () => { this.change(); }); } get current() { if (localStorage.hasOwnProperty("theme")) { return localStorage.getItem("theme"); } return this.themes[this.themes.length - 1]; } #load() { this.#show(this.current); } #save(target) { localStorage.setItem("theme", target); } #show(target) { const themes = this.themes; const body = document.querySelector("body"); body.classList.forEach((count) => { if (themes.indexOf(count) !== -1) { body.classList.remove(count); } }); body.classList.add(target); } change() { const themes = this.themes; const current = this.current; let position = themes.indexOf(current) + 1; if (position === themes.length) { position = 0; } const updated = themes[position]; this.#save(updated); this.#show(updated); } }; // application/scripts/core.js document.addEventListener("DOMContentLoaded", async () => { const top_bar_spacing = new height_equaler( document.querySelector(".top-bar"), document.querySelector(".top-bar-spacing") ); const container = document.querySelector(".products"); const search_bar = document.querySelector("form.search"); const search_title = document.querySelector(".search-title"); const login_space = document.querySelector(".top-bar .right"); const scroll_up_button = document.querySelector(".scroll-up-button"); const reverse_colors = document.querySelector(".reverse-colors"); const manager = new product_containers(container); new login_bar(login_space); new scroll_up(scroll_up_button); new color_theme(reverse_colors); new searcher(search_bar, manager, search_title).show_all(); }); })();