Skip to content

Commit

Permalink
Subject card fav button (#24)
Browse files Browse the repository at this point in the history
* Remove unneeded default project context value

* Add favorites context

* Refactor favorites container

* Init fav functionality

* Refactor to favoriteCollection and linkedSubjects
  • Loading branch information
mcbouslog authored Nov 29, 2018
1 parent 0217ffe commit 97939d5
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 85 deletions.
83 changes: 47 additions & 36 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import GrommetApp from 'grommet/components/App';
import Box from 'grommet/components/Box';
import { ZooFooter, ZooHeader } from 'zooniverse-react-components';

import {
FavoritesProvider,
FavoritesContext
} from '../context/FavoritesContext';
import { ProjectProvider, ProjectContext } from '../context/ProjectContext';
import { UserProvider, UserContext } from '../context/UserContext';

import AuthContainer from '../containers/AuthContainer';
import UserHeading from './UserHeading';
import RecentsContainer from '../containers/RecentsContainer';
Expand All @@ -17,45 +22,51 @@ const App = () => (
<UserProvider>
<ProjectProvider>
<UserContext.Consumer>
{userContext => (
{({ user }) => (
<GrommetApp centered={false}>
<ZooHeader authContainer={<AuthContainer />} />
<Box className="main" pad="large" tag="main">
<ProjectContext.Consumer>
{projectContext => (
<UserHeading
project={projectContext.project}
user={userContext.user}
/>
)}
</ProjectContext.Consumer>
<Box
direction="row"
full="horizontal"
margin={{ bottom: 'medium' }}
responsive
>
<Box
basis="2/3"
colorIndex="light-1"
justify="between"
margin={{ right: 'medium' }}
>
<RecentsContainer user={userContext.user} />
<hr className="main__hr" />
<FavoritesContainer user={userContext.user} />
<ProjectContext.Consumer>
{({ project }) => (
<Box className="main" pad="large" tag="main">
<UserHeading project={project} user={user} />
<Box
direction="row"
full="horizontal"
margin={{ bottom: 'medium' }}
responsive
>
<FavoritesProvider project={project} user={user}>
<FavoritesContext.Consumer>
{({ favoriteCollection, linkedSubjects }) => (
<Box
basis="2/3"
colorIndex="light-1"
justify="between"
margin={{ right: 'medium' }}
>
<RecentsContainer user={user} />
<hr className="main__hr" />
<FavoritesContainer
favoriteCollection={favoriteCollection}
linkedSubjects={linkedSubjects}
/>
</Box>
)}
</FavoritesContext.Consumer>
</FavoritesProvider>
<StatsContainer user={user} />
</Box>
<Box
colorIndex="light-1"
full="horizontal"
pad="medium"
style={{ height: '250px' }}
>
<Title>Your Badges</Title>
</Box>
</Box>
<StatsContainer user={userContext.user} />
</Box>
<Box
colorIndex="light-1"
full="horizontal"
pad="medium"
style={{ height: '250px' }}
>
<Title>Your Badges</Title>
</Box>
</Box>
)}
</ProjectContext.Consumer>
<ZooFooter />
</GrommetApp>
)}
Expand Down
48 changes: 48 additions & 0 deletions src/components/FavoritesButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import PropTypes from 'prop-types';
import React from 'react';
import Button from 'grommet/components/Button';

export default function FavoritesButton({
addSubjectTo,
linkedSubjects,
removeSubjectFrom,
subject
}) {
const subjectId = subject.links.subject || subject.id;
const favorited =
linkedSubjects && linkedSubjects.length
? !!linkedSubjects.some(subj => subj === subjectId)
: false;

const favClassName = favorited ? 'fas fa-heart fa-fw' : 'far fa-heart fa-fw';

return (
<Button
onClick={() => {
if (favorited) {
removeSubjectFrom(subjectId);
} else {
addSubjectTo(subjectId);
}
}}
type="button"
>
<i className={favClassName} />
</Button>
);
}

FavoritesButton.defaultProps = {
addSubjectTo: () => {},
linkedSubjects: [],
removeSubjectFrom: () => {}
};

FavoritesButton.propTypes = {
addSubjectTo: PropTypes.func,
linkedSubjects: PropTypes.arrayOf(PropTypes.string),
removeSubjectFrom: PropTypes.func,
subject: PropTypes.shape({
id: PropTypes.string
}).isRequired
};
19 changes: 12 additions & 7 deletions src/components/SubjectCard.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import PropTypes from 'prop-types';
import React from 'react';
import Box from 'grommet/components/Box';
import Button from 'grommet/components/Button';
import { Thumbnail } from 'zooniverse-react-components';

import { config } from '../config';
import { ProjectContext } from '../context/ProjectContext';
import getSubjectLocations from '../lib/get-subject-locations';
import { FavoritesContext } from '../context/FavoritesContext';
import FavoritesButton from './FavoritesButton';

export default function SubjectCard({ subject }) {
const locations = getSubjectLocations(subject);
Expand Down Expand Up @@ -45,12 +46,16 @@ export default function SubjectCard({ subject }) {
/>
</a>
<Box direction="row" justify="center">
<Button type="button">
<i className="fa fa-heart fa-fw" />
</Button>
<Button type="button">
<i className="fa fa-list fa-fw" />
</Button>
<FavoritesContext.Consumer>
{({ addSubjectTo, linkedSubjects, removeSubjectFrom }) => (
<FavoritesButton
addSubjectTo={addSubjectTo}
linkedSubjects={linkedSubjects}
removeSubjectFrom={removeSubjectFrom}
subject={subject}
/>
)}
</FavoritesContext.Consumer>
</Box>
</Box>
)}
Expand Down
68 changes: 29 additions & 39 deletions src/containers/FavoritesContainer.jsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,63 @@
import PropTypes from 'prop-types';
import React from 'react';
import Box from 'grommet/components/Box';
import apiClient from 'panoptes-client';
import { Paginator } from 'zooniverse-react-components';

import { config } from '../config';
import Title from '../components/Title';
import SubjectCard from '../components/SubjectCard';

class FavoritesContainer extends React.Component {
constructor() {
super();
this.state = {
favorites: null,
favoriteSubjects: null,
meta: null
};

this.onPageChange = this.onPageChange.bind(this);
}

componentDidMount() {
this.fetchFavorites();
this.fetchFavoriteSubjects();
}

componentDidUpdate(prevProps) {
if (prevProps.user !== this.props.user) {
this.fetchFavorites();
if (prevProps.favoriteCollection !== this.props.favoriteCollection) {
this.fetchFavoriteSubjects();
}
}

onPageChange(page) {
this.fetchFavorites(page);
this.fetchFavoriteSubjects(page);
}

fetchFavorites(page = 1) {
const { user } = this.props;
fetchFavoriteSubjects(page = 1) {
const { favoriteCollection, linkedSubjects } = this.props;

if (user) {
if (favoriteCollection && linkedSubjects.length) {
const query = {
page,
page_size: 3
};

apiClient
.type('collections')
.get({
project_ids: config.projectId,
favorite: true,
sort: 'display_name'
})
.then(collections => {
if (collections && collections[0]) {
collections[0]
.get('subjects', query)
.then(favorites =>
this.setState({ favorites, meta: favorites[0].getMeta() })
)
.catch(() => {
if (console) {
console.warn('Failed to fetch favorites');
}
});
}
})
favoriteCollection
.get('subjects', query)
.then(favoriteSubjects =>
this.setState({
favoriteSubjects,
meta: favoriteSubjects[0].getMeta()
})
)
.catch(() => {
if (console) {
console.warn('Failed to fetch colletions for favorites');
console.warn('Failed to fetch favorites');
}
});
} else {
this.setState({ meta: null, favorites: null });
this.setState({
favoriteSubjects: null,
meta: null
});
}
}

Expand All @@ -78,8 +66,8 @@ class FavoritesContainer extends React.Component {
<Box basis="1/2" pad="medium">
<Title>Your Favorites</Title>
<Box direction="row" justify="around" responsive>
{this.state.favorites &&
this.state.favorites.map(favorite => (
{this.state.favoriteSubjects &&
this.state.favoriteSubjects.map(favorite => (
<SubjectCard key={favorite.id} subject={favorite} />
))}
</Box>
Expand All @@ -97,13 +85,15 @@ class FavoritesContainer extends React.Component {
}

FavoritesContainer.propTypes = {
user: PropTypes.shape({
get: PropTypes.func
})
favoriteCollection: PropTypes.shape({
id: PropTypes.string
}),
linkedSubjects: PropTypes.arrayOf(PropTypes.string)
};

FavoritesContainer.defaultProps = {
user: null
favoriteCollection: null,
linkedSubjects: []
};

export default FavoritesContainer;
Loading

0 comments on commit 97939d5

Please sign in to comment.