Skip to content

Commit

Permalink
Fix(#266): displayed reaction tyoes with their counts
Browse files Browse the repository at this point in the history
  • Loading branch information
Philimuhire committed Nov 28, 2024
1 parent 728e1e3 commit c0fbf24
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 102 deletions.
27 changes: 23 additions & 4 deletions src/pages/Blogs/BlogReactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ const BlogReaction: React.FC<BlogReactionProps> = ({ blogId }) => {
const typedReactions: Reaction = reactions;

useEffect(() => {
const storedReaction = localStorage.getItem(`reaction_${blogId}`);
if (storedReaction) {
setCurrentReaction(storedReaction);
}

if (blogId) {
dispatch(getReactionsByBlogId(blogId));
}
Expand All @@ -44,13 +49,18 @@ const BlogReaction: React.FC<BlogReactionProps> = ({ blogId }) => {
if (type === currentReaction) {
await dispatch(removeReactionAction(blogId));
setCurrentReaction(null);
localStorage.removeItem(`reaction_${blogId}`);
} else {
if (currentReaction) {
await dispatch(removeReactionAction(blogId));
localStorage.removeItem(`reaction_${blogId}`);
}

await dispatch(addReactionAction(blogId, type));
setCurrentReaction(type);
localStorage.setItem(`reaction_${blogId}`, type);
}

dispatch(getReactionsByBlogId(blogId));
setShowReactionsMenu(false);
};
Expand All @@ -59,9 +69,6 @@ const BlogReaction: React.FC<BlogReactionProps> = ({ blogId }) => {
? Object.values(typedReactions).reduce((total, count) => total + count, 0)
: 0;

useEffect(() => {
}, [typedReactions, totalReactions]);

return (
<div className="relative">
<button
Expand Down Expand Up @@ -98,8 +105,20 @@ const BlogReaction: React.FC<BlogReactionProps> = ({ blogId }) => {
<div className="text-sm text-gray-400 mb-4">
{`${totalReactions} reactions`}
</div>

<div className="mb-4 flex items-center gap-2">
{reactionTypes.map(({ type, emoji }) => {
const count = typedReactions[type] || 0;
return (
<div key={type} className="flex items-center gap-1 text-gray-600">
<span className="text-xl">{emoji}</span>
<span>{count}</span>
</div>
);
})}
</div>
</div>
);
};

export default BlogReaction;
export default BlogReaction;
33 changes: 25 additions & 8 deletions src/redux/actions/reactionActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,27 @@ export const getReactionsByBlogId = (blogId: string) => async (dispatch: any) =>
const response = await axios.post("/", {
query: `
query GetReactionsByBlog($blog: ID!) {
getAllReactionsCount(blog: $blog)
getReactionsByBlog(blog: $blog) {
id
type
}
}
`,
variables: { blog: blogId },
});

const reactionsData = response?.data?.data?.getAllReactionsCount;
dispatch(creator(fetchReactions.FETCH_REACTIONS_SUCCESS, reactionsData));
} catch (err: any) {}
const reactions = response?.data?.data?.getReactionsByBlog;
const reactionCounts = reactions.reduce((acc: any, reaction: any) => {
acc[reaction.type] = (acc[reaction.type] || 0) + 1;
return acc;
}, {});

dispatch(creator(fetchReactions.FETCH_REACTIONS_SUCCESS, reactionCounts));
} catch (err: any) {
dispatch(creator(fetchReactions.FETCH_REACTIONS_FAILURE, err.message));
toast.error("Failed to fetch reactions.");
}
};


export const addReactionAction = (blogId: string, type: string) => async (dispatch: any) => {
const userId = localStorage.getItem("userId");
Expand Down Expand Up @@ -64,7 +74,10 @@ export const addReactionAction = (blogId: string, type: string) => async (dispat
const reaction = response?.data?.data?.addReaction;
dispatch(creator(addReaction.ADD_REACTION_SUCCESS, reaction));
toast.success("Reaction added successfully!");
} catch (err: any) {}
} catch (err: any) {
dispatch(creator(addReaction.ADD_REACTION_FAIL, err.message));
toast.error("Failed to add reaction.");
}
};

export const removeReactionAction = (blogId: string) => async (dispatch: any) => {
Expand All @@ -90,5 +103,9 @@ export const removeReactionAction = (blogId: string) => async (dispatch: any) =>
});

dispatch(creator(removeReaction.REMOVE_REACTION_SUCCESS, { userId, blogId }));
} catch (err: any) {}
};
toast.success("Reaction removed successfully!");
} catch (err: any) {
dispatch(creator(removeReaction.REMOVE_REACTION_FAIL, err.message));
toast.error("Failed to remove reaction.");
}
};
2 changes: 1 addition & 1 deletion src/redux/actiontypes/reactionTypes.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export enum fetchReactions {
FETCH_REACTIONS_LOADING = "FETCH_REACTIONS_LOADING",
FETCH_REACTIONS_SUCCESS = "FETCH_REACTIONS_SUCCESS",
FETCH_REACTIONS_FAIL = "FETCH_REACTIONS_FAIL",
FETCH_REACTIONS_FAILURE = "FETCH_REACTIONS_FAILURE",
}

export enum addReaction {
Expand Down
11 changes: 10 additions & 1 deletion src/redux/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,13 @@ export const FETCH_REPLIES_SUCCESS = "FETCH_REPLIES_SUCCESS";
export const FETCH_REPLIES_FAIL = "FETCH_REPLIES_FAIL";
export const ADD_REPLY_LOADING = "ADD_REPLY_LOADING";
export const ADD_REPLY_SUCCESS = "ADD_REPLY_SUCCESS";
export const ADD_REPLY_FAIL = "ADD_REPLY_FAIL";
export const ADD_REPLY_FAIL = "ADD_REPLY_FAIL";
export const FETCH_REACTIONS_LOADING = "FETCH_REACTIONS_LOADING";
export const FETCH_REACTIONS_SUCCESS = "FETCH_REACTIONS_SUCCESS";
export const FETCH_REACTIONS_FAILURE = "FETCH_REACTIONS_FAILURE";
export const ADD_REACTION_LOADING = "ADD_REACTION_LOADING";
export const ADD_REACTION_SUCCESS = "ADD_REACTION_SUCCESS";
export const ADD_REACTION_FAILURE = "ADD_REACTION_FAILURE";
export const REMOVE_REACTION_LOADING = "REMOVE_REACTION_LOADING";
export const REMOVE_REACTION_SUCCESS = "REMOVE_REACTION_SUCCESS";
export const REMOVE_REACTION_FAILURE = "REMOVE_REACTION_FAILURE";
179 changes: 91 additions & 88 deletions src/redux/reducers/reactionReducers.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,97 @@
import {
fetchReactions,
addReaction,
removeReaction,
} from "../actiontypes/reactionTypes";


interface ReactionState {
isReactionLoading: boolean;
reactions: Record<string, number>;
errors: null | string;
}

const initialState: ReactionState = {
isReactionLoading: false,
reactions: {},
errors: null,
};

export default (
state = initialState,
{ type, payload }: { type: string; payload: any }
): ReactionState => {
switch (type) {
case fetchReactions.FETCH_REACTIONS_LOADING:
case addReaction.ADD_REACTION_LOADING:
case removeReaction.REMOVE_REACTION_LOADING:
return {
...state,
isReactionLoading: true,
};

case fetchReactions.FETCH_REACTIONS_SUCCESS:

const transformedReactions =
typeof payload === "number"
? { TOTAL: payload }
: Array.isArray(payload)
? payload.reduce((acc: Record<string, number>, reaction: { type: string }) => {
if (reaction.type) {
acc[reaction.type] = (acc[reaction.type] || 0) + 1;
}
return acc;
}, {})
: {};

fetchReactions,
addReaction,
removeReaction,
} from "../actiontypes/reactionTypes";

interface ReactionState {
isReactionLoading: boolean;
reactions: Record<string, number>;
errors: null | string;
}

const initialState: ReactionState = {
isReactionLoading: false,
reactions: {},
errors: null,
};

export default (
state = initialState,
{ type, payload }: { type: string; payload: any }
): ReactionState => {
switch (type) {
case fetchReactions.FETCH_REACTIONS_LOADING:
return {
...state,
isReactionLoading: true,
errors: null,
};

case fetchReactions.FETCH_REACTIONS_SUCCESS:
return {
...state,
isReactionLoading: false,
reactions: payload,
errors: null,
};

case fetchReactions.FETCH_REACTIONS_FAILURE:
return {
...state,
isReactionLoading: false,
errors: payload,
};

case addReaction.ADD_REACTION_LOADING:
case removeReaction.REMOVE_REACTION_LOADING:
return {
...state,
isReactionLoading: true,
errors: null,
};

case addReaction.ADD_REACTION_SUCCESS: {
const updatedReactions = { ...state.reactions };
const { type } = payload;

if (type) {
updatedReactions[type] = (updatedReactions[type] || 0) + 1;
}

return {
...state,
isReactionLoading: false,
reactions: transformedReactions,
reactions: updatedReactions,
errors: null,
};

case addReaction.ADD_REACTION_SUCCESS:
const updatedReactions = (payload || []).reduce(
(acc: Record<string, number>, reaction: { type: string; count: number }) => {
acc[reaction.type] = reaction.count;
return acc;
},
{}
);
return {
...state,
isReactionLoading: false,
reactions: updatedReactions,
};

case removeReaction.REMOVE_REACTION_SUCCESS:
const reactionsAfterRemoval = (payload || []).reduce(
(acc: Record<string, number>, reaction: { type: string; count: number }) => {
acc[reaction.type] = reaction.count;
return acc;
},
{}
);
return {
...state,
isReactionLoading: false,
reactions: reactionsAfterRemoval,
};

case fetchReactions.FETCH_REACTIONS_FAIL:
case addReaction.ADD_REACTION_FAIL:
case removeReaction.REMOVE_REACTION_FAIL:
return {
...state,
isReactionLoading: false,
errors: payload,
};

default:
return state;
}

case removeReaction.REMOVE_REACTION_SUCCESS: {
const updatedReactions = { ...state.reactions };
const { type } = payload;

if (type && updatedReactions[type] > 0) {
updatedReactions[type] -= 1;
}
};


return {
...state,
isReactionLoading: false,
reactions: updatedReactions,
errors: null,
};
}

case addReaction.ADD_REACTION_FAIL:
case removeReaction.REMOVE_REACTION_FAIL:
return {
...state,
isReactionLoading: false,
errors: payload,
};

default:
return state;
}
};

0 comments on commit c0fbf24

Please sign in to comment.