|
@@ -23,6 +23,7 @@ export default function ChatbotWidgetLive() {
|
|
|
const [localMessages, setLocalMessages] = useState<Array<{ id: number; sender: string; content: string; createdAt: string }>>([]);
|
|
const [localMessages, setLocalMessages] = useState<Array<{ id: number; sender: string; content: string; createdAt: string }>>([]);
|
|
|
const [isTyping, setIsTyping] = useState(false);
|
|
const [isTyping, setIsTyping] = useState(false);
|
|
|
const [showQuickReplies, setShowQuickReplies] = useState(true);
|
|
const [showQuickReplies, setShowQuickReplies] = useState(true);
|
|
|
|
|
+ const [pendingMessage, setPendingMessage] = useState<string | null>(null);
|
|
|
const [csatRating, setCsatRating] = useState<number | null>(null);
|
|
const [csatRating, setCsatRating] = useState<number | null>(null);
|
|
|
const [csatHover, setCsatHover] = useState<number | null>(null);
|
|
const [csatHover, setCsatHover] = useState<number | null>(null);
|
|
|
const [csatSubmitted, setCsatSubmitted] = useState(false);
|
|
const [csatSubmitted, setCsatSubmitted] = useState(false);
|
|
@@ -33,6 +34,10 @@ export default function ChatbotWidgetLive() {
|
|
|
const startSession = trpc.chat.startSession.useMutation({
|
|
const startSession = trpc.chat.startSession.useMutation({
|
|
|
onSuccess: (data) => {
|
|
onSuccess: (data) => {
|
|
|
setSessionId(data.sessionId);
|
|
setSessionId(data.sessionId);
|
|
|
|
|
+ if (pendingMessage) {
|
|
|
|
|
+ sendMessage.mutate({ sessionId: data.sessionId, content: pendingMessage });
|
|
|
|
|
+ setPendingMessage(null);
|
|
|
|
|
+ }
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -112,7 +117,19 @@ export default function ChatbotWidgetLive() {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleQuickReply = (reply: typeof QUICK_REPLIES[0]) => {
|
|
const handleQuickReply = (reply: typeof QUICK_REPLIES[0]) => {
|
|
|
- handleSend(reply.value);
|
|
|
|
|
|
|
+ const text = reply.value;
|
|
|
|
|
+ setShowQuickReplies(false);
|
|
|
|
|
+ setIsTyping(true);
|
|
|
|
|
+ isNearBottomRef.current = true;
|
|
|
|
|
+ setLocalMessages(prev => [...prev, {
|
|
|
|
|
+ id: Date.now(), sender: "visitor", content: text, createdAt: new Date().toISOString(),
|
|
|
|
|
+ }]);
|
|
|
|
|
+ if (sessionId) {
|
|
|
|
|
+ sendMessage.mutate({ sessionId, content: text });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Session still starting — queue until onSuccess fires
|
|
|
|
|
+ setPendingMessage(text);
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
@@ -208,7 +225,7 @@ export default function ChatbotWidgetLive() {
|
|
|
)}
|
|
)}
|
|
|
|
|
|
|
|
{/* Quick reply buttons — Tidio-style */}
|
|
{/* Quick reply buttons — Tidio-style */}
|
|
|
- {showQuickReplies && !hasUserMessages && sessionId && (
|
|
|
|
|
|
|
+ {showQuickReplies && !hasUserMessages && (
|
|
|
<div className="flex flex-wrap gap-2 justify-center py-2">
|
|
<div className="flex flex-wrap gap-2 justify-center py-2">
|
|
|
{QUICK_REPLIES.map((reply) => (
|
|
{QUICK_REPLIES.map((reply) => (
|
|
|
<button
|
|
<button
|