This commit is contained in:
PxlLoewe
2025-07-23 18:44:12 -07:00
2 changed files with 22 additions and 9 deletions

View File

@@ -2,7 +2,7 @@
import { ChatBubbleIcon, PaperPlaneIcon } from "@radix-ui/react-icons"; import { ChatBubbleIcon, PaperPlaneIcon } from "@radix-ui/react-icons";
import { useLeftMenuStore } from "_store/leftMenuStore"; import { useLeftMenuStore } from "_store/leftMenuStore";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { Fragment, useEffect, useState } from "react"; import { Fragment, useEffect, useState, useRef } from "react";
import { cn } from "@repo/shared-components"; import { cn } from "@repo/shared-components";
import { asPublicUser } from "@repo/db"; import { asPublicUser } from "@repo/db";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
@@ -30,6 +30,8 @@ export const Chat = () => {
const [message, setMessage] = useState<string>(""); const [message, setMessage] = useState<string>("");
const dispatcherConnected = useDispatchConnectionStore((state) => state.status === "connected"); const dispatcherConnected = useDispatchConnectionStore((state) => state.status === "connected");
const pilotConnected = usePilotConnectionStore((state) => state.status === "connected"); const pilotConnected = usePilotConnectionStore((state) => state.status === "connected");
const [someChat, setSomeChat] = useState(false);
const audioRef = useRef<HTMLAudioElement | null>(null);
const { data: dispatcher } = useQuery({ const { data: dispatcher } = useQuery({
queryKey: ["dispatcher"], queryKey: ["dispatcher"],
@@ -61,16 +63,27 @@ export const Chat = () => {
} }
}, [btnActive, setChatOpen]); }, [btnActive, setChatOpen]);
useEffect(() => {
if (Object.values(chats).some((c) => c.notification)) {
setSomeChat(true);
if (audioRef.current) {
audioRef.current.volume = 0.5;
audioRef.current.play().catch(() => {});
}
} else {
setSomeChat(false);
}
}, [chats]);
return ( return (
<div className={cn("dropdown dropdown-right dropdown-center", chatOpen && "dropdown-open")}> <div className={cn("dropdown dropdown-right dropdown-center", chatOpen && "dropdown-open")}>
<audio ref={audioRef} src="/sounds/newChat.mp3" preload="auto" />
<div className="indicator"> <div className="indicator">
{Object.values(chats).some((c) => c.notification) && (
<span className="indicator-item status status-info animate-ping"></span>
)}
<button <button
className={cn( className={cn(
"btn btn-soft btn-sm cursor-default", "btn btn-soft btn-sm cursor-default",
btnActive && "btn-primary cursor-pointer", btnActive && "btn-primary cursor-pointer",
someChat && "border-warning animate-pulse",
)} )}
onClick={() => { onClick={() => {
if (!btnActive) return; if (!btnActive) return;
@@ -81,23 +94,23 @@ export const Chat = () => {
} }
}} }}
> >
<ChatBubbleIcon className="w-4 h-4" /> <ChatBubbleIcon className="h-4 w-4" />
</button> </button>
</div> </div>
{chatOpen && ( {chatOpen && (
<div <div
tabIndex={0} tabIndex={0}
className="dropdown-content card bg-base-200 w-150 shadow-md z-[1100] max-h-[480px] ml-2 border-1 border-primary" className="dropdown-content card bg-base-200 w-150 border-1 border-primary z-[1100] ml-2 max-h-[480px] shadow-md"
> >
<div className="card-body relative"> <div className="card-body relative">
<button <button
className="absolute top-2 right-2 btn btn-xs btn-circle btn-ghost" className="btn btn-xs btn-circle btn-ghost absolute right-2 top-2"
onClick={() => setChatOpen(false)} onClick={() => setChatOpen(false)}
type="button" type="button"
> >
<span className="text-xl leading-none">&times;</span> <span className="text-xl leading-none">&times;</span>
</button> </button>
<h2 className="inline-flex items-center gap-2 text-lg font-bold mb-2"> <h2 className="mb-2 inline-flex items-center gap-2 text-lg font-bold">
<ChatBubbleIcon /> Chat <ChatBubbleIcon /> Chat
</h2> </h2>
<div className="join"> <div className="join">
@@ -164,7 +177,7 @@ export const Chat = () => {
{chat.name} {chat.name}
{chat.notification && <span className="indicator-item status status-info" />} {chat.notification && <span className="indicator-item status status-info" />}
</a> </a>
<div className="tab-content bg-base-100 border-base-300 p-6 overflow-y-auto max-h-[250px]"> <div className="tab-content bg-base-100 border-base-300 max-h-[250px] overflow-y-auto p-6">
{/* So macht man kein overflow handeling, weiß ich. Aber es funktioniert... */} {/* So macht man kein overflow handeling, weiß ich. Aber es funktioniert... */}
{chat.messages.map((chatMessage) => { {chat.messages.map((chatMessage) => {
const isSender = chatMessage.senderId === session.data?.user.id; const isSender = chatMessage.senderId === session.data?.user.id;

Binary file not shown.