<main class="layout-maxed ajouter-un-album" id="app"> <h1>Ajouter un album</h1> <div class="grid sm:grid-cols-2"> <div> <form @submit="search"> <label for="q">Nom de l'album ou code barre</label> <div class="field has-addons"> <input type="text" name="q" id="q" v-model="q" placeholder="ex : Hybrid Theory" autofocus> <button class="button is-primary" :disabled="loading" aria-label="Chercher"> <i class="icon-search" v-if="!loading"></i> <i class="icon-spin animate-spin" v-if="loading"></i> </button> </div> </form> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 list hover"> <div class="item" v-if="!loading" v-for="item in items"> <a @click="loadDetails(item.id)" class="title">{{ item.artists_sort }} {{ item.title }}</a> <div class="grid grid-cols-2 md:grid-cols-4"> <div> <img :src="item.thumb" :alt="item.title" @click="loadDetails(item.id)"/> </div> <div class="md:col-span-3"> <span><strong>Année :</strong> {{ item.year }}</span> <br /> <span><strong>Pays :</strong> {{ item.country }}</span> <br /> <span> <strong>Format : </strong> <template v-for="(format, index) in item.format"> {{ format }}<template v-if="index < item.format.length - 1">, </template> </template> </span> <br /> <span> <strong>Genre : </strong> <template v-for="(genre, index) in item.genre"> {{ genre }}<template v-if="index < item.genre.length - 1">, </template> </template> </span> <br /> <span> <strong>Style : </strong> <template v-for="(style, index) in item.style"> {{ style }}<template v-if="index < item.style.length - 1">, </template> </template> </span> </div> </div> </div> </div> <div class="modal" :class="{'is-visible': modalIsVisible}"> <div class="modal-background"></div> <div class="modal-card"> <header> <div>{{details.artists_sort}} - {{details.title}}</div> <button aria-label="Fermer" class="close" @click="toggleModal"></button> </header> <section> <div class="grid grid-cols-2 gap-16"> <div> <div class="text-center"> <img :src="details.thumb %>" :alt="`Miniature pour l'album ${details.title}`" /> <hr /> <img v-for="image in details.images" :src="image.uri150" :alt="`Miniature de type ${image.type}`" style="max-width: 60px;" /> <hr /> </div> <ol class="ml-4"> <li v-for="track in details.tracklist">{{ track.title }} ({{track.duration}})</li> </ol> </div> <div> <div class="grid grid-cols-2 gap-10"> <div> <strong>Genres</strong> <br /> <template v-for="(genre, index) in details.genres"> {{genre}}<template v-if="index < details.genres.length - 1">, </template> </template> </div> <div> <strong>Styles</strong> <br /> <span v-for="(style, index) in details.styles"> {{style}}<template v-if="index < details.styles.length - 1">, </template> </span> </div> </div> <hr /> <div class="grid grid-cols-3 gap-10"> <div> <strong>Pays</strong> <br /> <span>{{details.country}}</span> </div> <div> <strong>Année</strong> <br /> <span>{{details.year}}</span> </div> <div> <strong>Date de sortie</strong> <br /> <span>{{details.released}}</span> </div> </div> <hr /> <div class="grid grid-cols-2 gap-10"> <div> <strong>Format</strong> <br /> <span v-for="(format, index) in details.formats"> {{format.name}}<template v-if="index < details.formats.length - 1">, </template> </span> </div> </div> <hr /> <div class="grid grid-cols-2 gap-10"> <div> <strong>Codes barres</strong> <ol> <li v-for="identifier in details.identifiers"> {{identifier.value}} ({{identifier.type}}) </li> </ol> </div> <div> <strong>Label</strong> <ol> <li v-for="label in details.labels"> {{label.name}} </li> </ol> <strong>Société</strong> <ol> <li v-for="company in details.companie"> {{company.name}} </li> </ol> </div> </div> </div> </div> </section> <footer> <button class="button is-primary" @click="add">Ajouter</button> <button class="button" @click="toggleModal">Annuler</button> </footer> </div> </div> </main> <script> Vue.createApp({ data() { return { q: '', loading: false, items: [], details: {}, modalIsVisible: false, } }, methods: { search(event) { event.preventDefault(); if ( this.loading ) { return false; } this.loading = true; axios.get(`/api/v1/search?q=${this.q}`) .then( response => { const { results, } = response.data; let items = []; for (let i = 0 ; i < results.length ; i += 1 ) { const { id, title, thumb, year, country, format, genre, style, } = results[i]; items.push({ id, title, thumb, year, country, format, genre, style, }); } this.items = items; }) .catch((err) => { showToastr(err.response?.data?.message || "Aucun résultat trouvé :/"); }) .finally(() => { this.loading = false; }); }, toggleModal() { this.modalIsVisible = !this.modalIsVisible; }, loadDetails(discogsId) { axios.get(`/api/v1/search/${discogsId}`) .then( response => { const { data, } = response; this.details = data; this.toggleModal(); }) .catch((err) => { showToastr(err.response?.data?.message || "Impossible de charger les détails de cet album"); }) .finally(() => { this.loading = false; }); }, add() { axios.post('/api/v1/albums', this.details) .then(() => { window.location.href = '/ma-collection'; }) .catch((err) => { showToastr(err.response?.data?.message || "Impossible d'ajouter ce album pour le moment…"); }); }, } }).mount('#app'); </script>