Add a component to scan books

This commit is contained in:
2026-02-05 18:30:24 +01:00
parent 928fd9ddac
commit f73defdad3
10 changed files with 143 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
<script setup>
import AppNavBar from './AppNavBar.vue'
import { RouterView } from 'vue-router'
import AppNavBar from './AppNavBar.vue'
import { RouterView } from 'vue-router'
</script>
<template>

View File

@@ -1,4 +1,5 @@
<script setup>
import { ref } from 'vue'
import { useRouter, RouterLink } from 'vue-router'
import NavBarSearch from './NavBarSearch.vue'
import { useAuthStore } from './auth.store.js'
@@ -6,6 +7,8 @@
const authStore = useAuthStore();
const router = useRouter();
const popupDisplay = ref(false)
function logout() {
authStore.logout();
router.push('/');
@@ -21,7 +24,7 @@
</div>
<div class="navbar-menu">
<div class="navbar-start">
<NavBarSearch/>
<NavBarSearch @open-scan-popup="popupDisplay = true"/>
<RouterLink v-if="authStore.user" to="/books" class="navbar-item" activeClass="is-active">
{{ $t('navbar.mybooks')}}
</RouterLink>

62
front/src/Modal.vue Normal file
View File

@@ -0,0 +1,62 @@
<script setup>
import ScanBook from './ScanBook.vue'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const open = ref(false);
const router = useRouter();
function onBarcodeDecode(isbn) {
open.value = false;
router.push('/search/' + isbn)
}
</script>
<template>
<div class="control">
<button @click="open = true" class="button">
<span class="icon" title="Barcode">
<b-icon-upc-scan />
</span>
</button>
</div>
<Teleport to="body">
<div v-if="open">
<div @click="open = false" class="modal-backdrop"></div>
<div class="modal has-background-dark">
<ScanBook @read-barcode="onBarcodeDecode"/>
</div>
</div>
</Teleport>
</template>
<style scoped>
.modal-backdrop {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
.modal {
height: 70%;
width: 70%;
top: 10%;
left: 15%;
box-shadow: 2px 2px 20px 1px;
overflow-x: auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 15px;
z-index: 1000;
}
</style>

View File

@@ -1,6 +1,7 @@
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import Modal from './Modal.vue'
const searchterm = ref("");
const router = useRouter();
@@ -26,6 +27,7 @@
</span>
</button>
</div>
<Modal/>
</div>
</div>
</template>

31
front/src/ScanBook.vue Normal file
View File

@@ -0,0 +1,31 @@
<script setup>
import { useTemplateRef, onMounted, ref } from 'vue'
import { BrowserMultiFormatReader } from "@zxing/library";
const emit = defineEmits('readBarcode')
const scanResult = ref(null);
const codeReader = new BrowserMultiFormatReader();
const scannerElement = useTemplateRef("scanner");
onMounted(() => {
codeReader.decodeFromVideoDevice(undefined, scannerElement.value, (result, err) => {
if (result) {
emit('readBarcode', result.text)
}
});
});
function onResult(result) {
scanResult.value = result
}
</script>
<template>
<h1 class="title">{{$t('barcode.title')}}</h1>
<div v-if="scanResult">{{scanResult}}</div>
<video poster="data:image/gif,AAAA" ref="scanner"></video>
</template>
<style scoped>
</style>

View File

@@ -10,6 +10,9 @@
"signup": "Sign up",
"login": "Log In"
},
"barcode": {
"title": "Scan your barcode"
},
"addbook": {
"title":"Title",
"author":"Author",

View File

@@ -10,6 +10,9 @@
"signup": "S'inscrire",
"login": "Se connecter"
},
"barcode": {
"title": "Scanner le code-barre"
},
"addbook": {
"title":"Titre",
"author":"Auteur",

View File

@@ -7,12 +7,14 @@ import BookForm from './BookForm.vue'
import SignUp from './SignUp.vue'
import LogIn from './LogIn.vue'
import Home from './Home.vue'
import ScanBook from './ScanBook.vue'
import SearchBook from './SearchBook.vue'
import ImportInventaire from './ImportInventaire.vue'
import { useAuthStore } from './auth.store'
const routes = [
{ path: '/', component: Home },
{ path: '/scan', component: ScanBook },
{ path: '/books', component: BooksBrowser },
{ path: '/book/:id', component: BookForm, props: true },
{ path: '/author/:id', component: AuthorForm, props: true },