Skip to content

Commit 3a6908a

Browse files
committed
refactor front end
1 parent 95c5365 commit 3a6908a

File tree

15 files changed

+8234
-7843
lines changed

15 files changed

+8234
-7843
lines changed

chatfront/src/App.js

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,84 @@
1-
import {Chat} from './components/chat';
2-
import 'bootstrap/dist/css/bootstrap.min.css';
1+
import { useState } from "react";
2+
import Chat from "./components/chat";
3+
import "./index.css";
4+
import SockJS from "sockjs-client";
5+
import { over } from "stompjs";
6+
import RegisterScreen from "./components/RegisterScreen";
7+
import ChatScreen from "./components/ChatScreen";
8+
9+
let stomClient = null;
10+
311
function App() {
12+
const [connected, setConnected] = useState(false);
13+
const [name, setName] = useState("");
14+
const [publicRoom, setPublicRoom] = useState([]);
15+
const [privateRoom, setPrivateRoom] = useState(new Map());
16+
17+
function register(e) {
18+
e.preventDefault();
19+
const Sock = new SockJS("http://localhost:8080/ws");
20+
stomClient = over(Sock);
21+
stomClient.connect({}, onConnected, (err) =>
22+
alert(`An error has occurred: ${err}`)
23+
);
24+
}
25+
26+
function onConnected() {
27+
setConnected(true);
28+
stomClient.subscribe("/chat/public", onPublic);
29+
stomClient.subscribe("/user/" + name + "/private", onPrivate);
30+
stomClient.send(
31+
"/app/message",
32+
{},
33+
JSON.stringify({ author: name, status: "JOIN" })
34+
);
35+
}
36+
37+
function onPublic(payload) {
38+
console.log(payload);
39+
let payloadData = JSON.parse(payload.body);
40+
if (payload.status === "JOIN") {
41+
if (!privateRoom.get(payloadData.senderName)) {
42+
privateRoom.set(payloadData.senderName, []);
43+
setPrivateRoom(new Map(privateRoom));
44+
}
45+
} else {
46+
publicRoom.push(payloadData);
47+
setPublicRoom([...publicRoom]);
48+
}
49+
}
50+
51+
function onPrivate(payload) {
52+
let payloadData = JSON.parse(payload);
53+
if (privateRoom.get(payloadData.name)) {
54+
let data = [];
55+
data.push(payloadData);
56+
privateRoom.set(payloadData.name, data);
57+
setPrivateRoom(new Map(privateRoom));
58+
}
59+
}
60+
61+
function sendMessage(message) {
62+
if (stomClient) {
63+
var chatMsg = {
64+
author: name,
65+
message: message,
66+
status: "MESSAGE",
67+
};
68+
stomClient.send("/app/message", {}, JSON.stringify(chatMsg));
69+
}
70+
}
71+
72+
if (!connected) {
73+
return <RegisterScreen name={name} setName={setName} register={register} />;
74+
}
75+
476
return (
5-
<div className="App">
6-
<Chat/>
7-
</div>
77+
<ChatScreen
78+
messages={publicRoom.filter((msg) => msg.message !== null)}
79+
sendMessage={sendMessage}
80+
user={name}
81+
/>
882
);
983
}
1084

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import "./styles.css";
2+
3+
export default function Button({ children, ...rest }) {
4+
return <button {...rest}>{children}</button>;
5+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
button {
2+
background-color: #f3fc8a;
3+
border: none;
4+
outline: none;
5+
margin: 0;
6+
7+
font-size: 1.6rem;
8+
9+
padding: 1.2rem;
10+
11+
border-radius: 12px;
12+
13+
cursor: pointer;
14+
15+
font-weight: 600;
16+
17+
transition: 0.3s;
18+
}
19+
20+
button:hover {
21+
background-color: #e2f04c;
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { useMemo } from "react";
2+
import "./styles.css";
3+
4+
export default function ChatBubble({ isYou, messages, user }) {
5+
const initials = useMemo(() =>
6+
user
7+
.split(" ")
8+
.map((token) => token[0])
9+
.join("")
10+
.toUpperCase()
11+
);
12+
return (
13+
<div className={`bubble-container ${isYou ? "left" : ""}`}>
14+
<div className="bubble-messages">
15+
{messages.map((msg) => (
16+
<p>{msg.message}</p>
17+
))}
18+
</div>
19+
<div className="profile-picture">{initials}</div>
20+
</div>
21+
);
22+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
@keyframes appear {
2+
from {
3+
opacity: 0;
4+
transform: translateY(-10px);
5+
}
6+
to {
7+
opacity: 1;
8+
transform: translateY(0);
9+
}
10+
}
11+
12+
.bubble-container {
13+
display: flex;
14+
align-items: flex-start;
15+
16+
width: 100%;
17+
}
18+
19+
.bubble-container.left .profile-picture {
20+
order: 0;
21+
margin-left: 0;
22+
margin-right: 1.5rem;
23+
}
24+
25+
.bubble-container.left .bubble-messages {
26+
order: 1;
27+
}
28+
29+
.profile-picture {
30+
width: 50px;
31+
height: 50px;
32+
33+
margin-left: 1.5rem;
34+
35+
border-radius: 50%;
36+
37+
background-color: #f3fc8a;
38+
color: #16171b;
39+
font-size: 1.6rem;
40+
font-weight: 600;
41+
42+
display: flex;
43+
align-items: center;
44+
justify-content: center;
45+
}
46+
47+
.bubble-messages {
48+
width: calc(100% - 50px - 1rem);
49+
}
50+
51+
.bubble-container.left .bubble-messages > * {
52+
text-align: left;
53+
}
54+
55+
.bubble-messages > * {
56+
text-align: right;
57+
animation: appear 0.3s;
58+
font-size: 1.5rem;
59+
60+
background-color: #16171b;
61+
color: white;
62+
63+
padding: 0.8rem;
64+
}
65+
66+
.bubble-messages > * + * {
67+
margin-top: 0.5rem;
68+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { useState, useMemo } from "react";
2+
import Input from "../Input";
3+
import Button from "../Button";
4+
import ChatBubble from "../ChatBubble";
5+
import "./styles.css";
6+
7+
export default function ChatScreen({ messages, sendMessage, user }) {
8+
const [message, setMessage] = useState("");
9+
10+
function onSubmit(e) {
11+
e.preventDefault();
12+
sendMessage(message);
13+
setMessage("");
14+
}
15+
16+
const groupedMessages = useMemo(
17+
() =>
18+
messages.reduce((acc, current, i) => {
19+
if (i === 0 || acc[acc.length - 1][0]?.author !== current.author) {
20+
acc.push([current]);
21+
} else {
22+
acc[acc.length - 1].push(current);
23+
}
24+
return acc;
25+
}, []),
26+
[messages]
27+
);
28+
29+
return (
30+
<div className="chat-container">
31+
<h1 style={{ marginBottom: "3rem" }}>chatgpD - {user}</h1>
32+
<div className="messages">
33+
{groupedMessages.map((group) => (
34+
<ChatBubble
35+
messages={group}
36+
isYou={group[0]?.author === user}
37+
user={group[0].author}
38+
/>
39+
))}
40+
</div>
41+
42+
<form className="send-form" onSubmit={onSubmit}>
43+
<Input
44+
value={message}
45+
onChange={(e) => setMessage(e.target.value)}
46+
style={{
47+
paddingTop: "2.4rem",
48+
paddingBottom: "2.4rem",
49+
borderRadius: "12px",
50+
fontSize: "1.8rem",
51+
width: "88%",
52+
}}
53+
/>
54+
<Button style={{ width: "10%" }}>Enviar</Button>
55+
</form>
56+
</div>
57+
);
58+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.chat-container {
2+
overflow-y: hidden;
3+
width: 75%;
4+
max-width: 900px;
5+
height: 100vh;
6+
margin: 0 auto;
7+
8+
display: flex;
9+
flex-direction: column;
10+
justify-content: space-between;
11+
12+
padding-top: 4rem;
13+
padding-bottom: 2rem;
14+
}
15+
16+
.messages {
17+
width: 100%;
18+
height: 90%;
19+
}
20+
21+
.messages > * + * {
22+
margin-top: 3rem;
23+
}
24+
25+
.send-form {
26+
width: 100%;
27+
display: flex;
28+
justify-content: space-between;
29+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import "./styles.css";
2+
3+
export default function Input(props) {
4+
return <input {...props} />;
5+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
input {
2+
background-color: #16171b;
3+
outline: none;
4+
5+
border: none;
6+
7+
padding: 1.6rem;
8+
9+
border-radius: 16px;
10+
color: white;
11+
font-size: 1.6rem;
12+
}
13+
14+
input:focus {
15+
border: 1px solid rgba(196, 196, 196, 0.3);
16+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import Input from "../Input";
2+
import Button from "../Button";
3+
4+
export default function RegisterScreen({ name, setName, register }) {
5+
return (
6+
<form
7+
onSubmit={register}
8+
style={{
9+
position: "absolute",
10+
top: "50%",
11+
left: "50%",
12+
transform: "translate(-50%, -50%)",
13+
width: "400px",
14+
display: "flex",
15+
flexDirection: "column",
16+
alignItems: "center",
17+
justifyContent: "center",
18+
}}
19+
>
20+
<h1 style={{ marginBottom: "3rem", fontSize: "3rem" }}>
21+
Por favor, insira seu nome
22+
</h1>
23+
<Input
24+
style={{ width: "100%", marginBottom: "1.5rem" }}
25+
placeholder="Seu nome"
26+
value={name}
27+
onChange={(e) => setName(e.target.value)}
28+
/>
29+
<Button style={{ width: "100%" }}>Confirmar</Button>
30+
</form>
31+
);
32+
}

0 commit comments

Comments
 (0)