Merge branch 'staging' of https://github.com/VAR-Virtual-Air-Rescue/var-monorepo into staging
This commit is contained in:
@@ -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">×</span>
|
<span className="text-xl leading-none">×</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;
|
||||||
|
|||||||
BIN
apps/dispatch/public/sounds/newChat.mp3
Normal file
BIN
apps/dispatch/public/sounds/newChat.mp3
Normal file
Binary file not shown.
Reference in New Issue
Block a user