Marker für HPG Position-amanded, prettier plugin für Tailwind, #61

This commit is contained in:
PxlLoewe
2025-07-18 17:00:31 -07:00
parent 23c0d601eb
commit 15012820ab
10 changed files with 188 additions and 69 deletions

View File

@@ -2,5 +2,6 @@
"tabWidth": 2,
"useTabs": true,
"printWidth": 100,
"singleQuote": false
"singleQuote": false,
"plugins": ["prettier-plugin-tailwindcss"]
}

View File

@@ -15,15 +15,15 @@ const DispatchPage = () => {
const { isOpen } = usePannelStore();
/* return null; */
return (
<div className="relative flex-1 flex transition-all duration-500 ease w-full">
<div className="ease relative flex w-full flex-1 transition-all duration-500">
{/* <MapToastCard2 /> */}
<div className="flex flex-1 relative">
<div className="absolute left-0 top-1/2 transform -translate-y-1/2 pl-4 z-999999 space-y-2">
<div className="relative flex flex-1">
<div className="z-999999 absolute left-0 top-1/2 flex -translate-y-1/2 transform flex-col space-y-2 pl-4">
<Chat />
<Report />
<BugReport />
</div>
<div className="absolute left-0 top-19/20 transform -translate-y-1/2 pl-4 z-999999">
<div className="top-19/20 z-999999 absolute left-0 -translate-y-1/2 transform pl-4">
<div className="flex items-center justify-between gap-4">
<SituationBoard />
</div>
@@ -32,7 +32,7 @@ const DispatchPage = () => {
</div>
<div
className={cn(
"absolute right-0 w-[500px] z-999 transition-transform",
"z-999 absolute right-0 w-[500px] transition-transform",
isOpen ? "translate-x-0" : "translate-x-full",
)}
>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 366 KiB

View File

@@ -30,23 +30,23 @@ const PilotPage = () => {
const ownAircraft = aircrafts?.find((aircraft) => aircraft.id === connectedAircraft?.id);
const simulatorConnected = ownAircraft ? checkSimulatorConnected(ownAircraft) : false;
return (
<div className="relative flex-1 flex transition-all duration-500 ease w-full h-screen overflow-hidden">
<div className="ease relative flex h-screen w-full flex-1 overflow-hidden transition-all duration-500">
{/* <MapToastCard2 /> */}
<div className="flex flex-1 relative w-full h-full">
<div className="absolute left-0 top-1/2 transform -translate-y-1/2 pl-4 z-999999 space-y-2">
<div className="relative flex h-full w-full flex-1">
<div className="z-999999 absolute left-0 top-1/2 flex -translate-y-1/2 transform flex-col space-y-2 pl-4">
<Chat />
<Report />
<BugReport />
</div>
<div className="flex w-2/3 h-full">
<div className="relative flex flex-1 h-full">
<div className="absolute left-0 top-19/20 transform -translate-y-1/2 pl-4 z-999999">
<div className="flex h-full w-2/3">
<div className="relative flex h-full flex-1">
<div className="top-19/20 z-999999 absolute left-0 -translate-y-1/2 transform pl-4">
<div className="flex items-center justify-between gap-4">
<SettingsBoard />
</div>
</div>
<Map />
<div className="absolute top-5 right-10 z-99999 space-y-2">
<div className="z-99999 absolute right-10 top-5 space-y-2">
{!simulatorConnected && status === "connected" && (
<SimConnectionAlert lastUpdated={ownAircraft?.lastHeartbeat} />
)}
@@ -54,18 +54,18 @@ const PilotPage = () => {
</div>
</div>
</div>
<div className="flex w-1/3 h-full">
<div className="flex flex-col w-full h-full p-4 bg-base-300">
<div className="flex h-full w-1/3">
<div className="bg-base-300 flex h-full w-full flex-col p-4">
<h2 className="card-title mb-2">MRT & DME</h2>
<div className="card bg-base-200 shadow-xl mb-4">
<div className="card-body w-full h-full flex items-center justify-center">
<div className="card bg-base-200 mb-4 shadow-xl">
<div className="card-body flex h-full w-full items-center justify-center">
<div className="max-w-150">
<Mrt />
</div>
</div>
</div>
<div className="card bg-base-200 shadow-xl h-1/2 flex">
<div className="card-body w-full h-full p-4 mb-0 flex items-center justify-center">
<div className="card bg-base-200 flex h-1/2 shadow-xl">
<div className="card-body mb-0 flex h-full w-full items-center justify-center p-4">
<div className="max-w-140">
<Dme />
</div>

View File

@@ -2,19 +2,75 @@
import { usePannelStore } from "_store/pannelStore";
import { Marker } from "react-leaflet";
import L from "leaflet";
import { useQuery } from "@tanstack/react-query";
import { getMissionsAPI } from "_querys/missions";
import { HPGValidationRequired } from "_helpers/hpgValidationRequired";
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
import { useMapStore } from "_store/mapStore";
export const MapAdditionals = () => {
const missionForm = usePannelStore((state) => state.missionFormValues);
const { isOpen, missionFormValues } = usePannelStore((state) => state);
const { data: missions = [] } = useQuery({
queryKey: ["missions"],
queryFn: () =>
getMissionsAPI({
OR: [{ state: "draft" }, { state: "running" }],
}),
refetchInterval: 10_000,
});
const mapStore = useMapStore((state) => state);
if (!missionForm?.addressLat || !missionForm?.addressLng) return null;
const { data: aircrafts } = useQuery({
queryKey: ["aircrafts"],
queryFn: () => getConnectedAircraftsAPI(),
refetchInterval: 10000,
});
const markersNeedingAttention = missions.filter(
(m) =>
HPGValidationRequired(m.missionStationIds, aircrafts, m.hpgMissionString) &&
m.hpgValidationState === "POSITION_AMANDED" &&
m.state === "draft" &&
m.hpgLocationLat &&
m.hpgLocationLng,
);
return (
<>
{missionFormValues?.addressLat && missionFormValues?.addressLng && isOpen && (
<Marker
position={[missionForm.addressLat, missionForm.addressLng]}
icon={L.icon({ iconUrl: "/icons/mapMarker.png", iconSize: [40, 40], iconAnchor: [20, 35] })}
position={[missionFormValues.addressLat, missionFormValues.addressLng]}
icon={L.icon({
iconUrl: "/icons/mapMarker.png",
iconSize: [40, 40],
iconAnchor: [20, 35],
})}
interactive={false}
/>
)}
{markersNeedingAttention.map((mission) => (
<Marker
key={mission.id}
position={[mission.hpgLocationLat!, mission.hpgLocationLng!]}
icon={L.icon({
iconUrl: "/icons/mapMarker.png",
iconSize: [40, 40],
iconAnchor: [20, 35],
})}
eventHandlers={{
click: () =>
mapStore.setOpenMissionMarker({
open: [
{
id: mission.id,
tab: "home",
},
],
close: [],
}),
}}
/>
))}
</>
);
};

View File

@@ -338,22 +338,15 @@ const MissionMarker = ({ mission }: { mission: Mission }) => {
return [
editingMissionId === mission.id && missionFormValues?.addressLat
? missionFormValues.addressLat
: mission.hpgValidationState !== "POSITION_AMANDED" && mission.hpgLocationLat
? mission.hpgLocationLat
: mission.addressLat,
editingMissionId === mission.id && missionFormValues?.addressLng
? missionFormValues.addressLng
: mission.hpgValidationState !== "POSITION_AMANDED" && mission.hpgLocationLng
? mission.hpgLocationLng
: mission.addressLng,
];
}, [
editingMissionId,
mission.addressLat,
mission.addressLng,
mission.hpgLocationLat,
mission.hpgLocationLng,
mission.hpgValidationState,
mission.id,
missionFormValues?.addressLat,
missionFormValues?.addressLng,

View File

@@ -93,8 +93,8 @@ const Einsatzdetails = ({
const { setMissionFormValues, setOpen, setEditingMission } = usePannelStore((state) => state);
const [ignoreHpg, setIgnoreHpg] = useState(false);
return (
<div className="p-4 text-base-content">
<div className="flex items-center justify-between mb-3">
<div className="text-base-content p-4">
<div className="mb-3 flex items-center justify-between">
<h2 className="flex items-center gap-2 text-lg font-bold">
<Flag /> Einsatzdetails
</h2>
@@ -126,7 +126,7 @@ const Einsatzdetails = ({
</button>
</div>
<div
className="tooltip tooltip-warning tooltip-left font-semibold z-[9999]"
className="tooltip tooltip-warning tooltip-left z-[9999] font-semibold"
data-tip="Einsatz abschließen"
>
<button
@@ -161,19 +161,19 @@ const Einsatzdetails = ({
)}
</div>
<ul className="text-base-content font-semibold">
<li className="flex items-center gap-2 mb-1">
<li className="mb-1 flex items-center gap-2">
<BellRing size={16} /> {mission.missionKeywordCategory}
</li>
<li className="flex items-center gap-2 mb-1">
<li className="mb-1 flex items-center gap-2">
<ListCollapse size={16} />
{mission.missionKeywordName}
</li>
<li className="flex items-center gap-2 mt-3">
<li className="mt-3 flex items-center gap-2">
<Hash size={16} />
{mission.publicId}
</li>
</ul>
<div className="divider mt-0 mb-0" />
<div className="divider mb-0 mt-0" />
<div className="text-sm font-semibold">
<p className="flex items-center gap-2">
<MapPin size={16} /> {mission.addressLat} {mission.addressLng}
@@ -192,7 +192,7 @@ const Einsatzdetails = ({
</div>
{mission.type == "sekundär" && (
<>
<div className="divider mt-0 mb-0" />
<div className="divider mb-0 mt-0" />
<div className="text-sm font-semibold">
<p className="flex items-center gap-2">
<Route size={16} /> {mission.addressMissionDestination}
@@ -202,11 +202,11 @@ const Einsatzdetails = ({
)}
{mission.state === "draft" && (
<div>
<div className="divider mt-0 mb-0" />
<div className="divider mb-0 mt-0" />
{hpgNeedsAttention && mission.hpgValidationState !== "POSITION_AMANDED" && (
<div className="form-control mb-2 flex justify-between items-center">
<label className="flex items-center gap-2 cursor-pointer">
<div className="form-control mb-2 flex items-center justify-between">
<label className="flex cursor-pointer items-center gap-2">
<input
type="checkbox"
className="checkbox checkbox-sm checkbox-primary"
@@ -214,7 +214,7 @@ const Einsatzdetails = ({
onChange={(e) => setIgnoreHpg(e.target.checked)}
/>
<span
className="label-text font-semibold leading-6 tooltip"
className="label-text tooltip font-semibold leading-6"
data-tip="Die HPG-Alarmierung wird trotzdem ausgeführt. Die Position des HPG-Einsatzes kann gravierend von der Einsatzposition abweichen"
>
HPG-Fehler ignorieren
@@ -235,7 +235,7 @@ const Einsatzdetails = ({
</div>
)}
<div className="flex items-center gap-2 w-full">
<div className="flex w-full items-center gap-2">
{(!hpgNeedsAttention || ignoreHpg) &&
mission.hpgValidationState !== HpgValidationState.POSITION_AMANDED && (
<button
@@ -354,13 +354,13 @@ const Einsatzdetails = ({
const Patientdetails = ({ mission }: { mission: Mission }) => {
return (
<div className="p-4 text-base-content">
<h2 className="flex items-center gap-2 text-lg font-bold mb-3">
<div className="text-base-content p-4">
<h2 className="mb-3 flex items-center gap-2 text-lg font-bold">
<User /> Patientendetails
</h2>
<p className="text-base-content font-semibold">{mission.missionPatientInfo}</p>
<div className="divider my-2" />
<h2 className="flex items-center gap-2 text-lg font-bold mb-3">
<h2 className="mb-3 flex items-center gap-2 text-lg font-bold">
<Cross /> Einsatzinformationen
</h2>
<p className="text-base-content font-semibold">{mission.missionAdditionalInfo}</p>
@@ -440,7 +440,7 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
const HPGVehicle = ({ state, name }: { state: HpgState; name: string }) => (
<li className="flex items-center gap-2">
<span
className="font-bold text-base"
className="text-base font-bold"
style={{
color: FMS_STATUS_TEXT_COLORS[hpgStateToFMSStatus(state)],
}}
@@ -457,8 +457,8 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
);
return (
<div className="p-4 text-base-content">
<div className="flex items-center w-full justify-between mb-2">
<div className="text-base-content p-4">
<div className="mb-2 flex w-full items-center justify-between">
<h2 className="flex items-center gap-2 text-lg font-bold">
<SmartphoneNfc /> Rettungsmittel
</h2>
@@ -480,9 +480,9 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
</div>
)}
</div>
<ul className="space-y-2 h-[130px] overflow-y-auto overflow-x-auto flex-1">
<ul className="h-[130px] flex-1 space-y-2 overflow-x-auto overflow-y-auto">
{mission.missionStationIds.length === 0 && (
<p className="text-gray-500 w-full text-center my-10 font-semibold">
<p className="my-10 w-full text-center font-semibold text-gray-500">
Keine Rettungsmittel zugewiesen
</p>
)}
@@ -494,7 +494,7 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
return (
<li key={index} className="flex items-center gap-2">
<span
className="font-bold text-base"
className="text-base font-bold"
style={{
color: FMS_STATUS_TEXT_COLORS[connectedAircraft?.fmsStatus || "6"],
}}
@@ -504,7 +504,7 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
<span className="text-base-content flex flex-col">
<span className="font-bold">{station.bosCallsign}</span>
{!connectedAircraft && (
<span className="text-gray-400 text-xs">Kein Benutzer verbunden</span>
<span className="text-xs text-gray-400">Kein Benutzer verbunden</span>
)}
</span>
</li>
@@ -522,7 +522,7 @@ const Rettungsmittel = ({ mission }: { mission: Mission }) => {
</ul>
{dispatcherConnected && (
<div>
<div className="divider mt-0 mb-0" />
<div className="divider mb-0 mt-0" />
<div className="flex items-center gap-2">
{/* TODO: make it a small multiselect */}
<StationsSelect
@@ -657,7 +657,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
<div className="flex items-center gap-2">
{!isAddingNote ? (
<button
className="text-base-content text-base cursor-pointer"
className="text-base-content cursor-pointer text-base"
onClick={() => setIsAddingNote(true)}
>
<span className="flex items-center gap-2">
@@ -665,7 +665,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
</span>
</button>
) : (
<div className="flex items-center gap-2 w-full">
<div className="flex w-full items-center gap-2">
<input
type="text"
placeholder=""
@@ -697,7 +697,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
<div className="divider m-0" />
</div>
)}
<ul className="space-y-1 max-h-[300px] overflow-y-auto overflow-x-auto">
<ul className="max-h-[300px] space-y-1 overflow-x-auto overflow-y-auto">
{(mission.missionLog as unknown as MissionLog[])
.slice()
.reverse()
@@ -712,7 +712,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
})}
</span>
<span
className="font-bold text-base"
className="text-base font-bold"
style={{
color: FMS_STATUS_TEXT_COLORS[entry.data.newFMSstatus],
}}
@@ -732,7 +732,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
})}
</span>
<span
className="font-bold text-base flex items-center gap-0.5"
className="flex items-center gap-0.5 text-base font-bold"
style={{
color: FMS_STATUS_TEXT_COLORS[6],
}}
@@ -781,7 +781,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
})}
</span>
<span
className="font-bold text-base flex items-center gap-0.5"
className="flex items-center gap-0.5 text-base font-bold"
style={{
color: FMS_STATUS_TEXT_COLORS[6],
}}
@@ -830,7 +830,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
})}
</ul>
{!mission.missionLog.length && (
<p className="text-gray-500 w-full text-center my-10 font-semibold">
<p className="my-10 w-full text-center font-semibold text-gray-500">
Keine Notizen verfügbar
</p>
)}

View File

@@ -13,6 +13,7 @@
},
"devDependencies": {
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"turbo": "^2.5.5",
"typescript": "^5.8.3"
},

68
pnpm-lock.yaml generated
View File

@@ -15,6 +15,9 @@ importers:
prettier:
specifier: ^3.6.2
version: 3.6.2
prettier-plugin-tailwindcss:
specifier: ^0.6.14
version: 0.6.14(prettier@3.6.2)
turbo:
specifier: ^2.5.5
version: 2.5.5
@@ -4416,6 +4419,67 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
prettier-plugin-tailwindcss@0.6.14:
resolution: {integrity: sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==}
engines: {node: '>=14.21.3'}
peerDependencies:
'@ianvs/prettier-plugin-sort-imports': '*'
'@prettier/plugin-hermes': '*'
'@prettier/plugin-oxc': '*'
'@prettier/plugin-pug': '*'
'@shopify/prettier-plugin-liquid': '*'
'@trivago/prettier-plugin-sort-imports': '*'
'@zackad/prettier-plugin-twig': '*'
prettier: ^3.0
prettier-plugin-astro: '*'
prettier-plugin-css-order: '*'
prettier-plugin-import-sort: '*'
prettier-plugin-jsdoc: '*'
prettier-plugin-marko: '*'
prettier-plugin-multiline-arrays: '*'
prettier-plugin-organize-attributes: '*'
prettier-plugin-organize-imports: '*'
prettier-plugin-sort-imports: '*'
prettier-plugin-style-order: '*'
prettier-plugin-svelte: '*'
peerDependenciesMeta:
'@ianvs/prettier-plugin-sort-imports':
optional: true
'@prettier/plugin-hermes':
optional: true
'@prettier/plugin-oxc':
optional: true
'@prettier/plugin-pug':
optional: true
'@shopify/prettier-plugin-liquid':
optional: true
'@trivago/prettier-plugin-sort-imports':
optional: true
'@zackad/prettier-plugin-twig':
optional: true
prettier-plugin-astro:
optional: true
prettier-plugin-css-order:
optional: true
prettier-plugin-import-sort:
optional: true
prettier-plugin-jsdoc:
optional: true
prettier-plugin-marko:
optional: true
prettier-plugin-multiline-arrays:
optional: true
prettier-plugin-organize-attributes:
optional: true
prettier-plugin-organize-imports:
optional: true
prettier-plugin-sort-imports:
optional: true
prettier-plugin-style-order:
optional: true
prettier-plugin-svelte:
optional: true
prettier@3.6.2:
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
engines: {node: '>=14'}
@@ -10263,6 +10327,10 @@ snapshots:
prelude-ls@1.2.1: {}
prettier-plugin-tailwindcss@0.6.14(prettier@3.6.2):
dependencies:
prettier: 3.6.2
prettier@3.6.2: {}
pretty-format@3.8.0: {}