Nachalarmieren select
Alarmieren aus Einsatz erstellen Maske Map-Tiles SDS sound: Status J SDS Nachricht: public-User Audio: Es kann nur ein Nutzer gleichzeitig Funken Select in Report und Chat: default value -> OnChange
This commit is contained in:
@@ -27,6 +27,7 @@ export const Audio = () => {
|
||||
speakingParticipants,
|
||||
isTalking,
|
||||
toggleTalking,
|
||||
transmitBlocked,
|
||||
connect,
|
||||
state,
|
||||
connectionQuality,
|
||||
@@ -41,6 +42,7 @@ export const Audio = () => {
|
||||
isReceiving: speakingParticipants.length > 0,
|
||||
isTransmitting: isTalking,
|
||||
unpausedTracks: speakingParticipants,
|
||||
transmitBlocked,
|
||||
});
|
||||
|
||||
const { selectedStation, status: pilotState } = usePilotConnectionStore((state) => state);
|
||||
@@ -154,6 +156,7 @@ export const Audio = () => {
|
||||
"btn btn-sm btn-soft border-none hover:bg-inherit",
|
||||
!isTalking && "bg-transparent hover:bg-sky-400/20",
|
||||
isTalking && "bg-green-700 hover:bg-green-600",
|
||||
transmitBlocked && "bg-yellow-500 hover:bg-yellow-500",
|
||||
state === "disconnected" && "bg-red-500 hover:bg-red-500",
|
||||
state === "error" && "bg-red-500 hover:bg-red-500",
|
||||
state === "connecting" && "bg-yellow-500 hover:bg-yellow-500 cursor-default",
|
||||
|
||||
@@ -7,10 +7,12 @@ export const useSounds = ({
|
||||
isReceiving,
|
||||
isTransmitting,
|
||||
unpausedTracks,
|
||||
transmitBlocked,
|
||||
}: {
|
||||
isReceiving: boolean;
|
||||
isTransmitting: boolean;
|
||||
unpausedTracks: unknown[];
|
||||
transmitBlocked?: boolean;
|
||||
}) => {
|
||||
const { room } = useAudioStore();
|
||||
// Sounds as refs
|
||||
@@ -56,6 +58,17 @@ export const useSounds = ({
|
||||
}
|
||||
}, [isReceiving, isTransmitting, soundConnectionStarted]);
|
||||
|
||||
useEffect(() => {
|
||||
if (transmitBlocked && foreignCallBlocked.current) {
|
||||
foreignCallBlocked.current.volume = 0.2;
|
||||
foreignCallBlocked.current.currentTime = 0;
|
||||
foreignCallBlocked.current.loop = true;
|
||||
foreignCallBlocked.current.play().catch(() => {});
|
||||
} else if (foreignCallBlocked.current) {
|
||||
foreignCallBlocked.current.pause();
|
||||
}
|
||||
}, [transmitBlocked]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isTransmitting && connectionStart.current!.paused) {
|
||||
ownCallStarted.current!.volume = 0.2;
|
||||
|
||||
@@ -39,7 +39,7 @@ export const Chat = () => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if(!session.data?.user.id) return;
|
||||
if (!session.data?.user.id) return;
|
||||
setOwnId(session.data?.user.id);
|
||||
}, [session.data?.user.id]);
|
||||
|
||||
@@ -47,7 +47,7 @@ export const Chat = () => {
|
||||
const filteredAircrafts = aircrafts?.filter((a) => a.userId !== session.data?.user.id);
|
||||
|
||||
return (
|
||||
<div className={cn("dropdown dropdown-right", chatOpen && "dropdown-open")}>
|
||||
<div className={cn("dropdown dropdown-right dropdown-center", chatOpen && "dropdown-open")}>
|
||||
<div className="indicator">
|
||||
{Object.values(chats).some((c) => c.notification) && (
|
||||
<span className="indicator-item status status-info"></span>
|
||||
@@ -68,9 +68,9 @@ export const Chat = () => {
|
||||
{chatOpen && (
|
||||
<div
|
||||
tabIndex={0}
|
||||
className="dropdown-content card bg-base-200 w-150 shadow-md z-[1100] ml-2 border-1 border-primary"
|
||||
className="dropdown-content card bg-base-200 w-150 shadow-md z-[1100] max-h-[400px] ml-2 border-1 border-primary"
|
||||
>
|
||||
<div className="card-body">
|
||||
<div className="card-body overflow-y-auto">
|
||||
<h2 className="inline-flex items-center gap-2 text-lg font-bold mb-2">
|
||||
<ChatBubbleIcon /> Chat
|
||||
</h2>
|
||||
@@ -118,7 +118,7 @@ export const Chat = () => {
|
||||
<span className="text-xl">+</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="tabs tabs-lift">
|
||||
<div className="tabs tabs-lift max-h-full">
|
||||
{Object.keys(chats).map((userId) => {
|
||||
const chat = chats[userId];
|
||||
if (!chat) return null;
|
||||
@@ -126,7 +126,6 @@ export const Chat = () => {
|
||||
<Fragment key={userId}>
|
||||
<input
|
||||
type="radio"
|
||||
name="my_tabs_3"
|
||||
className="tab"
|
||||
aria-label={`<${chat.name}>`}
|
||||
checked={selectedChat === userId}
|
||||
@@ -140,7 +139,7 @@ export const Chat = () => {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="tab-content bg-base-100 border-base-300 p-6">
|
||||
<div className="tab-content bg-base-100 border-base-300 p-6 overflow-y-auto">
|
||||
{chat.messages.map((chatMessage) => {
|
||||
const isSender = chatMessage.senderId === session.data?.user.id;
|
||||
return (
|
||||
@@ -173,6 +172,22 @@ export const Chat = () => {
|
||||
onChange={(e) => {
|
||||
setMessage(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
if (message.length < 1) return;
|
||||
if (!selectedChat) return;
|
||||
setSending(true);
|
||||
sendMessage(selectedChat, message)
|
||||
.then(() => {
|
||||
setMessage("");
|
||||
setSending(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setSending(false);
|
||||
});
|
||||
}
|
||||
}}
|
||||
value={message}
|
||||
/>
|
||||
</label>
|
||||
|
||||
@@ -38,7 +38,9 @@ export const Report = () => {
|
||||
const filteredAircrafts = aircrafts?.filter((a) => a.userId !== session.data?.user.id);
|
||||
|
||||
return (
|
||||
<div className={cn("dropdown dropdown-right", reportTabOpen && "dropdown-open")}>
|
||||
<div
|
||||
className={cn("dropdown dropdown-right dropdown-center", reportTabOpen && "dropdown-open")}
|
||||
>
|
||||
<div className="indicator">
|
||||
<button
|
||||
className="btn btn-soft btn-sm btn-error"
|
||||
@@ -70,12 +72,11 @@ export const Report = () => {
|
||||
Keine Nutzer gefunden
|
||||
</option>
|
||||
)}
|
||||
{filteredDispatcher?.length ||
|
||||
(filteredAircrafts?.length && (
|
||||
<option disabled value="default">
|
||||
Nutzer auswählen
|
||||
</option>
|
||||
))}
|
||||
{(filteredDispatcher?.length || filteredAircrafts?.length) && (
|
||||
<option disabled value="default">
|
||||
Nutzer auswählen
|
||||
</option>
|
||||
)}
|
||||
|
||||
{filteredDispatcher?.map((dispatcher) => (
|
||||
<option key={dispatcher.userId} value={dispatcher.userId}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import "./mapStyles.css";
|
||||
import { useMapStore } from "_store/mapStore";
|
||||
import { MapContainer } from "react-leaflet";
|
||||
import { BaseMaps } from "_components/map/BaseMaps";
|
||||
@@ -39,7 +40,7 @@ const Map = () => {
|
||||
return (
|
||||
<MapContainer
|
||||
ref={ref}
|
||||
className="flex-1"
|
||||
className="flex-1 bg-base-200"
|
||||
center={map.center}
|
||||
zoom={map.zoom}
|
||||
fadeAnimation={false}
|
||||
|
||||
@@ -397,7 +397,9 @@ const SDSTab = ({
|
||||
stationId: aircraft.Station.id,
|
||||
station: aircraft.Station,
|
||||
message: note,
|
||||
user: getPublicUser(session.data!.user),
|
||||
user: getPublicUser(session.data!.user, {
|
||||
ignorePrivacy: true,
|
||||
}),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -341,10 +341,10 @@ const Patientdetails = ({ mission }: { mission: Mission }) => {
|
||||
|
||||
const Rettungsmittel = ({ mission }: { mission: Mission }) => {
|
||||
const queryClient = useQueryClient();
|
||||
const [selectedStation, setSelectedStation] = useState<Station | "RTW" | "POL" | "FW" | null>(
|
||||
const [selectedStation, setSelectedStation] = useState<number | "RTW" | "POL" | "FW" | null>(
|
||||
null,
|
||||
);
|
||||
const { data: conenctedAircrafts } = useQuery({
|
||||
const { data: connectedAircrafts } = useQuery({
|
||||
queryKey: ["aircrafts"],
|
||||
queryFn: getConnectedAircraftsAPI,
|
||||
});
|
||||
@@ -383,17 +383,6 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
|
||||
queryFn: () => getStationsAPI(),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (allStations) {
|
||||
const stationsNotItMission = allStations.filter(
|
||||
(s) => !mission.missionStationIds.includes(s.id),
|
||||
);
|
||||
if (stationsNotItMission[0]) {
|
||||
setSelectedStation(stationsNotItMission[0]);
|
||||
}
|
||||
}
|
||||
}, [allStations, mission.missionStationIds]);
|
||||
|
||||
const sendAlertMutation = useMutation({
|
||||
mutationKey: ["missions"],
|
||||
mutationFn: ({
|
||||
@@ -421,7 +410,7 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
|
||||
label: station.bosCallsign,
|
||||
value: station.id,
|
||||
type: "station" as const,
|
||||
isOnline: !!conenctedAircrafts?.find((a) => a.stationId === station.id),
|
||||
isOnline: !!connectedAircrafts?.find((a) => a.stationId === station.id),
|
||||
})) || []),
|
||||
...(!mission.hpgFireEngineState || mission.hpgFireEngineState === "NOT_REQUESTED"
|
||||
? [{ label: "Feuerwehr", value: "FW", type: "vehicle" as const }]
|
||||
@@ -447,18 +436,6 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
|
||||
return a.label.localeCompare(b.label);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const firstOption = stationsOptions[0];
|
||||
if (!firstOption) {
|
||||
setSelectedStation(null);
|
||||
} else if (firstOption.type === "station") {
|
||||
const station = allStations?.find((s) => s.id === firstOption.value);
|
||||
setSelectedStation(station ?? null);
|
||||
} else {
|
||||
setSelectedStation(firstOption.value as "RTW" | "POL" | "FW");
|
||||
}
|
||||
}, [stationsOptions, allStations]);
|
||||
|
||||
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
|
||||
|
||||
const HPGVehicle = ({ state, name }: { state: HpgState; name: string }) => (
|
||||
@@ -506,7 +483,7 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
|
||||
</div>
|
||||
<ul className="space-y-2 max-h-[300px] overflow-y-auto overflow-x-auto">
|
||||
{missionStations?.map((station, index) => {
|
||||
const connectedAircraft = conenctedAircrafts?.find(
|
||||
const connectedAircraft = connectedAircrafts?.find(
|
||||
(aircraft) => aircraft.stationId === station.id,
|
||||
);
|
||||
|
||||
@@ -550,15 +527,15 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
|
||||
<select
|
||||
className="select select-sm select-primary select-bordered flex-1"
|
||||
onChange={(e) => {
|
||||
const selected = allStations?.find((s) => s.id.toString() === e.target.value);
|
||||
if (selected) {
|
||||
setSelectedStation(selected);
|
||||
} else {
|
||||
setSelectedStation(e.target.value as "RTW" | "POL" | "FW");
|
||||
}
|
||||
const value = e.target.value;
|
||||
const parsedValue = !isNaN(Number(value)) ? parseInt(value, 10) : value;
|
||||
setSelectedStation(parsedValue as number | "RTW" | "POL" | "FW" | null);
|
||||
}}
|
||||
value={typeof selectedStation === "string" ? selectedStation : selectedStation?.id}
|
||||
value={selectedStation || "default"}
|
||||
>
|
||||
<option disabled value={"default"}>
|
||||
Rettungsmittel auswählen
|
||||
</option>
|
||||
{stationsOptions.map((option) => (
|
||||
<option
|
||||
key={option.value}
|
||||
@@ -582,18 +559,18 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
|
||||
vehicleName: selectedStation,
|
||||
});
|
||||
} else {
|
||||
if (!selectedStation?.id) return;
|
||||
if (!selectedStation) return;
|
||||
await updateMissionMutation.mutateAsync({
|
||||
id: mission.id,
|
||||
missionEdit: {
|
||||
missionStationIds: {
|
||||
push: selectedStation?.id,
|
||||
push: selectedStation,
|
||||
},
|
||||
},
|
||||
});
|
||||
await sendAlertMutation.mutate({
|
||||
id: mission.id,
|
||||
stationId: selectedStation?.id ?? 0,
|
||||
stationId: selectedStation,
|
||||
});
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -1,106 +1,3 @@
|
||||
.no-pointer {
|
||||
cursor: unset;
|
||||
}
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.leaflet-tooltip-aircraft {
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
color: rgb(254, 254, 254) !important;
|
||||
left: 35px !important;
|
||||
top: 40px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.leaflet-popup-content-wrapper {
|
||||
background-color: var(--dark-background);
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
right: -20%;
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
right: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from {
|
||||
right: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
right: -20%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-tooltip-aircraft:before {
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
color: rgb(255, 255, 255) !important;
|
||||
left: 0px !important;
|
||||
top: 0px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.custom-tooltip-bg {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.custom-tooltip-bg:before {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.no-pointer {
|
||||
cursor: unset;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.leaflet-tooltip-aircraft {
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
background-color: var(--surface) !important;
|
||||
color: var(--on-surface) !important;
|
||||
}
|
||||
|
||||
.leaflet-tooltip-aircraft:before {
|
||||
border-bottom-color: var(--dark-surface) !important;
|
||||
}
|
||||
|
||||
.modal-box {
|
||||
position: fixed;
|
||||
bottom: 50%;
|
||||
right: 50px;
|
||||
background-color: rgba(255, 255, 255, 0.75);
|
||||
border: 5px solid #243671;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
|
||||
z-index: 1000;
|
||||
max-width: 300px;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal-box-close {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
color: #243671;
|
||||
.leaflet-container {
|
||||
background: var(--color-base-200) !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user