completed Rescuetrack
29
apps/dispatch/app/_components/Badge/Badge.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { BADGES } from "@repo/db";
|
||||||
|
import P1 from "./p-1.png";
|
||||||
|
import P2 from "./p-2.png";
|
||||||
|
import P3 from "./p-3.png";
|
||||||
|
import D1 from "./d-1.png";
|
||||||
|
import D2 from "./d-2.png";
|
||||||
|
import D3 from "./d-3.png";
|
||||||
|
import DAY1 from "./day-1-member.png";
|
||||||
|
import { cn } from "_helpers/cn";
|
||||||
|
|
||||||
|
const BadgeImage = {
|
||||||
|
[BADGES.P1]: P1,
|
||||||
|
[BADGES.P2]: P2,
|
||||||
|
[BADGES.P3]: P3,
|
||||||
|
[BADGES.D1]: D1,
|
||||||
|
[BADGES.D2]: D2,
|
||||||
|
[BADGES.D3]: D3,
|
||||||
|
[BADGES.DAY1]: DAY1,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Badge = ({ name, className }: { name: BADGES; className?: string }) => {
|
||||||
|
const image = BadgeImage[name];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className={cn("flex h-fit p-1", className)}>
|
||||||
|
<img src={image.src} alt={name} width={100} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
BIN
apps/dispatch/app/_components/Badge/d-1.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
apps/dispatch/app/_components/Badge/d-2.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
apps/dispatch/app/_components/Badge/d-3.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
apps/dispatch/app/_components/Badge/day-1-member.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
apps/dispatch/app/_components/Badge/p-1.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
apps/dispatch/app/_components/Badge/p-2.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
apps/dispatch/app/_components/Badge/p-3.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
@@ -1,4 +1,4 @@
|
|||||||
import { ConnectedAircraft, Prisma, Station } from "@repo/db";
|
import { ConnectedAircraft, Prisma, PublicUser, Station } from "@repo/db";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { serverApi } from "_helpers/axios";
|
import { serverApi } from "_helpers/axios";
|
||||||
|
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import { useRef } from "react";
|
|
||||||
import { GearIcon } from "@radix-ui/react-icons";
|
|
||||||
import { SettingsIcon, Volume2 } from "lucide-react";
|
|
||||||
|
|
||||||
export const SettingsBtn = () => {
|
|
||||||
const modalRef = useRef<HTMLDialogElement>(null);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
className="btn btn-ghost"
|
|
||||||
onSubmit={() => false}
|
|
||||||
onClick={() => {
|
|
||||||
modalRef.current?.showModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<GearIcon className="w-5 h-5" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<dialog ref={modalRef} className="modal">
|
|
||||||
<div className="modal-box">
|
|
||||||
<h3 className="flex items-center gap-2 text-lg font-bold mb-5">
|
|
||||||
<SettingsIcon size={20} /> Einstellungen
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-col items-center justify-center">
|
|
||||||
<fieldset className="fieldset w-full">
|
|
||||||
<label className="floating-label w-full text-base">
|
|
||||||
<span>Eingabegerät</span>
|
|
||||||
<select className="input w-full" defaultValue={0}>
|
|
||||||
<option key={0} value={0} disabled>
|
|
||||||
Bitte wähle ein Eingabegerät...
|
|
||||||
</option>
|
|
||||||
<option key={1} value={1}>
|
|
||||||
Audiogerät 1
|
|
||||||
</option>
|
|
||||||
<option key={2} value={2}>
|
|
||||||
Audiogerät 2
|
|
||||||
</option>
|
|
||||||
<option key={3} value={3}>
|
|
||||||
Audiogerät 3
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</fieldset>
|
|
||||||
{/* FÜGE HIER BITTE DEN MIKROFONAUSSCHLAG EIN WIE IN DER V1 */}
|
|
||||||
<div className="divider w-full" />
|
|
||||||
</div>
|
|
||||||
<p className="flex items-center gap-2 text-base mb-2">
|
|
||||||
<Volume2 size={20} /> Ausgabelautstärke
|
|
||||||
</p>
|
|
||||||
<div className="w-full">
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
defaultValue={40}
|
|
||||||
className="range range-xs range-accent w-full"
|
|
||||||
/>
|
|
||||||
<div className="flex justify-between px-2.5 mt-2 text-xs">
|
|
||||||
<span>0</span>
|
|
||||||
<span>25</span>
|
|
||||||
<span>50</span>
|
|
||||||
<span>75</span>
|
|
||||||
<span>100</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex justify-between modal-action">
|
|
||||||
<button
|
|
||||||
className="btn btn-soft"
|
|
||||||
type="submit"
|
|
||||||
onSubmit={() => false}
|
|
||||||
onClick={() => {
|
|
||||||
modalRef.current?.close();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Schließen
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="btn btn-soft btn-success"
|
|
||||||
type="submit"
|
|
||||||
onSubmit={() => false}
|
|
||||||
onClick={() => {
|
|
||||||
modalRef.current?.close();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Speichern
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</dialog>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Settings = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<SettingsBtn />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,50 +1,56 @@
|
|||||||
|
import { BADGES, PublicUser } from "@repo/db";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { Badge } from "_components/Badge/Badge";
|
||||||
|
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
||||||
import { getConnectedDispatcherAPI } from "_querys/connected-user";
|
import { getConnectedDispatcherAPI } from "_querys/connected-user";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
export const ConnectedDispatcher = () => {
|
export const ConnectedDispatcher = () => {
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const { data: dispatcher } = useQuery({
|
const { data: dispatcher } = useQuery({
|
||||||
queryKey: ["dispatcher"],
|
queryKey: ["dispatcher"],
|
||||||
queryFn: () => getConnectedDispatcherAPI(),
|
queryFn: () => getConnectedDispatcherAPI(),
|
||||||
refetchInterval: 10000,
|
refetchInterval: 10000,
|
||||||
});
|
});
|
||||||
console.log("ConnectedDispatcher", dispatcher);
|
const { data: aircrafts } = useQuery({
|
||||||
|
queryKey: ["aircrafts"],
|
||||||
|
queryFn: () => getConnectedAircraftsAPI(),
|
||||||
|
refetchInterval: 10000,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute top-5 right-10 min-w-120 z-99999">
|
<div className="absolute top-5 right-10 min-w-120 z-99999">
|
||||||
<div className="collapse collapse-arrow bg-base-100 border-base-300 border">
|
<div className="collapse collapse-arrow bg-base-100 border-base-300 border">
|
||||||
<input type="checkbox" />
|
<input type="checkbox" />
|
||||||
{/* <div className="collapse-title font-semibold">Kein Disponent Online</div> */}
|
{/* <div className="collapse-title font-semibold">Kein Disponent Online</div> */}
|
||||||
<div className="collapse-title font-semibold">15 Verbundene Mitglieder</div>
|
<div className="collapse-title font-semibold">
|
||||||
|
{(aircrafts?.length || 0) + (dispatcher?.length || 0)} Verbundene Mitglieder
|
||||||
|
</div>
|
||||||
<div className="collapse-content">
|
<div className="collapse-content">
|
||||||
<ul className="list bg-base-100 rounded-box shadow-md">
|
<ul className="list bg-base-100 rounded-box shadow-md">
|
||||||
<li className="text-xs opacity-60 tracking-wide">Disponenten: 1</li>
|
<li className="text-xs opacity-60 tracking-wide">
|
||||||
<li className="pb-2 text-xs opacity-60 tracking-wide">Piloten: 14</li>
|
Disponenten: {dispatcher?.length || 0}
|
||||||
|
</li>
|
||||||
<li className="flex list-row justify-between items-center">
|
<li className="pb-2 text-xs opacity-60 tracking-wide">
|
||||||
<div>
|
Piloten: {aircrafts?.length || 0}
|
||||||
<div>Nicolas K.</div>
|
|
||||||
<div className="text-xs uppercase font-semibold opacity-60">LST_1</div>
|
|
||||||
</div>
|
|
||||||
<div>INSERT BADGES HERE</div>
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li className="flex list-row justify-between items-center">
|
{dispatcher?.map((d) => {
|
||||||
<div>
|
console.log("dispatcher", d);
|
||||||
<div>Marvin S.</div>
|
return (
|
||||||
<div className="text-xs uppercase font-semibold opacity-60">Christoph 100</div>
|
<li className="flex list-row justify-between items-center" key={d.id}>
|
||||||
</div>
|
<div>
|
||||||
<div>INSERT BADGES HERE</div>
|
<div>{(d.publicUser as unknown as PublicUser)?.firstname}</div>
|
||||||
</li>
|
<div className="text-xs uppercase font-semibold opacity-60">{d.zone}</div>
|
||||||
|
</div>
|
||||||
<li className="flex list-row justify-between items-center">
|
<div>
|
||||||
<div>
|
{(d.publicUser as unknown as PublicUser).badges
|
||||||
<div>Sabrino Gardener</div>
|
.filter((b) => b.startsWith("D"))
|
||||||
<div className="text-xs uppercase font-semibold opacity-60">Christophorus 1</div>
|
.map((b) => (
|
||||||
</div>
|
<Badge name={b as BADGES} className="h-8 w-12" />
|
||||||
<div>INSERT BADGES HERE</div>
|
))}
|
||||||
</li>
|
</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const Map = dynamic(() => import("../_components/map/Map"), {
|
|||||||
const Page = () => {
|
const Page = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Map />;
|
<Map />
|
||||||
<ConnectedDispatcher />
|
<ConnectedDispatcher />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||