implement the random location

This commit is contained in:
Ahmed-Ayman 2018-12-21 14:44:18 +02:00
parent 6e6af71ad1
commit aa65fa4b11
6 changed files with 184 additions and 35 deletions

View File

@ -3,6 +3,13 @@ export const START_LOADING_ALL_TOPICS = 'START_LOADING_ALL_TOPICS';
export const LOADED_ALL_TOPICS = 'LOADED_ALL_TOPICS';
export const START_LOADING_RANDOM_TOPIC = 'START_LOADING_RANDOM_TOPIC';
export const LOADED_RANDOM_TOPIC = 'LOADED_RANDOM_TOPIC';
// Locations/Places
// Places Action Types
export const START_LOADING_ALL_PLACES = 'START_LOADING_ALL_PLACES';
export const LOADED_ALL_PLACES = 'LOADED_ALL_PLACES';
export const START_LOADING_RANDOM_PLACE = 'START_LOADING_RANDOM_PLACE';
export const LOADED_RANDOM_PLACE = 'LOADED_RANDOM_PLACE';
// Videos Action Types
export const ADD_VIDEOS_TO_STATE = 'ADD_VIDEOS_TO_STATE';

70
src/actions/places.js Normal file
View File

@ -0,0 +1,70 @@
import { fetchPlaces, fetchVideosByPlace } from '../utils/api';
import { APIError } from './errors';
import { getItem, setItem } from '../utils/safe-storage';
import getRandomTopic from '../utils/get-random-place';
import { addVideosToState } from './videos';
import {
START_LOADING_ALL_PLACES,
LOADED_ALL_PLACES,
START_LOADING_RANDOM_PLACE,
LOADED_RANDOM_PLACE
} from './action_types';
export function getAllPlaces() {
return dispatch => {
dispatch(startLoadingAllPlaces());
// this calls the API
fetchPlaces()
.then(places => {
dispatch(loadedPlaces(places));
}).catch(error => {
dispatch(APIError(error));
})
};
};
function startLoadingAllPlaces() {
return {
type: START_LOADING_ALL_PLACES
};
};
function loadedPlaces(places) {
// cache
setItem('allPlaces', JSON.stringify(places));
setItem('placesUpdatedAt', new Date());
return {
type: LOADED_ALL_PLACES,
payload: places
};
};
// actions :
// - async actions
// - simple: return action type and payload.
export function getRandomPlaceVideos(allPlaces, numVideos=3) {
return dispatch => {
const randomTopic = getRandomTopic(allPlaces);
dispatch(loadingRandomTopicVideos());
fetchVideosByPlace(randomTopic.name, 0, numVideos)
.then(videos => {
dispatch(addVideosToState(videos));
dispatch(loadedRandomTopicVideos(randomTopic, videos));
});
};
};
function loadedRandomTopicVideos(place, videos) {
return {
type: LOADED_RANDOM_PLACE,
payload: {
place: place,
videos: videos
}
};
};
function loadingRandomTopicVideos() {
return {
type: START_LOADING_RANDOM_PLACE
};
};

View File

@ -1,24 +0,0 @@
import React from 'react';
import VideoItem from "./VideoItem";
import Grid from 'react-css-grid'
import SectionHeading from "./SectionHeading";
class RandomLocation extends React.Component {
render() {
return (
<section>
<SectionHeading title="Random Location"/>
<Grid
width={225}
gap={24}>
<VideoItem/>
<VideoItem/>
<VideoItem/>
</Grid>
</section>
)
}
}
export default (RandomLocation);

View File

@ -0,0 +1,62 @@
import Grid from 'react-css-grid'
import React from 'react';
import PropTypes from 'prop-types';
import VideoItem from "./VideoItem";
import RandomItemTitle from "./SectionHeading";
import {Link} from 'react-router-dom';
class RandomPlace extends React.Component {
shufflePlace() {
this.props.getRandomPlaceVideos(this.props.allPlaces);
}
render() {
return (
<section>
<h2 className="section-heading">from the Archive Places - من مواضيع الارشيف</h2>
<RandomItemTitle title={this.props.placeName}
count={this.props.placeCount}
src={'/results/place/' + this.props.placeName}
/>
<Grid
width={450}
>
{/* View all places button*/}
<Link to="/places">
<button className="view-all-places">
<span className="english-text">All Places - </span>
<span className="arabic-text"> جميع الأماكن </span>
</button>
</Link>
{/* Shuffle button */}
<button className="shuffle-button" onClick={this.shufflePlace.bind(this)}>
<span className="english-text">Shuffle Places - </span>
<span className="arabic-text"> موضوع عشوائي </span>
<i className="fa fa-random"></i>
</button>
</Grid>
<Grid className="random-places"
width={220}
gap={12}>
{this.props.videos.map(video =>
<VideoItem id={video.id} key={video.id} title={video.title}/>
)}
</Grid>
</section>
)
}
}
RandomPlace.propTypes = {
placeName: PropTypes.string,
allPlaces: PropTypes.array,
videos: PropTypes.array,
loading: PropTypes.bool,
placeCount: PropTypes.number,
getRandomPlaceVideos: PropTypes.func
};
export default (RandomPlace);

View File

@ -1,7 +1,8 @@
import React from 'react';
import {connect} from 'react-redux';
import { getAllTopics, getRandomTopicVideos } from '../actions/topics';
import RandomLocation from "../components/RandomLocation";
import {getAllTopics, getRandomTopicVideos} from '../actions/topics';
import {getAllPlaces, getRandomPlaceVideos} from '../actions/places';
import RandomPlace from "../components/RandomPlace";
import RandomDate from "../components/RandomDate";
import RandomTopic from "../components/RandomTopic";
@ -12,6 +13,12 @@ class Home extends React.Component {
} else {
this.props.getAllTopics();
}
// places
if (this.props.allPlaces && this.props.allPlaces.length > 0 && !this.props.randomPlace) {
this.props.getRandomPlaceVideos()(this.props.allPlaces);
} else {
this.props.getAllPlaces();
}
}
componentWillReceiveProps(nextProps) {
@ -20,20 +27,31 @@ class Home extends React.Component {
if ((this.props.allTopics || nextProps.allTopics) && !this.props.loadingRandomTopic && !nextProps.loadingRandomTopic && !this.props.randomTopic) {
this.props.getRandomTopicVideos(nextProps.allTopics);
}
// places
if ((this.props.allPlaces || nextProps.allPlaces) && !this.props.loadingRandomPlace && !nextProps.loadingRandomPlace && !this.props.randomPlace) {
this.props.getRandomPlaceVideos()(nextProps.allPlaces);
}
}
render() {
return (
<div>
<RandomTopic
topicName={ this.props.randomTopic || ''}
allTopics={ this.props.allTopics || [] }
topicCount={ this.props.randomTopicCount }
videos = { this.props.randomTopicVideos || [] }
loading = { this.props.loadingAllTopics || this.props.loadingRandomTopic }
getRandomTopicVideos={ this.props.getRandomTopicVideos }
topicName={this.props.randomTopic || ''}
allTopics={this.props.allTopics || []}
topicCount={this.props.randomTopicCount}
videos={this.props.randomTopicVideos || []}
loading={this.props.loadingAllTopics || this.props.loadingRandomTopic}
getRandomTopicVideos={this.props.getRandomTopicVideos}
/>
<RandomPlace
placeName={this.props.randomPlace || ''}
allPlaces={this.props.allPlaces || []}
placeCount={this.props.randomPlaceCount}
videos={this.props.randomPlaceVideos || []}
loading={this.props.loadingAllPlaces || this.props.loadingRandomPlace}
getRandomPlaceVideos={this.props.getRandomPlaceVideos}
/>
<RandomLocation/>
<RandomDate/>
</div>
);
@ -46,12 +64,23 @@ const mapStateToProps = state => ({
randomTopic: state.topics.randomTopic,
randomTopicCount: state.topics.randomTopicCount,
loadingRandomTopic: state.topics.loadingRandomTopic,
randomTopicVideos: state.topics.randomTopicVideos
randomTopicVideos: state.topics.randomTopicVideos,
// places
allPlaces: state.topics.allPlaces,
loadingAllPlaces: state.topics.loadingAllPlaces,
randomPlace: state.topics.randomPlace,
randomPlaceCount: state.topics.randomPlaceCount,
loadingRandomPlace: state.topics.loadingRandomPlace,
randomPlaceVideos: state.topics.randomPlaceVideos,
});
const mapDispatchToProps = dispatch => ({
getAllTopics: () => dispatch(getAllTopics()),
getRandomTopicVideos: allTopics => dispatch(getRandomTopicVideos(allTopics))
getRandomTopicVideos: allTopics => dispatch(getRandomTopicVideos(allTopics)),
// places
getAllPlaces: () => dispatch(getAllPlaces()),
getRandomPlaceVideos: allTopics => dispatch(getRandomPlaceVideos(allTopics)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Home);

View File

@ -0,0 +1,5 @@
export default function getRandomPlace(allPlaces, minVideos=3) {
const validPlaces = allPlaces.filter(place => place.items >= minVideos);
return validPlaces[Math.floor(Math.random() * validPlaces.length)];
}