use tabs to seperate search results

This commit is contained in:
geoffrey45
2022-05-22 19:29:16 +03:00
parent 6ef725c0ae
commit 6a2b87b48c
19 changed files with 463 additions and 346 deletions
@@ -0,0 +1,47 @@
<template>
<div class="albums-results border">
<div class="grid">
<AlbumCard
v-for="album in search.albums.value"
:key="album.image"
:album="album"
/>
</div>
<LoadMore v-if="search.albums.more" @loadMore="loadMore()" />
</div>
</template>
<script setup lang="ts">
import AlbumCard from "../../shared/AlbumCard.vue";
import LoadMore from "./LoadMore.vue";
import useSearchStore from "../../../stores/search";
const search = useSearchStore();
let counter = 0;
function loadMore() {
counter += 6;
search.loadAlbums(counter);
}
</script>
<style lang="scss">
.right-search .albums-results {
border-radius: 0.5rem;
margin-top: $small;
padding: $small;
overflow-x: hidden;
.result-item:hover {
background-color: $gray4;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
flex-wrap: wrap;
gap: 0.75rem;
}
}
</style>
@@ -0,0 +1,45 @@
<template>
<div class="artists-results border">
<div class="grid">
<ArtistCard
v-for="artist in search.artists.value"
:key="artist.image"
:artist="artist"
/>
</div>
<LoadMore v-if="search.artists.more" @loadMore="loadMore" />
</div>
</template>
<script setup lang="ts">
import ArtistCard from "../../shared/ArtistCard.vue";
import LoadMore from "./LoadMore.vue";
import useSearchStore from "../../../stores/search";
const search = useSearchStore();
let counter = 0;
function loadMore() {
counter += 6;
search.loadArtists(counter);
}
</script>
<style lang="scss">
.right-search .artists-results {
border-radius: 0.5rem;
padding: $small;
margin-bottom: $small;
.xartist {
background-color: $gray;
}
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.75rem;
}
}
</style>
@@ -0,0 +1,52 @@
<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">
.gsearch-input .filter {
display: flex;
.item {
transition: all 0.2s ease-in-out;
background-color: $gray3;
height: 2.5rem;
&: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,40 @@
<template>
<div class="morexx">
<div @click="loadMore" class="btn circular">
<div class="text">Load More</div>
</div>
</div>
</template>
<script setup lang="ts">
const emit = defineEmits<{
(e: "loadMore"): void;
}>();
function loadMore() {
emit("loadMore");
}
</script>
<style lang="scss">
.morexx {
display: grid;
place-items: center;
margin-top: $small;
.btn {
height: 2.5rem;
width: 15rem;
display: grid;
place-items: center;
transition: all 0.5s ease;
background-image: linear-gradient(37deg, $red, $blue);
cursor: pointer;
&:hover {
background-color: $blue !important;
width: 12rem;
}
}
}
</style>
@@ -0,0 +1,90 @@
<template>
<div class="options border rounded">
<div class="item info header">Filter by:</div>
<div
class="item"
v-for="option in options"
:key="option"
@click="search.addFilter(option.icon)"
>
<div>
<span class="icon">{{ option.icon }}</span>
<span class="title">&nbsp;&nbsp;{{ option.title }}</span>
</div>
</div>
</div>
</template>
<script setup>
import useSearchStore from "../../stores/gsearch";
const search = useSearchStore();
const options = [
{
title: "Track",
icon: "🎵",
},
{
title: "Album",
icon: "💿",
},
{
title: "Artist",
icon: "👤",
},
{
title: "Playlist",
icon: "🎧",
},
{
title: "Folder",
icon: "📁",
},
];
</script>
<style lang="scss">
.right-search .options {
display: flex;
margin-bottom: $small;
.item {
margin: $small;
width: 2.5rem;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
transition: all 0.2s ease-in-out;
position: relative;
background-color: $gray3;
.title {
position: absolute;
left: 1.5rem;
top: 0.5rem;
visibility: hidden;
}
.icon {
position: absolute;
top: 0.5rem;
left: 0.75rem;
}
&:hover {
width: 5.5rem;
background-color: $gray5;
.title {
visibility: visible;
}
}
}
.header {
width: 5.5rem;
}
}
</style>
@@ -0,0 +1,58 @@
<template>
<div id="tracks-results" v-if="search.tracks.value">
<TransitionGroup name="list">
<TrackItem
v-for="track in search.tracks.value"
:key="track.trackid"
:track="track"
:isPlaying="queue.playing"
:isCurrent="queue.current.trackid == track.trackid"
:isSearchTrack="true"
@PlayThis="updateQueue"
/>
</TransitionGroup>
<LoadMore v-if="search.tracks.more" @loadMore="loadMore" />
</div>
</template>
<script setup lang="ts">
import LoadMore from "./LoadMore.vue";
import TrackItem from "../../shared/TrackItem.vue";
import useQStore from "../../../stores/queue";
import { Track } from "../../../interfaces";
import useSearchStore from "../../../stores/search";
let counter = 0;
const queue = useQStore();
const search = useSearchStore();
function loadMore() {
counter += 5;
search.loadTracks(counter);
}
function updateQueue(track: Track) {
queue.playFromSearch(search.query, search.tracks.value);
queue.play(track);
}
</script>
<style lang="scss">
.right-search #tracks-results {
border-radius: 0.5rem;
padding: $small;
height: 100% !important;
overflow: hidden;
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
transition-delay: 0.5s;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateY(2rem);
}
}
</style>