refactor(mascot): simplify chat visibility logic and add persistent chat mode

This commit is contained in:
MythEclipse
2026-06-03 15:08:31 +07:00
parent 7904d7f38d
commit f303b04684
2 changed files with 11 additions and 11 deletions
+6 -10
View File
@@ -1,6 +1,5 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { BarChart3, MessageSquare, Radio } from "lucide-react"; import { BarChart3, MessageSquare, Radio } from "lucide-react";
import { useEffect, useState } from "react";
import type { DashboardTab } from "../entities/ui/types"; import type { DashboardTab } from "../entities/ui/types";
import type { MessageRecord } from "../shared/api/client"; import type { MessageRecord } from "../shared/api/client";
import { useMascotChat } from "../shared/hooks/useMascotChat"; import { useMascotChat } from "../shared/hooks/useMascotChat";
@@ -34,7 +33,6 @@ export function Sidebar({
guildId, guildId,
channelId, channelId,
}: SidebarProps) { }: SidebarProps) {
const [showChat, setShowChat] = useState(false);
const mascotChat = useMascotChat({ const mascotChat = useMascotChat({
messageCount: recentMessages.length, messageCount: recentMessages.length,
activeParticipants: new Set(recentMessages.map((message) => message.user_id)).size, activeParticipants: new Set(recentMessages.map((message) => message.user_id)).size,
@@ -43,12 +41,6 @@ export function Sidebar({
guildId, guildId,
channelId, channelId,
}); });
useEffect(() => {
if (mascotChatMessage) {
setShowChat(true);
}
}, [mascotChatMessage]);
return ( return (
<motion.nav <motion.nav
className={cn( className={cn(
@@ -121,8 +113,12 @@ export function Sidebar({
> >
<MascotImage <MascotImage
size="sm" size="sm"
showChat={showChat && !mascotChat.isOpen} showChat={!mascotChat.isOpen}
chatMessage={mascotChatMessage} chatMessage={
mascotChatMessage ||
"Halo! Saya mascot mu. Klik aku kalau mau tanya soal obrolan atau moderasi ✨"
}
persistChat
/> />
</button> </button>
<MascotChatbot <MascotChatbot
@@ -13,6 +13,7 @@ interface MascotImageProps {
className?: string; className?: string;
showChat?: boolean; showChat?: boolean;
chatMessage?: string; chatMessage?: string;
persistChat?: boolean;
} }
const sizeMap = { const sizeMap = {
@@ -32,6 +33,7 @@ export function MascotImage({
className = "", className = "",
showChat = false, showChat = false,
chatMessage = "", chatMessage = "",
persistChat = false,
}: MascotImageProps) { }: MascotImageProps) {
const sizeClass = sizeMap[size]; const sizeClass = sizeMap[size];
const chatSizeClass = chatSizeMap[size]; const chatSizeClass = chatSizeMap[size];
@@ -40,10 +42,12 @@ export function MascotImage({
useEffect(() => { useEffect(() => {
if (showChat && chatMessage) { if (showChat && chatMessage) {
setIsVisible(true); setIsVisible(true);
if (persistChat) return;
const timer = setTimeout(() => setIsVisible(false), 8000); // Auto hide after 8s const timer = setTimeout(() => setIsVisible(false), 8000); // Auto hide after 8s
return () => clearTimeout(timer); return () => clearTimeout(timer);
} }
}, [showChat, chatMessage]); setIsVisible(false);
}, [showChat, chatMessage, persistChat]);
return ( return (
<div className="relative inline-block"> <div className="relative inline-block">