Scanner.svelte 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <script>
  2. import { configData, db, scan_status } from "./../stores.js";
  3. import { DontBubbleException } from './../exceptions.js'
  4. import { onDestroy } from 'svelte';
  5. import { focus } from './../helpers.js';
  6. onDestroy(() => $scan_status = {})
  7. export let scaninterface
  8. const { update, ausleihe, rueckgabe, zuordnung } = scaninterface
  9. $scan_status = { ausleihe, rueckgabe, zuordnung }
  10. const prefix_length = $configData.scan_prefix.length;
  11. let buffer = [],
  12. barcode,
  13. barcode_manuell,
  14. barcode_input,
  15. registrieren,
  16. lastKeyTime = Date.now(),
  17. medium,
  18. neuer_titel = "",
  19. medium_selected;
  20. function handle_keydown(event) {
  21. if (event.key === 'Escape') {
  22. barcode_manuell = !barcode_manuell
  23. }
  24. if (barcode_manuell) return
  25. if (registrieren) {
  26. (event.key === 'Escape') && (registrieren = false)
  27. return
  28. }
  29. const currentTime = Date.now();
  30. if (currentTime - lastKeyTime > 1000) buffer = [];
  31. if (event.key === 'Enter' && !buffer.length) return
  32. if (
  33. event.key === "Enter" &&
  34. buffer.slice(0, prefix_length).join("") === $configData.scan_prefix
  35. ) {
  36. barcode = buffer.slice(prefix_length).join("");
  37. buffer = [];
  38. scan();
  39. } else {
  40. const charList = "abcdefghijklmnopqrstuvwxyz0123456789";
  41. const key = event.key.toLowerCase();
  42. if (charList.indexOf(key) === -1) return;
  43. buffer.push(event.key);
  44. lastKeyTime = currentTime;
  45. }
  46. }
  47. function scan() {
  48. const res = $db
  49. .prepare(
  50. `
  51. SELECT x.barcode, x.id AS x_id, m.name, m.id AS m_id, x.medienbezeichnung_id, a.*, a.id AS ausleihe_id
  52. FROM medienexemplar x
  53. LEFT JOIN medienbezeichnung AS m ON (x.medienbezeichnung_id = m.id)
  54. LEFT JOIN ausleihe AS a ON (a.medienexemplar_id = x.id)
  55. WHERE barcode = ?
  56. `
  57. )
  58. .get(barcode);
  59. console.log('Ergebnis Barcodesuche in DB: ', res || '– nichts gefunden –');
  60. if (!res) {
  61. try {
  62. zuordnung(barcode);
  63. } catch (e) {
  64. medium = $db.prepare(`SELECT * FROM medienbezeichnung`).all();
  65. registrieren = true
  66. console.log(e, "Barcode unbekannt; Medium registrieren");
  67. return
  68. }
  69. } else if (res.ausleihe_id) {
  70. try {
  71. rueckgabe(res);
  72. } catch (e) {
  73. if (e instanceof DontBubbleException) return
  74. }
  75. } else {
  76. try {
  77. ausleihe(res);
  78. } catch (e) {
  79. if (e instanceof DontBubbleException) return
  80. }
  81. }
  82. try {
  83. update();
  84. } catch (e) {
  85. console.log("Ausgeliehene Medien konnten nicht aktualisiert werden");
  86. }
  87. }
  88. function neu_anlegen() {
  89. if (!neuer_titel.length) return
  90. const res = $db
  91. .prepare(
  92. `
  93. INSERT INTO medienbezeichnung (name) VALUES (?)
  94. `
  95. )
  96. .run(neuer_titel.trim());
  97. neuer_titel = ''
  98. zuordnen(res.lastInsertRowid)
  99. }
  100. function zuordnen(medien_id) {
  101. if (!medien_id) return
  102. const res = $db
  103. .prepare(
  104. `
  105. INSERT INTO medienexemplar (barcode, medienbezeichnung_id) VALUES (?,?)
  106. `
  107. )
  108. .run(barcode, medien_id);
  109. registrieren = false;
  110. scan()
  111. }
  112. </script>
  113. <svelte:window on:keydown={handle_keydown} />
  114. {#if barcode_manuell}
  115. <div class="modal is-active">
  116. <div class="modal-background" on:click={()=>barcode_manuell=false}/>
  117. <button class="modal-close is-large" aria-label="close" on:click={()=>barcode_manuell=false}></button>
  118. <div class="modal-content">
  119. <div class="box">
  120. <div class="field">
  121. <label class="label">Barcode eingeben</label>
  122. <div class="control">
  123. <input
  124. class="input"
  125. type="text"
  126. bind:value={barcode}
  127. use:focus
  128. on:keydown={e => {if (e.key === 'Enter') { barcode_manuell=false; scan()}}} />
  129. </div>
  130. </div>
  131. </div>
  132. </div>
  133. </div>
  134. {/if}
  135. {#if registrieren}
  136. <div class="modal is-active">
  137. <div class="modal-background" on:click={()=>registrieren=false}/>
  138. <button class="modal-close is-large" aria-label="close" on:click={()=>registrieren=false}></button>
  139. <div class="modal-content">
  140. <div class="box">
  141. Was machen wir mit dem Barcode?
  142. <pre>{barcode}</pre>
  143. <hr />
  144. {#if medium.length}
  145. <label class="label">Das gehört zu</label>
  146. <div class="field has-addons">
  147. <div class="control is-expanded">
  148. <div class="select is-fullwidth">
  149. <select bind:value={medium_selected}>
  150. <option>– nichts ausgewählt –</option>
  151. {#each medium as m}
  152. <option value={m.id}>{m.name}</option>
  153. {/each}
  154. </select>
  155. </div>
  156. </div>
  157. <div class="control">
  158. <button
  159. class="button is-primary"
  160. on:click={() => zuordnen(medium_selected)}>
  161. Titel verwenden
  162. </button>
  163. </div>
  164. </div>
  165. {/if}
  166. <label class="label">Neu anlegen unter</label>
  167. <div class="field has-addons">
  168. <div class="control is-expanded">
  169. <input
  170. class="input is-fullwidth"
  171. type="text"
  172. bind:value={neuer_titel}
  173. on:keydown={e => e.key === 'Enter' && neu_anlegen()} />
  174. </div>
  175. <div class="control">
  176. <button
  177. class="button is-primary"
  178. on:click={() => zuordnen(medium_selected)}>
  179. Titel anlegen
  180. </button>
  181. </div>
  182. </div>
  183. </div>
  184. </div>
  185. </div>
  186. {/if}