improve playlist pages

This commit is contained in:
SrGooglo 2023-04-17 22:20:39 +00:00
parent 66ab5b1e52
commit 9bd1fe9702
2 changed files with 146 additions and 99 deletions

View File

@ -8,6 +8,98 @@ import FeedModel from "models/feed"
import "./index.less" import "./index.less"
const PlaylistsList = (props) => {
const hopNumber = props.hopsPerPage ?? 6
const [offset, setOffset] = React.useState(0)
const [ended, setEnded] = React.useState(false)
const [loading, result, error, makeRequest] = app.cores.api.useRequest(props.fetchMethod, {
limit: hopNumber,
trim: offset
})
const onClickPrev = () => {
if (offset === 0) {
return
}
setOffset((value) => value - hopNumber)
}
const onClickNext = () => {
if (ended) {
return
}
setOffset((value) => value + hopNumber)
}
React.useEffect(() => {
if (typeof makeRequest === "function") {
makeRequest()
}
}, [offset])
React.useEffect(() => {
if (result) {
setEnded(result.length < hopNumber)
}
}, [result])
if (error) {
console.error(error)
return <div className="playlistExplorer_section">
<antd.Result
status="warning"
title="Failed to load"
subTitle="We are sorry, but we could not load this requests. Please try again later."
/>
</div>
}
return <div className="playlistExplorer_section">
<div className="playlistExplorer_section_header">
<h1>
{
props.headerIcon
}
<Translation>
{(t) => t(props.headerTitle)}
</Translation>
</h1>
<div className="playlistExplorer_section_header_actions">
<antd.Button
icon={<Icons.MdChevronLeft />}
onClick={onClickPrev}
disabled={offset === 0 || loading}
/>
<antd.Button
icon={<Icons.MdChevronRight />}
onClick={onClickNext}
disabled={ended || loading}
/>
</div>
</div>
<div className="playlistExplorer_section_list">
{
loading && <antd.Skeleton active />
}
{
!loading && result.map((playlist, index) => {
return <PlaylistItem
key={index}
playlist={playlist}
/>
})
}
</div>
</div>
}
const PlaylistItem = (props) => { const PlaylistItem = (props) => {
const { playlist } = props const { playlist } = props
@ -74,87 +166,6 @@ const RecentlyPlayed = (props) => {
</div> </div>
} }
const FollowingArtists = (props) => {
const [L_MusicFeed, R_MusicFeed, E_MusicFeed] = app.cores.api.useRequest(FeedModel.getPlaylistsFeed)
if (E_MusicFeed) {
console.error(E_MusicFeed)
return <div className="playlistExplorer_section">
<antd.Result
status="warning"
title="Failed to load"
subTitle="We are sorry, but we could not load your playlists. Please try again later."
/>
</div>
}
return <div className="playlistExplorer_section">
<div className="playlistExplorer_section_header">
<h1>
<Icons.MdPerson />
<Translation>
{(t) => t("From following artists")}
</Translation>
</h1>
</div>
<div className="playlistExplorer_section_list">
{
L_MusicFeed && <antd.Skeleton active />
}
{
!L_MusicFeed && R_MusicFeed.map((playlist, index) => {
return <PlaylistItem
key={index}
playlist={playlist}
/>
})
}
</div>
</div>
}
const PlaylistExplorer = (props) => {
const [L_MusicFeed, R_MusicFeed, E_MusicFeed] = app.cores.api.useRequest(FeedModel.getGlobalMusicFeed)
if (E_MusicFeed) {
console.error(E_MusicFeed)
return <div className="playlistExplorer_section">
<antd.Result
status="warning"
title="Failed to load"
subTitle="We are sorry, but we could not load your playlists. Please try again later."
/>
</div>
}
return <div className="playlistExplorer_section">
<div className="playlistExplorer_section_header">
<h1>
<Icons.MdExplore />
<Translation>
{(t) => t("Explore from global")}
</Translation>
</h1>
</div>
<div className="playlistExplorer_section_list">
{
L_MusicFeed && <antd.Skeleton active />
}
{
!L_MusicFeed && R_MusicFeed.map((playlist, index) => {
return <PlaylistItem
key={index}
playlist={playlist}
/>
})
}
</div>
</div>
}
const MayLike = (props) => { const MayLike = (props) => {
return <div className="playlistExplorer_section"> return <div className="playlistExplorer_section">
<div className="playlistExplorer_section_header"> <div className="playlistExplorer_section_header">
@ -180,9 +191,17 @@ export default () => {
return <div className="playlistExplorer"> return <div className="playlistExplorer">
<RecentlyPlayed /> <RecentlyPlayed />
<FollowingArtists /> <PlaylistsList
headerTitle="From your following artists"
headerIcon={<Icons.MdPerson />}
fetchMethod={FeedModel.getPlaylistsFeed}
/>
<PlaylistExplorer /> <PlaylistsList
headerTitle="Explore from global"
headerIcon={<Icons.MdExplore />}
fetchMethod={FeedModel.getGlobalMusicFeed}
/>
<MayLike /> <MayLike />
</div> </div>

View File

@ -4,34 +4,62 @@
width: 100%; width: 100%;
max-width: 70vw; gap: 50px;
overflow: visible;
.playlistExplorer_section { .playlistExplorer_section {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-bottom: 50px; overflow: visible;
.playlistExplorer_section_header { .playlistExplorer_section_header {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 20px;
h1 { h1 {
font-size: 1.5rem; font-size: 1.5rem;
margin: 0;
}
.playlistExplorer_section_header_actions {
display: flex;
flex-direction: row;
gap: 10px;
align-self: center;
margin-left: auto;
} }
} }
.playlistExplorer_section_list { .playlistExplorer_section_list {
display: flex; display: grid;
//flex-direction: row;
flex-wrap: wrap;
max-height: 30vh; grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
align-items: center; grid-column-gap: 10px;
grid-row-gap: 10px;
}
gap: 20px; // add a media query to change the grid-template-columns when the screen can't fit 3 columns
@media (max-width: 1500px) {
.playlistExplorer_section_list {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(3, 1fr);
}
}
overflow-x: scroll; @media (max-width: 800px) {
.playlistExplorer_section_list {
grid-template-columns: repeat(1, 1fr);
grid-template-rows: repeat(6, 1fr);
}
} }
} }
} }
@ -43,11 +71,11 @@
cursor: pointer; cursor: pointer;
width: 15vw; width: 10vw;
height: 10vh; height: 10vh;
min-width: 450px; min-width: 400px;
max-width: 850px; max-width: 800px;
border-radius: 12px; border-radius: 12px;
@ -99,7 +127,7 @@
.playlistItem_info { .playlistItem_info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
max-width: 265px; max-width: 265px;
@ -140,7 +168,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 30px; width: 30px;
height: 30px; height: 30px;
} }