57 lines
2.7 KiB
TypeScript
57 lines
2.7 KiB
TypeScript
"use client";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { getSocket } from "../lib/socket-client";
|
|
import { useGame } from "../lib/store";
|
|
|
|
export default function ChatBox({ placeholder = "Type your guess..." }: { placeholder?: string }) {
|
|
const chat = useGame((s) => s.chat);
|
|
const myId = useGame((s) => s.myId);
|
|
const room = useGame((s) => s.room);
|
|
const [text, setText] = useState("");
|
|
const scrollRef = useRef<HTMLDivElement | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (scrollRef.current) {
|
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
}
|
|
}, [chat.length]);
|
|
|
|
const send = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
const t = text.trim();
|
|
if (!t) return;
|
|
getSocket().emit("chat:send", { text: t });
|
|
setText("");
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col h-full min-h-[360px]">
|
|
<div ref={scrollRef} data-testid="chat-messages" className="flex-1 overflow-y-auto flex flex-col gap-2 pr-1">
|
|
{chat.map((m) => {
|
|
const me = m.fromId && m.fromId === myId;
|
|
if (m.kind === "system") {
|
|
return <div key={m.id} className="text-center italic text-xs" style={{color:"rgba(45,45,45,0.6)"}}>{m.text}</div>;
|
|
}
|
|
if (m.kind === "correct") {
|
|
return <div key={m.id} className="rounded-xl px-3 py-2 text-sm font-semibold" style={{background:"rgba(78,205,196,0.18)", border:"2px dashed var(--mint)"}}>
|
|
<strong>{m.fromName}</strong> {m.text}
|
|
</div>;
|
|
}
|
|
if (m.kind === "close") {
|
|
return <div key={m.id} className="rounded-xl px-3 py-2 text-sm italic" style={{background:"rgba(255,210,63,0.3)"}}>{m.text}</div>;
|
|
}
|
|
return <div key={m.id} className="rounded-xl px-3 py-2 text-sm" style={{background:"var(--cream)"}}>
|
|
<span className="font-bold mr-1.5" style={{color: me ? "var(--mint)" : "var(--coral)"}}>{m.fromName}:</span>{m.text}
|
|
</div>;
|
|
})}
|
|
</div>
|
|
<form className="flex gap-2 pt-2.5 mt-2.5" style={{borderTop:"2px dashed rgba(45,45,45,0.15)"}} onSubmit={send}>
|
|
<input data-testid="chat-input" value={text} onChange={(e)=>setText(e.target.value)} maxLength={200} className="input-text" style={{borderRadius:9999}} placeholder={placeholder}/>
|
|
<button type="submit" data-testid="chat-send" className="w-11 h-11 rounded-full grid place-items-center border-2 border-dark shadow-chunky" style={{background:"var(--mint)"}}>
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2.5" strokeLinecap="round"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4z"/></svg>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|