156 lines
4.7 KiB
TypeScript
156 lines
4.7 KiB
TypeScript
'use client';
|
|
|
|
import Image from 'next/image';
|
|
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
|
|
interface MessageInputProps {
|
|
onSend?: (message: string) => void;
|
|
onTypingStart?: () => void;
|
|
onTypingStop?: () => void;
|
|
}
|
|
|
|
export function MessageInput({ onSend, onTypingStart, onTypingStop }: MessageInputProps) {
|
|
const [message, setMessage] = useState('');
|
|
const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
const isTypingRef = useRef(false);
|
|
|
|
// Handle typing indicator
|
|
const handleTyping = useCallback(() => {
|
|
// Start typing indicator
|
|
if (!isTypingRef.current && onTypingStart) {
|
|
isTypingRef.current = true;
|
|
onTypingStart();
|
|
}
|
|
|
|
// Clear existing timeout
|
|
if (typingTimeoutRef.current) {
|
|
clearTimeout(typingTimeoutRef.current);
|
|
}
|
|
|
|
// Set timeout to stop typing indicator after 2 seconds of inactivity
|
|
typingTimeoutRef.current = setTimeout(() => {
|
|
if (isTypingRef.current && onTypingStop) {
|
|
isTypingRef.current = false;
|
|
onTypingStop();
|
|
}
|
|
}, 2000);
|
|
}, [onTypingStart, onTypingStop]);
|
|
|
|
// Cleanup on unmount
|
|
useEffect(() => {
|
|
return () => {
|
|
if (typingTimeoutRef.current) {
|
|
clearTimeout(typingTimeoutRef.current);
|
|
}
|
|
if (isTypingRef.current && onTypingStop) {
|
|
onTypingStop();
|
|
}
|
|
};
|
|
}, [onTypingStop]);
|
|
|
|
const handleSend = () => {
|
|
if (message.trim() && onSend) {
|
|
// Stop typing indicator before sending
|
|
if (typingTimeoutRef.current) {
|
|
clearTimeout(typingTimeoutRef.current);
|
|
}
|
|
if (isTypingRef.current && onTypingStop) {
|
|
isTypingRef.current = false;
|
|
onTypingStop();
|
|
}
|
|
|
|
onSend(message.trim());
|
|
setMessage('');
|
|
}
|
|
};
|
|
|
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault();
|
|
handleSend();
|
|
}
|
|
};
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
setMessage(e.target.value);
|
|
handleTyping();
|
|
};
|
|
|
|
return (
|
|
<div className="border border-[#00293d]/10 rounded-[20px] bg-white p-4">
|
|
{/* Text input area */}
|
|
<div className="border border-[#00293d]/10 rounded-[20px] p-4 mb-3">
|
|
<textarea
|
|
value={message}
|
|
onChange={handleChange}
|
|
onKeyDown={handleKeyDown}
|
|
placeholder="Write a Message........"
|
|
className="w-full min-h-[120px] resize-none font-serif font-normal text-[14px] leading-[19px] text-[#00293D] placeholder-[#00293D]/50 focus:outline-none"
|
|
/>
|
|
</div>
|
|
|
|
{/* Action bar */}
|
|
<div className="flex items-center justify-between">
|
|
{/* Attachment buttons */}
|
|
<div className="flex items-center gap-3">
|
|
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
|
<Image
|
|
src="/assets/icons/gallery-icon.svg"
|
|
alt="Add image"
|
|
width={24}
|
|
height={24}
|
|
/>
|
|
</button>
|
|
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
|
<Image
|
|
src="/assets/icons/chain-icon.svg"
|
|
alt="Add link"
|
|
width={24}
|
|
height={24}
|
|
/>
|
|
</button>
|
|
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
|
<Image
|
|
src="/assets/icons/gif-icon.svg"
|
|
alt="Add GIF"
|
|
width={24}
|
|
height={24}
|
|
/>
|
|
</button>
|
|
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
|
<Image
|
|
src="/assets/icons/emoji-icon.svg"
|
|
alt="Add emoji"
|
|
width={24}
|
|
height={24}
|
|
/>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Send button and more options */}
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={handleSend}
|
|
disabled={!message.trim()}
|
|
className={`px-4 py-1.5 font-serif font-normal text-[14px] leading-[19px] rounded-[15px] transition-colors cursor-pointer ${
|
|
message.trim()
|
|
? 'bg-[#e58625] text-[#00293d] hover:bg-[#d47720]'
|
|
: 'bg-[#e58625]/50 text-[#00293d]/50 cursor-not-allowed'
|
|
}`}
|
|
>
|
|
Send
|
|
</button>
|
|
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
|
<Image
|
|
src="/assets/icons/three-dots-icon.svg"
|
|
alt="More options"
|
|
width={24}
|
|
height={24}
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|