add cards & tracks
This commit is contained in:
		| @@ -130,7 +130,7 @@ onMounted(() => { | |||||||
|   const down = (ev: PointerEvent) => { |   const down = (ev: PointerEvent) => { | ||||||
|     ev.preventDefault() |     ev.preventDefault() | ||||||
|     dragging = true |     dragging = true | ||||||
|     scene.value?.setPointerCapture(ev.pointerId) |     box.value?.setPointerCapture(ev.pointerId) | ||||||
|     lastPointer = { x: ev.clientX, y: ev.clientY, time: performance.now() } |     lastPointer = { x: ev.clientX, y: ev.clientY, time: performance.now() } | ||||||
|     velocity = { x: 0, y: 0 } |     velocity = { x: 0, y: 0 } | ||||||
|     if (raf) { cancelAnimationFrame(raf); raf = null } |     if (raf) { cancelAnimationFrame(raf); raf = null } | ||||||
| @@ -158,17 +158,17 @@ onMounted(() => { | |||||||
|   const end = (ev: PointerEvent) => { |   const end = (ev: PointerEvent) => { | ||||||
|     if (!dragging) return |     if (!dragging) return | ||||||
|     dragging = false |     dragging = false | ||||||
|     try { scene.value?.releasePointerCapture(ev.pointerId) } catch { } |     try { box.value?.releasePointerCapture(ev.pointerId) } catch { } | ||||||
|     if (enableInertia && (Math.abs(velocity.x) > minVelocity || Math.abs(velocity.y) > minVelocity)) { |     if (enableInertia && (Math.abs(velocity.x) > minVelocity || Math.abs(velocity.y) > minVelocity)) { | ||||||
|       if (!raf) raf = requestAnimationFrame(tickInertia) |       if (!raf) raf = requestAnimationFrame(tickInertia) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   scene.value?.addEventListener('pointerdown', down) |   box.value?.addEventListener('pointerdown', down) | ||||||
|   scene.value?.addEventListener('pointermove', move) |   box.value?.addEventListener('pointermove', move) | ||||||
|   scene.value?.addEventListener('pointerup', end) |   box.value?.addEventListener('pointerup', end) | ||||||
|   scene.value?.addEventListener('pointercancel', end) |   box.value?.addEventListener('pointercancel', end) | ||||||
|   scene.value?.addEventListener('pointerleave', end) |   box.value?.addEventListener('pointerleave', end) | ||||||
|  |  | ||||||
|   onBeforeUnmount(() => { |   onBeforeUnmount(() => { | ||||||
|     cancelAnimationFrame(raf!) |     cancelAnimationFrame(raf!) | ||||||
|   | |||||||
| @@ -1,14 +1,17 @@ | |||||||
| <template> | <template> | ||||||
|   <article class="relative"> |   <article class="relative"> | ||||||
|     <main |     <main | ||||||
|       class="absolute top-0 backdrop-blur-sm z-40 -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> |       class="backdrop-blur-sm border-2 -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-40 hover:bg-opacity-80 hover:shadow-xl transition-all bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> | ||||||
|       <!-- Cover --> |       <!-- Cover --> | ||||||
|       <figure class="flex-1 overflow-hidden rounded-t-xl"> |       <figure @click="playerStore.playTrack(props.track)" class="flex-1 overflow-hidden rounded-t-xl cursor-pointer"> | ||||||
|         <img :src="coverUrl" alt="Pochette de l'album" class="w-full h-full object-cover object-center" /> |         <img :src="coverUrl" alt="Pochette de l'album" class="w-full h-full object-cover object-center" /> | ||||||
|       </figure> |       </figure> | ||||||
|  |  | ||||||
|       <!-- Body --> |       <!-- Body --> | ||||||
|       <div class="p-3 text-center bg-white rounded-b-xl"> |       <div class="p-3 text-center bg-white rounded-b-xl"> | ||||||
|  |         <div class="label"> | ||||||
|  |           {{ props.track.order }} | ||||||
|  |         </div> | ||||||
|         <h2 class="text-base text-neutral-800 font-bold truncate">{{ props.track.title }}</h2> |         <h2 class="text-base text-neutral-800 font-bold truncate">{{ props.track.title }}</h2> | ||||||
|         <p class="text-sm text-neutral-500 truncate"> |         <p class="text-sm text-neutral-500 truncate"> | ||||||
|           {{ props.track.artist.name }} |           {{ props.track.artist.name }} | ||||||
| @@ -17,11 +20,14 @@ | |||||||
|     </main> |     </main> | ||||||
|  |  | ||||||
|     <footer |     <footer | ||||||
|       class="absolute top-0 ml-32 backdrop-blur-sm -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> |       class="ml-32 backdrop-blur-sm -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> | ||||||
|       <!-- Back --> |       <!-- Back --> | ||||||
|       <div class="h-full flex p-16 text-center bg-slate-800 rounded-xl"> |       <div class="h-full flex p-16 text-center bg-slate-800 rounded-xl"> | ||||||
|         <img src="/favicon.svg" /> |         <img src="/favicon.svg" /> | ||||||
|       </div> |       </div> | ||||||
|  |       <div class="label"> | ||||||
|  |         {{ props.track.id }} | ||||||
|  |       </div> | ||||||
|     </footer> |     </footer> | ||||||
|   </article> |   </article> | ||||||
|  |  | ||||||
| @@ -29,7 +35,19 @@ | |||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import type { Track } from '~~/types/types' | import type { Track } from '~~/types/types' | ||||||
|  | import { usePlayerStore } from '~/store/player' | ||||||
|  |  | ||||||
| const props = defineProps<{ track: Track }>() | const props = defineProps<{ track: Track }>() | ||||||
| const coverUrl = `https://f4.bcbits.com/img/${props.track.artist.coverId}_4.jpg` | const playerStore = usePlayerStore() | ||||||
|  | const coverUrl = props.track.coverId.startsWith('http') | ||||||
|  |   ? props.track.coverId | ||||||
|  |   : `https://f4.bcbits.com/img/${props.track.coverId}_4.jpg`; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|  | <style> | ||||||
|  | .label { | ||||||
|  |   @apply rounded-full size-7 p-2 bg-esyellow leading-3 -mt-6; | ||||||
|  |   font-weight: bold; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										38
									
								
								app/components/molecule/player.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/components/molecule/player.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | <template> | ||||||
|  |   <audio ref="audioRef" class="fixed z-50 bottom-0 left-1/2 -translate-x-1/2 w-1/2" | ||||||
|  |     :src="playerStore.currentTrack ? playerStore.getCompilationUrlFromTrack(playerStore.currentTrack) : ''" controls | ||||||
|  |     @timeupdate="updatePosition" @ended="onEnded" /> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { ref, onMounted, watch } from 'vue' | ||||||
|  | import { usePlayerStore } from '~/store/player' | ||||||
|  |  | ||||||
|  | const playerStore = usePlayerStore() | ||||||
|  | const audioRef = ref<HTMLAudioElement | null>(null) | ||||||
|  |  | ||||||
|  | onMounted(() => { | ||||||
|  |   if (audioRef.value) playerStore.audio = audioRef.value | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | // Mettre à jour la position | ||||||
|  | function updatePosition() { | ||||||
|  |   if (audioRef.value) playerStore.position = audioRef.value.currentTime | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function onEnded() { | ||||||
|  |   playerStore.isPlaying = false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Si la track change, mettre à jour le src et le start | ||||||
|  | watch( | ||||||
|  |   () => playerStore.currentTrack, | ||||||
|  |   (newTrack) => { | ||||||
|  |     if (newTrack && audioRef.value) { | ||||||
|  |       audioRef.value.src = newTrack.url | ||||||
|  |       audioRef.value.currentTime = newTrack.start || 0 | ||||||
|  |       if (playerStore.isPlaying) audioRef.value.play() | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | ) | ||||||
|  | </script> | ||||||
| @@ -12,7 +12,6 @@ import type { BoxState } from '~~/types/types' | |||||||
| import { useRouter } from 'vue-router' | import { useRouter } from 'vue-router' | ||||||
|  |  | ||||||
| const dataStore = useDataStore() | const dataStore = useDataStore() | ||||||
| const router = useRouter() |  | ||||||
| const boxStates = ref<Record<string, BoxState>>({}) | const boxStates = ref<Record<string, BoxState>>({}) | ||||||
|  |  | ||||||
| function openCompilation(id: string) { | function openCompilation(id: string) { | ||||||
| @@ -20,7 +19,6 @@ function openCompilation(id: string) { | |||||||
|     for (const key in boxStates.value) { |     for (const key in boxStates.value) { | ||||||
|       boxStates.value[key] = (key === id) ? 'selected' : 'hide' |       boxStates.value[key] = (key === id) ? 'selected' : 'hide' | ||||||
|     } |     } | ||||||
|     window.history.pushState({}, '', '/compilation/' + id) |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -30,7 +28,6 @@ function closeCompilation(e: KeyboardEvent) { | |||||||
|       boxStates.value[key] = 'list' |       boxStates.value[key] = 'list' | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   window.history.pushState({}, '', '/') |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="mt-8 p-8 w-96"> |   <div class="mt-8 p-8 w-96 flex flex-wrap"> | ||||||
|     <MoleculeCard v-for="track in dataStore.getTracksByCompilationId(compilation.id)" :key="track.id" :track="track" /> |     <MoleculeCard v-for="track in dataStore.getTracksByCompilationId(compilation.id)" :key="track.id" :track="track" /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| @@ -13,5 +13,4 @@ const props = defineProps<{ | |||||||
| }>() | }>() | ||||||
|  |  | ||||||
| const dataStore = useDataStore() | const dataStore = useDataStore() | ||||||
|  |  | ||||||
| </script> | </script> | ||||||
| @@ -9,6 +9,7 @@ | |||||||
|     </header> |     </header> | ||||||
|     <main> |     <main> | ||||||
|       <OrganismCompilationList /> |       <OrganismCompilationList /> | ||||||
|  |       <MoleculePlayer /> | ||||||
|     </main> |     </main> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="flex flex-wrap justify-center"> |   <div class="flex flex-wrap justify-center items-center h-screen"> | ||||||
|     <div class="bg-page-dark-bg text-white"> |     <div class="bg-page-dark-bg text-white"> | ||||||
|       <div class="flex flex-col-reverse bg-gradient-to-r from-primary to-primary-dark"> |       <div class="flex flex-col-reverse bg-gradient-to-r from-primary to-primary-dark"> | ||||||
|         <div class="mt-8 flex flex-wrap justify-center"> |         <div class="mt-8 flex flex-wrap justify-center"> | ||||||
|           <molecule-box :compilation="compilation" /> |           <!-- <molecule-box :compilation="compilation" /> --> | ||||||
|           <div class="devtool  absolute right-4 text-white bg-black rounded-2xl px-4 py-2"> |           <div class="devtool  absolute right-4 text-white bg-black rounded-2xl px-4 py-2"> | ||||||
|             <!-- <button @click="currentPosition = boxPositions.side">side</button> |             <!-- <button @click="currentPosition = boxPositions.side">side</button> | ||||||
|             <button @click="currentPosition = boxPositions.front">front</button> |             <button @click="currentPosition = boxPositions.front">front</button> | ||||||
|   | |||||||
							
								
								
									
										57
									
								
								app/store/player.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/store/player.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | // ~/store/player.ts | ||||||
|  | import { defineStore } from 'pinia' | ||||||
|  | import type { Track } from '~/types/types' | ||||||
|  |  | ||||||
|  | export const usePlayerStore = defineStore('player', { | ||||||
|  |   state: () => ({ | ||||||
|  |     currentTrack: null as Track | null, | ||||||
|  |     isPlaying: false, | ||||||
|  |     position: 0, | ||||||
|  |     audio: null as HTMLAudioElement | null, | ||||||
|  |   }), | ||||||
|  |  | ||||||
|  |   actions: { | ||||||
|  |     setTrack(track: Track) { | ||||||
|  |       this.currentTrack = track | ||||||
|  |       if (!this.audio) this.audio = new Audio(this.getCompilationUrlFromTrack(track)) | ||||||
|  |       else this.audio.src = this.getCompilationUrlFromTrack(track) | ||||||
|  |  | ||||||
|  |       // Commencer à start secondes | ||||||
|  |       this.audio.currentTime = track.start || 0 | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     playTrack(track?: Track) { | ||||||
|  |       if (track) this.setTrack(track) | ||||||
|  |       if (!this.currentTrack || !this.audio) return | ||||||
|  |  | ||||||
|  |       this.audio.play() | ||||||
|  |       this.isPlaying = true | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     pauseTrack() { | ||||||
|  |       if (this.audio) this.audio.pause() | ||||||
|  |       this.isPlaying = false | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     togglePlay(track?: Track) { | ||||||
|  |       if (track && (!this.currentTrack || track.id !== this.currentTrack.id)) { | ||||||
|  |         this.playTrack(track) | ||||||
|  |       } else { | ||||||
|  |         this.isPlaying ? this.pauseTrack() : this.playTrack() | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     setPosition(time: number) { | ||||||
|  |       if (this.audio) this.audio.currentTime = time | ||||||
|  |       this.position = time | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   getters: { | ||||||
|  |     getCurrentTrack: (state) => state.currentTrack, | ||||||
|  |     getPlaying: (state) => state.isPlaying, | ||||||
|  |     getCompilationUrlFromTrack: (state) => { | ||||||
|  |       return (track: Track) => `https://files.erudi.fr/evilspins/${track.compilationId}.mp3` | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | }) | ||||||
| @@ -36,7 +36,7 @@ export default eventHandler(() => { | |||||||
|       id: 5, |       id: 5, | ||||||
|       name: "New candys", |       name: "New candys", | ||||||
|       url: "https://newcandys.bandcamp.com", |       url: "https://newcandys.bandcamp.com", | ||||||
|       coverId: "0033518637", |       coverId: "0039963261", | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 6, |       id: 6, | ||||||
| @@ -67,6 +67,84 @@ export default eventHandler(() => { | |||||||
|       name: "I love UFO", |       name: "I love UFO", | ||||||
|       url: "https://bruitblanc.bandcamp.com", |       url: "https://bruitblanc.bandcamp.com", | ||||||
|       coverId: "a2203158939", |       coverId: "a2203158939", | ||||||
|     } |     }, | ||||||
|  |     { | ||||||
|  |       id: 11, | ||||||
|  |       name: "Kid Congo & The Pink Monkey Birds", | ||||||
|  |       url: "https://kidcongothepinkmonkeybirds.bandcamp.com/", | ||||||
|  |       coverId: "0017196290", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 12, | ||||||
|  |       name: "Firefriend", | ||||||
|  |       url: "https://firefriend.bandcamp.com/", | ||||||
|  |       coverId: "0031072203", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 13, | ||||||
|  |       name: "Squid", | ||||||
|  |       url: "https://squiduk.bandcamp.com/", | ||||||
|  |       coverId: "0037649385", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 14, | ||||||
|  |       name: "Lysistrata", | ||||||
|  |       url: "https://lysistrata.bandcamp.com/", | ||||||
|  |       coverId: "0033900158", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 15, | ||||||
|  |       name: "Pablo X Broadcasting Services", | ||||||
|  |       url: "https://pabloxbroadcastingservices.bandcamp.com/", | ||||||
|  |       coverId: "0036956486", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 16, | ||||||
|  |       name: "Night Beats", | ||||||
|  |       url: "https://nightbeats.bandcamp.com/", | ||||||
|  |       coverId: "0036987720", | ||||||
|  |     }, | ||||||
|  |         { | ||||||
|  |       id: 17, | ||||||
|  |       name: "Deltron 3030", | ||||||
|  |       url: "https://delthefunkyhomosapien.bandcamp.com/", | ||||||
|  |       coverId: "0005254781", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 18, | ||||||
|  |       name: "The Amorphous Androgynous", | ||||||
|  |       url: "https://theaa.bandcamp.com/", | ||||||
|  |       coverId: "0022226700", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 19, | ||||||
|  |       name: "Wooden Shjips", | ||||||
|  |       url: "https://woodenshjips.bandcamp.com/", | ||||||
|  |       coverId: "0012406678", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 20, | ||||||
|  |       name: "Silas J. Dirge", | ||||||
|  |       url: "https://silasjdirge.bandcamp.com/", | ||||||
|  |       coverId: "0035751570", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 21, | ||||||
|  |       name: "Secret Colours", | ||||||
|  |       url: "https://secretcolours.bandcamp.com/", | ||||||
|  |       coverId: "0010661379", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 22, | ||||||
|  |       name: "Larry McNeil And The Blue Knights", | ||||||
|  |       url: "https://www.discogs.com/artist/6528940-Larry-McNeil-And-The-Blue-Knights", | ||||||
|  |       coverId: "https://i.discogs.com/Yr05_neEXwzPwKlDeV7dimmTG34atkAMgpxbMBhHBkI/rs:fit/g:sm/q:90/h:600/w:600/czM6Ly9kaXNjb2dz/LWRhdGFiYXNlLWlt/YWdlcy9SLTEyMTEw/ODE1LTE1Mjg1NjU1/NzQtMjcyOC5qcGVn.jpeg", | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 23, | ||||||
|  |       name: "Hugo Blanco", | ||||||
|  |       url: "https://elpalmasmusic.bandcamp.com/album/color-de-tr-pico-compiled-by-el-dr-gon-criollo-el-palmas", | ||||||
|  |       coverId: "0016886708", | ||||||
|  |     }, | ||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
|   | |||||||
| @@ -3,7 +3,8 @@ import { eventHandler } from 'h3' | |||||||
| export default eventHandler(() => { | export default eventHandler(() => { | ||||||
|   return [ |   return [ | ||||||
|     { |     { | ||||||
|       id: 1, |       id: 0, | ||||||
|  |       order: 1, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'The grinding wheel', |       title: 'The grinding wheel', | ||||||
|       artist: 0, |       artist: 0, | ||||||
| @@ -12,7 +13,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a3236746052', |       coverId: 'a3236746052', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 2, |       id: 1, | ||||||
|  |       order: 2, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Bleach', |       title: 'Bleach', | ||||||
|       artist: 1, |       artist: 1, | ||||||
| @@ -21,7 +23,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a1714786533', |       coverId: 'a1714786533', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 3, |       id: 2, | ||||||
|  |       order: 3, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Televised mind', |       title: 'Televised mind', | ||||||
|       artist: 2, |       artist: 2, | ||||||
| @@ -30,7 +33,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a3772806156' |       coverId: 'a3772806156' | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 4, |       id: 3, | ||||||
|  |       order: 4, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'In it', |       title: 'In it', | ||||||
|       artist: 3, |       artist: 3, | ||||||
| @@ -39,7 +43,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a1720372066', |       coverId: 'a1720372066', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 5, |       id: 4, | ||||||
|  |       order: 5, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Bad michel', |       title: 'Bad michel', | ||||||
|       artist: 4, |       artist: 4, | ||||||
| @@ -48,7 +53,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a0984622869', |       coverId: 'a0984622869', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 6, |       id: 5, | ||||||
|  |       order: 6, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Overall', |       title: 'Overall', | ||||||
|       artist: 5, |       artist: 5, | ||||||
| @@ -57,7 +63,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a0559661270', |       coverId: 'a0559661270', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 7, |       id: 6, | ||||||
|  |       order: 7, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Blowup', |       title: 'Blowup', | ||||||
|       artist: 6, |       artist: 6, | ||||||
| @@ -66,7 +73,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a1444895293', |       coverId: 'a1444895293', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 8, |       id: 7, | ||||||
|  |       order: 8, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Guitar jet', |       title: 'Guitar jet', | ||||||
|       artist: 7, |       artist: 7, | ||||||
| @@ -75,7 +83,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a1494681687', |       coverId: 'a1494681687', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 9, |       id: 8, | ||||||
|  |       order: 9, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Intercontinental radio waves', |       title: 'Intercontinental radio waves', | ||||||
|       artist: 8, |       artist: 8, | ||||||
| @@ -84,7 +93,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a0046738552', |       coverId: 'a0046738552', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 10, |       id: 9, | ||||||
|  |       order: 10, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Here comes the sun', |       title: 'Here comes the sun', | ||||||
|       artist: 9, |       artist: 9, | ||||||
| @@ -93,7 +103,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a4102567047', |       coverId: 'a4102567047', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 11, |       id: 10, | ||||||
|  |       order: 0, | ||||||
|       compilationId: 'ES00A', |       compilationId: 'ES00A', | ||||||
|       title: 'Like in the movies', |       title: 'Like in the movies', | ||||||
|       artist: 10, |       artist: 10, | ||||||
| @@ -102,7 +113,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a2203158939', |       coverId: 'a2203158939', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 21, |       id: 11, | ||||||
|  |       order: 1, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Ce que révèle l\'éclipse', |       title: 'Ce que révèle l\'éclipse', | ||||||
|       artist: 0, |       artist: 0, | ||||||
| @@ -111,7 +123,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a3236746052', |       coverId: 'a3236746052', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 22, |       id: 12, | ||||||
|  |       order: 2, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Bleedin\' Gums Mushrool', |       title: 'Bleedin\' Gums Mushrool', | ||||||
|       artist: 1, |       artist: 1, | ||||||
| @@ -120,7 +133,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a1714786533', |       coverId: 'a1714786533', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 23, |       id: 13, | ||||||
|  |       order: 3, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'A lucid dream', |       title: 'A lucid dream', | ||||||
|       artist: 2, |       artist: 2, | ||||||
| @@ -129,7 +143,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a3772806156', |       coverId: 'a3772806156', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 24, |       id: 14, | ||||||
|  |       order: 4, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Lights off', |       title: 'Lights off', | ||||||
|       artist: 3, |       artist: 3, | ||||||
| @@ -138,7 +153,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a1720372066', |       coverId: 'a1720372066', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 25, |       id: 15, | ||||||
|  |       order: 5, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'I\'m sentimental', |       title: 'I\'m sentimental', | ||||||
|       artist: 4, |       artist: 4, | ||||||
| @@ -147,7 +163,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a2333676849', |       coverId: 'a2333676849', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 26, |       id: 16, | ||||||
|  |       order: 6, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Thrill or trip', |       title: 'Thrill or trip', | ||||||
|       artist: 5, |       artist: 5, | ||||||
| @@ -156,7 +173,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a0559661270', |       coverId: 'a0559661270', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 27, |       id: 17, | ||||||
|  |       order: 7, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Redhead', |       title: 'Redhead', | ||||||
|       artist: 6, |       artist: 6, | ||||||
| @@ -165,7 +183,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a0594426943', |       coverId: 'a0594426943', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 28, |       id: 18, | ||||||
|  |       order: 8, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Supersonic twist', |       title: 'Supersonic twist', | ||||||
|       artist: 7, |       artist: 7, | ||||||
| @@ -174,7 +193,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a1494681687', |       coverId: 'a1494681687', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 29, |       id: 19, | ||||||
|  |       order: 9, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Flowers', |       title: 'Flowers', | ||||||
|       artist: 8, |       artist: 8, | ||||||
| @@ -183,7 +203,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a3644668199', |       coverId: 'a3644668199', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 30, |       id: 20, | ||||||
|  |       order: 10, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'The shade', |       title: 'The shade', | ||||||
|       artist: 9, |       artist: 9, | ||||||
| @@ -192,7 +213,8 @@ export default eventHandler(() => { | |||||||
|       coverId: 'a0804204790', |       coverId: 'a0804204790', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       id: 31, |       id: 21, | ||||||
|  |       order: 0, | ||||||
|       compilationId: 'ES00B', |       compilationId: 'ES00B', | ||||||
|       title: 'Like in the movies', |       title: 'Like in the movies', | ||||||
|       artist: 10, |       artist: 10, | ||||||
| @@ -200,5 +222,225 @@ export default eventHandler(() => { | |||||||
|       url: 'https://bruitblanc.bandcamp.com/track/like-in-the-movies', |       url: 'https://bruitblanc.bandcamp.com/track/like-in-the-movies', | ||||||
|       coverId: 'a3647322740', |       coverId: 'a3647322740', | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |       id: 22, | ||||||
|  |       order: 1, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'He Walked In', | ||||||
|  |       artist: 11, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://kidcongothepinkmonkeybirds.bandcamp.com/track/he-walked-in', | ||||||
|  |       coverId: 'a0336300523', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 23, | ||||||
|  |       order: 2, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'The Third Wave', | ||||||
|  |       artist: 12, | ||||||
|  |       start: 854, | ||||||
|  |       url: 'https://firefriend.bandcamp.com/track/the-third-wave', | ||||||
|  |       coverId: 'a2803689859', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 24, | ||||||
|  |       order: 3, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'Broadcaster', | ||||||
|  |       artist: 13, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://squiduk.bandcamp.com/track/broadcaster', | ||||||
|  |       coverId: 'a3391719769', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 25, | ||||||
|  |       order: 4, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'Mourn', | ||||||
|  |       artist: 14, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://lysistrata.bandcamp.com/track/mourn-2', | ||||||
|  |       coverId: 'a0872900041', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 26, | ||||||
|  |       order: 5, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'Let it Blow', | ||||||
|  |       artist: 15, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://pabloxbroadcastingservices.bandcamp.com/track/let-it-blow', | ||||||
|  |       coverId: 'a4000148031', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 27, | ||||||
|  |       order: 6, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'Sunday Mourning', | ||||||
|  |       artist: 16, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://nightbeats.bandcamp.com/track/sunday-mourning', | ||||||
|  |       coverId: 'a0031987121', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 28, | ||||||
|  |       order: 7, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: '3030 Instrumental', | ||||||
|  |       artist: 17, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://delthefunkyhomosapien.bandcamp.com/track/3030', | ||||||
|  |       coverId: 'a1948146136', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 29, | ||||||
|  |       order: 8, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'Immortality Break', | ||||||
|  |       artist: 18, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://theaa.bandcamp.com/track/immortality-break', | ||||||
|  |       coverId: 'a2749250329', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 30, | ||||||
|  |       order: 9, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'Lazy Bones', | ||||||
|  |       artist: 19, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://woodenshjips.bandcamp.com/track/lazy-bones', | ||||||
|  |       coverId: 'a1884221104', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 31, | ||||||
|  |       order: 10, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'On the Train of Aches', | ||||||
|  |       artist: 20, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://silasjdirge.bandcamp.com/track/on-the-train-of-aches', | ||||||
|  |       coverId: 'a1124177379', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 32, | ||||||
|  |       order: 0, | ||||||
|  |       compilationId: 'ES01A', | ||||||
|  |       title: 'Me', | ||||||
|  |       artist: 21, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://secretcolours.bandcamp.com/track/me', | ||||||
|  |       coverId: 'a1497022499', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 33, | ||||||
|  |       order: 1, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'Lady Hawke Blues', | ||||||
|  |       artist: 11, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://kidcongothepinkmonkeybirds.bandcamp.com/track/lady-hawke-blues', | ||||||
|  |       coverId: 'a2532623230', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 34, | ||||||
|  |       order: 2, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'Dreamscapes', | ||||||
|  |       artist: 12, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://littlecloudrecords.bandcamp.com/track/dreamscapes', | ||||||
|  |       coverId: 'a3498981203', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 35, | ||||||
|  |       order: 3, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'Crispy Skin', | ||||||
|  |       artist: 13, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://squiduk.bandcamp.com/track/crispy-skin-2', | ||||||
|  |       coverId: 'a2516727021', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 36, | ||||||
|  |       order: 4, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'The Boy Who Stood Above The Earth', | ||||||
|  |       artist: 14, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://lysistrata.bandcamp.com/track/the-boy-who-stood-above-the-earth-2', | ||||||
|  |       coverId: 'a0350933426', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 37, | ||||||
|  |       order: 5, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'Better Off Alone', | ||||||
|  |       artist: 15, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://pabloxbroadcastingservices.bandcamp.com/track/better-off-alone', | ||||||
|  |       coverId: 'a4000148031', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 38, | ||||||
|  |       order: 6, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'Celebration #1', | ||||||
|  |       artist: 16, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://nightbeats.bandcamp.com/track/celebration-1', | ||||||
|  |       coverId: 'a0031987121', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 39, | ||||||
|  |       order: 7, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: '3030 Instrumental', | ||||||
|  |       artist: 17, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://delthefunkyhomosapien.bandcamp.com/track/3030', | ||||||
|  |       coverId: 'a1948146136', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 40, | ||||||
|  |       order: 8, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'The Emptiness Of Nothingness', | ||||||
|  |       artist: 18, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://theaa.bandcamp.com/track/the-emptiness-of-nothingness', | ||||||
|  |       coverId: 'a1053923875', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 41, | ||||||
|  |       order: 9, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'Rising', | ||||||
|  |       artist: 19, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://woodenshjips.bandcamp.com/track/rising', | ||||||
|  |       coverId: 'a1884221104', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 42, | ||||||
|  |       order: 10, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'The Last Time / Jealous Woman', | ||||||
|  |       artist: 22, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://www.discogs.com/release/12110815-Larry-McNeil-And-The-Blue-Knights-Jealous-Woman', | ||||||
|  |       coverId: 'https://i.discogs.com/Yr05_neEXwzPwKlDeV7dimmTG34atkAMgpxbMBhHBkI/rs:fit/g:sm/q:90/h:600/w:600/czM6Ly9kaXNjb2dz/LWRhdGFiYXNlLWlt/YWdlcy9SLTEyMTEw/ODE1LTE1Mjg1NjU1/NzQtMjcyOC5qcGVn.jpeg', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       id: 43, | ||||||
|  |       order: 0, | ||||||
|  |       compilationId: 'ES01B', | ||||||
|  |       title: 'Guajira Con Arpa', | ||||||
|  |       artist: 23, | ||||||
|  |       start: 0, | ||||||
|  |       url: 'https://elpalmasmusic.bandcamp.com/track/guajira-con-arpa', | ||||||
|  |       coverId: 'a3463036407', | ||||||
|  |     }, | ||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ export interface Artist { | |||||||
|  |  | ||||||
| export interface Track { | export interface Track { | ||||||
|   id: number |   id: number | ||||||
|  |   order: number | ||||||
|   compilationId: string |   compilationId: string | ||||||
|   title: string |   title: string | ||||||
|   artist: Artist |   artist: Artist | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user