mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-12-12 00:31:11 -05:00
refactor: [UEPR-116] move playlist component to separate file
This commit is contained in:
parent
1854d11e45
commit
c9405ffafb
4 changed files with 98 additions and 93 deletions
|
@ -0,0 +1,66 @@
|
||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
import api from '../../lib/api';
|
||||||
|
import {YoutubeVideoButton} from '../youtube-video-button/youtube-video-button.jsx';
|
||||||
|
import Spinner from '../spinner/spinner.jsx';
|
||||||
|
|
||||||
|
import './youtube-playlist-item.scss';
|
||||||
|
|
||||||
|
export const YoutubePlaylistItem = ({playlistRequestUri, playlistTitleId, onSelectedVideo}) => {
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [playlistVideos, setPlaylistVideos] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
api({
|
||||||
|
host: process.env.ROOT_URL,
|
||||||
|
method: 'GET',
|
||||||
|
uri: playlistRequestUri,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}, (_err, body, res) => {
|
||||||
|
setLoading(false);
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
setPlaylistVideos(body);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="playlist">
|
||||||
|
<div className="playlist-title">
|
||||||
|
<FormattedMessage id={playlistTitleId} />
|
||||||
|
</div>
|
||||||
|
{loading ? (
|
||||||
|
<Spinner
|
||||||
|
className="spinner"
|
||||||
|
color="transparent-gray"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<section className="playlist-videos">
|
||||||
|
{playlistVideos
|
||||||
|
.sort(
|
||||||
|
(firstVideo, secondVideo) =>
|
||||||
|
new Date(firstVideo.publishedAt).getTime() <
|
||||||
|
new Date(secondVideo.publishedAt).getTime()
|
||||||
|
)
|
||||||
|
.map(video => (
|
||||||
|
<YoutubeVideoButton
|
||||||
|
key={video.videoId}
|
||||||
|
onSelectedVideo={onSelectedVideo}
|
||||||
|
{...video}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
YoutubePlaylistItem.propTypes = {
|
||||||
|
playlistRequestUri: PropTypes.string,
|
||||||
|
playlistTitleId: PropTypes.string,
|
||||||
|
onSelectedVideo: PropTypes.func
|
||||||
|
};
|
|
@ -0,0 +1,26 @@
|
||||||
|
.playlist {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
.playlist-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: start;
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-videos {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(13.125rem, auto));
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: start;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
const FormattedMessage = require('react-intl').FormattedMessage;
|
const FormattedMessage = require('react-intl').FormattedMessage;
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const {useState, useCallback, useEffect} = require('react');
|
const {useState, useCallback} = require('react');
|
||||||
const PropTypes = require('prop-types');
|
|
||||||
const api = require('../../lib/api');
|
|
||||||
|
|
||||||
const Button = require('../../components/forms/button.jsx');
|
const Button = require('../../components/forms/button.jsx');
|
||||||
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
||||||
|
@ -12,13 +10,10 @@ const Page = require('../../components/page/www/page.jsx');
|
||||||
const render = require('../../lib/render.jsx');
|
const render = require('../../lib/render.jsx');
|
||||||
|
|
||||||
const {useIntl} = require('react-intl');
|
const {useIntl} = require('react-intl');
|
||||||
const {
|
|
||||||
YoutubeVideoButton
|
|
||||||
} = require('../../components/youtube-video-button/youtube-video-button.jsx');
|
|
||||||
const {
|
const {
|
||||||
YoutubeVideoModal
|
YoutubeVideoModal
|
||||||
} = require('../../components/youtube-video-modal/youtube-video-modal.jsx');
|
} = require('../../components/youtube-video-modal/youtube-video-modal.jsx');
|
||||||
const Spinner = require('../../components/spinner/spinner.jsx');
|
const {YoutubePlaylistItem} = require('../../components/youtube-playlist-item/youtube-playlist-item.jsx');
|
||||||
|
|
||||||
require('./ideas.scss');
|
require('./ideas.scss');
|
||||||
|
|
||||||
|
@ -101,57 +96,6 @@ const playlists = {
|
||||||
'advanced-topics': 'ideas.advancedTopics'
|
'advanced-topics': 'ideas.advancedTopics'
|
||||||
};
|
};
|
||||||
|
|
||||||
const PlaylistItem = ({playlistKey, onSelectedVideo}) => {
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [playlistVideos, setPlaylistVideos] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
api({
|
|
||||||
host: process.env.ROOT_URL,
|
|
||||||
method: 'GET',
|
|
||||||
uri: `/ideas/videos/${playlistKey}`,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
}, (_err, body, res) => {
|
|
||||||
setLoading(false);
|
|
||||||
if (res.statusCode === 200) {
|
|
||||||
setPlaylistVideos(body);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="playlist">
|
|
||||||
<div className="playlist-title">
|
|
||||||
<FormattedMessage id={playlists[playlistKey]} />
|
|
||||||
</div>
|
|
||||||
{loading ? (
|
|
||||||
<Spinner
|
|
||||||
className="spinner"
|
|
||||||
color="transparent-gray"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<section className="playlist-videos">
|
|
||||||
{playlistVideos
|
|
||||||
.sort(
|
|
||||||
(firstVideo, secondVideo) =>
|
|
||||||
new Date(firstVideo.publishedAt).getTime() <
|
|
||||||
new Date(secondVideo.publishedAt).getTime()
|
|
||||||
)
|
|
||||||
.map(video => (
|
|
||||||
<YoutubeVideoButton
|
|
||||||
key={video.videoId}
|
|
||||||
onSelectedVideo={onSelectedVideo}
|
|
||||||
{...video}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Ideas = () => {
|
const Ideas = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [youtubeVideoId, setYoutubeVideoId] = useState('');
|
const [youtubeVideoId, setYoutubeVideoId] = useState('');
|
||||||
|
@ -252,9 +196,10 @@ const Ideas = () => {
|
||||||
</div>
|
</div>
|
||||||
<section className="playlists">
|
<section className="playlists">
|
||||||
{Object.keys(playlists).map(playlistKey => (
|
{Object.keys(playlists).map(playlistKey => (
|
||||||
<PlaylistItem
|
<YoutubePlaylistItem
|
||||||
key={playlistKey}
|
key={playlistKey}
|
||||||
playlistKey={playlistKey}
|
playlistRequestUri={`/ideas/videos/${playlistKey}`}
|
||||||
|
playlistTitleId={playlists[playlistKey]}
|
||||||
onSelectedVideo={onSelectedVideo}
|
onSelectedVideo={onSelectedVideo}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
@ -368,11 +313,6 @@ const Ideas = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
PlaylistItem.propTypes = {
|
|
||||||
playlistKey: PropTypes.string,
|
|
||||||
onSelectedVideo: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Page>
|
<Page>
|
||||||
<Ideas />
|
<Ideas />
|
||||||
|
|
|
@ -92,33 +92,6 @@ $base-bg: $ui-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
|
|
||||||
.playlist-title {
|
|
||||||
display: flex;
|
|
||||||
justify-content: start;
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playlist-videos {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(13.125rem, auto));
|
|
||||||
justify-content: space-around;
|
|
||||||
align-items: start;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.physical-ideas {
|
.physical-ideas {
|
||||||
.inner {
|
.inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -203,7 +176,7 @@ $base-bg: $ui-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tips, .physical-ideas, .playlist {
|
.tips, .physical-ideas {
|
||||||
.section-header {
|
.section-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
|
|
Loading…
Reference in a new issue