diff --git a/src/assets/scss/_variables.scss b/src/assets/scss/_variables.scss index eb38065..49df347 100644 --- a/src/assets/scss/_variables.scss +++ b/src/assets/scss/_variables.scss @@ -15,7 +15,7 @@ $larger: 2rem; $banner-height: 18rem; $song-item-height: 4rem; -$content-padding-bottom: 4rem; +$content-padding-bottom: 2rem; // apple human design guideline colors $black: #181a1c; diff --git a/src/components/AlbumView/ArtistAlbums.vue b/src/components/AlbumView/ArtistAlbums.vue index f431039..cb65cff 100644 --- a/src/components/AlbumView/ArtistAlbums.vue +++ b/src/components/AlbumView/ArtistAlbums.vue @@ -1,11 +1,11 @@ @@ -13,26 +13,25 @@ diff --git a/src/components/ArtistView/Header.vue b/src/components/ArtistView/Header.vue index 01e6790..2739b2a 100644 --- a/src/components/ArtistView/Header.vue +++ b/src/components/ArtistView/Header.vue @@ -1,9 +1,119 @@ - + + + diff --git a/src/components/ArtistView/TopTracks.vue b/src/components/ArtistView/TopTracks.vue new file mode 100644 index 0000000..7cc3b46 --- /dev/null +++ b/src/components/ArtistView/TopTracks.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/components/shared/AlbumCard.vue b/src/components/shared/AlbumCard.vue index d3c5100..06b2fe3 100644 --- a/src/components/shared/AlbumCard.vue +++ b/src/components/shared/AlbumCard.vue @@ -16,11 +16,11 @@ diff --git a/src/composables/enums.ts b/src/composables/enums.ts index 8589606..36adc00 100644 --- a/src/composables/enums.ts +++ b/src/composables/enums.ts @@ -31,6 +31,7 @@ export enum Routes { playlists = "PlaylistList", playlist = "PlaylistView", albums = "AlbumsView", + artist = "ArtistView", album = "AlbumView", artists = "ArtistsView", settings = "SettingsView", diff --git a/src/composables/fetch/album.ts b/src/composables/fetch/album.ts index 9f93b71..9fba766 100644 --- a/src/composables/fetch/album.ts +++ b/src/composables/fetch/album.ts @@ -1,6 +1,6 @@ import { paths } from "@/config"; import { NotifType, useNotifStore } from "@/stores/notification"; -import { AlbumInfo, Track } from "../../interfaces"; +import { Album, Track } from "../../interfaces"; import useAxios from "./useAxios"; const { @@ -12,7 +12,7 @@ const { const getAlbumData = async (hash: string, ToastStore: typeof useNotifStore) => { interface AlbumData { - info: AlbumInfo; + info: Album; tracks: Track[]; } @@ -26,7 +26,7 @@ const getAlbumData = async (hash: string, ToastStore: typeof useNotifStore) => { if (status == 204) { ToastStore().showNotification("Album not created yet!", NotifType.Error); return { - info: {} as AlbumInfo, + info: {} as Album, tracks: [], }; } @@ -88,9 +88,9 @@ const getAlbumsFromArtist = async ( }; export { - getAlbumData as getAlbumTracks, - getAlbumArtists, - getAlbumBio, - getAlbumsFromArtist, + getAlbumData as getAlbumTracks, + getAlbumArtists, + getAlbumBio, + getAlbumsFromArtist, }; diff --git a/src/composables/fetch/artists.ts b/src/composables/fetch/artists.ts new file mode 100644 index 0000000..b01b842 --- /dev/null +++ b/src/composables/fetch/artists.ts @@ -0,0 +1,26 @@ +import { paths } from "@/config"; +import useAxios from "./useAxios"; +import { Artist, Track, Album } from "@/interfaces"; + +const getArtistData = async (hash: string) => { + interface ArtistData { + artist: Artist; + albums: Album[]; + tracks: Track[]; + } + + const { data, error } = await useAxios({ + get: true, + url: paths.api.artist + `/${hash}`, + }); + + if (error) { + console.error(error); + } + + console.log(data); + + return data as ArtistData; +}; + +export { getArtistData }; diff --git a/src/config.ts b/src/config.ts index 05f5346..d633c42 100644 --- a/src/config.ts +++ b/src/config.ts @@ -38,14 +38,15 @@ const baseApiUrl = domain() + ports.api; const paths = { api: { album: baseApiUrl + "/album", + artist: baseApiUrl + "/artist", get albumartists() { return this.album + "/artists"; }, get albumbio() { return this.album + "/bio"; }, - get albumsByArtistUrl(){ - return this.album + "/from-artist" + get albumsByArtistUrl() { + return this.album + "/from-artist"; }, folder: baseApiUrl + "/folder", playlist: { diff --git a/src/interfaces.ts b/src/interfaces.ts index e25edd4..89f2386 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -34,7 +34,7 @@ export interface Folder { is_sym: boolean; } -export interface AlbumInfo { +export interface Album { albumid: string; title: string; albumartists: { @@ -61,6 +61,11 @@ export interface AlbumInfo { export interface Artist { name: string; image: string; + artisthash: string; + trackcount: number; + albumcount: number; + duration: number; + colors: string[]; } export interface Option { diff --git a/src/router/routes.ts b/src/router/routes.ts index 2f9c2ac..d1bda91 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -1,8 +1,9 @@ import state from "@/composables/state"; -import useAStore from "@/stores/pages/album"; -import useFStore from "@/stores/pages/folder"; -import usePTrackStore from "@/stores/pages/playlist"; -import usePStore from "@/stores/pages/playlists"; +import useAlbumPageStore from "@/stores/pages/album"; +import useFolderPageStore from "@/stores/pages/folder"; +import usePlaylistPageStore from "@/stores/pages/playlist"; +import usePlaylistListPageStore from "@/stores/pages/playlists"; +import useArtistPageStore from "@/stores/pages/artist"; const routes = [ { @@ -16,7 +17,7 @@ const routes = [ component: () => import("@/views/FolderView.vue"), beforeEnter: async (to: any) => { state.loading.value = true; - await useFStore() + await useFolderPageStore() .fetchAll(to.params.path) .then(() => { state.loading.value = false; @@ -29,7 +30,7 @@ const routes = [ component: () => import("@/views/PlaylistList.vue"), beforeEnter: async () => { state.loading.value = true; - await usePStore() + await usePlaylistListPageStore() .fetchAll() .then(() => { state.loading.value = false; @@ -42,7 +43,7 @@ const routes = [ component: () => import("@/views/PlaylistView/index.vue"), beforeEnter: async (to: any) => { state.loading.value = true; - await usePTrackStore() + await usePlaylistPageStore() .fetchAll(to.params.pid) .then(() => { state.loading.value = false; @@ -60,7 +61,7 @@ const routes = [ component: () => import("@/views/AlbumView/index.vue"), beforeEnter: async (to: any) => { state.loading.value = true; - const store = useAStore(); + const store = useAlbumPageStore(); await store.fetchTracksAndArtists(to.params.hash).then(() => { state.loading.value = false; @@ -76,6 +77,15 @@ const routes = [ path: "/artists/:hash", name: "ArtistView", component: () => import("@/views/ArtistView"), + beforeEnter: async (to: any) => { + state.loading.value = true; + + await useArtistPageStore() + .getData(to.params.hash) + .then(() => { + state.loading.value = false; + }); + }, }, { path: "/settings", diff --git a/src/stores/pages/album.ts b/src/stores/pages/album.ts index b711a9f..26b29d1 100644 --- a/src/stores/pages/album.ts +++ b/src/stores/pages/album.ts @@ -7,10 +7,10 @@ import { FuseTrackOptions } from "@/composables/enums"; import { content_width } from "@/stores/content-width"; import { - getAlbumsFromArtist, - getAlbumTracks, + getAlbumsFromArtist, + getAlbumTracks } from "../../composables/fetch/album"; -import { AlbumInfo, Artist, FuseResult, Track } from "../../interfaces"; +import { Album, Artist, FuseResult, Track } from "../../interfaces"; import { useNotifStore } from "../notification"; interface Disc { @@ -27,7 +27,7 @@ function sortByTrackNumber(tracks: Track[]) { }); } -function albumHasNoDiscs(album: AlbumInfo) { +function albumHasNoDiscs(album: Album) { if (album.is_single) return true; return false; @@ -50,10 +50,10 @@ function createDiscs(tracks: Track[]) { export default defineStore("album", { state: () => ({ query: "", - info: {}, + info: {}, rawTracks: [], artists: [], - albumArtists: <{ artist: string; albums: AlbumInfo[] }[]>[], + albumArtists: <{ artist: string; albums: Album[] }[]>[], bio: null, }), actions: { diff --git a/src/stores/pages/artist.ts b/src/stores/pages/artist.ts new file mode 100644 index 0000000..5ac2389 --- /dev/null +++ b/src/stores/pages/artist.ts @@ -0,0 +1,21 @@ +import { defineStore } from "pinia"; + +import { Artist, Album, Track } from "@/interfaces"; +import { getArtistData } from "@/composables/fetch/artists"; + +export default defineStore("artistPage", { + state: () => ({ + info: {}, + albums: [], + tracks: [], + }), + actions: { + async getData(hash: string) { + const { artist, albums, tracks } = await getArtistData(hash); + + this.info = artist; + this.albums = albums; + this.tracks = tracks; + }, + }, +}); diff --git a/src/stores/search.ts b/src/stores/search.ts index e5ed580..c2d92ca 100644 --- a/src/stores/search.ts +++ b/src/stores/search.ts @@ -1,20 +1,17 @@ -import { Routes } from "./../composables/enums"; -import { ref, reactive } from "@vue/reactivity"; -import { defineStore } from "pinia"; -import { AlbumInfo, Artist, Playlist, Track } from "../interfaces"; -import { - searchTracks, - searchAlbums, - searchArtists, - loadMoreTracks, - loadMoreAlbums, - loadMoreArtists, -} from "../composables/fetch/searchMusic"; -import { watch } from "vue"; -import useTabStore from "./tabs"; -import useLoaderStore from "./loader"; -import { useRoute } from "vue-router"; +import { reactive, ref } from "@vue/reactivity"; import { useDebounce } from "@vueuse/core"; +import { defineStore } from "pinia"; +import { watch } from "vue"; +import { useRoute } from "vue-router"; +import { + loadMoreAlbums, + loadMoreArtists, loadMoreTracks, searchAlbums, + searchArtists, searchTracks +} from "../composables/fetch/searchMusic"; +import { Album, Artist, Playlist, Track } from "../interfaces"; +import { Routes } from "./../composables/enums"; +import useLoaderStore from "./loader"; +import useTabStore from "./tabs"; /** * * Scrolls on clicking the loadmore button @@ -56,7 +53,7 @@ export default defineStore("search", () => { const albums = reactive({ query: "", - value: [], + value: [], more: false, }); diff --git a/src/views/ArtistView/Main.vue b/src/views/ArtistView/Main.vue index 5674f14..0624a72 100644 --- a/src/views/ArtistView/Main.vue +++ b/src/views/ArtistView/Main.vue @@ -4,16 +4,28 @@ style="height: 100%" :class="{ isSmall, isMedium }" > - - - + + @@ -21,29 +33,54 @@ import { isMedium, isSmall } from "@/stores/content-width"; import Header from "@/components/ArtistView/Header.vue"; +import TopTracks from "@/components/ArtistView/TopTracks.vue"; +// import Albums from "@/components/ArtistView/Albums.vue"; +import useArtistPageStore from "@/stores/pages/artist"; +import ArtistAlbums from "@/components/AlbumView/ArtistAlbums.vue"; + import { computed } from "vue"; +import { onBeforeRouteUpdate } from "vue-router"; + +const artistStore = useArtistPageStore(); interface ScrollerItem { id: string | number; - component: typeof Header; - // props: Record; - size: number; + component: any; + props?: Record; + // size: number; } const header: ScrollerItem = { id: "artist-header", component: Header, - size: 19 * 16, + // size: 16 * 19, +}; + +const top_tracks: ScrollerItem = { + id: "artist-top-tracks", + component: TopTracks, + // size: 16 * 25, +}; + +const artistAlbums: ScrollerItem = { + id: "artist-albums", + component: ArtistAlbums, + // size: 16 * 16, + props: { title: "Albums", albums: artistStore.albums }, }; const scrollerItems = computed(() => { - return [header]; + return [header, top_tracks, artistAlbums]; +}); + +onBeforeRouteUpdate((to, from, next) => { + artistStore.getData(to.params.hash as string); });