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"
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 { playlist } = props
@ -74,87 +166,6 @@ const RecentlyPlayed = (props) => {
</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) => {
return <div className="playlistExplorer_section">
<div className="playlistExplorer_section_header">
@ -180,9 +191,17 @@ export default () => {
return <div className="playlistExplorer">
<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 />
</div>

View File

@ -4,34 +4,62 @@
width: 100%;
max-width: 70vw;
overflow: visible;
gap: 50px;
.playlistExplorer_section {
display: flex;
flex-direction: column;
margin-bottom: 50px;
overflow: visible;
.playlistExplorer_section_header {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 20px;
h1 {
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 {
display: flex;
//flex-direction: row;
flex-wrap: wrap;
display: grid;
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;
width: 15vw;
width: 10vw;
height: 10vh;
min-width: 450px;
max-width: 850px;
min-width: 400px;
max-width: 800px;
border-radius: 12px;
@ -99,7 +127,7 @@
.playlistItem_info {
display: flex;
flex-direction: column;
width: 100%;
max-width: 265px;
@ -140,7 +168,7 @@
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
}