feat: 채팅 유저 이름 표시 추가
This commit is contained in:
parent
06ef530edd
commit
7963ece5bb
@ -3,6 +3,7 @@ import styles from './ChatRoom.module.css';
|
||||
import { chatClient } from '../../utils/chat/chatClient';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import SendIcon from '/src/assets/icons/send.svg?react';
|
||||
import useBoundStore from '../../store';
|
||||
|
||||
const USER_ID = crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
|
||||
@ -11,6 +12,7 @@ export default function ChatRoom() {
|
||||
const { lectureId } = useParams();
|
||||
const client = chatClient;
|
||||
const [messages, setMessages] = useState([]);
|
||||
const userName = useBoundStore((state) => state.userName) ?? '익명';
|
||||
const inputRef = useRef(null);
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
@ -24,7 +26,7 @@ export default function ChatRoom() {
|
||||
destination: `/pub/message/${lectureId}`,
|
||||
body: JSON.stringify({
|
||||
userId: USER_ID,
|
||||
name: '홍길동',
|
||||
name: userName,
|
||||
content: text,
|
||||
}),
|
||||
});
|
||||
@ -35,8 +37,8 @@ export default function ChatRoom() {
|
||||
client.onConnect = () => {
|
||||
client.subscribe(`/sub/channel/${lectureId}`, (response) => {
|
||||
const data = JSON.parse(response.body);
|
||||
const message = data.content;
|
||||
setMessages((prev) => [...prev, { id: prev.length, text: message, isMine: USER_ID === data.userId }]);
|
||||
const { content: message, name } = data;
|
||||
setMessages((prev) => [...prev, { id: prev.length, text: message, isMine: USER_ID === data.userId, name }]);
|
||||
});
|
||||
};
|
||||
client.activate();
|
||||
@ -49,13 +51,14 @@ export default function ChatRoom() {
|
||||
return (
|
||||
<section className={styles.room}>
|
||||
<h2 className={styles.title}>채팅</h2>
|
||||
<ol className={styles.bubbles}>
|
||||
<ol className={styles.messageList}>
|
||||
{messages.map((message) => (
|
||||
<li
|
||||
key={message.id}
|
||||
className={message.isMine ? styles.my : styles.your}
|
||||
>
|
||||
{message.text}
|
||||
<span className={styles.name}>{message.name}</span>
|
||||
<span className={styles.bubble}>{message.text}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
|
@ -6,7 +6,6 @@
|
||||
height: 100%;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 16px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@ -21,65 +20,105 @@
|
||||
backdrop-filter: blur(16px); */
|
||||
}
|
||||
|
||||
.bubbles {
|
||||
.messageList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: end;
|
||||
align-items: start;
|
||||
gap: 8px;
|
||||
gap: 12px;
|
||||
list-style: none;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@keyframes show {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.your,
|
||||
.my {
|
||||
display: flex;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--background-secondary);
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
font-weight: 500;
|
||||
white-space: pre-wrap;
|
||||
flex-direction: column;
|
||||
animation: show 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
transform-origin: left bottom;
|
||||
|
||||
& > .bubble {
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
background-color: var(--background-secondary);
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
font-weight: 500;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.my {
|
||||
align-self: end;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--on-primary);
|
||||
align-items: end;
|
||||
transform-origin: right bottom;
|
||||
|
||||
& > .name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& > .bubble {
|
||||
background-color: var(--primary-color);
|
||||
color: var(--on-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
padding: 0 4px;
|
||||
color: var(--text-color-secondary);
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 16px;
|
||||
background-color: var(--background);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow);
|
||||
overflow: hidden;
|
||||
|
||||
& > input[type='text'] {
|
||||
flex-grow: 1;
|
||||
padding: 8px;
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
border-radius: 12px;
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
font-weight: 400;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
& > button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
|
5
frontend/src/store/userNameSlice.js
Normal file
5
frontend/src/store/userNameSlice.js
Normal file
@ -0,0 +1,5 @@
|
||||
export const userNameSlice = (set) => ({
|
||||
userName: null,
|
||||
setUserName: (userName) => set({ userName }),
|
||||
isAnonymous: () => set.userName === null,
|
||||
});
|
Loading…
Reference in New Issue
Block a user