import { models, errors } from '@r/api-client';
import * as platformActions from '@r/platform/actions';

import { apiOptionsFromState } from 'lib/apiOptionsFromState';
import { LOGGEDOUT_REDIRECT } from 'app/constants';


const { ResponseError } = errors;

export const PENDING = 'VOTE__PENDING';
export const SUCCESS = 'VOTE__SUCCESS';
export const FAILURE = 'VOTE__FAILURE';

export const pending = (id, model) => ({ type: PENDING, id, model });
export const success = (id, model) => ({ type: SUCCESS, id, model });
export const failure = direction => {
  const voteWord = direction === 1 ? 'upvote' : 'downvote';
  return {
    type: FAILURE,
    message: `Failed to ${voteWord} the comment.`,
  };
};

export const vote = (id, direction) => async (dispatch, getState) => {
  const state = getState();
  if (!state.session.isValid) {
    dispatch(platformActions.setPage(LOGGEDOUT_REDIRECT));
    return;
  }

  const type = models.ModelTypes.thingType(id);
  const thing = state[`${type}s`][id];

  const stub = thing._vote(apiOptionsFromState(state), direction);
  dispatch(pending(id, stub));

  try {
    const model = await stub.promise();
    dispatch(success(id, model));

  } catch (e) {
    dispatch(failure(direction));
    if (!(e instanceof ResponseError)) {
      throw e;
    }
  }
};

import { models, errors } from '@r/api-client';
import * as platformActions from '@r/platform/actions';

import { apiOptionsFromState } from 'lib/apiOptionsFromState';
import { LOGGEDOUT_REDIRECT } from 'app/constants';


const { ResponseError } = errors;

export const PENDING = 'VOTE__PENDING';
export const SUCCESS = 'VOTE__SUCCESS';
export const FAILURE = 'VOTE__FAILURE';

export const pending = (id, model) => ({ type: PENDING, id, model });
export const success = (id, model) => ({ type: SUCCESS, id, model });
export const failure = (direction, type) => {
  const voteWord = direction === 1 ? 'upvote' : 'downvote';
  return {
    type: FAILURE,
    message: `Failed to ${voteWord} the ${type}.`,
  };
};

export const vote = (id, direction) => async (dispatch, getState) => {
  const state = getState();
  if (!state.session.isValid) {
    dispatch(platformActions.setPage(LOGGEDOUT_REDIRECT));
    return;
  }

  const type = models.ModelTypes.thingType(id);
  const thing = state[`${type}s`][id];

  const stub = thing._vote(apiOptionsFromState(state), direction);
  dispatch(pending(id, stub));

  try {
    const model = await stub.promise();
    dispatch(success(id, model));

  } catch (e) {
    dispatch(failure(direction, type));
    if (!(e instanceof ResponseError)) {
      throw e;
    }
  }
};

Correct types on the error toaster
Correct types on the error toaster

Bug:
This copy was hardcoded to just 'comment' but the action applies to both
comments and posts. When something went wrong on a post upvote we'd show
"failed to upvote the comment", which makes no sense.

Fix:
Use the `type` (which is either 'post' or 'comment') in the copy.
