@stackend/api
Version:
JS bindings to api.stackend.com
167 lines (142 loc) • 3.19 kB
text/typescript
import { VoteSummary, Vote } from './index';
import update from 'immutability-helper';
import { Comment } from '../comments';
export const XCAP_VOTES_RECEIVED = 'XCAP_VOTES_RECEIVED';
export const XCAP_VOTES_UPDATE = 'XCAP_VOTES_UPDATE';
type VoteActionBase = {
context: string;
/**
* Has the current user voted?
*/
hasVoted?: boolean;
/**
* My review comment, if any
*/
myReview?: Comment | null;
/**
* Summary of votes
*/
voteSummary: VoteSummary;
};
export type VoteActions =
| (VoteActionBase & {
type: typeof XCAP_VOTES_RECEIVED;
votes: { [referenceGroupId: number]: Vote };
})
| (VoteActionBase & {
type: typeof XCAP_VOTES_UPDATE;
vote: Vote;
});
export interface VoteInfo {
/**
* Summary of votes
*/
voteSummary: VoteSummary;
votes: { [referenceGroupId: number]: Vote };
/**
* Has the current user voted?
* */
hasVoted: boolean;
/**
* My review comment, if any
*/
myReview?: Comment | null;
}
export interface VoteState {
[context: string]: {
[referenceId: string]: VoteInfo;
};
}
/**
* Update the votes
* @param state
* @param context
* @param voteSummary
* @param votes
* @param vote
* @param hasVoted
* @param myReview
*/
function updateVotes({
state,
context,
voteSummary,
votes,
vote,
hasVoted,
myReview
}: {
state: VoteState;
context: string;
voteSummary: VoteSummary;
votes?: { [referenceGroupId: number]: Vote };
vote?: Vote;
hasVoted?: boolean;
myReview?: Comment | null;
}): VoteState {
const x: VoteState = Object.assign({}, state);
if (!x[context]) {
x[context] = {};
}
const refId = voteSummary.referenceId;
if (!x[context][refId]) {
x[context][refId] = {
voteSummary,
votes: {},
hasVoted: false,
myReview: null
};
}
let v = Object.assign({}, x[context][refId]);
v.voteSummary = voteSummary;
if (votes) {
v = update(v, {
votes: { $merge: votes }
});
}
if (vote) {
v.votes[vote.referenceGroupId] = vote;
}
if (typeof hasVoted === 'boolean') {
v.hasVoted = hasVoted;
}
if (myReview) {
if (v.myReview) {
console.log('D=', v.myReview.modifiedDate, myReview.modifiedDate);
}
v.myReview = myReview;
}
(x as any).n = Math.random(); // Hack to make this update
x[context][refId] = v;
return x;
}
const voteReducer = (state: VoteState = {}, action: VoteActions): VoteState => {
let c = state;
switch (action.type) {
case XCAP_VOTES_RECEIVED:
c = updateVotes({
state,
context: action.context,
voteSummary: action.voteSummary,
votes: action.votes,
hasVoted: action.hasVoted,
myReview: action.myReview
});
break;
case XCAP_VOTES_UPDATE:
c = updateVotes({
state,
context: action.context,
voteSummary: action.voteSummary,
vote: action.vote,
hasVoted: action.hasVoted,
myReview: action.myReview
});
//console.log('XCAP_VOTES_UPDATE', state, c, 'same=', state === c);
break;
default:
break;
}
return c;
};
export default voteReducer;