Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review #80

Open
wants to merge 431 commits into
base: architecture
Choose a base branch
from
Open

Review #80

wants to merge 431 commits into from

Conversation

zsli16
Copy link
Contributor

@zsli16 zsli16 commented Apr 4, 2019

PR for Arol's review - Do not merge

nataliaero and others added 30 commits March 25, 2019 17:19
Feature: offers automatically update, with closing edits to modal on react spring and offer expiration drop down
Copy link

@arol arol left a comment

Choose a reason for hiding this comment

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

All components are in the components folder. Maybe you can start splitting the folder, creating a containers one that contains all components connected to the store. This makes the new developer's landing a bit easier.

Also, I think the components in this project have too much logic in them. You can offload them a little bit by using some models (question) or services (apiClient).

Good job! 🚀

case 'UPDATE_QUESTIONS': // updates questions after fetching from database
return action.questions;
case 'UPDATE_QUESTION_STATUS': // updates the question answered status in the array of questions, should be combined eventually with question as a single source of truth
let questions = [...state]
Copy link

Choose a reason for hiding this comment

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

case 'UPDATE_QUESTION_STATUS': // updates the question answered status in the array of questions, should be combined eventually with question as a single source of truth
      return state.map(question => {
        if (question.question_id === action.question.question_id) {
          return {
            ...question,
            answered: true
          };
        } else {
          return question;
        }
      });

Copy link

Choose a reason for hiding this comment

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

Do you don't mutate the previous state.

</>
)

const Platform = () => (
Copy link

Choose a reason for hiding this comment

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

const Platform = ({ match }) => (
  <>
    <Navbar socket={socket} landingPage={match.path === "/"} />
    <Route exact path="/" component={LandingPage} />
    <Route path="/ask" component={AskQuestions} />
    <PrivateRoute
      path="/question-posted/:questionid"
      component={QuestionPosted}
    />
    <PrivateRoute path="/answer" component={AnswerPage} />
    <PrivateRoute path="/my-questions" component={MyQuestions} />
  </>
);

Copy link

Choose a reason for hiding this comment

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

So you can avoid EntryPage.

}

renderQuestions = () => {
//User is not logged in
Copy link

Choose a reason for hiding this comment

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

This function needs a refactor.

Maybe I'm missing something, but after some detailed reading, all this questions processing seems like you're just filtering out any question which status is not included into ['help-now', 'pending', 'closed'] and the learner is online. Which is:

this.state.questions.filter(question => 
  !['help-now', 'pending', 'closed'].includes(question.status)
  || !this.state.offlineUsers.find(user => user.user_id === question.learner)
)

Copy link

Choose a reason for hiding this comment

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

Anyways, all this processing in the render makes it difficult to read, try some abstractions. For example:

const questionsHelpNow = this.state.questions.filter((question) => question.isHelpNow() && question.learnerIsOffline());
      

is more readable than:

const questionsHelpNow = this.state.questions.filter((question) => question.status==='help-now' && this.state.offlineUsers.filter(user => user.user_id===question.learner).length===0);

}
}

msToTime() {
Copy link

Choose a reason for hiding this comment

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

Generic, it doesn't belong here. Create a Time class as a helper in lib folder in the root.


componentDidMount() {
this.props.socket.on('chat message', (msg) => {
let currentId = this.props.socket.id;
Copy link

Choose a reason for hiding this comment

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

No further assignment, use const. This applies for the rest as well.

}

scrollToBottom = () => {
const messages = document.getElementById('messages');
Copy link

Choose a reason for hiding this comment

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

Imperative again, I think this can be a good use case to use React Refs.

overTime: 'black'
}

startTimer = () => {
Copy link

Choose a reason for hiding this comment

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

Not used.


{this.state.tutorJoined ? null : this.renderOverlay()}

<div className="chat-header">
Copy link

Choose a reason for hiding this comment

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

As this component is quite large, I recommend you not rendering any specific parts, but to delegate in other presentational components. You did it correctly with the rest of sections in this render function but not with this header.

question: state.question,
questions: state.questions,
offers: state.offers,
tutors: state.tutors,
Copy link

Choose a reason for hiding this comment

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

users, questions and tutors aren't used.

fetch(`${process.env.REACT_APP_SERVER_URL}/questions/${props.questionId}/feedback`, {
method: 'PUT',
headers : {
'Authorization' : 'Bearer ' + token,
Copy link

Choose a reason for hiding this comment

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

DRY, you're constructing the headers every time you need to make a fetch. Even if you are not using a middleware, you still can centralize the fetch logic into a JS module, that will works as a single instance. Take advantage of it to set the headers once you log in.

The result should look like:

apiClient.sendFeedback(karma, credits)
  .then(question => props.closeQuestion(question))
  

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants