app.js 70 KB

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