Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions reactjs/components/Error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'

const Error = () => {
return (
<div>
<p>There was an error loading your gifs, please try again later...</p>
</div>
)
}
export default Error;
15 changes: 15 additions & 0 deletions reactjs/components/GifPages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import Gifs from '../../components/Gifs';

const GifPages = () => (
<div>
<nav className="navbar navbar-dark bg-primary mb-4">
<span className="navbar-brand mb-0 h1">The SystemSeed Giphy Client</span>
</nav>
<div className="container">
<Gifs />
</div>
</div>
);

export default GifPages;
94 changes: 94 additions & 0 deletions reactjs/components/Gifs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { gifsRequest, gotoNextPage } from '../store/actions/Gifs';
import Loading from './Loading';
import Error from './Error';
import GifData from './gifdata/GifData';

class Gifs extends Component {

state = {
currentPage: 0,
numItemsToDisplay: 12,
response: null,
slicedItems: null,
pageNum: null,
error: null,
totalItems: 0
}


componentDidMount() {
this.props.gifsRequest();
}

getSlicedItems = (page, displayItems, response) => {
let start = page * displayItems;
let end = start + displayItems;
let slicedItems = response.slice(start, end);
return slicedItems;
}

componentWillReceiveProps(nextProps) {
const { currentPage, numItemsToDisplay, response } = this.state;
if (nextProps.response != null) {
let slicedItems = this.getSlicedItems(currentPage, numItemsToDisplay, nextProps.response);
this.setState({
response: nextProps.response,
slicedItems: slicedItems,
totalItems: nextProps.response.length
})
}
if (nextProps.pageNum != null) {
let slicedItems = this.getSlicedItems(nextProps.pageNum, numItemsToDisplay, response);
this.setState({
currentPage: nextProps.pageNum,
slicedItems: slicedItems,
pageNum: nextProps.pageNum
})
}
}

render() {
const { response, gotoNextPage, pageNum, error } = this.props;
const { slicedItems, numItemsToDisplay, totalItems, currentPage } = this.state;

if (response == null && pageNum == null && error == null) {
return (
<React.Fragment>
<Loading />
</React.Fragment>
)
} else if ((response !== null || pageNum != null) && error == null) {
return (
<React.Fragment>
<GifData slicedItems={slicedItems}
totalItems={totalItems}
numItemsToDisplay={numItemsToDisplay}
gotoNextPage={gotoNextPage}
/>
</React.Fragment>
)
}
else if (response == null && pageNum == null && error != null) {
return (
<React.Fragment>
<Error />
</React.Fragment>
)
} else {
return null;
}
}
}
const mapStateToProps = (state) => ({
response: state.gifs.response,
error: state.gifs.error,
pageNum: state.gifs.pageNum
})

const mapDispatchToProps = {
gifsRequest, gotoNextPage
}

export default connect(mapStateToProps, mapDispatchToProps)(Gifs);
12 changes: 0 additions & 12 deletions reactjs/components/HelloFriend/index.js

This file was deleted.

1 change: 1 addition & 0 deletions reactjs/components/HtmlHead/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const HtmlHead = () => {
SystemSeed Technical Assessment
</title>
<meta charSet="utf-8" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<link rel="shortcut icon" href="/static/favicon.ico" type="image/vnd.microsoft.icon" />
Expand Down
10 changes: 10 additions & 0 deletions reactjs/components/Loading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'

const Loading = () => {
return (
<div className="text-center">
<h1>Loading your gifs...</h1>
</div>
)
}
export default Loading;
16 changes: 16 additions & 0 deletions reactjs/components/gifdata/GifData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import GifGrid from './GifGrid';
import Pagination from '../pagination/Pagination';

const GifData = ({ slicedItems, totalItems, numItemsToDisplay, gotoNextPage }) => {
return (
<React.Fragment>
<GifGrid slicedItems={slicedItems} />
{
numItemsToDisplay < totalItems &&
<Pagination totalItems={totalItems} numItemsToDisplay={numItemsToDisplay} gotoNextPage={gotoNextPage} />
}
</React.Fragment>
)
}
export default GifData;
21 changes: 21 additions & 0 deletions reactjs/components/gifdata/GifGrid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'

const GifGrid = ({ slicedItems }) => {
return (
<div className="row">
{
slicedItems.map(item => (
<div className="col-lg-4 col-md-6 col-sm-12" key={item.id}>
<div className="card mb-4" key={item.id}>
<img className="card-img-top" src={item.images.original.url} alt={item.title} style={{height: "275px"}} />
<div className="card-body">
<h5 className="card-title text-center text-capitalize">{item.title}</h5>
</div>
</div>
</div>
))
}
</div>
)
}
export default GifGrid;
43 changes: 43 additions & 0 deletions reactjs/components/pagination/Pagination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { Component } from 'react';
import PaginationItem from './PaginationItem';

class Pagination extends Component {

constructor(props) {
super(props);
const { totalItems, numItemsToDisplay } = this.props;
this.totalItems = typeof totalItems === "number" ? totalItems : 0;
this.numItemsToDisplay = typeof numItemsToDisplay === "number" ? numItemsToDisplay : 0;
}

getPages(totalPage) {
let pages = [];
let i = 0;

while (i < totalPage) {
pages.push(i);
i++;
}

return pages;
}

handleClick = (page, e) => {
e.preventDefault();
this.props.gotoNextPage(page);
}

render() {
let pages = this.getPages(Math.ceil(this.totalItems / this.numItemsToDisplay));
return (
<div className="Pagination">
{
pages.map((page, index) =>
<PaginationItem key={index} page={page} onClick={e => this.handleClick(page, e)} />
)
}
</div>
)
}
}
export default Pagination;
10 changes: 10 additions & 0 deletions reactjs/components/pagination/PaginationItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'

const PaginationItem = ({ page, onClick }) => {
return (
<div onClick={onClick} className="Pagination_Item">
{page + 1}
</div>
)
}
export default PaginationItem;
1 change: 1 addition & 0 deletions reactjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "^0.18.0",
"compression": "^1.7.3",
"express": "^4.16.3",
"next": "^6.1.1",
Expand Down
4 changes: 2 additions & 2 deletions reactjs/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import HelloFriend from '../components/HelloFriend';
import GifPages from '../components/GifPages';

class Page extends React.Component {
static async getInitialProps() {
Expand All @@ -9,7 +9,7 @@ class Page extends React.Component {
}

render() {
return <HelloFriend />;
return <GifPages />;
}
}

Expand Down
29 changes: 29 additions & 0 deletions reactjs/store/actions/Gifs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as types from './Types';

export const gifsRequest = () => {
return {
type: types.GIFS_REQ,
payload: ''
}
}

export const gifsResponse = (data) => {
return {
type: types.GIFS_RES,
payload: data
}
}

export const gifsError = (data) => {
return {
type: types.GIFS_ERROR,
payload: data
}
}

export const gotoNextPage = (pageNum) => {
return {
type: types.GO_NEXT_PAGE,
payload: pageNum
}
}
5 changes: 5 additions & 0 deletions reactjs/store/actions/Types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const GIFS_REQ = "GIFS_REQ";
export const GIFS_RES = "GIFS_RES";
export const GIFS_ERROR = "GIFS_ERROR";

export const GO_NEXT_PAGE = "GO_NEXT_PAGE";
6 changes: 0 additions & 6 deletions reactjs/store/actions/example.js

This file was deleted.

7 changes: 7 additions & 0 deletions reactjs/store/api/Api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import axios from 'axios';

export default {
gif: {
gifs:() => axios.get('http://api.giphy.com/v1/gifs/trending?api_key=ovU9KlXS8RtZr0VgRT6X02ZaH02P30qw&limit=120')
}
}
29 changes: 29 additions & 0 deletions reactjs/store/reducers/GifReducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as types from '../actions/Types';

const init = {
response: null,
error: null,
pageNum: null
}

const gifReducer = (state = init, action) => {
switch (action.type) {
case types.GIFS_REQ:
state = { ...state, response: null, error: null, pageNum: null }
break;
case types.GIFS_RES:
state = { ...state, response: action.payload, error: null, pageNum: null }
break;
case types.GIFS_ERROR:
state = { ...state, response: null, error: action.payload, pageNum: null }
break;
case types.GO_NEXT_PAGE:
state = { ...state, response: null, error: null, pageNum: action.payload }
break;
default:
break;
}
return state;
}

export default gifReducer;
12 changes: 0 additions & 12 deletions reactjs/store/reducers/example.js

This file was deleted.

6 changes: 3 additions & 3 deletions reactjs/store/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { combineReducers } from 'redux';
// Put all your reducers here.
import example from './example';
import gifReducer from './GifReducer';

export default combineReducers({
example,
});
gifs: gifReducer
});
Loading