• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atlp-rwanda / trojans-ec-fe / 0cb862e4-0fa2-47c7-95e9-d93125127b5b

pending completion
0cb862e4-0fa2-47c7-95e9-d93125127b5b

push

circleci

GitHub
feature(navbar/sidebar):Dashboard sidebar/navbar and main navbar [Finishes #185032608] (#33)

452 of 602 branches covered (75.08%)

Branch coverage included in aggregate %.

309 of 309 new or added lines in 56 files covered. (100.0%)

1056 of 1253 relevant lines covered (84.28%)

23.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.95
/src/components/chatModel.js
1
/* eslint-disable react/jsx-key */
2
/* eslint-disable no-unused-vars */
3
import React from "react";
4

5
import { useEffect, useState, useRef } from "react";
6
import { useDispatch, useSelector } from "react-redux";
7
import { socket } from "../config/socket";
8
import chatIcon from "../assets/images/chat.svg";
9
import { ToastContainer, toast } from "react-toastify";
10
import {
11
  setLoading,
12
  setData,
13
  setSingle,
14
  setHasNewMessages,
15
} from "../redux/features/slices/chat";
16
import ChatMessage from "./chatMessage";
17

18
const chatModel = () => {
8✔
19
  const dispatch = useDispatch();
20✔
20

21
  const { loading, data, hasNewMessage, error, success } = useSelector(
18✔
22
    (state) => state.chat
24✔
23
  );
24

25
  const [username, setUsername] = useState("");
18✔
26
  const [currentUser, setCurrentUser] = useState("");
18✔
27
  const [showNewMessages, setShowNewMessages] = useState(false);
18✔
28
  const [message, setMessage] = useState("");
18✔
29
  const [showChat, setShowChat] = useState(false);
18✔
30
  const messagesEndRef = useRef(null);
18✔
31
  const [connectedUser, setConnectedUser] = useState("");
18✔
32
  const [showConnectedUser, setShowConnectedUser] = useState(false);
18✔
33

34
  const currentUserLocal = localStorage.getItem("name");
18✔
35

36
  const scrollToBottom = () => {
18✔
37
    messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
×
38
  };
39
  const handleScroll = (event) => {
18✔
40
    const { scrollTop, scrollHeight, clientHeight } = event.target;
×
41
    console.log(scrollTop + clientHeight);
×
42
    console.log(scrollHeight);
×
43

44
    if (
×
45
      scrollTop + clientHeight === scrollHeight - 0.5 ||
×
46
      scrollTop + clientHeight === scrollHeight + 0.5 ||
47
      scrollTop + clientHeight === scrollHeight
48
    ) {
49
      setShowNewMessages(false);
×
50
    } else {
51
      setShowNewMessages(true);
×
52
    }
53
  };
54
  useEffect(() => {
18✔
55
    setCurrentUser(currentUserLocal);
8✔
56
    socket.on("chat-message", (messageData) => {
8✔
57
      dispatch(setHasNewMessages(true));
×
58
      const msg = {
×
59
        User: {
60
          email: "testBuyer@example.com",
61
          name: messageData.name,
62
          profilePic:
63
            "https://res.cloudinary.com/dmjxukx09/image/upload/v1675844692/profiles/Profile-Avatar-PNG-Free-Download_paqfrf.png",
64
          role: "buyer",
65
        },
66
        createdAt: new Date(),
67
        message: messageData.message,
68
      };
69

70
      dispatch(setSingle(msg));
×
71

72
      dispatch(setSingle(msg));
×
73
    });
74

75
    socket.emit("new-user", username);
8✔
76

77
    socket.on("user-connected", (name) => {
8✔
78
      console.log(`${name} connected`, "");
×
79
      setConnectedUser(name);
×
80
      setShowConnectedUser(true);
×
81

82
      setTimeout(() => {
×
83
        setConnectedUser("");
×
84
        setShowConnectedUser(false);
×
85
      }, 4000);
86
    });
87

88
    socket.on("notifications", (message) => {
8✔
89
      console.log(message);
×
90
    });
91
    socket.on("all-messages", (message) => {
8✔
92
      console.log("here");
×
93
      console.log(message);
×
94
      dispatch(setData(message));
×
95
    });
96
    socket.on("connect_error", (err) => {});
8✔
97

98
    socket.on("username", (name) => {
8✔
99
      console.log(username);
×
100
      setUsername(name);
×
101
    });
102
  }, [setData]);
103

104
  const sendMessage = (e) => {
18✔
105
    e.preventDefault();
2✔
106
    const date = formatISODate(new Date());
2✔
107
    if (message != "" && data) {
2!
108
      dispatch(
2✔
109
        setData([
110
          ...data,
111
          {
112
            User: {
113
              email: "testBuyer@example.com",
114
              name: username,
115
              profilePic:
116
                "https://res.cloudinary.com/dmjxukx09/image/upload/v1675844692/profiles/Profile-Avatar-PNG-Free-Download_paqfrf.png",
117
              role: "buyer",
118
            },
119
            createdAt: new Date(),
120
            message: message,
121
          },
122
        ])
123
      );
124

125
      socket.emit("send-chat-message", { username, message, date });
2✔
126
      setMessage("");
2✔
127
    }
128
  };
129

130
  function formatISODate(isoDate) {
131
    const date = new Date(isoDate);
2✔
132
    const options = {
2✔
133
      year: "numeric",
134
      month: "long",
135
      day: "numeric",
136
      hour: "numeric",
137
      minute: "numeric",
138
      hour12: false,
139
    };
140
    return date.toLocaleDateString(undefined, options);
2✔
141
  }
142

143
  const Show = () => {
18✔
144
    setShowChat(!showChat);
×
145
    dispatch(setHasNewMessages(false));
×
146
  };
147

148
  return (
18✔
149
    <>
150
      <ToastContainer />
151

152
      <div
153
        className={
154
          showChat
18!
155
            ? "fixed bottom-28 flex flex-col h-2/3 bg-white md:w-1/3 md:right-4 right-6 w-11/12"
156
            : "hidden"
157
        }
158
      >
159
        <header className="bg-purple-900 rounded-t-lg text-white p-4 px-6 flex justify-between ">
160
          <p className="text-white">Chat</p>
161

162
          <button onClick={() => setShowChat(false)}>x</button>
×
163
        </header>
164
        <div className="flex justify-center z-10">
165
          <p className="bg-gray-400 rounded-full px-2">
166
            {" "}
167
            {showConnectedUser ? connectedUser + " connected" : ""}{" "}
18!
168
          </p>
169
        </div>
170
        <div
171
          className="flex flex-col flex-1 overflow-y-auto px-4 py-6"
172
          onScroll={handleScroll}
173
        >
174
          {data &&
36✔
175
            data.map((message) => (
176
              <ChatMessage
12✔
177
                key={data.indexOf(message)}
178
                message={message}
179
                currentUser={currentUser}
180
                isSelf={message.isSelf}
181
              />
182
            ))}
183

184
          <div ref={messagesEndRef}></div>
185
        </div>
186
        {showNewMessages && (
18!
187
          <div className="flex justify-center bg-white">
188
            <button
189
              className="bottom-4 right-4 bg-gray-500 text-white rounded-full p-4 "
190
              onClick={scrollToBottom}
191
            >
192
              <svg
193
                width="12"
194
                height="8"
195
                viewBox="0 0 12 8"
196
                fill="none"
197
                xmlns="http://www.w3.org/2000/svg"
198
              >
199
                <path
200
                  d="M1.41 0L6 4.58L10.59 0L12 1.41L6 7.41L0 1.41L1.41 0Z"
201
                  fill="white"
202
                />
203
              </svg>
204
            </button>
205
          </div>
206
        )}
207

208
        <div className="bg-white ">
209
          <form className="flex flex-row px-4 py-2" onSubmit={sendMessage}>
210
            <input
211
              type="text"
212
              value={message}
213
              onChange={(e) => setMessage(e.target.value)}
2✔
214
              placeholder="Type a message..."
215
              className="flex-grow rounded-full bg-gray-200 py-2 px-4"
216
            />
217
            <button
218
              type="submit"
219
              data-testid="send message"
220
              className="ml-4 bg-purple-900 hover:bg-purple-800 text-white font-bold py-2 px-4 rounded-full"
221
            >
222
              Send
223
            </button>
224
          </form>
225
        </div>
226
      </div>
227

228
      <button
229
        onClick={() => Show()}
×
230
        title="Chat"
231
        className="fixed z-90 bottom-10 right-8  w-20 h-20 rounded-full drop-shadow-lg flex justify-center items-center text-white text-4xl  hover:animate-pulse duration-300"
232
      >
233
        <div style={{ position: "relative", display: "inline-block" }}>
234
          <img src={chatIcon} alt="Chat icon" />
235

236
          {hasNewMessage && (
18!
237
            <div
238
              style={{
239
                position: "absolute",
240
                top: "-5px",
241
                left: "-5px",
242
                backgroundColor: "red",
243
                width: "10px",
244
                height: "10px",
245
                borderRadius: "50%",
246
              }}
247
            />
248
          )}
249
        </div>
250
      </button>
251
    </>
252
  );
253
};
254

255
export default chatModel;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc