mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
break down search component into smaler components
This commit is contained in:
+4
-3
@@ -50,7 +50,7 @@ def search_by_title():
|
|||||||
for song in albums:
|
for song in albums:
|
||||||
album_obj = {
|
album_obj = {
|
||||||
"name": song["album"],
|
"name": song["album"],
|
||||||
"artists": song["artists"],
|
"artist": song["album_artist"],
|
||||||
}
|
}
|
||||||
|
|
||||||
if album_obj not in albums_dicts:
|
if album_obj not in albums_dicts:
|
||||||
@@ -67,6 +67,7 @@ def search_by_title():
|
|||||||
|
|
||||||
artist_obj = {
|
artist_obj = {
|
||||||
"name": artist,
|
"name": artist,
|
||||||
|
"image": "http://0.0.0.0:8900/images/artists/webp/" + artist.replace("/", "::") + ".webp"
|
||||||
}
|
}
|
||||||
|
|
||||||
if artist_obj not in artists_dicts:
|
if artist_obj not in artists_dicts:
|
||||||
@@ -91,8 +92,8 @@ def search_by_title():
|
|||||||
|
|
||||||
return {'data': [
|
return {'data': [
|
||||||
{'tracks': tracks[:5], 'more': more_tracks},
|
{'tracks': tracks[:5], 'more': more_tracks},
|
||||||
{'albums': albums_dicts[:10], 'more': more_albums},
|
{'albums': albums_dicts[:5], 'more': more_albums},
|
||||||
{'artists': artists_dicts[:10], 'more': more_artists}
|
{'artists': artists_dicts[:5], 'more': more_artists}
|
||||||
]}
|
]}
|
||||||
|
|
||||||
@bp.route('/populate')
|
@bp.route('/populate')
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
.right-search .v0 {
|
||||||
|
max-height: 0em;
|
||||||
|
transition: max-height 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-search .v1 {
|
||||||
|
max-height: 25rem;
|
||||||
|
transition: max-height 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-search {
|
||||||
|
position: relative;
|
||||||
|
border-radius: $small;
|
||||||
|
margin: 0.5rem 0 0 0;
|
||||||
|
padding: 1rem $small 0 0;
|
||||||
|
background-color: #03000eab;
|
||||||
|
overflow: hidden;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
.no-res {
|
||||||
|
text-align: center;
|
||||||
|
height: calc(100% - 1rem);
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
padding: $small;
|
||||||
|
background-color: rgb(29, 26, 26);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
margin-left: $small;
|
||||||
|
background-color: rgb(3, 54, 112);
|
||||||
|
width: 6rem;
|
||||||
|
padding: $small;
|
||||||
|
border-radius: $small;
|
||||||
|
margin-bottom: $small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
position: absolute;
|
||||||
|
height: 2.5rem;
|
||||||
|
width: 2.5rem;
|
||||||
|
background-image: url(../../icons/search.svg);
|
||||||
|
background-size: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v11 {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-4rem);
|
||||||
|
transition: all 0.2s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v00 {
|
||||||
|
opacity: 1;
|
||||||
|
transition: all 0.2s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-left: 1rem;
|
||||||
|
position: absolute;
|
||||||
|
right: 2.5rem;
|
||||||
|
|
||||||
|
.item::before {
|
||||||
|
content: "#";
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-search .scrollable {
|
||||||
|
width: 100%;
|
||||||
|
height: 26rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
padding: 0 $small 0 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-search {
|
||||||
|
.input-loader {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: calc(100% - 6rem);
|
||||||
|
border: none;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
background-color: transparent;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
font-size: 1rem;
|
||||||
|
outline: none;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
padding-left: $small;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,7 +142,6 @@ button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
@@ -248,4 +247,19 @@ button {
|
|||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
background-color: rgba(34, 33, 33, 0.637);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 $small 0 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: rgb(250, 250, 250);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgb(170, 50, 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<div class="s2"></div>
|
<div class="s2"></div>
|
||||||
<p>Featured Artists</p>
|
<p>Featured Artists</p>
|
||||||
</div>
|
</div>
|
||||||
<ArtistCard v-for="artist in artists" :key="artist" :artist="artist" />
|
<ArtistCard v-for="artist in artists" :key="artist" :artist="artist" :color="232452" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+76
-456
@@ -2,16 +2,7 @@
|
|||||||
<div class="right-search border" ref="searchComponent">
|
<div class="right-search border" ref="searchComponent">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<div class="search-icon image"></div>
|
<div class="search-icon image"></div>
|
||||||
<div class="filter">
|
<Filters :filters="filters" @removeFilter="removeFilter" />
|
||||||
<div
|
|
||||||
class="item"
|
|
||||||
v-for="filter in filters"
|
|
||||||
:key="filter"
|
|
||||||
@click="removeFilter(filter)"
|
|
||||||
>
|
|
||||||
{{ filter }}<span class="cancel image"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="input-loader border">
|
<div class="input-loader border">
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
@@ -22,7 +13,7 @@
|
|||||||
placeholder="find your music"
|
placeholder="find your music"
|
||||||
v-model="query"
|
v-model="query"
|
||||||
/>
|
/>
|
||||||
<div class="loader" v-if="loading"></div>
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="suggestions v00"
|
class="suggestions v00"
|
||||||
@@ -35,127 +26,87 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="separator no-border"></div>
|
<div class="separator no-border"></div>
|
||||||
<div class="options" v-if="magic_flag">
|
<Options :magic_flag="magic_flag" @addFilter="addFilter" />
|
||||||
<div class="item info">Filter by:</div>
|
|
||||||
<div
|
|
||||||
class="item"
|
|
||||||
v-for="option in options"
|
|
||||||
:key="option"
|
|
||||||
@click="addFilter(option.icon)"
|
|
||||||
>
|
|
||||||
{{ option.title }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="scrollable" :class="{ v0: !is_hidden, v1: is_hidden }">
|
<div class="scrollable" :class="{ v0: !is_hidden, v1: is_hidden }">
|
||||||
<div class="tracks-results border" v-if="songs.tracks">
|
<TracksGrid
|
||||||
<div class="heading">TRACKS</div>
|
:tracks="tracks.tracks"
|
||||||
<div class="items">
|
:more="tracks.more"
|
||||||
<table>
|
v-if="tracks.tracks.length"
|
||||||
<tbody>
|
/>
|
||||||
<SongItem v-for="song in songs.tracks" :key="song" :song="song" />
|
<AlbumGrid
|
||||||
</tbody>
|
v-if="albums.albums.length"
|
||||||
</table>
|
:albums="albums.albums"
|
||||||
<div class="more" v-if="songs.more">
|
:more="albums.more"
|
||||||
<button>
|
/>
|
||||||
<div class="text">Load All</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- -->
|
|
||||||
<div class="albums-results border">
|
|
||||||
<div class="heading">ALBUMS <span class="more">SEE ALL</span></div>
|
|
||||||
<div class="grid">
|
|
||||||
<div
|
|
||||||
class="result-item border"
|
|
||||||
v-for="album in albums.albums"
|
|
||||||
:key="album"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="album-art image"
|
|
||||||
:style="{
|
|
||||||
backgroundImage: `url('${album.image}')`,
|
|
||||||
}"
|
|
||||||
></div>
|
|
||||||
<div class="title ellip">{{ album.name }}</div>
|
|
||||||
<div class="artistsx ellipsis">
|
|
||||||
<span v-for="artist in putCommas(album.artists)" :key="artist">{{
|
|
||||||
artist
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="separator no-border"></div>
|
<div class="separator no-border"></div>
|
||||||
<!-- -->
|
<ArtistGrid
|
||||||
<!-- <div class="artists-results border" v-if="artists">
|
v-if="artists.artists.length"
|
||||||
<div class="heading">ARTISTS <span class="more">SEE ALL</span></div>
|
:artists="artists.artists"
|
||||||
<div class="grid">
|
:more="artists.more"
|
||||||
<div
|
/>
|
||||||
class="result-item border"
|
<div
|
||||||
v-for="artist in artists.artists"
|
class="no-res"
|
||||||
:key="artist"
|
v-if="
|
||||||
>
|
!artists.artists.length &&
|
||||||
<div
|
!tracks.tracks.length &&
|
||||||
class="image"
|
!albums.albums.length
|
||||||
:style="{
|
"
|
||||||
backgroundImage: `url(${artist.image})`,
|
>
|
||||||
}"
|
<div class="no-res-icon image"></div>
|
||||||
></div>
|
<div class="no-res-text">
|
||||||
<div class="title ellip">{{ artist.name }}</div>
|
No results for <span class="highlight rounded">{{ query }}</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, toRefs } from "@vue/reactivity";
|
import { reactive, ref, toRefs } from "@vue/reactivity";
|
||||||
|
|
||||||
import { onMounted, watch } from "@vue/runtime-core";
|
import { onMounted, watch } from "@vue/runtime-core";
|
||||||
import state from "@/composables/state.js";
|
import state from "@/composables/state.js";
|
||||||
import searchMusic from "@/composables/searchMusic.js";
|
import searchMusic from "@/composables/searchMusic.js";
|
||||||
import useDebouncedRef from "@/composables/useDebouncedRef";
|
import useDebouncedRef from "@/composables/useDebouncedRef";
|
||||||
import SongItem from "@/components/shared/SongItem.vue";
|
import AlbumGrid from "@/components/Search/AlbumGrid.vue";
|
||||||
import perks from "@/composables/perks.js";
|
import ArtistGrid from "@/components/Search/ArtistGrid.vue";
|
||||||
|
import TracksGrid from "@/components/Search/TracksGrid.vue";
|
||||||
|
import Loader from "@/components/Search/Loader.vue";
|
||||||
|
import Options from "@/components/Search/Options.vue";
|
||||||
|
import Filters from "@/components/Search/Filters.vue";
|
||||||
|
import "@/assets/css/Search/Search.scss";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits: ["expandSearch", "collapseSearch"],
|
emits: ["expandSearch", "collapseSearch"],
|
||||||
props: ["search"],
|
props: ["search"],
|
||||||
components: {
|
components: {
|
||||||
SongItem,
|
AlbumGrid,
|
||||||
|
ArtistGrid,
|
||||||
|
TracksGrid,
|
||||||
|
Loader,
|
||||||
|
Options,
|
||||||
|
Filters,
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
title: "🎵 Track",
|
|
||||||
icon: "🎵",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "💿 Album",
|
|
||||||
icon: "💿",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "🙄 Artist",
|
|
||||||
icon: "🙄",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "😍 Playlist",
|
|
||||||
icon: "😍",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "📁 Folder",
|
|
||||||
icon: "📁",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
setup(props, { emit }) {
|
||||||
const loading = ref(state.loading);
|
const loading = ref(state.loading);
|
||||||
const searchComponent = ref(null);
|
const searchComponent = ref(null);
|
||||||
const filters = ref([]);
|
const filters = ref([]);
|
||||||
|
|
||||||
const albums = ref([]);
|
const tracks = reactive({
|
||||||
const artists = ref([]);
|
tracks: [],
|
||||||
|
more: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let albums = reactive({
|
||||||
|
albums: [],
|
||||||
|
more: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const artists = reactive({
|
||||||
|
artists: [],
|
||||||
|
more: false,
|
||||||
|
});
|
||||||
|
|
||||||
const query = useDebouncedRef("", 400);
|
const query = useDebouncedRef("", 400);
|
||||||
const magic_flag = ref(state.magic_flag);
|
const magic_flag = ref(state.magic_flag);
|
||||||
@@ -202,10 +153,14 @@ export default {
|
|||||||
|
|
||||||
watch(query, (new_query) => {
|
watch(query, (new_query) => {
|
||||||
searchMusic(new_query).then((res) => {
|
searchMusic(new_query).then((res) => {
|
||||||
albums.value = res.albums;
|
albums.albums = res.albums.albums;
|
||||||
artists.value = res.artists;
|
albums.more = res.albums.more;
|
||||||
state.search_tracks.value = res.tracks;
|
|
||||||
// console.log(albums.value)
|
artists.artists = res.artists.artists;
|
||||||
|
artists.more = res.artists.more;
|
||||||
|
|
||||||
|
tracks.tracks = res.tracks.tracks;
|
||||||
|
tracks.more = res.tracks.more;
|
||||||
});
|
});
|
||||||
|
|
||||||
state.search_query.value = new_query;
|
state.search_query.value = new_query;
|
||||||
@@ -218,13 +173,14 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// const dom = document.getElementsByClassName("right-search")[0];
|
const dom = document.getElementsByClassName("right-search")[0];
|
||||||
// document.addEventListener("click", (e) => {
|
|
||||||
// var isClickedInside = dom.contains(e.target);
|
document.addEventListener("click", (e) => {
|
||||||
// if (!isClickedInside) {
|
var isClickedInside = dom.contains(e.target);
|
||||||
// emit("collapseSearch");
|
if (!isClickedInside) {
|
||||||
// }
|
emit("collapseSearch");
|
||||||
// });
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -233,353 +189,17 @@ export default {
|
|||||||
removeMagicFlag,
|
removeMagicFlag,
|
||||||
removeFilter,
|
removeFilter,
|
||||||
removeLastFilter,
|
removeLastFilter,
|
||||||
songs: state.search_tracks,
|
tracks,
|
||||||
albums,
|
albums,
|
||||||
artists,
|
artists,
|
||||||
query,
|
query,
|
||||||
is_hidden,
|
is_hidden,
|
||||||
magic_flag,
|
magic_flag,
|
||||||
options,
|
|
||||||
filters,
|
filters,
|
||||||
searchComponent,
|
searchComponent,
|
||||||
loading,
|
loading,
|
||||||
searchMusic,
|
searchMusic,
|
||||||
putCommas: perks.putCommas,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.loader {
|
|
||||||
position: absolute;
|
|
||||||
right: 0.65rem;
|
|
||||||
top: 0.65rem;
|
|
||||||
width: 1.5rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
border: dotted $blue;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 0.25s linear infinite;
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.right-search .v0 {
|
|
||||||
max-height: 0em;
|
|
||||||
transition: max-height 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-search .v1 {
|
|
||||||
max-height: 25rem;
|
|
||||||
transition: max-height 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-search {
|
|
||||||
position: relative;
|
|
||||||
border-radius: $small;
|
|
||||||
margin: 0.5rem 0 0 0;
|
|
||||||
padding: 1rem $small 0 0;
|
|
||||||
background-color: $card-dark;
|
|
||||||
overflow: hidden;
|
|
||||||
width: auto;
|
|
||||||
|
|
||||||
.item {
|
|
||||||
position: relative;
|
|
||||||
background-color: rgba(34, 33, 33, 0.637);
|
|
||||||
padding: 0.5rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
margin: 0 $small 0 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
color: rgb(250, 250, 250);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgb(170, 50, 50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.filter {
|
|
||||||
display: flex;
|
|
||||||
margin-left: 3rem;
|
|
||||||
height: 2rem;
|
|
||||||
// border: solid;
|
|
||||||
|
|
||||||
.item {
|
|
||||||
&:hover {
|
|
||||||
width: 4rem;
|
|
||||||
|
|
||||||
.cancel {
|
|
||||||
position: absolute;
|
|
||||||
right: 0.5rem;
|
|
||||||
width: 1.5rem;
|
|
||||||
height: 1.5rem;
|
|
||||||
background-image: url(../assets/icons/a.svg);
|
|
||||||
background-size: 70%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-icon {
|
|
||||||
position: absolute;
|
|
||||||
height: 2.5rem;
|
|
||||||
width: 2.5rem;
|
|
||||||
background-image: url(../assets/icons/search.svg);
|
|
||||||
background-size: 70%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v11 {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-4rem);
|
|
||||||
transition: all 0.2s ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v00 {
|
|
||||||
opacity: 1;
|
|
||||||
transition: all 0.2s ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suggestions {
|
|
||||||
display: flex;
|
|
||||||
gap: 0.5rem;
|
|
||||||
margin-left: 1rem;
|
|
||||||
position: absolute;
|
|
||||||
right: 2.5rem;
|
|
||||||
|
|
||||||
.item::before {
|
|
||||||
content: "#";
|
|
||||||
color: grey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-search .options {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.item {
|
|
||||||
margin: $small;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-search .scrollable {
|
|
||||||
height: 26rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
padding: 0 $small 0 0;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-search .heading {
|
|
||||||
font-size: small;
|
|
||||||
position: relative;
|
|
||||||
padding: $small;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.more {
|
|
||||||
position: absolute;
|
|
||||||
right: $small;
|
|
||||||
padding: 0.5rem;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.more:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-search {
|
|
||||||
.input-loader {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 0.4rem;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: calc(100% - 6rem);
|
|
||||||
border: none;
|
|
||||||
line-height: 2.5rem;
|
|
||||||
background-color: transparent;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
font-size: 1rem;
|
|
||||||
outline: none;
|
|
||||||
transition: all 0.5s ease;
|
|
||||||
padding-left: $small;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
transition: all 0.5s ease;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
&::placeholder {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tracks */
|
|
||||||
|
|
||||||
.right-search .tracks-results {
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
margin-left: $small;
|
|
||||||
padding: $small;
|
|
||||||
|
|
||||||
.more {
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
margin-top: $small;
|
|
||||||
|
|
||||||
button {
|
|
||||||
height: 2.5rem;
|
|
||||||
width: 10rem;
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.items {
|
|
||||||
border-radius: $small;
|
|
||||||
background-color: $card-dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 4.5rem;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.album-art {
|
|
||||||
width: 3.5rem;
|
|
||||||
height: 3.5rem;
|
|
||||||
background-color: rgb(27, 150, 74);
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
margin: 0 $small 0 $small;
|
|
||||||
background-image: url(../assets/images/null.webp);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tags .artist {
|
|
||||||
font-size: small;
|
|
||||||
color: rgba(255, 255, 255, 0.63);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $blue;
|
|
||||||
border-radius: $small;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-search hr {
|
|
||||||
margin: 0.1rem;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* albums */
|
|
||||||
|
|
||||||
.right-search .albums-results {
|
|
||||||
width: calc(100% - $small);
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
|
|
||||||
background: #0f131b44;
|
|
||||||
|
|
||||||
margin-left: $small;
|
|
||||||
margin-top: $small;
|
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 0 0 0 $small;
|
|
||||||
gap: $small;
|
|
||||||
|
|
||||||
.result-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: $small;
|
|
||||||
border-radius: $small;
|
|
||||||
text-align: left !important;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
width: 9rem;
|
|
||||||
|
|
||||||
.album-art {
|
|
||||||
height: 7rem;
|
|
||||||
width: 7rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
background-image: url("../assets/images/null.webp");
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
width: 7rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.artistsx {
|
|
||||||
width: 7rem;
|
|
||||||
display: flex;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
text-align: left;
|
|
||||||
color: rgba(40, 116, 216, 0.767);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* artits */
|
|
||||||
|
|
||||||
.right-search .artists-results {
|
|
||||||
width: calc(100% - $small);
|
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
background: #1214178c;
|
|
||||||
margin: 0 0 0 $small;
|
|
||||||
|
|
||||||
.grid {
|
|
||||||
padding: 0 0 0 $small;
|
|
||||||
display: flex;
|
|
||||||
gap: 1rem;
|
|
||||||
|
|
||||||
.result-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: $small;
|
|
||||||
border-radius: $small;
|
|
||||||
background-color: $card-dark;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
|
|
||||||
.image {
|
|
||||||
height: 7rem;
|
|
||||||
width: 7rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
background-size: 50%;
|
|
||||||
background-image: url("../assets/images/null.webp");
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
width: 7rem;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<template>
|
||||||
|
<div class="albums-results border">
|
||||||
|
<div class="heading">💿 ALBUMS</div>
|
||||||
|
<div class="grid">
|
||||||
|
<AlbumCard v-for="album in albums" :key="album" :album="album" />
|
||||||
|
</div>
|
||||||
|
<LoadMore v-if="more" @loadMore="loadMore" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AlbumCard from "@/components/shared/AlbumCard.vue";
|
||||||
|
import LoadMore from "./LoadMore.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ["albums", "more"],
|
||||||
|
components: {
|
||||||
|
AlbumCard,
|
||||||
|
LoadMore,
|
||||||
|
},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
function loadMore() {
|
||||||
|
emit("loadMore");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadMore,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.right-search .albums-results {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background: #0f131b44;
|
||||||
|
|
||||||
|
margin-left: $small;
|
||||||
|
margin-top: $small;
|
||||||
|
padding: $small 0;
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0 0 0 $small;
|
||||||
|
gap: $small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div class="artists-results border">
|
||||||
|
<div class="heading">😳 ARTISTS</div>
|
||||||
|
<div class="grid">
|
||||||
|
<ArtistCard
|
||||||
|
v-for="artist in artists"
|
||||||
|
:key="artist"
|
||||||
|
:artist="artist"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<LoadMore v-if="more" @loadMore="loadMore" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ArtistCard from "@/components/shared/ArtistCard.vue";
|
||||||
|
import LoadMore from "./LoadMore.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ["artists", "more"],
|
||||||
|
components: {
|
||||||
|
ArtistCard,
|
||||||
|
LoadMore,
|
||||||
|
},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
function loadMore() {
|
||||||
|
emit("loadMore");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadMore,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.right-search .artists-results {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background: #1214178c;
|
||||||
|
margin: 0 0 0 $small;
|
||||||
|
padding: $small 0;
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
padding: 0 0 0 $small;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div class="filter">
|
||||||
|
<div
|
||||||
|
class="item"
|
||||||
|
v-for="filter in filters"
|
||||||
|
:key="filter"
|
||||||
|
@click="removeFilter(filter)"
|
||||||
|
>
|
||||||
|
{{ filter }}<span class="cancel image"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: ["filters"],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const removeFilter = (filter) => {
|
||||||
|
emit("removeFilter", filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
removeFilter,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.right-search .filter {
|
||||||
|
display: flex;
|
||||||
|
margin-left: 3rem;
|
||||||
|
height: 2rem;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
&:hover {
|
||||||
|
width: 4rem;
|
||||||
|
|
||||||
|
.cancel {
|
||||||
|
position: absolute;
|
||||||
|
right: 0.5rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
background-image: url(../../assets/icons/a.svg);
|
||||||
|
background-size: 70%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<div class="morexx">
|
||||||
|
<button @click="loadMore">
|
||||||
|
<div class="text">Load All</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
setup(props, { emit }) {
|
||||||
|
function loadMore() {
|
||||||
|
emit("loadMore");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadMore,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.morexx {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
margin-top: $small;
|
||||||
|
|
||||||
|
button {
|
||||||
|
height: 2.5rem;
|
||||||
|
width: 10rem;
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<div class="loader" v-if="loading"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import state from "@/composables/state.js";
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
loading: state.loading,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.loader {
|
||||||
|
position: absolute;
|
||||||
|
right: 0.65rem;
|
||||||
|
top: 0.65rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
border: dotted $blue;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.25s linear infinite;
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<template>
|
||||||
|
<div class="options" v-if="magic_flag">
|
||||||
|
<div class="item info">Filter by:</div>
|
||||||
|
<div
|
||||||
|
class="item"
|
||||||
|
v-for="option in options"
|
||||||
|
:key="option"
|
||||||
|
@click="addFilter(option.icon)"
|
||||||
|
>
|
||||||
|
{{ option.title }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: ["magic_flag"],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
title: "🎵 Track",
|
||||||
|
icon: "🎵",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "💿 Album",
|
||||||
|
icon: "💿",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "🙄 Artist",
|
||||||
|
icon: "🙄",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "😍 Playlist",
|
||||||
|
icon: "😍",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "📁 Folder",
|
||||||
|
icon: "📁",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function addFilter(value) {
|
||||||
|
emit("addFilter", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
options,
|
||||||
|
addFilter,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.right-search .options {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin: $small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tracks-results border" v-if="tracks">
|
||||||
|
<div class="heading">🎵 TRACKS</div>
|
||||||
|
<div class="items">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<SongItem v-for="track in tracks" :key="track" :song="track" />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<LoadMore v-if="more" @loadMore="loadMore" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SongItem from "@/components/shared/SongItem.vue";
|
||||||
|
import LoadMore from "./LoadMore.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ["tracks", "more"],
|
||||||
|
components: {
|
||||||
|
SongItem,
|
||||||
|
LoadMore,
|
||||||
|
},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
function loadMore() {
|
||||||
|
emit("loadMore", "tracks");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadMore,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.right-search .tracks-results {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
margin-left: $small;
|
||||||
|
padding: $small;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<div class="result-item border">
|
||||||
|
<div
|
||||||
|
class="album-art image"
|
||||||
|
:style="{
|
||||||
|
backgroundImage: `url("${album.image}")`,
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
|
<div class="title ellip">{{ album.name }}</div>
|
||||||
|
<div class="artistsx ellipsis">{{ album.artist }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: ["album"],
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.result-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: $small;
|
||||||
|
border-radius: $small;
|
||||||
|
text-align: left !important;
|
||||||
|
width: 9rem;
|
||||||
|
|
||||||
|
.album-art {
|
||||||
|
height: 7rem;
|
||||||
|
width: 7rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
width: 7rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artistsx {
|
||||||
|
width: 7rem;
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
text-align: left;
|
||||||
|
color: rgba(40, 116, 216, 0.767);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="xartist border">
|
<div class="xartist border" :style="{ backgroundColor: `#${color}` }">
|
||||||
<div
|
<div
|
||||||
class="artist-image image"
|
class="artist-image image"
|
||||||
:style="{ backgroundImage: `url('${artist.image}')` }"
|
:style="{ backgroundImage: `url('${artist.image}')` }"
|
||||||
></div>
|
></div>
|
||||||
<div>
|
<div>
|
||||||
<p class="artist-name ellipsis">{{ artist.name }}</p>
|
<p class="artist-name ellipsis">{{ artist.name }}</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="a-circle"></div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["artist"],
|
props: ["artist", "color"],
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -22,11 +21,11 @@ export default {
|
|||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 $smaller 0 $smaller;
|
margin: 0 $small 0 0;
|
||||||
|
|
||||||
width: 9em;
|
width: 9em;
|
||||||
height: 11em;
|
height: 11em;
|
||||||
border-radius: $small;
|
border-radius: $small;
|
||||||
background-color: #232452;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<tr
|
<tr
|
||||||
class="songlist-item"
|
class="songlist-item"
|
||||||
:class="{ current: current._id.$oid == song._id.$oid }"
|
|
||||||
>
|
>
|
||||||
|
<!-- :class="{ current: current._id.$oid == song._id.$oid }" -->
|
||||||
<td class="flex" @click="emitUpdate(song)">
|
<td class="flex" @click="emitUpdate(song)">
|
||||||
<div
|
<div
|
||||||
class="album-art rounded image"
|
class="album-art rounded image"
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ async function search(query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
console.log(data.data[1]);
|
|
||||||
|
|
||||||
state.loading.value = false;
|
state.loading.value = false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user