app.js 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590
  1. (() => {
  2. // application/scripts/height_equaler.js
  3. var height_equaler = class {
  4. #to;
  5. #from;
  6. constructor(from, to) {
  7. this.#from = from;
  8. this.#to = to;
  9. this.#set_styles();
  10. new ResizeObserver(() => {
  11. this.#update();
  12. }).observe(from);
  13. setTimeout(() => {
  14. this.#update();
  15. }, 100);
  16. }
  17. get height() {
  18. return this.#from.offsetHeight;
  19. }
  20. #set_styles() {
  21. this.#to.style.height = "0px";
  22. this.#to.style.transition = "height 0.5s";
  23. }
  24. #update() {
  25. this.#to.style.height = this.height + "px";
  26. }
  27. };
  28. // application/scripts/product.js
  29. var product = class _product {
  30. name;
  31. description;
  32. author;
  33. image;
  34. stock_count;
  35. barcode;
  36. thumbnail;
  37. on_stock;
  38. constructor(target) {
  39. this.name = null;
  40. this.description = null;
  41. this.author = null;
  42. this.image = null;
  43. this.stock_count = null;
  44. this.barcode = null;
  45. this.thumbnail = null;
  46. this.on_stock = null;
  47. if ("name" in target) this.name = target["name"];
  48. if ("description" in target) this.description = target["description"];
  49. if ("author" in target) this.author = target["author"];
  50. if ("image" in target) this.image = target["image"];
  51. if ("stock_count" in target) this.stock_count = target["stock_count"];
  52. if ("barcode" in target) this.barcode = target["barcode"];
  53. if ("thumbnail" in target) this.thumbnail = target["thumbnail"];
  54. if ("on_stock" in target) this.on_stock = target["on_stock"];
  55. try {
  56. this.stock_count = Number(this.stock_count);
  57. } catch {
  58. this.stock_count = 0;
  59. }
  60. try {
  61. this.on_stock = Number(this.on_stock);
  62. } catch {
  63. this.on_stock = 0;
  64. }
  65. }
  66. get dump() {
  67. const dumped = {
  68. "name": new String(this.name),
  69. "description": new String(this.description),
  70. "author": new String(this.author),
  71. "image": new String(this.image),
  72. "barcode": new String(this.barcode),
  73. "thumbnail": new String(this.thumbnail),
  74. "stock_count": new String(this.stock_count)
  75. };
  76. if (this.on_stock !== null) {
  77. dumped["on_stock"] = new String(this.on_stock);
  78. }
  79. return dumped;
  80. }
  81. get ready() {
  82. if (this.name === null || this.description === null) return false;
  83. if (this.author === null || this.image === null) return false;
  84. if (this.stock_count === null || this.barcode === null) return false;
  85. if (this.thumbnail === null) return false;
  86. return true;
  87. }
  88. copy() {
  89. return new _product(this.dump);
  90. }
  91. };
  92. // application/scripts/products_loader.js
  93. var products_loader = class _products_loader {
  94. static async all() {
  95. const request2 = await fetch("/products/");
  96. const response = await request2.json();
  97. return _products_loader.#response_to_collection(response);
  98. }
  99. static #response_to_collection(response) {
  100. if (response.result !== "success") {
  101. return new Array();
  102. }
  103. if ("collection" in response) {
  104. return this.#list_response_to_collection(response);
  105. }
  106. return this.#single_response_to_collection(response);
  107. }
  108. static #single_response_to_collection(response) {
  109. const result = new Array();
  110. result.push(new product(response.product));
  111. return result;
  112. }
  113. static #list_response_to_collection(response) {
  114. const result = new Array();
  115. response.collection.forEach((serialized) => {
  116. result.push(new product(serialized));
  117. });
  118. return result;
  119. }
  120. static async search_name(name) {
  121. return await _products_loader.#search(
  122. "/product/search/name",
  123. name
  124. );
  125. }
  126. static async search_author(author) {
  127. return await _products_loader.#search(
  128. "/product/search/author",
  129. author
  130. );
  131. }
  132. static async search_barcode(barcode) {
  133. return await _products_loader.#search(
  134. "/product/get/barcode",
  135. barcode
  136. );
  137. }
  138. static async #search(path, parameter) {
  139. const coded = encodeURI(parameter);
  140. const request2 = await fetch(path + "/" + coded);
  141. const response = await request2.json();
  142. return _products_loader.#response_to_collection(response);
  143. }
  144. };
  145. // application/scripts/fullscreen.js
  146. var fullscreen = class {
  147. #node;
  148. constructor() {
  149. this.#node = null;
  150. }
  151. get visible() {
  152. return this.#node !== null;
  153. }
  154. _build_node() {
  155. throw new TypeError("This is virtual method!");
  156. }
  157. get #opacity() {
  158. if (!this.visible) {
  159. throw new TypeError("Can not change opacity of not existed.");
  160. }
  161. return Number(this.#node.style.opacity);
  162. }
  163. set #opacity(target) {
  164. if (!this.visible) {
  165. throw new TypeError("Can not change opacity of not existed.");
  166. }
  167. this.#node.style.opacity = String(target);
  168. }
  169. get_query(selector) {
  170. if (!this.visible) {
  171. throw new TypeError("Can not get item from not visible.");
  172. }
  173. return this.#node.querySelector(selector);
  174. }
  175. #prepare() {
  176. const container = document.createElement("div");
  177. container.classList.add("fullscreen-viewer");
  178. container.style.transition = "opacity 0.5s";
  179. container.appendChild(this._build_node());
  180. return container;
  181. }
  182. hide() {
  183. if (!this.visible) {
  184. return;
  185. }
  186. this.#opacity = 0;
  187. setTimeout(() => {
  188. if (!this.visible) {
  189. return;
  190. }
  191. this.#node.remove();
  192. this.#node = null;
  193. }, 500);
  194. }
  195. show() {
  196. if (this.visible) {
  197. return;
  198. }
  199. this.#node = this.#prepare();
  200. this.#opacity = 0;
  201. document.querySelector("body").appendChild(this.#node);
  202. setTimeout(() => {
  203. this.#opacity = 1;
  204. }, 100);
  205. }
  206. };
  207. // application/scripts/product_fullscreen.js
  208. var product_fullscreen = class extends fullscreen {
  209. #target;
  210. constructor(target) {
  211. super();
  212. this.#target = target;
  213. }
  214. get target() {
  215. return this.#target;
  216. }
  217. _build_node() {
  218. const container = document.createElement("div");
  219. container.classList.add("product-fullscreen-viewer");
  220. const image = document.createElement("div");
  221. image.style.backgroundImage = 'url("' + this.target.image + '")';
  222. image.classList.add("image");
  223. container.appendChild(image);
  224. const title = document.createElement("div");
  225. title.classList.add("title");
  226. container.appendChild(title);
  227. const title_content = document.createElement("h1");
  228. title_content.innerText = this.target.name;
  229. title.appendChild(title_content);
  230. const bottom = document.createElement("div");
  231. bottom.classList.add("bottom-side");
  232. container.appendChild(bottom);
  233. const bottom_header = document.createElement("div");
  234. bottom_header.classList.add("bottom-header");
  235. bottom.appendChild(bottom_header);
  236. const barcode_icon = document.createElement("span");
  237. barcode_icon.classList.add("material-icons");
  238. barcode_icon.innerText = "qr_code_scanner";
  239. const barcode_content = document.createElement("span");
  240. barcode_content.innerText = this.target.barcode;
  241. barcode_content.classList.add("numbers");
  242. const barcode = document.createElement("p");
  243. barcode.appendChild(barcode_icon);
  244. barcode.appendChild(barcode_content);
  245. bottom_header.appendChild(barcode);
  246. const author_icon = document.createElement("span");
  247. author_icon.classList.add("material-icons");
  248. author_icon.innerText = "attribution";
  249. const author_content = document.createElement("span");
  250. author_content.innerText = this.target.author;
  251. const author = document.createElement("p");
  252. author.appendChild(author_icon);
  253. author.appendChild(author_content);
  254. bottom_header.appendChild(author);
  255. const description = document.createElement("div");
  256. description.classList.add("description");
  257. bottom.appendChild(description);
  258. const description_content = document.createElement("p");
  259. description_content.innerText = this.target.description;
  260. description.appendChild(description_content);
  261. const close_button = document.createElement("button");
  262. close_button.classList.add("material-icons");
  263. close_button.classList.add("close");
  264. close_button.innerText = "close";
  265. container.appendChild(close_button);
  266. close_button.addEventListener("click", () => {
  267. this.hide();
  268. });
  269. return container;
  270. }
  271. };
  272. // application/scripts/user.js
  273. var user = class {
  274. #nick;
  275. #apikey;
  276. constructor(nick, apikey) {
  277. this.#nick = nick;
  278. this.#apikey = apikey;
  279. }
  280. get nick() {
  281. return this.#nick;
  282. }
  283. get apikey() {
  284. return this.#apikey;
  285. }
  286. };
  287. // application/scripts/login_manager.js
  288. var login_manager = class {
  289. get apikey() {
  290. return localStorage.getItem("apikey");
  291. }
  292. get logged_in() {
  293. return localStorage.getItem("apikey") !== null;
  294. }
  295. #create_request(data) {
  296. return {
  297. method: "POST",
  298. body: JSON.stringify(data),
  299. headers: {
  300. "Content-Type": "application/json"
  301. }
  302. };
  303. }
  304. async get_user() {
  305. if (!this.logged_in) {
  306. return null;
  307. }
  308. const request_data = this.#create_request({
  309. apikey: this.apikey
  310. });
  311. const request2 = await fetch("/user", request_data);
  312. const response = await request2.json();
  313. if (response.result !== "success") {
  314. return null;
  315. }
  316. return new user(
  317. response.nick,
  318. response.apikey
  319. );
  320. }
  321. async login(nick, password) {
  322. const request_data = this.#create_request({
  323. nick,
  324. password
  325. });
  326. const request2 = await fetch("/user/login", request_data);
  327. const response = await request2.json();
  328. if (response.result !== "success") {
  329. return false;
  330. }
  331. localStorage.setItem("apikey", response.apikey);
  332. return true;
  333. }
  334. logout() {
  335. localStorage.removeItem("apikey");
  336. }
  337. };
  338. // application/scripts/confirm_action.js
  339. var confirm_action = class {
  340. #node;
  341. #action;
  342. constructor() {
  343. this.#node = null;
  344. this.#action = true;
  345. }
  346. get _description() {
  347. throw new TypeError("It must be overwriten.");
  348. }
  349. get _title() {
  350. return _("you-must-confirm-it");
  351. }
  352. _action() {
  353. throw new TypeError("It must be overwriten.");
  354. }
  355. get _info() {
  356. return false;
  357. }
  358. show() {
  359. if (this.#node !== null) {
  360. return;
  361. }
  362. this.#action = true;
  363. this.#node = this.#create_window();
  364. document.querySelector("body").appendChild(this.#node);
  365. setTimeout(() => {
  366. this.#node.style.opacity = "1";
  367. }, 100);
  368. }
  369. hide() {
  370. if (this.#node === null) {
  371. return;
  372. }
  373. this.#action = false;
  374. this.#node.style.opacity = "0";
  375. setTimeout(() => {
  376. if (this.#node === null) {
  377. return;
  378. }
  379. this.#node.remove();
  380. this.#node = null;
  381. }, 500);
  382. }
  383. #create_window() {
  384. const container = document.createElement("div");
  385. container.classList.add("confirm-window");
  386. container.style.transition = "opacity 0.5s";
  387. container.style.opacity = "0";
  388. const center = document.createElement("div");
  389. center.classList.add("center");
  390. container.appendChild(center);
  391. const title = document.createElement("div");
  392. title.classList.add("title");
  393. center.appendChild(title);
  394. const title_text = document.createElement("h3");
  395. title_text.innerText = this._title;
  396. title.appendChild(title_text);
  397. const description = document.createElement("div");
  398. description.classList.add("description");
  399. center.appendChild(description);
  400. const description_text = document.createElement("p");
  401. description_text.innerText = this._description;
  402. description.appendChild(description_text);
  403. const buttons = document.createElement("div");
  404. buttons.classList.add("buttons");
  405. center.appendChild(buttons);
  406. const cancel_button = document.createElement("button");
  407. cancel_button.classList.add("cancel");
  408. cancel_button.classList.add("material-icons");
  409. cancel_button.innerText = "close";
  410. buttons.appendChild(cancel_button);
  411. cancel_button.addEventListener("click", () => {
  412. this.hide();
  413. });
  414. if (!this._info) {
  415. const confirm_button = document.createElement("button");
  416. confirm_button.classList.add("confirm");
  417. confirm_button.classList.add("material-icons");
  418. confirm_button.innerText = "send";
  419. buttons.appendChild(confirm_button);
  420. confirm_button.addEventListener("click", () => {
  421. if (this.#action === false) {
  422. return;
  423. }
  424. this._action();
  425. this.hide();
  426. });
  427. }
  428. return container;
  429. }
  430. };
  431. // application/scripts/request.js
  432. var request = class {
  433. get settings() {
  434. const settings = {
  435. "method": this.method,
  436. "headers": this.headers
  437. };
  438. if (this.method === "GET" || this.method === "HEAD") {
  439. return settings;
  440. }
  441. if (this.body === null) {
  442. return settings;
  443. }
  444. settings.body = this.body;
  445. return settings;
  446. }
  447. get _apikey() {
  448. const manager = new login_manager();
  449. if (manager.logged_in) {
  450. return manager.apikey;
  451. }
  452. throw new Error(_("user-must-be-logged-in"));
  453. }
  454. get method() {
  455. throw new TypeError("It must be overwrite.");
  456. }
  457. get url() {
  458. throw new TypeError("It must be overwrite.");
  459. }
  460. get headers() {
  461. if (this.method === "GET" || this.method === "HEAD") {
  462. return {};
  463. }
  464. if (typeof this.data === "string") {
  465. return {
  466. "Content-Type": "text/plain"
  467. };
  468. }
  469. return {
  470. "Content-Type": "application/json"
  471. };
  472. }
  473. get body() {
  474. if (this.data === null) {
  475. return null;
  476. }
  477. if (typeof this.data === "string") {
  478. return this.data;
  479. }
  480. return JSON.stringify(this.data);
  481. }
  482. get _response() {
  483. throw new TypeError("It must be overwrite.");
  484. }
  485. async connect() {
  486. const request2 = await fetch(this.url, this.settings);
  487. if (!request2.ok) {
  488. throw new Error(_("fail-when-request-__url__").format({
  489. url: this.url
  490. }));
  491. }
  492. const response = await request2.json();
  493. if (!("result" in response)) {
  494. throw new Error(_("bad-response-not-contain-result"));
  495. }
  496. return new this._response(response);
  497. }
  498. get data() {
  499. throw new TypeError("This must be overwrite.");
  500. }
  501. };
  502. // application/scripts/bool_response.js
  503. var bool_response = class {
  504. #result;
  505. #cause;
  506. constructor(target) {
  507. this.#result = target.result === "success";
  508. this.#cause = null;
  509. if (!this.result) {
  510. this.#cause = target.cause;
  511. }
  512. }
  513. get cause() {
  514. return this.#cause;
  515. }
  516. get result() {
  517. return this.#result;
  518. }
  519. };
  520. // application/scripts/delete_request.js
  521. var delete_request = class extends request {
  522. #product;
  523. constructor(product2) {
  524. super();
  525. this.#product = product2;
  526. }
  527. get _response() {
  528. return bool_response;
  529. }
  530. get data() {
  531. return {
  532. "apikey": this._apikey
  533. };
  534. }
  535. get url() {
  536. return "/product/barcode/" + this.#product.barcode;
  537. }
  538. get method() {
  539. return "DELETE";
  540. }
  541. };
  542. // application/scripts/product_containers.js
  543. var product_containers = class {
  544. #content;
  545. #where;
  546. #inserted;
  547. #counter;
  548. #count;
  549. #next_button;
  550. #previous_button;
  551. constructor(where) {
  552. this.#counter = 0;
  553. this.#count = 24;
  554. this.#content = new Array();
  555. this.#inserted = new Array();
  556. this.#where = document.createElement("div");
  557. this.#where.classList.add("products-list");
  558. this.#next_button = document.createElement("input");
  559. this.#next_button.type = "button";
  560. this.#next_button.value = _("show-next");
  561. this.#previous_button = document.createElement("input");
  562. this.#previous_button.type = "button";
  563. this.#previous_button.value = _("show-previous");
  564. this.#next_button.addEventListener("click", () => {
  565. this.#next();
  566. });
  567. this.#previous_button.addEventListener("click", () => {
  568. this.#previous();
  569. });
  570. where.appendChild(this.#previous_button);
  571. where.appendChild(this.#where);
  572. where.appendChild(this.#next_button);
  573. }
  574. add_list(target) {
  575. target.forEach((count) => {
  576. this.add(count);
  577. });
  578. return this;
  579. }
  580. add(target) {
  581. const current = new product_container(target);
  582. this.#content.push(current);
  583. return this;
  584. }
  585. clean() {
  586. this.#counter = 0;
  587. this.#content = new Array();
  588. return this;
  589. }
  590. #update_buttons() {
  591. if (this.previous_avairable) {
  592. this.#previous_button.style.opacity = "1";
  593. } else {
  594. this.#previous_button.style.opacity = "0";
  595. }
  596. if (this.next_avairable) {
  597. this.#next_button.style.opacity = "1";
  598. } else {
  599. this.#next_button.style.opacity = "0";
  600. }
  601. }
  602. update() {
  603. this.#update_buttons();
  604. this.#hide();
  605. setTimeout(() => {
  606. const first = this.#counter;
  607. const last = this.#counter + this.#count;
  608. const current = this.#content.slice(first, last);
  609. current.forEach((count) => {
  610. this.#show_sigle(count);
  611. });
  612. }, 500);
  613. return this;
  614. }
  615. get next_avairable() {
  616. return this.#counter + this.#count <= this.#content.length;
  617. }
  618. get previous_avairable() {
  619. return this.#counter >= this.#count;
  620. }
  621. #next() {
  622. if (!this.next_avairable) return;
  623. this.#counter += this.#count;
  624. this.update();
  625. }
  626. #previous() {
  627. if (!this.previous_avairable) return;
  628. this.#counter -= this.#count;
  629. this.#counter = this.#counter < 0 ? 0 : this.#counter;
  630. this.update();
  631. }
  632. #show_sigle(target) {
  633. this.#inserted.push(target);
  634. target.add(this.#where);
  635. }
  636. #hide() {
  637. this.#inserted.forEach((count) => {
  638. count.drop();
  639. });
  640. this.#inserted = new Array();
  641. return this;
  642. }
  643. };
  644. // application/scripts/searcher.js
  645. var searcher = class _searcher {
  646. #input;
  647. #category;
  648. #manager;
  649. #result;
  650. #counter;
  651. static #instances;
  652. static #add(instance) {
  653. if (typeof _searcher.#instances !== "object") {
  654. _searcher.#instances = new Array();
  655. }
  656. _searcher.#instances.push(instance);
  657. }
  658. static reload() {
  659. if (typeof _searcher.#instances !== "object") {
  660. return;
  661. }
  662. _searcher.#instances.forEach((instance) => {
  663. instance.update();
  664. });
  665. }
  666. constructor(search_form, manager, result, counter) {
  667. this.#input = search_form.querySelector('input[type="text"]');
  668. this.#category = search_form.querySelector("select");
  669. this.#manager = manager;
  670. this.#result = result;
  671. this.#counter = counter;
  672. this.#selector_complete();
  673. search_form.addEventListener("submit", (target) => {
  674. target.preventDefault();
  675. this.update();
  676. });
  677. _searcher.#add(this);
  678. }
  679. get categories() {
  680. return {
  681. "name": _("name-category"),
  682. "author": _("author-category"),
  683. "barcode": _("barcode-category")
  684. };
  685. }
  686. #selector_complete() {
  687. const category = this.#category;
  688. const categories = this.categories;
  689. Object.keys(categories).forEach((name) => {
  690. const option = document.createElement("option");
  691. option.value = name;
  692. option.innerText = categories[name];
  693. category.appendChild(option);
  694. });
  695. }
  696. get #loader() {
  697. return {
  698. "name": products_loader.search_name,
  699. "author": products_loader.search_author,
  700. "barcode": products_loader.search_barcode
  701. }[this.category];
  702. }
  703. get category() {
  704. return this.#category.value;
  705. }
  706. get phrase() {
  707. return this.#input.value.trim();
  708. }
  709. get #result_title() {
  710. return this.#result.innerText;
  711. }
  712. set #result_title(target) {
  713. this.#result.innerText = target;
  714. }
  715. async update() {
  716. if (this.phrase.length === 0) {
  717. this.show_all();
  718. return;
  719. }
  720. this.#insert(await this.#loader(this.phrase));
  721. }
  722. set #how_many(target) {
  723. this.#counter.innerText = _("found-count") + target;
  724. }
  725. get #how_many() {
  726. return this.#counter.innerText;
  727. }
  728. #insert(list) {
  729. if (list.length === 0) {
  730. this.#result_title = _("not-found-anything");
  731. } else {
  732. this.#result_title = _("browse-our-products");
  733. }
  734. this.#how_many = list.length;
  735. this.#manager.clean().add_list(list).update();
  736. }
  737. async show_all() {
  738. this.#insert(await products_loader.all());
  739. }
  740. };
  741. // application/scripts/delete_product_window.js
  742. var delete_product_window = class extends confirm_action {
  743. #target;
  744. constructor(target) {
  745. super();
  746. this.#target = target;
  747. }
  748. get _title() {
  749. return _("do-you-want-to-remove-it");
  750. }
  751. get _description() {
  752. let content = _("you-try-to-remove-__name__").format({
  753. name: this.#target.name
  754. });
  755. return content;
  756. }
  757. async _action() {
  758. new delete_request(this.#target).connect();
  759. searcher.reload();
  760. }
  761. };
  762. // application/scripts/formscreen.js
  763. var formscreen = class extends fullscreen {
  764. #form;
  765. #result;
  766. constructor() {
  767. super();
  768. this.#form = null;
  769. this.#result = null;
  770. }
  771. get _name() {
  772. throw new TypeError("This is virtual getter!");
  773. }
  774. _process() {
  775. this._error = "This is abstract, and must be overwriten.";
  776. }
  777. _build_form() {
  778. throw new TypeError("This is virtual method!");
  779. }
  780. _get_input(name) {
  781. return this.get_query('input[name="' + name + '"]');
  782. }
  783. get _has_submit() {
  784. return true;
  785. }
  786. _build_node() {
  787. const center = document.createElement("div");
  788. center.classList.add("center");
  789. const title = document.createElement("div");
  790. title.classList.add("title");
  791. center.appendChild(title);
  792. const title_content = document.createElement("h3");
  793. title_content.innerText = this._name;
  794. title.appendChild(title_content);
  795. const form = document.createElement("form");
  796. center.appendChild(form);
  797. form.addEventListener("change", () => {
  798. this._clear_results();
  799. });
  800. this.#form = document.createElement("div");
  801. this.#form.classList.add("content");
  802. form.appendChild(this.#form);
  803. this.#result = document.createElement("div");
  804. this.#result.classList.add("result");
  805. form.appendChild(this.#result);
  806. const bottom = document.createElement("div");
  807. bottom.classList.add("bottom");
  808. form.appendChild(bottom);
  809. const close_button = document.createElement("button");
  810. close_button.classList.add("close");
  811. close_button.classList.add("material-icons");
  812. close_button.innerText = "close";
  813. close_button.type = "button";
  814. bottom.appendChild(close_button);
  815. if (this._has_submit) {
  816. const send_button = document.createElement("button");
  817. send_button.classList.add("send");
  818. send_button.classList.add("material-icons");
  819. send_button.innerText = "send";
  820. send_button.type = "submit";
  821. bottom.appendChild(send_button);
  822. }
  823. close_button.addEventListener("click", () => {
  824. this.hide();
  825. });
  826. form.addEventListener("submit", (target) => {
  827. target.preventDefault();
  828. this._process();
  829. });
  830. this._refresh();
  831. return center;
  832. }
  833. _refresh() {
  834. while (this.#form.lastChild) {
  835. this.#form.lastChild.remove();
  836. }
  837. this._build_form();
  838. }
  839. _create_input(name, label_text, placeholder, worker = null) {
  840. const container = document.createElement("div");
  841. container.classList.add("input-container");
  842. container.classList.add("input-" + name);
  843. const label = document.createElement("label");
  844. label.htmlFor = name;
  845. label.innerText = label_text;
  846. container.appendChild(label);
  847. const input = document.createElement("input");
  848. input.type = "text";
  849. input.placeholder = placeholder;
  850. input.name = name;
  851. input.id = name;
  852. container.appendChild(input);
  853. if (worker !== null) {
  854. worker(input);
  855. }
  856. if (!this.#form) {
  857. throw new Error("Screen is not visible yet!");
  858. }
  859. this._append_child(container);
  860. return (target = null) => {
  861. if (target !== null) {
  862. input.value = target;
  863. }
  864. return input.value;
  865. };
  866. }
  867. _append_child(target) {
  868. this.#form.appendChild(target);
  869. }
  870. _clear_results() {
  871. if (!this.#result) {
  872. return;
  873. }
  874. while (this.#result.lastChild) {
  875. this.#result.lastChild.remove();
  876. }
  877. }
  878. set _info(target) {
  879. this._clear_results();
  880. const info = document.createElement("p");
  881. info.classList.add("info");
  882. info.innerText = target;
  883. if (this.#result) {
  884. this.#result.appendChild(info);
  885. }
  886. }
  887. set _error(target) {
  888. this._clear_results();
  889. const info = document.createElement("p");
  890. info.classList.add("error");
  891. info.innerText = target;
  892. if (this.#result) {
  893. this.#result.appendChild(info);
  894. }
  895. }
  896. set _success(target) {
  897. this._clear_results();
  898. const info = document.createElement("p");
  899. info.classList.add("success");
  900. info.innerText = target;
  901. if (this.#result) {
  902. this.#result.appendChild(info);
  903. }
  904. }
  905. };
  906. // application/scripts/product_base.js
  907. var product_base = class {
  908. name;
  909. description;
  910. author;
  911. barcode;
  912. stock_count;
  913. constructor(target = null) {
  914. this.name = this._extract(target, "name");
  915. this.description = this._extract(target, "description");
  916. this.author = this._extract(target, "author");
  917. this.barcode = this._extract(target, "barcode");
  918. this.stock_count = this._extract(target, "stock_count");
  919. if (this.stock_count !== null) {
  920. try {
  921. this.stock_count = Number(this.stock_count);
  922. } catch {
  923. this.stock_count = 0;
  924. }
  925. }
  926. }
  927. get dump() {
  928. return {
  929. "name": new String(this.name),
  930. "description": new String(this.description),
  931. "author": new String(this.author),
  932. "barcode": new String(this.barcode),
  933. "stock_count": new String(this.stock_count)
  934. };
  935. }
  936. _extract(dict, name) {
  937. if (dict === null) {
  938. return null;
  939. }
  940. if (name in dict) {
  941. return dict[name];
  942. }
  943. return null;
  944. }
  945. get avairable() {
  946. return this.stock_count > 0;
  947. }
  948. };
  949. // application/scripts/edit_request.js
  950. var edit_request = class extends request {
  951. #target;
  952. #updated;
  953. constructor(target, updated) {
  954. super();
  955. this.#target = target;
  956. this.#updated = updated;
  957. }
  958. get _response() {
  959. return bool_response;
  960. }
  961. get data() {
  962. return Object.assign(this.#updated.dump, {
  963. "apikey": this._apikey
  964. });
  965. }
  966. get method() {
  967. return "POST";
  968. }
  969. get url() {
  970. return "/product/update/barcode/" + this.#target.barcode;
  971. }
  972. };
  973. // application/scripts/edit_image_request.js
  974. var edit_image_request = class extends request {
  975. #image;
  976. #target;
  977. constructor(target, image) {
  978. super();
  979. this.#target = target;
  980. this.#image = image;
  981. }
  982. get _response() {
  983. return bool_response;
  984. }
  985. get data() {
  986. return {
  987. "image": this.#image,
  988. "apikey": this._apikey
  989. };
  990. }
  991. get method() {
  992. return "POST";
  993. }
  994. get url() {
  995. return "/product/update/image/barcode/" + this.#target.barcode;
  996. }
  997. };
  998. // application/scripts/product_editor.js
  999. var product_editor = class extends formscreen {
  1000. #target;
  1001. #name;
  1002. #description;
  1003. #author;
  1004. #barcode;
  1005. #stock_count;
  1006. #image;
  1007. #loaded_image_type;
  1008. #loaded_image;
  1009. #image_preview;
  1010. constructor(target) {
  1011. super();
  1012. this.#target = target;
  1013. }
  1014. get target() {
  1015. return this.#target;
  1016. }
  1017. get _name() {
  1018. return _("product-editor");
  1019. }
  1020. _build_form() {
  1021. this.#loaded_image = null;
  1022. this.#loaded_image_type = null;
  1023. this.#name = this._create_input(
  1024. "name",
  1025. _("name-prompt"),
  1026. _("name-sample"),
  1027. (input) => {
  1028. input.value = this.#target.name;
  1029. }
  1030. );
  1031. this.#description = this._create_input(
  1032. "description",
  1033. _("description-prompt"),
  1034. _("description-sample"),
  1035. (input) => {
  1036. input.value = this.#target.description;
  1037. }
  1038. );
  1039. this.#author = this._create_input(
  1040. "author",
  1041. _("author-prompt"),
  1042. _("author-sample"),
  1043. (input) => {
  1044. input.value = this.#target.author;
  1045. }
  1046. );
  1047. this.#barcode = this._create_input(
  1048. "barcode",
  1049. _("barcode-prompt"),
  1050. _("barcode-sample"),
  1051. (input) => {
  1052. input.type = "number";
  1053. input.value = this.#target.barcode;
  1054. }
  1055. );
  1056. this.#stock_count = this._create_input(
  1057. "stock_count",
  1058. _("stock-count-prompt"),
  1059. _("stock-count-sample"),
  1060. (input) => {
  1061. input.type = "number";
  1062. input.value = this.#target.stock_count;
  1063. }
  1064. );
  1065. this._create_input(
  1066. "image",
  1067. _("change-product-image"),
  1068. "",
  1069. (input) => {
  1070. this.#image = input;
  1071. input.type = "file";
  1072. input.accept = "image/*";
  1073. input.addEventListener("change", () => {
  1074. this.#load_image_from_file();
  1075. });
  1076. }
  1077. );
  1078. this.#image_preview = document.createElement("img");
  1079. this.#image_preview.style.opacity = "1";
  1080. this.#image_preview.src = this.#target.image;
  1081. this._append_child(this.#image_preview);
  1082. }
  1083. get #ready_image() {
  1084. return this.#loaded_image;
  1085. }
  1086. #update_image_preview() {
  1087. this.#image_preview.src = "data:" + this.#loaded_image_type + ";base64," + this.#loaded_image;
  1088. this.#image_preview.style.opacity = "1";
  1089. }
  1090. #reset_image() {
  1091. this.#loaded_image = null;
  1092. this.#loaded_image_type = null;
  1093. this.#image_preview.style.opacity = "0";
  1094. this.#image_preview.src = "";
  1095. }
  1096. async #load_image_from_file() {
  1097. if (this.#image.files.length === 0) {
  1098. this.#reset_image();
  1099. }
  1100. const file = this.#image.files.item(0);
  1101. const buffer = await file.arrayBuffer();
  1102. let as_string = new String();
  1103. new Uint8Array(buffer).forEach((letter) => {
  1104. as_string += String.fromCharCode(letter);
  1105. });
  1106. this.#loaded_image = btoa(as_string);
  1107. this.#loaded_image_type = file.type;
  1108. this.#update_image_preview();
  1109. }
  1110. async #submit() {
  1111. const copy = this.#target.copy();
  1112. copy.name = this.#name();
  1113. copy.description = this.#description();
  1114. copy.author = this.#author();
  1115. copy.barcode = this.#barcode();
  1116. copy.stock_count = this.#stock_count();
  1117. const request2 = new edit_request(this.#target, copy);
  1118. const response = await request2.connect();
  1119. if (!response.result) {
  1120. throw new Error(response.cause);
  1121. }
  1122. this.#target = copy;
  1123. }
  1124. async #image_submit() {
  1125. const image = await this.#ready_image;
  1126. if (image === null) {
  1127. return;
  1128. }
  1129. const request2 = new edit_image_request(this.#target, image);
  1130. const response = await request2.connect();
  1131. if (!response.result) {
  1132. throw new Error(response.cause);
  1133. }
  1134. }
  1135. async _process() {
  1136. try {
  1137. this._info = _("updating-product-data");
  1138. await this.#submit();
  1139. this._info = _("processing-image");
  1140. await this.#image_submit();
  1141. this._success = _("uploaded-successfull");
  1142. searcher.reload();
  1143. setTimeout(() => {
  1144. this.hide();
  1145. }, 500);
  1146. } catch (error) {
  1147. this._error = new String(error);
  1148. }
  1149. }
  1150. };
  1151. // application/scripts/rents_screen.js
  1152. var rents_screen = class extends formscreen {
  1153. #target;
  1154. #email;
  1155. #phone;
  1156. get _email() {
  1157. return this.#email();
  1158. }
  1159. get _phone() {
  1160. return this.#phone();
  1161. }
  1162. constructor(target) {
  1163. super();
  1164. this.#target = target;
  1165. }
  1166. get _target() {
  1167. return this.#target;
  1168. }
  1169. _build_form() {
  1170. this.#email = this._create_input(
  1171. "email",
  1172. _("email-prompt"),
  1173. _("email-sample"),
  1174. (input) => {
  1175. input.type = "email";
  1176. }
  1177. );
  1178. this.#phone = this._create_input(
  1179. "phone",
  1180. _("phone-number-prompt"),
  1181. _("phone-number-sample"),
  1182. (input) => {
  1183. input.type = "tel";
  1184. const add_prefix = () => {
  1185. if (input.value.length === 0) {
  1186. input.value = "+48 ";
  1187. }
  1188. };
  1189. input.addEventListener("click", add_prefix);
  1190. input.addEventListener("focus", add_prefix);
  1191. }
  1192. );
  1193. }
  1194. };
  1195. // application/scripts/reservation.js
  1196. var reservation = class _reservation {
  1197. email;
  1198. phone_number;
  1199. product_barcode;
  1200. constructor(target = null) {
  1201. this.email = null;
  1202. this.phone_number = null;
  1203. this.product_barcode = null;
  1204. if (target === null) {
  1205. return;
  1206. }
  1207. if ("email" in target) {
  1208. this.email = target["email"];
  1209. }
  1210. if ("target_barcode" in target) {
  1211. this.product_barcode = target["target_barcode"];
  1212. }
  1213. if ("phone_number" in target) {
  1214. this.phone_number = target["phone_number"];
  1215. }
  1216. }
  1217. get dump() {
  1218. const dumped = {
  1219. "target_barcode": this.product_barcode
  1220. };
  1221. if (this.email !== null) {
  1222. dumped["email"] = this.email;
  1223. }
  1224. if (this.phone_number !== null) {
  1225. dumped["phone_number"] = this.phone_number;
  1226. }
  1227. return dumped;
  1228. }
  1229. get ready() {
  1230. if (this.product_barcode === null) return false;
  1231. if (this.email === null && this.phone_number === null) return false;
  1232. return true;
  1233. }
  1234. copy() {
  1235. return new _reservation(this.dump);
  1236. }
  1237. };
  1238. // application/scripts/product_rent_request.js
  1239. var product_rent_request = class extends request {
  1240. #reservation;
  1241. constructor(reservation2) {
  1242. super();
  1243. this.#reservation = reservation2;
  1244. }
  1245. get data() {
  1246. return Object.assign(this.#reservation.dump, {
  1247. "apikey": this._apikey
  1248. });
  1249. }
  1250. get _response() {
  1251. return bool_response;
  1252. }
  1253. get method() {
  1254. return "POST";
  1255. }
  1256. get url() {
  1257. return "/rent/product/barcode/" + this.#reservation.product_barcode;
  1258. }
  1259. };
  1260. // application/scripts/reservation_factory.js
  1261. var reservation_factory = class {
  1262. #target;
  1263. constructor() {
  1264. this.#target = new reservation();
  1265. }
  1266. phone_number(target) {
  1267. target = target.trim().replaceAll("-", "");
  1268. if (target.length === 0) {
  1269. target = null;
  1270. }
  1271. this.#target.phone_number = target;
  1272. return this;
  1273. }
  1274. email(target) {
  1275. target = target.trim();
  1276. if (target.length === 0) {
  1277. target = null;
  1278. }
  1279. this.#target.email = target;
  1280. return this;
  1281. }
  1282. product(target) {
  1283. this.#target.product_barcode = target.barcode;
  1284. return this;
  1285. }
  1286. result() {
  1287. if (this.#target.ready) {
  1288. return this.#target;
  1289. }
  1290. throw new Error("Target reservation is not ready yet.");
  1291. }
  1292. };
  1293. // application/scripts/product_rent.js
  1294. var product_rent = class extends rents_screen {
  1295. get _name() {
  1296. return _("product-rent");
  1297. }
  1298. async _process() {
  1299. try {
  1300. this._info = _("processing");
  1301. const target = new reservation_factory().email(this._email).phone_number(this._phone).product(this._target).result();
  1302. const request2 = new product_rent_request(target);
  1303. const response = await request2.connect();
  1304. if (!response.result) {
  1305. throw new Error(response.cause);
  1306. }
  1307. this._success = _("new-rent-added");
  1308. searcher.reload();
  1309. setTimeout(() => {
  1310. this.hide();
  1311. }, 500);
  1312. } catch (error) {
  1313. this._error = String(error);
  1314. }
  1315. }
  1316. };
  1317. // application/scripts/product_give_back_request.js
  1318. var product_give_back_request = class extends request {
  1319. #reservation;
  1320. constructor(reservation2) {
  1321. super();
  1322. this.#reservation = reservation2;
  1323. }
  1324. get data() {
  1325. return Object.assign(this.#reservation.dump, {
  1326. "apikey": this._apikey
  1327. });
  1328. }
  1329. get _response() {
  1330. return bool_response;
  1331. }
  1332. get method() {
  1333. return "POST";
  1334. }
  1335. get url() {
  1336. return "/give_back/product/barcode/" + this.#reservation.product_barcode;
  1337. }
  1338. };
  1339. // application/scripts/product_give_back.js
  1340. var product_give_back = class extends rents_screen {
  1341. get _name() {
  1342. return _("product-give-back");
  1343. }
  1344. async _process() {
  1345. try {
  1346. this._info = _("processing");
  1347. const target = new reservation_factory().email(this._email).phone_number(this._phone).product(this._target).result();
  1348. const request2 = new product_give_back_request(target);
  1349. const response = await request2.connect();
  1350. if (!response.result) {
  1351. throw new Error(response.cause);
  1352. }
  1353. this._success = _("give-back-successfull");
  1354. searcher.reload();
  1355. setTimeout(() => {
  1356. this.hide();
  1357. }, 500);
  1358. } catch (error) {
  1359. this._error = String(error);
  1360. }
  1361. }
  1362. };
  1363. // application/scripts/reservations_response.js
  1364. var reservations_response = class extends bool_response {
  1365. #collection;
  1366. constructor(target) {
  1367. super(target);
  1368. if (!this.result) {
  1369. return;
  1370. }
  1371. this.#collection = new Array();
  1372. target["reservations"].forEach((count) => {
  1373. this.#collection.push(new reservation(count));
  1374. });
  1375. }
  1376. get collection() {
  1377. if (!this.result) {
  1378. throw new Error(this.cause);
  1379. }
  1380. return this.#collection;
  1381. }
  1382. };
  1383. // application/scripts/product_reservations_request.js
  1384. var product_reservations_request = class extends request {
  1385. #target;
  1386. constructor(target) {
  1387. super();
  1388. this.#target = target;
  1389. }
  1390. get _response() {
  1391. return reservations_response;
  1392. }
  1393. get data() {
  1394. return {
  1395. "apikey": this._apikey
  1396. };
  1397. }
  1398. get method() {
  1399. return "POST";
  1400. }
  1401. get url() {
  1402. return "/reservations/product/barcode/" + this.#target.barcode;
  1403. }
  1404. };
  1405. // application/scripts/product_all_rents.js
  1406. var product_all_rents = class extends formscreen {
  1407. #target;
  1408. constructor(target) {
  1409. super();
  1410. this.#target = target;
  1411. }
  1412. get _name() {
  1413. return _("all-rents");
  1414. }
  1415. get _has_submit() {
  1416. return false;
  1417. }
  1418. #create_single(target) {
  1419. const container = document.createElement("div");
  1420. container.classList.add("reservation-info");
  1421. if (target.phone_number !== null) {
  1422. const phone_icon = document.createElement("span");
  1423. phone_icon.classList.add("material-icons");
  1424. phone_icon.innerText = "phone";
  1425. const phone_number = document.createElement("span");
  1426. phone_number.classList.add("numbers");
  1427. phone_number.innerText = target.phone_number;
  1428. const phone_number_container = document.createElement("p");
  1429. phone_number_container.appendChild(phone_icon);
  1430. phone_number_container.appendChild(phone_number);
  1431. container.appendChild(phone_number_container);
  1432. }
  1433. if (target.email !== null) {
  1434. const email_icon = document.createElement("span");
  1435. email_icon.classList.add("material-icons");
  1436. email_icon.innerText = "mail";
  1437. const email = document.createElement("span");
  1438. email.innerText = target.email;
  1439. const email_container = document.createElement("p");
  1440. email_container.appendChild(email_icon);
  1441. email_container.appendChild(email);
  1442. container.appendChild(email_container);
  1443. }
  1444. return container;
  1445. }
  1446. #create_single_button(target) {
  1447. const button = document.createElement("button");
  1448. button.classList.add("material-icons");
  1449. button.classList.add("give-back-button");
  1450. button.innerText = "save_alt";
  1451. button.addEventListener("click", async () => {
  1452. try {
  1453. this._info = _("processing");
  1454. const request2 = new product_give_back_request(target);
  1455. const response = await request2.connect();
  1456. if (!response.result) {
  1457. throw new Error(_(response.cause));
  1458. }
  1459. this._refresh();
  1460. searcher.reload();
  1461. } catch (error) {
  1462. this._error = String(error);
  1463. }
  1464. });
  1465. return button;
  1466. }
  1467. _process() {
  1468. return;
  1469. }
  1470. async _build_form() {
  1471. try {
  1472. this._info = _("loading");
  1473. const request2 = new product_reservations_request(this.#target);
  1474. const response = await request2.connect();
  1475. const list = document.createElement("div");
  1476. list.classList.add("reservations-list");
  1477. let empty = true;
  1478. response.collection.forEach((count) => {
  1479. const item = document.createElement("div");
  1480. item.classList.add("reservation");
  1481. const left = this.#create_single(count);
  1482. const right = this.#create_single_button(count);
  1483. empty = false;
  1484. item.appendChild(left);
  1485. item.appendChild(right);
  1486. list.appendChild(item);
  1487. });
  1488. this._append_child(list);
  1489. if (empty) {
  1490. this._success = "not-found-any-reservations";
  1491. } else {
  1492. this._clear_results();
  1493. }
  1494. } catch (error) {
  1495. this._error = String(error);
  1496. }
  1497. }
  1498. };
  1499. // application/scripts/product_not_avairable.js
  1500. var product_not_avairable = class extends confirm_action {
  1501. get _title() {
  1502. return _("product-not-avairable");
  1503. }
  1504. get _description() {
  1505. return _("this-product-is-not-avairable-yet");
  1506. }
  1507. get _info() {
  1508. return true;
  1509. }
  1510. };
  1511. // application/scripts/product_container.js
  1512. var product_container = class {
  1513. #target;
  1514. #node;
  1515. #login;
  1516. constructor(target) {
  1517. this.#target = new product(target.dump);
  1518. this.#node = null;
  1519. this.#login = new login_manager().logged_in;
  1520. }
  1521. get #header() {
  1522. const header = document.createElement("div");
  1523. header.classList.add("header");
  1524. const title = document.createElement("h3");
  1525. title.innerText = this.#target.name;
  1526. header.appendChild(title);
  1527. if (this.#login) {
  1528. header.appendChild(this.#manage);
  1529. }
  1530. return header;
  1531. }
  1532. get #manage() {
  1533. const manage = document.createElement("div");
  1534. manage.classList.add("manage");
  1535. const all_rents_button = document.createElement("button");
  1536. all_rents_button.classList.add("material-icons");
  1537. all_rents_button.classList.add("all-rents-button");
  1538. all_rents_button.innerText = "list";
  1539. manage.appendChild(all_rents_button);
  1540. const rent_button = document.createElement("button");
  1541. rent_button.classList.add("material-icons");
  1542. rent_button.classList.add("rent-button");
  1543. rent_button.innerText = "backpack";
  1544. manage.appendChild(rent_button);
  1545. const give_back_button = document.createElement("button");
  1546. give_back_button.classList.add("material-icons");
  1547. give_back_button.classList.add("give-back-button");
  1548. give_back_button.innerText = "save_alt";
  1549. manage.appendChild(give_back_button);
  1550. const edit_button = document.createElement("button");
  1551. edit_button.classList.add("material-icons");
  1552. edit_button.classList.add("edit-button");
  1553. edit_button.innerText = "edit";
  1554. manage.appendChild(edit_button);
  1555. const delete_button = document.createElement("button");
  1556. delete_button.classList.add("material-icons");
  1557. delete_button.classList.add("delete-button");
  1558. delete_button.innerText = "remove_circle_outline";
  1559. manage.appendChild(delete_button);
  1560. all_rents_button.addEventListener("click", () => {
  1561. new product_all_rents(this.#target).show();
  1562. });
  1563. rent_button.addEventListener("click", () => {
  1564. if (this.#target.on_stock > 0) {
  1565. new product_rent(this.#target).show();
  1566. } else {
  1567. new product_not_avairable().show();
  1568. }
  1569. });
  1570. give_back_button.addEventListener("click", () => {
  1571. new product_give_back(this.#target).show();
  1572. });
  1573. edit_button.addEventListener("click", () => {
  1574. new product_editor(this.#target).show();
  1575. });
  1576. delete_button.addEventListener("click", () => {
  1577. new delete_product_window(this.#target).show();
  1578. });
  1579. return manage;
  1580. }
  1581. get #description() {
  1582. const container = document.createElement("div");
  1583. container.classList.add("description");
  1584. const description = document.createElement("p");
  1585. description.innerText = this.#target.description;
  1586. description.classList.add("content");
  1587. const author_container = document.createElement("div");
  1588. author_container.classList.add("author");
  1589. const author = document.createElement("span");
  1590. author.innerText = this.#target.author;
  1591. const author_icon = document.createElement("span");
  1592. author_icon.classList.add("material-icons");
  1593. author_icon.innerText = "attribution";
  1594. author_container.appendChild(author_icon);
  1595. author_container.appendChild(author);
  1596. const stock_count = document.createElement("p");
  1597. stock_count.classList.add("stock-count");
  1598. stock_count.classList.add("material-icons");
  1599. if (this.#target.on_stock > 0) {
  1600. stock_count.innerText = "check_circle";
  1601. stock_count.classList.add("avairable");
  1602. } else {
  1603. stock_count.innerText = "cancel";
  1604. stock_count.classList.add("unavairable");
  1605. }
  1606. const barcode_container = document.createElement("p");
  1607. barcode_container.classList.add("barcode");
  1608. const barcode = document.createElement("span");
  1609. barcode.innerText = this.#target.barcode;
  1610. barcode.classList.add("numbers");
  1611. const barcode_icon = document.createElement("span");
  1612. barcode_icon.classList.add("material-icons");
  1613. barcode_icon.innerText = "qr_code_scanner";
  1614. barcode_container.appendChild(barcode_icon);
  1615. barcode_container.appendChild(barcode);
  1616. container.appendChild(description);
  1617. container.appendChild(author_container);
  1618. container.appendChild(barcode_container);
  1619. container.appendChild(stock_count);
  1620. return container;
  1621. }
  1622. get #cache_bypass() {
  1623. if (!this.#login) {
  1624. return "?cache=1";
  1625. }
  1626. return "?cache=" + new String(Math.floor(Math.random() * 100));
  1627. }
  1628. get #image() {
  1629. const image = document.createElement("img");
  1630. image.classList.add("image");
  1631. image.src = this.#target.thumbnail + this.#cache_bypass;
  1632. image.alt = this.#target.name;
  1633. image.loading = "lazy";
  1634. image.addEventListener("click", () => {
  1635. new product_fullscreen(this.#target).show();
  1636. });
  1637. return image;
  1638. }
  1639. get node() {
  1640. if (this.#node !== null) {
  1641. return this.#node;
  1642. }
  1643. const bottom_container = document.createElement("div");
  1644. bottom_container.classList.add("bottom-container");
  1645. bottom_container.appendChild(this.#description);
  1646. bottom_container.appendChild(this.#image);
  1647. const container = document.createElement("div");
  1648. container.classList.add("product");
  1649. container.appendChild(this.#header);
  1650. container.appendChild(bottom_container);
  1651. return this.#node = container;
  1652. }
  1653. add(target) {
  1654. const node = this.node;
  1655. node.style.opacity = "0";
  1656. node.style.transition = "opacity 0.5s";
  1657. target.appendChild(node);
  1658. setTimeout(() => {
  1659. node.style.opacity = "1";
  1660. }, 50);
  1661. }
  1662. drop() {
  1663. const container = this.#node;
  1664. if (container === null) {
  1665. throw new TypeError("It is not showed yet.");
  1666. }
  1667. container.style.opacity = "1";
  1668. container.style.transition = "opacity 0.5s";
  1669. setTimeout(() => {
  1670. container.style.opacity = "0";
  1671. }, 50);
  1672. setTimeout(() => {
  1673. this.#node = null;
  1674. container.remove();
  1675. }, 550);
  1676. }
  1677. };
  1678. // application/scripts/login_prompt.js
  1679. var login_prompt = class extends formscreen {
  1680. #nick;
  1681. #password;
  1682. constructor(target) {
  1683. super();
  1684. target.addEventListener("click", () => {
  1685. this.show();
  1686. });
  1687. }
  1688. get _name() {
  1689. return _("login-window");
  1690. }
  1691. async _process() {
  1692. try {
  1693. this._info = _("processing");
  1694. await this.#login();
  1695. this._success = _("logged-in");
  1696. setTimeout(() => {
  1697. location.reload();
  1698. }, 250);
  1699. } catch (error) {
  1700. this._error = new String(error);
  1701. }
  1702. }
  1703. async #login() {
  1704. const manager = new login_manager();
  1705. const result = await manager.login(
  1706. this.#nick(),
  1707. this.#password()
  1708. );
  1709. if (result) {
  1710. return;
  1711. }
  1712. throw new Error(_("can-not-login-check-nick-and-password"));
  1713. }
  1714. _build_form() {
  1715. this.#nick = this._create_input(
  1716. "nick",
  1717. _("nick-prompt"),
  1718. _("nick-sample")
  1719. );
  1720. this.#password = this._create_input(
  1721. "password",
  1722. _("password-prompt"),
  1723. _("password-sample"),
  1724. (input) => {
  1725. input.type = "password";
  1726. }
  1727. );
  1728. }
  1729. };
  1730. // application/scripts/create_request.js
  1731. var create_request = class extends request {
  1732. #image;
  1733. #product;
  1734. constructor(product2, image) {
  1735. super();
  1736. this.#image = image;
  1737. this.#product = product2;
  1738. }
  1739. get _response() {
  1740. return bool_response;
  1741. }
  1742. get data() {
  1743. return Object.assign(this.#product.dump, {
  1744. "image": this.#image,
  1745. "apikey": this._apikey
  1746. });
  1747. }
  1748. get method() {
  1749. return "POST";
  1750. }
  1751. get url() {
  1752. return "/product/create";
  1753. }
  1754. };
  1755. // application/scripts/autocomplete_response.js
  1756. var autocomplete_response = class extends bool_response {
  1757. #found;
  1758. constructor(target) {
  1759. super(target);
  1760. this.#found = null;
  1761. if (this.result) {
  1762. this.#found = target["found"];
  1763. }
  1764. }
  1765. get found() {
  1766. if (this.#found === null) {
  1767. throw new Error("Server response is not complete.");
  1768. }
  1769. return this.#found;
  1770. }
  1771. };
  1772. // application/scripts/autocomplete_request.js
  1773. var autocomplete_request = class extends request {
  1774. #barcode;
  1775. constructor(barcode) {
  1776. super();
  1777. this.#barcode = barcode;
  1778. }
  1779. get _response() {
  1780. return autocomplete_response;
  1781. }
  1782. get data() {
  1783. return {
  1784. "apikey": this._apikey
  1785. };
  1786. }
  1787. get method() {
  1788. return "POST";
  1789. }
  1790. get url() {
  1791. return "/complete/barcode/" + this.#barcode;
  1792. }
  1793. };
  1794. // application/scripts/product_adder.js
  1795. var product_adder = class extends formscreen {
  1796. #name;
  1797. #description;
  1798. #author;
  1799. #barcode;
  1800. #stock_count;
  1801. #image;
  1802. #loaded_image_type;
  1803. #loaded_image;
  1804. #image_preview;
  1805. get _name() {
  1806. return _("add-product");
  1807. }
  1808. async #autocomplete() {
  1809. const barcode = this.#barcode();
  1810. if (barcode.length === 0) {
  1811. this._info = _("fill-barcode-first");
  1812. return;
  1813. }
  1814. this._info = _("searching-in-the-web");
  1815. try {
  1816. const request2 = new autocomplete_request(barcode);
  1817. const response = await request2.connect();
  1818. if (!response.result) {
  1819. throw new Error(response.cause);
  1820. }
  1821. const product2 = response.found;
  1822. this.#name(product2.title);
  1823. this.#description(product2.description);
  1824. this.#author(product2.author);
  1825. this.#barcode(product2.barcode);
  1826. this.#loaded_image = product2.image;
  1827. this.#loaded_image_type = product2.image_type;
  1828. this.#update_image_preview();
  1829. this._info = _("autocomplete-ready-check-results");
  1830. } catch (error) {
  1831. this._error = new String(error);
  1832. }
  1833. }
  1834. #update_image_preview() {
  1835. this.#image_preview.src = "data:" + this.#loaded_image_type + ";base64," + this.#loaded_image;
  1836. this.#image_preview.style.opacity = "1";
  1837. }
  1838. get #autocomplete_button() {
  1839. const button = document.createElement("div");
  1840. button.classList.add("autocomplete-button");
  1841. button.classList.add("button");
  1842. const icon = document.createElement("span");
  1843. icon.classList.add("material-icons");
  1844. icon.innerText = "auto_fix_normal";
  1845. button.appendChild(icon);
  1846. const text = document.createElement("span");
  1847. text.classList.add("text");
  1848. text.innerText = _("autocomplete");
  1849. button.appendChild(text);
  1850. return button;
  1851. }
  1852. _build_form() {
  1853. this.#loaded_image = null;
  1854. this.#loaded_image_type = null;
  1855. this.#name = this._create_input(
  1856. "name",
  1857. _("name-prompt"),
  1858. _("name-sample")
  1859. );
  1860. this.#description = this._create_input(
  1861. "description",
  1862. _("description-prompt"),
  1863. _("description-sample")
  1864. );
  1865. this.#author = this._create_input(
  1866. "author",
  1867. _("author-prompt"),
  1868. _("author-sample")
  1869. );
  1870. this.#barcode = this._create_input(
  1871. "barcode",
  1872. _("barcode-prompt"),
  1873. _("barcode-sample"),
  1874. (input) => {
  1875. input.type = "number";
  1876. }
  1877. );
  1878. this.#stock_count = this._create_input(
  1879. "stock_count",
  1880. _("stock-count-prompt"),
  1881. _("stock-count-sample"),
  1882. (input) => {
  1883. input.type = "number";
  1884. }
  1885. );
  1886. this._create_input(
  1887. "image",
  1888. _("image-prompt"),
  1889. "",
  1890. (input) => {
  1891. this.#image = input;
  1892. input.type = "file";
  1893. input.accept = "image/*";
  1894. input.addEventListener("change", () => {
  1895. this.#load_image_from_file();
  1896. });
  1897. }
  1898. );
  1899. this.#image_preview = document.createElement("img");
  1900. this.#image_preview.style.opacity = "0";
  1901. this._append_child(this.#image_preview);
  1902. const autocomplete = this.#autocomplete_button;
  1903. this._append_child(autocomplete);
  1904. autocomplete.addEventListener("click", () => {
  1905. this.#autocomplete();
  1906. });
  1907. }
  1908. #reset_image() {
  1909. this.#loaded_image = null;
  1910. this.#loaded_image_type = null;
  1911. this.#image_preview.style.opacity = "0";
  1912. this.#image_preview.src = "";
  1913. }
  1914. async #load_image_from_file() {
  1915. if (this.#image.files.length === 0) {
  1916. this.#reset_image();
  1917. }
  1918. const file = this.#image.files.item(0);
  1919. const buffer = await file.arrayBuffer();
  1920. let as_string = new String();
  1921. new Uint8Array(buffer).forEach((letter) => {
  1922. as_string += String.fromCharCode(letter);
  1923. });
  1924. this.#loaded_image = btoa(as_string);
  1925. this.#loaded_image_type = file.type;
  1926. this.#update_image_preview();
  1927. }
  1928. get #ready_image() {
  1929. if (this.#loaded_image === null) {
  1930. throw new Error(_("load-any-image-first"));
  1931. }
  1932. return this.#loaded_image;
  1933. }
  1934. async #submit() {
  1935. const product2 = new product_base();
  1936. product2.name = this.#name();
  1937. product2.description = this.#description();
  1938. product2.author = this.#author();
  1939. product2.stock_count = this.#stock_count();
  1940. product2.barcode = this.#barcode();
  1941. const request2 = new create_request(product2, this.#ready_image);
  1942. const response = await request2.connect();
  1943. if (!response.result) {
  1944. throw new Error(response.cause);
  1945. }
  1946. }
  1947. async _process() {
  1948. try {
  1949. this._info = _("creating-new-product");
  1950. await this.#submit();
  1951. this._success = _("created-new-product-success");
  1952. searcher.reload();
  1953. setTimeout(() => {
  1954. this.hide();
  1955. }, 500);
  1956. } catch (error) {
  1957. this._error = new String(error);
  1958. }
  1959. }
  1960. };
  1961. // application/scripts/import_process_fail.js
  1962. var import_process_fail = class {
  1963. #product;
  1964. #error;
  1965. constructor(product2, error) {
  1966. this.#product = product2;
  1967. this.#error = error;
  1968. }
  1969. get error() {
  1970. return this.#error;
  1971. }
  1972. get product() {
  1973. return this.#product;
  1974. }
  1975. };
  1976. // application/scripts/database.js
  1977. var database = class {
  1978. #content;
  1979. #processed;
  1980. #on_skip;
  1981. constructor(content) {
  1982. this.#content = content;
  1983. this.#processed = /* @__PURE__ */ new Map();
  1984. this.#on_skip = null;
  1985. }
  1986. #append(target) {
  1987. if (this.#processed.has(target.barcode)) {
  1988. this.#processed.get(target.barcode).stock_count += 1;
  1989. return;
  1990. }
  1991. this.#processed.set(target.barcode, target);
  1992. }
  1993. #validate(target) {
  1994. if (!("id" in target)) {
  1995. throw new Error("One of item has no ID.");
  1996. }
  1997. if (!("title" in target)) {
  1998. throw new Error("Product " + target.barcode + " has no title.");
  1999. }
  2000. if (!("author" in target)) {
  2001. throw new Error("Product " + target.barcode + " has no author.");
  2002. }
  2003. }
  2004. #convert(target) {
  2005. this.#validate(target);
  2006. const product2 = new product_base();
  2007. product2.name = target.title;
  2008. product2.description = "";
  2009. product2.author = target.author;
  2010. product2.stock_count = 1;
  2011. product2.barcode = target.id;
  2012. return product2;
  2013. }
  2014. on_skip(target) {
  2015. this.#on_skip = target;
  2016. return this;
  2017. }
  2018. process() {
  2019. this.#processed.clear();
  2020. if (!(this.#content instanceof Array)) {
  2021. throw new Error("Database woud be array of objects.");
  2022. }
  2023. this.#content.forEach((count) => {
  2024. try {
  2025. const product2 = this.#convert(count);
  2026. this.#append(product2);
  2027. } catch (error) {
  2028. if (this.#on_skip === null) {
  2029. return;
  2030. }
  2031. try {
  2032. this.#on_skip(new import_process_fail(count, error));
  2033. } catch (fail) {
  2034. console.log(fail);
  2035. }
  2036. }
  2037. });
  2038. return this;
  2039. }
  2040. results() {
  2041. return Array.from(this.#processed.values());
  2042. }
  2043. };
  2044. // application/scripts/product_response.js
  2045. var product_response = class extends bool_response {
  2046. #product;
  2047. constructor(target) {
  2048. super(target);
  2049. this.#product = null;
  2050. if (this.result) {
  2051. if (!("product" in target)) {
  2052. throw new Error(_("incomplete-request-with-good-status"));
  2053. }
  2054. this.#product = new product(target.product);
  2055. }
  2056. }
  2057. get product() {
  2058. return this.#product;
  2059. }
  2060. };
  2061. // application/scripts/product_get_request.js
  2062. var product_get_request = class extends request {
  2063. #barcode;
  2064. constructor(barcode) {
  2065. super();
  2066. this.#barcode = barcode;
  2067. }
  2068. get _response() {
  2069. return product_response;
  2070. }
  2071. get data() {
  2072. return null;
  2073. }
  2074. get method() {
  2075. return "GET";
  2076. }
  2077. get url() {
  2078. return "/product/get/barcode/" + new String(this.#barcode);
  2079. }
  2080. };
  2081. // application/scripts/import_loop.js
  2082. var import_loop = class {
  2083. #content;
  2084. #on_autocomplete;
  2085. #on_create;
  2086. #on_single_fail;
  2087. #on_skip;
  2088. #on_single_success;
  2089. #finally;
  2090. on_autocomplete(target) {
  2091. this.#on_autocomplete = target;
  2092. return this;
  2093. }
  2094. on_create(target) {
  2095. this.#on_create = target;
  2096. return this;
  2097. }
  2098. on_single_fail(target) {
  2099. this.#on_single_fail = target;
  2100. return this;
  2101. }
  2102. on_skip(target) {
  2103. this.#on_skip = target;
  2104. return this;
  2105. }
  2106. on_single_success(target) {
  2107. this.#on_single_success = target;
  2108. return this;
  2109. }
  2110. finally(target) {
  2111. this.#finally = target;
  2112. return this;
  2113. }
  2114. constructor(dataset) {
  2115. this.#content = dataset;
  2116. this.#on_autocomplete = null;
  2117. this.#on_create = null;
  2118. this.#on_single_fail = null;
  2119. this.#on_skip = null;
  2120. this.#on_single_success = null;
  2121. this.#finally = null;
  2122. }
  2123. async #autocomplete(target) {
  2124. if (this.#on_autocomplete !== null) {
  2125. try {
  2126. this.#on_autocomplete(target);
  2127. } catch (error) {
  2128. console.log(error);
  2129. }
  2130. }
  2131. const request2 = new autocomplete_request(target.barcode);
  2132. const response = await request2.connect();
  2133. if (!response.result) {
  2134. throw new Error(response.cause);
  2135. }
  2136. const found = response.found;
  2137. target.description = found.description;
  2138. if (found.image.length === 0) {
  2139. throw new Error("Image for " + target.barcode + " not found.");
  2140. }
  2141. return new create_request(target, found.image);
  2142. }
  2143. async process() {
  2144. for (const count of this.#content) {
  2145. try {
  2146. await this.#create(count);
  2147. } catch (error) {
  2148. if (this.#on_single_fail !== null) {
  2149. try {
  2150. const fail = new import_process_fail(count, error);
  2151. this.#on_single_fail(fail);
  2152. } catch (error2) {
  2153. console.log(error2);
  2154. }
  2155. }
  2156. }
  2157. }
  2158. if (this.#finally !== null) {
  2159. try {
  2160. this.#finally();
  2161. } catch (error) {
  2162. console.log(error);
  2163. }
  2164. }
  2165. return this;
  2166. }
  2167. async #exists(target) {
  2168. const request2 = new product_get_request(target.barcode);
  2169. const response = await request2.connect();
  2170. return response.product !== null;
  2171. }
  2172. async #create(target) {
  2173. if (await this.#exists(target)) {
  2174. try {
  2175. const result = new import_process_fail(target, null);
  2176. this.#on_skip(result);
  2177. } catch (error) {
  2178. console.log(error);
  2179. }
  2180. return;
  2181. }
  2182. const request2 = await this.#autocomplete(target);
  2183. if (this.on_create !== null) {
  2184. try {
  2185. this.#on_create(target);
  2186. } catch (error) {
  2187. console.log(error);
  2188. }
  2189. }
  2190. const response = await request2.connect();
  2191. if (!response.result) {
  2192. throw new Error(response.cause);
  2193. }
  2194. if (this.#on_single_success !== null) {
  2195. try {
  2196. this.#on_single_success(target);
  2197. } catch (error) {
  2198. console.log(error);
  2199. }
  2200. }
  2201. }
  2202. };
  2203. // application/scripts/import_log.js
  2204. var import_log = class {
  2205. #log;
  2206. constructor() {
  2207. this.#log = new Array();
  2208. }
  2209. #append(target) {
  2210. this.#log.push(target);
  2211. }
  2212. #error_dump(error) {
  2213. return "Error: " + new String(error) + ".";
  2214. }
  2215. #product_dump(product2) {
  2216. return 'Product: barcode: "' + product2.barcode + '", title: "' + product2.title + '".';
  2217. }
  2218. fail(target) {
  2219. this.#append(
  2220. "Fail when processing item. " + this.#product_dump(target.product) + " " + this.#error_dump(target.error)
  2221. );
  2222. }
  2223. skip(target) {
  2224. this.#append(
  2225. "Skipping not ready item. " + this.#product_dump(target.product) + " " + this.#error_dump(target.error)
  2226. );
  2227. }
  2228. get length() {
  2229. return this.#log.length;
  2230. }
  2231. content() {
  2232. return this.#log.join("\n");
  2233. }
  2234. };
  2235. // application/scripts/downloader.js
  2236. var downloader = class {
  2237. #name;
  2238. #content;
  2239. #type;
  2240. #encode;
  2241. constructor() {
  2242. this.#name = "download.json";
  2243. this.#content = "";
  2244. this.#type = "text/plain";
  2245. this.#encode = "utf-8";
  2246. }
  2247. name(target) {
  2248. this.#name = target;
  2249. return this;
  2250. }
  2251. content(target) {
  2252. this.#content = target;
  2253. return this;
  2254. }
  2255. type(target) {
  2256. this.#type = target;
  2257. return this;
  2258. }
  2259. encode(target) {
  2260. this.#encode = target;
  2261. return this;
  2262. }
  2263. get #href() {
  2264. return "data:" + this.#type + ";charset=" + this.#encode + "," + encodeURIComponent(this.#content);
  2265. }
  2266. get #link() {
  2267. const link = document.createElement("a");
  2268. link.style.display = "none";
  2269. link.href = this.#href;
  2270. link.download = this.#name;
  2271. return link;
  2272. }
  2273. process() {
  2274. const link = this.#link;
  2275. const body = document.querySelector("body");
  2276. body.appendChild(link);
  2277. link.click();
  2278. body.removeChild(link);
  2279. return this;
  2280. }
  2281. };
  2282. // application/scripts/import_products.js
  2283. var import_products = class extends formscreen {
  2284. #file;
  2285. #content;
  2286. get _name() {
  2287. return _("import-products-json");
  2288. }
  2289. _build_form() {
  2290. this._create_input("file", "Database:", "", (input) => {
  2291. this.#file = input;
  2292. input.type = "file";
  2293. input.accept = "application/json";
  2294. });
  2295. }
  2296. async #load_file() {
  2297. if (this.#file.files.length === 0) {
  2298. throw new Error("select-products-json-database-first");
  2299. }
  2300. const file = this.#file.files.item(0);
  2301. const text = await file.text();
  2302. return JSON.parse(text);
  2303. }
  2304. async _process() {
  2305. try {
  2306. this._info = _("loading-file");
  2307. this.#content = await this.#load_file();
  2308. this._info = _("parsing-file-to-dataset");
  2309. const result = new import_log();
  2310. const dataset = new database(this.#content).on_skip((fail) => {
  2311. this._info = _("skipping-import-product-__barcode__").format({
  2312. barcode: fail.product.barcode
  2313. });
  2314. result.skip(fail);
  2315. }).process().results();
  2316. const loop = new import_loop(dataset).on_autocomplete((target) => {
  2317. this._info = _("searching-for-product-__barcode__").format({
  2318. barcode: target.barcode
  2319. });
  2320. }).on_create((target) => {
  2321. this._info = _("creating-product-__barcode__").format({
  2322. barcode: target.barcode
  2323. });
  2324. }).on_single_fail((target) => {
  2325. this._info = _("can-not-add-product-__barcode__").format({
  2326. barcode: target.product.barcode
  2327. });
  2328. result.fail(target);
  2329. }).on_skip((target) => {
  2330. this._info = _("skipping-product-__barcode").format({
  2331. barcode: target.product.barcode
  2332. });
  2333. result.skip(target);
  2334. }).on_single_success((target) => {
  2335. this._info = _("created-product-__barcode__").format({
  2336. barcode: target.barcode
  2337. });
  2338. }).finally(() => {
  2339. searcher.reload();
  2340. const log = new downloader().content(result.content()).type("text/plain").encode("utf-8").name("import-json.log").process();
  2341. if (result.length === 0) {
  2342. this._success = _("all-items-imported");
  2343. setTimeout(() => {
  2344. this.hide();
  2345. });
  2346. } else {
  2347. this._success = _("not-all-items-imported");
  2348. }
  2349. }).process();
  2350. } catch (error) {
  2351. this._error = new String(error);
  2352. }
  2353. }
  2354. };
  2355. // application/scripts/login_bar.js
  2356. var login_bar = class {
  2357. #manager;
  2358. constructor(target) {
  2359. this.#manager = new login_manager();
  2360. if (!this.#manager.logged_in) {
  2361. this.#not_logged(target);
  2362. return;
  2363. }
  2364. this.#logged(target);
  2365. }
  2366. #not_login_propertly() {
  2367. this.#manager.logout();
  2368. location.reload();
  2369. }
  2370. async #logged(target) {
  2371. const user2 = await this.#manager.get_user();
  2372. if (user2 === null) {
  2373. this.#not_login_propertly();
  2374. }
  2375. const info_icon = document.createElement("span");
  2376. info_icon.classList.add("icon");
  2377. info_icon.classList.add("material-icons");
  2378. info_icon.innerText = "account_circle";
  2379. const info_content = document.createElement("span");
  2380. info_content.innerText = user2.nick;
  2381. const info = document.createElement("p");
  2382. info.classList.add("login-info");
  2383. info.appendChild(info_icon);
  2384. info.appendChild(info_content);
  2385. target.appendChild(info);
  2386. const logout_button = document.createElement("button");
  2387. logout_button.innerText = "logout";
  2388. logout_button.classList.add("logout-button");
  2389. logout_button.classList.add("material-icons");
  2390. target.appendChild(logout_button);
  2391. const add_product_button = document.createElement("button");
  2392. add_product_button.innerText = "add";
  2393. add_product_button.classList.add("add-product-button");
  2394. add_product_button.classList.add("material-icons");
  2395. target.appendChild(add_product_button);
  2396. const import_products_button = document.createElement("button");
  2397. import_products_button.innerText = "dataset_linked";
  2398. import_products_button.classList.add("material-icons");
  2399. import_products_button.classList.add("import-products-button");
  2400. target.appendChild(import_products_button);
  2401. add_product_button.addEventListener("click", () => {
  2402. new product_adder().show();
  2403. });
  2404. import_products_button.addEventListener("click", () => {
  2405. new import_products().show();
  2406. });
  2407. logout_button.addEventListener("click", () => {
  2408. this.#manager.logout();
  2409. location.reload();
  2410. });
  2411. }
  2412. #not_logged(target) {
  2413. const login_button = document.createElement("button");
  2414. login_button.innerText = "account_circle";
  2415. login_button.classList.add("login-button");
  2416. login_button.classList.add("material-icons");
  2417. target.appendChild(login_button);
  2418. new login_prompt(login_button);
  2419. }
  2420. };
  2421. // application/scripts/scroll_up.js
  2422. var scroll_up = class {
  2423. #button;
  2424. constructor(button) {
  2425. this.#button = button;
  2426. this.#update();
  2427. document.addEventListener("scroll", () => {
  2428. this.#update();
  2429. });
  2430. this.#button.addEventListener("click", () => {
  2431. this.scroll();
  2432. });
  2433. }
  2434. scroll() {
  2435. this.#position = 0;
  2436. }
  2437. get #position() {
  2438. return document.scrollingElement.scrollTop;
  2439. }
  2440. set #position(target) {
  2441. document.scrollingElement.scrollTop = target;
  2442. }
  2443. get #visible() {
  2444. return Number(this.#button.style.opacity) === 1;
  2445. }
  2446. set #visible(target) {
  2447. this.#button.style.opacity = target ? "1" : "0";
  2448. }
  2449. get #margin() {
  2450. return 20;
  2451. }
  2452. #update() {
  2453. this.#visible = this.#position > this.#margin;
  2454. }
  2455. };
  2456. // application/scripts/color_theme.js
  2457. var color_theme = class {
  2458. #button;
  2459. #themes;
  2460. get themes() {
  2461. return Object.keys(this.#themes);
  2462. }
  2463. theme_name(target) {
  2464. return this.#themes[target];
  2465. }
  2466. constructor(button, themes = null) {
  2467. this.#button = button;
  2468. this.#themes = themes;
  2469. if (this.#themes === null) {
  2470. this.#themes = {
  2471. "dark-theme": "Dark",
  2472. "white-theme": "White"
  2473. };
  2474. }
  2475. this.#load();
  2476. this.#button.addEventListener("click", () => {
  2477. this.change();
  2478. });
  2479. }
  2480. get current() {
  2481. if (localStorage.hasOwnProperty("theme")) {
  2482. return localStorage.getItem("theme");
  2483. }
  2484. return this.themes[this.themes.length - 1];
  2485. }
  2486. #load() {
  2487. this.#show(this.current);
  2488. }
  2489. #save(target) {
  2490. localStorage.setItem("theme", target);
  2491. }
  2492. #show(target) {
  2493. const themes = this.themes;
  2494. const body = document.querySelector("body");
  2495. body.classList.forEach((count) => {
  2496. if (themes.indexOf(count) !== -1) {
  2497. body.classList.remove(count);
  2498. }
  2499. });
  2500. body.classList.add(target);
  2501. }
  2502. change() {
  2503. const themes = this.themes;
  2504. const current = this.current;
  2505. let position = themes.indexOf(current) + 1;
  2506. if (position === themes.length) {
  2507. position = 0;
  2508. }
  2509. const updated = themes[position];
  2510. this.#save(updated);
  2511. this.#show(updated);
  2512. }
  2513. };
  2514. // application/scripts/core.js
  2515. document.addEventListener("DOMContentLoaded", async () => {
  2516. const languages = new cx_libtranslate.languages("app/assets/languages");
  2517. await languages.load("index.json?ver=02112025");
  2518. const preferences = new cx_libtranslate.preferences(languages);
  2519. preferences.selector.insert().add_listener(() => {
  2520. location.reload();
  2521. });
  2522. const phrasebook = await preferences.load_choosen_phrasebook();
  2523. phrasebook.set_as_default();
  2524. const autotranslate = await preferences.get_autotranslate();
  2525. autotranslate.connect();
  2526. const top_bar_spacing = new height_equaler(
  2527. document.querySelector(".top-bar"),
  2528. document.querySelector(".top-bar-spacing")
  2529. );
  2530. const container = document.querySelector(".products");
  2531. const search_bar = document.querySelector("form.search");
  2532. const search_title = document.querySelector(".search-title");
  2533. const login_space = document.querySelector(".top-bar .right");
  2534. const scroll_up_button = document.querySelector(".scroll-up-button");
  2535. const reverse_colors = document.querySelector(".reverse-colors");
  2536. const counter = document.querySelector(".products-counter");
  2537. const manager = new product_containers(container);
  2538. new login_bar(login_space);
  2539. new scroll_up(scroll_up_button);
  2540. new color_theme(reverse_colors);
  2541. new searcher(search_bar, manager, search_title, counter).show_all();
  2542. });
  2543. })();