<main class="layout-maxed ajouter-un-album" id="app"> <h1>Ajouter un album</h1> <form @submit="search"> <div class="grid sm:grid-cols-2"> <div> <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 : Iron Maiden - Powerslave" 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> <div class="grid sm:grid-cols-3 gap-5"> <div class="field"> <label for="format">Format</label> <select id="format" v-model="format"> <option value="">Tous</option> <option v-for="format in orderedItems(formats)" :value="format">{{format}}</option> </select> </div> <div class="field"> <label for="year">Année</label> <input type="number" name="year" v-model="year" id="year" placeholder="1984"> </div> <div class="field"> <label for="country">Pays</label> <input type="string" name="country" v-model="country" id="country" placeholder="France"> </div> </div> </div> </div> </form> <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: '', year: '', country: '', format: '', loading: false, items: [], details: {}, modalIsVisible: false, formats: [ 'Vinyl', 'Acetate', 'Flexi-disc', 'Lathe Cut', 'Mighty Tiny', 'Shellac', 'Sopic', 'Pathé Disc', 'Edison Disc', 'Cylinder', 'CD', 'CDr', 'CDV', 'DVD', 'DVDr', 'HD DVD', 'HD DVD-R', 'Blu-ray', 'Blu-ray-R', 'Ultra HD Blu-ray', 'SACD', '4-Track Cartridge', '8-Track Cartridge', 'Cassette', 'DC-International', 'Elcaset', 'PlayTape', 'RCA Tape Cartridge', 'DAT', 'DCC', 'Microcassette', 'NT Cassette', 'Pocket Rocker', 'Revere Magnetic Stereo Tape Ca', 'Tefifon', 'Reel-To-Reel', 'Sabamobil', 'Betacam', 'Betacam SP', 'Betamax', 'Cartrivision', 'MiniDV', 'Super VHS', 'U-matic', 'VHS', 'Video 2000', 'Video8', 'Film Reel', 'HitClips', 'Laserdisc', 'SelectaVision', 'VHD', 'Wire Recording', 'Minidisc', 'MVD', 'UMD', 'Floppy Disk', 'File', 'Memory Stick', 'Hybrid', 'All Media', 'Box Set', ] } }, methods: { search(event) { event.preventDefault(); if ( this.loading ) { return false; } this.loading = true; let url = `/api/v1/search?q=${this.q}`; if ( this.year ) { url += `&year=${this.year}`; } if ( this.country ) { url += `&country=${this.country}`; } if ( this.format ) { url += `&format=${this.format}`; } axios.get(url) .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 cet album pour le moment…"); }); }, orderedItems(items) { return items.sort(); } } }).mount('#app'); </script>