Skip to content

Commit

Permalink
chapter 5
Browse files Browse the repository at this point in the history
  • Loading branch information
rwieruch committed Oct 15, 2017
1 parent 9e7b95c commit d594d4a
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 33 deletions.
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"classnames": "^2.2.5",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-scripts": "1.0.14"
Expand Down
162 changes: 137 additions & 25 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { Component } from 'react';
import fetch from 'isomorphic-fetch';
import { sortBy } from 'lodash';
import classNames from 'classnames';
import './App.css';

const DEFAULT_QUERY = 'redux';
Expand All @@ -11,6 +13,14 @@ const PARAM_SEARCH = 'query=';
const PARAM_PAGE = 'page=';
const PARAM_HPP = 'hitsPerPage=';

const SORTS = {
NONE: list => list,
TITLE: list => sortBy(list, 'title'),
AUTHOR: list => sortBy(list, 'author'),
COMMENTS: list => sortBy(list, 'num_comments').reverse(),
POINTS: list => sortBy(list, 'points').reverse(),
};

class App extends Component {
constructor(props) {
super(props);
Expand All @@ -20,6 +30,9 @@ class App extends Component {
searchKey: '',
searchTerm: DEFAULT_QUERY,
error: null,
isLoading: false,
sortKey: 'NONE',
isSortReverse: false,
};

this.needsToSearchTopStories = this.needsToSearchTopStories.bind(this);
Expand All @@ -28,6 +41,12 @@ class App extends Component {
this.onSearchChange = this.onSearchChange.bind(this);
this.onSearchSubmit = this.onSearchSubmit.bind(this);
this.onDismiss = this.onDismiss.bind(this);
this.onSort = this.onSort.bind(this);
}

onSort(sortKey) {
const isSortReverse = this.state.sortKey === sortKey && !this.state.isSortReverse;
this.setState({ sortKey, isSortReverse });
}

needsToSearchTopStories(searchTerm) {
Expand All @@ -51,11 +70,14 @@ class App extends Component {
results: {
...results,
[searchKey]: { hits: updatedHits, page }
}
},
isLoading: false
});
}

fetchSearchTopStories(searchTerm, page = 0) {
this.setState({ isLoading: true });

fetch(`${PATH_BASE}${PATH_SEARCH}?${PARAM_SEARCH}${searchTerm}&${PARAM_PAGE}${page}&${PARAM_HPP}${DEFAULT_HPP}`)
.then(response => response.json())
.then(result => this.setSearchTopStories(result))
Expand Down Expand Up @@ -103,7 +125,10 @@ class App extends Component {
searchTerm,
results,
searchKey,
error
error,
isLoading,
sortKey,
isSortReverse
} = this.state;

const page = (
Expand Down Expand Up @@ -135,13 +160,18 @@ class App extends Component {
</div>
: <Table
list={list}
sortKey={sortKey}
isSortReverse={isSortReverse}
onSort={this.onSort}
onDismiss={this.onDismiss}
/>
}
<div className="interactions">
<Button onClick={() => this.fetchSearchTopStories(searchKey, page + 1)}>
<ButtonWithLoading
isLoading={isLoading}
onClick={() => this.fetchSearchTopStories(searchKey, page + 1)}>
More
</Button>
</ButtonWithLoading>
</div>
</div>
);
Expand All @@ -165,39 +195,111 @@ const Search = ({
</button>
</form>

const Table = ({ list, onDismiss }) =>
<div className="table">
{list.map(item =>
<div key={item.objectID} className="table-row">
const Table = ({
list,
sortKey,
isSortReverse,
onSort,
onDismiss
}) => {
const sortedList = SORTS[sortKey](list);
const reverseSortedList = isSortReverse
? sortedList.reverse()
: sortedList;

return(
<div className="table">
<div className="table-header">
<span style={{ width: '40%' }}>
<a href={item.url}>{item.title}</a>
<Sort
sortKey={'TITLE'}
onSort={onSort}
activeSortKey={sortKey}
>
Title
</Sort>
</span>
<span style={{ width: '30%' }}>
{item.author}
<Sort
sortKey={'AUTHOR'}
onSort={onSort}
activeSortKey={sortKey}
>
Author
</Sort>
</span>
<span style={{ width: '10%' }}>
{item.num_comments}
<Sort
sortKey={'COMMENTS'}
onSort={onSort}
activeSortKey={sortKey}
>
Comments
</Sort>
</span>
<span style={{ width: '10%' }}>
{item.points}
<Sort
sortKey={'POINTS'}
onSort={onSort}
activeSortKey={sortKey}
>
Points
</Sort>
</span>
<span style={{ width: '10%' }}>
<Button
onClick={() => onDismiss(item.objectID)}
className="button-inline"
>
Dismiss
</Button>
Archive
</span>
</div>
)}
</div>
{reverseSortedList.map(item =>
<div key={item.objectID} className="table-row">
<span style={{ width: '40%' }}>
<a href={item.url}>{item.title}</a>
</span>
<span style={{ width: '30%' }}>
{item.author}
</span>
<span style={{ width: '10%' }}>
{item.num_comments}
</span>
<span style={{ width: '10%' }}>
{item.points}
</span>
<span style={{ width: '10%' }}>
<Button
onClick={() => onDismiss(item.objectID)}
className="button-inline"
>
Dismiss
</Button>
</span>
</div>
)}
</div>
);
}

const Button = ({
onClick,
className = '',
children,
}) =>
const Sort = ({
sortKey,
activeSortKey,
onSort,
children
}) => {
const sortClass = classNames(
'button-inline',
{ 'button-active': sortKey === activeSortKey }
);

return (
<Button
onClick={() => onSort(sortKey)}
className={sortClass}
>
{children}
</Button>
);
}

const Button = ({ onClick, className = '', children }) =>
<button
onClick={onClick}
className={className}
Expand All @@ -206,6 +308,16 @@ const Button = ({
{children}
</button>

const Loading = () =>
<div>Loading ...</div>

const withLoading = (Component) => ({ isLoading, ...rest }) =>
isLoading
? <Loading />
: <Component { ...rest } />

const ButtonWithLoading = withLoading(Button);

export {
Button,
Search,
Expand Down
2 changes: 2 additions & 0 deletions src/App.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ describe('Table', () => {
{ title: '1', author: '1', num_comments: 1, points: 2, objectID: 'y' },
{ title: '2', author: '2', num_comments: 1, points: 2, objectID: 'z' },
],
sortKey: 'TITLE',
isSortReverse: false,
};

it('renders without crashing', () => {
Expand Down
Loading

0 comments on commit d594d4a

Please sign in to comment.