Scanner.svelte 5.7 KB

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