Adding rating stars to chat - createIT
Get a free advice now!

    Pick the topic
    Developer OutsourcingWeb developingApp developingDigital MarketingeCommerce systemseEntertainment systems

    Thank you for your message. It has been sent.
    Tags

    Adding rating stars to chat

    Adding rating stars to chat

    CHALLENGE: allow chat members to rate chat by clicking stars

    SOLUTION: prepare a custom message type with custom rendering

    Building your own chat using SendBird? Do you want to get user rating at the end of a chat conversation? This tutorial will show you how.

    Typically, a Chat is a conversation between 2 users: the Client and the Agent or the Client and the Bot. It will be nice to allow the Client to rate the quality of the chat experience. We’re going to render clickable stars, which can be clicked only once. By clicking, the user will send a rate value as a response.

    ChannelList with default channel

    By default, channels are rendered from newest to oldest (based on channel creation time). We will use the sortChannelList parameter and place our DEFAULT_CHANNEL_URL as the first item on the list. It will also be autoloaded on page refresh ( setCurrentChannelUrl() ).

    Keep messages styling

    To keep messages styling included in React UIKit, we’re going to use renderCustomMessage prop that allows to change the render of only one customType, keeping other messages without change. Alternatively, we can overwrite renderChatItem, but the result will be the loss of all messages styling, removing reaction emoticons, typing indicator and the “message received” icon.

    Message HOC (High Order Component) expects a string as a returned value, so instead of using Component, renderStars will be a javascript function.

    Chat windows with star ratings

    Chat settings

    Make sure to change settings to your own values. You can also control the amount of displayed star icons.

    const APP_ID = "AAA";
    const USER_ID = "BBB";
    const DEFAULT_CHANNEL_URL = "CCC";
    const TOTAL_STARS = 10;

    RatingStars Message

    SendBirdProvider is a wrapper component for our customizations. Final changes include: changing the order of channel list and changing the rendering of one message type. The function is expecting: message.customType to be defined as “type2”. For this condition, starts will be rendered.

    // App.jsx
    import React, {useState, useCallback} from 'react';
    import {
      SendBirdProvider,
      Channel,
      ChannelSettings,
      ChannelList
    } from 'sendbird-uikit';
    import "sendbird-uikit/dist/index.css";
    import './App.css';
    import {renderStars} from "./renderStars";
    const APP_ID = "AAA";
    const USER_ID = "BBB";
    const DEFAULT_CHANNEL_URL = "CCC";
    const TOTAL_STARS = 10;
    export default function App() {
      const channelSort = useCallback((channels) => { // useCallback to memoize the fn
        if (channels.length === 0 ) {
          return channels;
        }
        const channel = channels.find(c => c.url === DEFAULT_CHANNEL_URL);
        if (!channel) {
          return channels;
        }
        const otherChannels = channels.filter(c => c.url !== channel.url);
        otherChannels.sort(function(a, b){
          if(a.name < b.name) { return -1; }
          if(a.name > b.name) { return 1; }
          return 0;
        });
        return [channel, ...otherChannels];
      }, []);
      const [currentChannelUrl, setCurrentChannelUrl] = useState("");
      return (
          <div className="App">
            <SendBirdProvider appId={APP_ID} userId={USER_ID} >
              <div style={{ display: 'flex', height: '100%' }}>
                <Channel
                    channelUrl={currentChannelUrl}
                    renderCustomMessage={(message, channel) => {
                      if (message.customType === 'type2') {
                        return (
                            renderStars(currentChannelUrl, TOTAL_STARS)
                        )
                      }
                    }}
                />
                <ChannelSettings channelUrl={currentChannelUrl} />
                <ChannelList
                    sortChannelList={channelSort}
                    onChannelSelect={(channel) => {
                      if (channel && channel.url) {
                        setCurrentChannelUrl(channel.url);
                      }
                    }}
                />
              </div>
            </SendBirdProvider>
          </div>
      );
    }

    Basic styling and disabling ability to rate the second time.

    .App {
      font-family: sans-serif;
      text-align: center;
      height: calc(100vh - 100px);
    }
    .sendbird-conversation {
      max-width:50%;
    }
    .starsRating {
      display:block;
      margin:2px 0;
    }
    .star {
      display:inline-block;
      font-size:2rem;
      color: #ff9933;
      cursor: pointer;
    }
    .starsRating.disabled {
      pointer-events:none;
      opacity: 0.5;
    }

    The component for sending a message (when a Star is clicked):

    // SendMessage.jsx
    import React, { useEffect } from "react";
    import {
        withSendBird,
        sendBirdSelectors,
    } from "sendbird-uikit";
    const CustomComponent = (props) => {
        const {
            msg,
            customType,
            channelUrl,
            extraData,
            sendMessage,
            updateLastMessage,
            sdk,
        } = props;
        const sendSelectTypeMessage = (msg, customType, channelUrl, extraData = null) => {
            const params = new sdk.UserMessageParams();
            if(!msg){
                return;
            }
            if(customType){
                params.customType = customType;
            }
            params.message = msg;
            if(extraData){
                params.data = extraData;
            }
            sendMessage(channelUrl, params)
                .then(message => {
                })
                .catch(e => {
                    console.warn(e);
                });
        }
        useEffect(() => {
            sendSelectTypeMessage(msg, customType, channelUrl, extraData);
        });
        return(
            <></>
        );
    };
    const SendMessageWithSendBird = withSendBird(CustomComponent, (state) => {
        const sendMessage = sendBirdSelectors.getSendUserMessage(state);
        const updateLastMessage = sendBirdSelectors.getUpdateUserMessage(state);
        const sdk = sendBirdSelectors.getSdk(state);
        return ({
            sendMessage,
            updateLastMessage,
            sdk
        });
    });
    export default SendMessageWithSendBird;

    And the most interesting part of the code – the main function for rendering stars, handling hover event and triggering sending a message.

    // renderStars.jsx
    import React, {useState, useEffect} from 'react';
    import SendMessageWithSendBird from "./SendMessage";
    /**
     * Stars rating
     */
    const Star = ({ marked, starId }) => {
        return (
            <span data-star-id={starId} className="star" role="button">
                  {marked ? '\u2605' : '\u2606'}
                </span>
        );
    };
    const StarRating = (props) => {
        const {channelUrl, total} = props;
        const [rating, setRating] = useState( 0);
        const [selection, setSelection] = useState(0);
        const [msgToSent, setMsgToSent] = useState({msg: "",msgType: "", currentRating:""});
        useEffect(() => {
            if(msgToSent.currentRating){
                setRating(msgToSent.currentRating);
            }
            // eslint-disable-next-line
        }, [msgToSent]);
        const hoverOver = event => {
            if(rating) {
              // do nothing
            } else {
                let val = 0;
                if (event && event.target && event.target.getAttribute('data-star-id')){
                    val = event.target.getAttribute('data-star-id');
                }
                setSelection(val);
            }
        };
        const component = !rating && msgToSent.msg ? (<SendMessageWithSendBird msg={msgToSent.msg} customType={msgToSent.msgType}  channelUrl={channelUrl} />) : (<></>);
        const classNameDisabled = rating ? "disabled" : "";
        return (
            <span
                onMouseOut={() => hoverOver(null)}
                onClick={e => {
                    if(rating) {
                        return false;
                    }
                    const currentRating = e.target.getAttribute('data-star-id') || rating;
                    setMsgToSent({msg: currentRating, msgType: "answer", currentRating: currentRating});
                }}
                onMouseOver={hoverOver}
                className={"starsRating " + classNameDisabled }
            >
                    {Array.from({ length: total }, (v, i) => (
                        <Star
                            starId={i + 1}
                            key={`star_${i + 1}`}
                            marked={selection ? selection >= i + 1 : rating >= i + 1}
                        />
                    ))}
                {component}
                </span>
        );
    };
    export const renderStars = (channelUrl, total) => {
        return () => (
            <StarRating channelUrl={channelUrl} total={total} />
        );
    }

    Conclusion

    Chat now has the ability to render a custom view for message customType. The stars functionality does not use any dependencies, you can easily change the color using CSS. The inspiration for this article was a snippet found here: https://www.30secondsofcode.org/react/s/star-rating

    Animation of chat window with star rating

    That’s it for today’s tutorial. Make sure to follow us for other useful guidelines and don’t forget to sign up for our newsletter.

    Comments
    0 response

    Add comment

    Your email address will not be published. Required fields are marked *

    Popular news

    Automating stock and price updates in WooCommerce
    • Dev Tips and Tricks

    Automating stock and price updates in WooCommerce

    September 23, 2024 by createIT
    Integrating advanced subscription features in WooCommerce
    • Dev Tips and Tricks

    Integrating advanced subscription features in WooCommerce

    September 16, 2024 by createIT
    Fetching Time records from ActiveCollab API
    • Dev Tips and Tricks

    Fetching Time records from ActiveCollab API

    September 9, 2024 by createIT
    Docker Compose for PrestaShop
    • Dev Tips and Tricks

    Docker Compose for PrestaShop

    September 2, 2024 by createIT
    WordPress wizard in admin – step by step
    • Dev Tips and Tricks

    WordPress wizard in admin – step by step

    August 29, 2024 by createIT
    Order Status Sync between PrestaShop and External APIs
    • Dev Tips and Tricks

    Order Status Sync between PrestaShop and External APIs

    August 26, 2024 by createIT
    What is PHP used for in web development 
    • Dev Tips and Tricks

    What is PHP used for in web development 

    August 22, 2024 by createIT
    Automating WooCommerce product availability date
    • Dev Tips and Tricks

    Automating WooCommerce product availability date

    August 15, 2024 by createIT
    WP Quiz Adventure – FAQ
    • Dev Tips and Tricks

    WP Quiz Adventure – FAQ

    August 12, 2024 by createIT

    Support – Tips and Tricks
    All tips in one place, and the database keeps growing. Stay up to date and optimize your work!

    Contact us