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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
public/bundles.js
public/bundles.js
/coverage.data
/coverage/
43 changes: 40 additions & 3 deletions client/components/App.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,54 @@
import React, { Component } from 'react';
import axios from 'axios';

import Header from './Header';
import RatingsList from './RatingsList';
import ReviewsList from './ReviewsList';
import Pagination from './Pagination';

class App extends Component {
constructor(props) {
super(props);
this.state = {
message: 'Howdy',
rating: {},
reviews: [],
reviewGroup: 0,
};
this.updateReviewGroup = this.updateReviewGroup.bind(this);
}

componentDidMount() {
axios.get('/api/reviews/0/')
.then((res) => this.setState(res.data))
.catch(console.log);
}

componentDidUpdate(prevProps, prevState) {
const { reviewGroup } = this.state;
if (prevState.reviewGroup !== reviewGroup) {
axios.get(`/api/reviews/0/?reviewgroup=${reviewGroup}`)
.then((res) => this.setState({
reviews: res.data.reviews,
}))
.catch(console.log);
}
}

updateReviewGroup(newReviewGroup) {
this.setState({
reviewGroup: newReviewGroup,
});
}

render() {
const { message } = this.state;
const { rating, reviews, reviewGroup } = this.state;
return (
<h1>{message}</h1>
<div id='reviewsComponent'>
<Header rating={rating.overall} />
<RatingsList rating={rating} />
<ReviewsList reviews={reviews} />
<Pagination reviewGroup={reviewGroup} updateReviewGroup={this.updateReviewGroup} />
</div>
);
}
}
Expand Down
10 changes: 10 additions & 0 deletions client/components/App.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';

describe('App rendering', () => {
test('App component should exist', () => {
const shallowReview = shallow(<App />);
expect(shallowReview).toExist();
});
});
18 changes: 18 additions & 0 deletions client/components/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';

const Header = (props) => {
const { rating } = props;

return (
<div id="reviewsComponent-header">
<h1>Reviews</h1>
<div id="reviewsComponent-subheader">
<h2>* {rating}</h2>
<h2>50 reviews</h2>
<input placeholder='Search reviews'/>
</div>
</div>
);
};

export default Header;
88 changes: 88 additions & 0 deletions client/components/Pagination.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { Component } from 'react';

class Pagination extends Component {
constructor(props) {
super(props);
this.state = {
previous: false,
next: true,
};
this.handleClick = this.handleClick.bind(this);
this.handleStateChange = this.handleStateChange.bind(this);
this.determineButtonVisiblility = this.determineButtonVisiblility.bind(this);
}

componentDidMount() {
document.getElementById('prev').style.visibility = 'hidden';
}

componentDidUpdate(prevProps, prevState) {
const { previous, next } = this.state;
if (prevState.previous !== previous || prevState.next !== next) {
this.determineButtonVisiblility();
}
}

determineButtonVisiblility() {
const { previous, next } = this.state;
if (previous === false) {
document.getElementById('prev').style.visibility = 'hidden';
} else if (previous === true) {
document.getElementById('prev').style.visibility = 'visible';
}

if (next === false) {
document.getElementById('next').style.visibility = 'hidden';
} else if (next === true) {
document.getElementById('next').style.visibility = 'visible';
}
}

handleClick(direction) {
const { reviewGroup, updateReviewGroup } = this.props;
const newReviewGroup = reviewGroup + direction;
const newReviewGroupIsWithinBounds = newReviewGroup <= 7 && newReviewGroup >= 0;
if (newReviewGroupIsWithinBounds) {
updateReviewGroup(newReviewGroup);
this.handleStateChange(newReviewGroup);
const topOfReviewDiv = document.getElementById('reviewsComponent-reviews').offsetTop - 10;
window.scrollTo({
top: topOfReviewDiv,
behavior: 'smooth',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so smooth

});
}
}

handleStateChange(newReviewGroup) {
const { previous, next } = this.state;
if ((newReviewGroup > 0 && newReviewGroup < 7) && (previous === false || next === false)) {
this.setState({
previous: true,
next: true,
});
} else if (newReviewGroup === 0 && previous === true) {
this.setState({
previous: false,
});
} else if (newReviewGroup === 7 && next === true) {
this.setState({
next: false,
});
}
}

render() {
const previousButton = <button id='prev' onClick={()=>this.handleClick(-1)}>Prev</button>
const nextButton = <button id='next' onClick={()=>this.handleClick(1)}>Next</button>
const currentGroup = this.props.reviewGroup + 1;
return (
<div id="reviewsComponent-pagination">
{previousButton}
{currentGroup}
{nextButton}
</div>
);
}
}

export default Pagination;
11 changes: 11 additions & 0 deletions client/components/RatingBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

const RatingBar = (props) => {
return (
<div className="reviewsComponent-rating-bar">
<div className="reviewsComponent-rating-barValue" style={{width: `${20 * props.rating}%`}}></div>
</div>
);
};

export default RatingBar;
17 changes: 17 additions & 0 deletions client/components/RatingsList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import RatingsListItem from './RatingsListItem';

const RatingsList = (props) => {
const { rating } = props;
return (
<div id="reviewsComponent-ratings">
{Object.keys(rating).map((ratingType, index) => {
if (ratingType !== 'overall') {
return <RatingsListItem key={ratingType + index} ratingType={ratingType} ratingValue={rating[ratingType]} />;
}
})}
</div>
);
};

export default RatingsList;
15 changes: 15 additions & 0 deletions client/components/RatingsListItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import RatingBar from './RatingBar';

const RatingsListItem = (props) => {
const { ratingType, ratingValue } = props;
return (
<div className="reviewsComponent-rating">
<div className="reviewsComponent-rating-type">{ratingType}</div>
<RatingBar rating={ratingValue} />
<div className="reviewsComponent-rating-value">{ratingValue}</div>
</div>
);
};

export default RatingsListItem;
15 changes: 15 additions & 0 deletions client/components/ReviewsList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import ReviewsListItem from './ReviewsListItem';

const ReviewsList = (props) => {
const { reviews } = props;
return (
<div id='reviewsComponent-reviews'>
{reviews.map((review, index) => (
<ReviewsListItem key={review.author + index} review={review} />
))}
</div>
);
};

export default ReviewsList;
23 changes: 23 additions & 0 deletions client/components/ReviewsListItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import convertDate from './util.js';

const ReviewsListItem = (props) => {
const { review } = props;
const convertedDate = convertDate(review.createdAt);
return (
<div className="reviewsComponent-review">
<div className="reviewsComponent-review-avatar">
<img src={review.authorsAvatar}></img>
</div>
<div className="reviewsComponent-review-info">
<p>{review.author}</p>
<p>{convertedDate}</p>
</div>
<div className="reviewsComponent-review-text">
{review.text}
</div>
</div>
);
};

export default ReviewsListItem;
8 changes: 8 additions & 0 deletions client/components/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const convertDate = (date) => {
const givenMonth = Number(date.slice(5, 7));
const months = ['Januray', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const convertedDate = `${months[givenMonth - 1]} ${date.slice(0, 4)}`;
return convertedDate;
};

export default convertDate;
2 changes: 1 addition & 1 deletion client/index.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.jsx';
import App from './components/App';

ReactDOM.render(<App />, document.getElementById('app'));
89 changes: 89 additions & 0 deletions coverage/clover.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1584566497824" clover="3.2.0">
<project timestamp="1584566497824" name="All files">
<metrics statements="53" coveredstatements="40" conditionals="0" coveredconditionals="0" methods="14" coveredmethods="6" elements="67" coveredelements="46" complexity="0" loc="53" ncloc="53" packages="2" files="8" classes="8"/>
<package name="client.components">
<metrics statements="23" coveredstatements="10" conditionals="0" coveredconditionals="0" methods="11" coveredmethods="3"/>
<file name="App.jsx" path="/Users/alexmitchell/Desktop/reviews-service/client/components/App.jsx">
<metrics statements="6" coveredstatements="5" conditionals="0" coveredconditionals="0" methods="4" coveredmethods="3"/>
<line num="10" count="1" type="stmt"/>
<line num="11" count="1" type="stmt"/>
<line num="18" count="1" type="stmt"/>
<line num="19" count="0" type="stmt"/>
<line num="24" count="1" type="stmt"/>
<line num="25" count="1" type="stmt"/>
</file>
<file name="Header.jsx" path="/Users/alexmitchell/Desktop/reviews-service/client/components/Header.jsx">
<metrics statements="3" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="3" count="1" type="stmt"/>
<line num="4" count="0" type="stmt"/>
<line num="6" count="0" type="stmt"/>
</file>
<file name="RatingsList.jsx" path="/Users/alexmitchell/Desktop/reviews-service/client/components/RatingsList.jsx">
<metrics statements="4" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="4" count="1" type="stmt"/>
<line num="5" count="0" type="stmt"/>
<line num="6" count="0" type="stmt"/>
<line num="9" count="0" type="stmt"/>
</file>
<file name="RatingsListItem.jsx" path="/Users/alexmitchell/Desktop/reviews-service/client/components/RatingsListItem.jsx">
<metrics statements="3" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="3" count="1" type="stmt"/>
<line num="4" count="0" type="stmt"/>
<line num="5" count="0" type="stmt"/>
</file>
<file name="ReviewsList.jsx" path="/Users/alexmitchell/Desktop/reviews-service/client/components/ReviewsList.jsx">
<metrics statements="4" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="2" coveredmethods="0"/>
<line num="4" count="1" type="stmt"/>
<line num="5" count="0" type="stmt"/>
<line num="6" count="0" type="stmt"/>
<line num="9" count="0" type="stmt"/>
</file>
<file name="ReviewsListItem.jsx" path="/Users/alexmitchell/Desktop/reviews-service/client/components/ReviewsListItem.jsx">
<metrics statements="3" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="1" coveredmethods="0"/>
<line num="3" count="1" type="stmt"/>
<line num="4" count="0" type="stmt"/>
<line num="5" count="0" type="stmt"/>
</file>
</package>
<package name="database">
<metrics statements="30" coveredstatements="30" conditionals="0" coveredconditionals="0" methods="3" coveredmethods="3"/>
<file name="RoomAndReview.js" path="/Users/alexmitchell/Desktop/reviews-service/database/RoomAndReview.js">
<metrics statements="6" coveredstatements="6" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/>
<line num="1" count="1" type="stmt"/>
<line num="3" count="1" type="stmt"/>
<line num="16" count="1" type="stmt"/>
<line num="24" count="1" type="stmt"/>
<line num="25" count="1" type="stmt"/>
<line num="27" count="1" type="stmt"/>
</file>
<file name="util.js" path="/Users/alexmitchell/Desktop/reviews-service/database/util.js">
<metrics statements="24" coveredstatements="24" conditionals="0" coveredconditionals="0" methods="3" coveredmethods="3"/>
<line num="1" count="1" type="stmt"/>
<line num="3" count="1" type="stmt"/>
<line num="4" count="1" type="stmt"/>
<line num="5" count="1" type="stmt"/>
<line num="6" count="5000" type="stmt"/>
<line num="13" count="5000" type="stmt"/>
<line num="15" count="1" type="stmt"/>
<line num="18" count="1" type="stmt"/>
<line num="19" count="101" type="stmt"/>
<line num="26" count="101" type="stmt"/>
<line num="27" count="101" type="stmt"/>
<line num="28" count="101" type="stmt"/>
<line num="29" count="101" type="stmt"/>
<line num="30" count="505" type="stmt"/>
<line num="31" count="505" type="stmt"/>
<line num="33" count="101" type="stmt"/>
<line num="34" count="101" type="stmt"/>
<line num="37" count="1" type="stmt"/>
<line num="38" count="1" type="stmt"/>
<line num="39" count="1" type="stmt"/>
<line num="40" count="100" type="stmt"/>
<line num="44" count="100" type="stmt"/>
<line num="46" count="1" type="stmt"/>
<line num="49" count="1" type="stmt"/>
</file>
</package>
</project>
</coverage>
Loading