Mission Popup WIP
This commit is contained in:
@@ -58,6 +58,13 @@ interface MapStore {
|
||||
aircraftId: string,
|
||||
tab: MapStore["aircraftTabs"][string],
|
||||
) => void;
|
||||
missionTabs: {
|
||||
[missionId: string]: "home" | "details" | "chat";
|
||||
};
|
||||
setMissionTab: (
|
||||
missionId: string,
|
||||
tab: MapStore["missionTabs"][string],
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const useMapStore = create<MapStore>((set, get) => ({
|
||||
@@ -106,4 +113,12 @@ export const useMapStore = create<MapStore>((set, get) => ({
|
||||
[aircraftId]: tab,
|
||||
},
|
||||
})),
|
||||
missionTabs: {},
|
||||
setMissionTab: (missionId, tab) =>
|
||||
set((state) => ({
|
||||
missionTabs: {
|
||||
...state.missionTabs,
|
||||
[missionId]: tab,
|
||||
},
|
||||
})),
|
||||
}));
|
||||
|
||||
@@ -4,6 +4,7 @@ import { create } from "zustand";
|
||||
interface MissionStore {
|
||||
missions: MissionOptionalDefaults[];
|
||||
setMissions: (missions: MissionOptionalDefaults[]) => void;
|
||||
setMission: (mission: MissionOptionalDefaults) => void;
|
||||
}
|
||||
|
||||
export const useMissionsStore = create<MissionStore>((set) => ({
|
||||
@@ -24,4 +25,17 @@ export const useMissionsStore = create<MissionStore>((set) => ({
|
||||
},
|
||||
],
|
||||
setMissions: (missions) => set({ missions }),
|
||||
setMission: (mission) =>
|
||||
set((state) => {
|
||||
const existingMissionIndex = state.missions.findIndex(
|
||||
(m) => m.id === mission.id,
|
||||
);
|
||||
if (existingMissionIndex !== -1) {
|
||||
const updatedMissions = [...state.missions];
|
||||
updatedMissions[existingMissionIndex] = mission;
|
||||
return { missions: updatedMissions };
|
||||
} else {
|
||||
return { missions: [...state.missions, mission] };
|
||||
}
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -2,11 +2,19 @@ import { useMissionsStore } from "_store/missionsStore";
|
||||
import { Marker, Popup, useMap } from "react-leaflet";
|
||||
import { DivIcon, Marker as LMarker, Popup as LPopup } from "leaflet";
|
||||
import { useMapStore } from "_store/mapStore";
|
||||
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Fragment,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { cn } from "helpers/cn";
|
||||
import { Cross, House, Minimize2, Route } from "lucide-react";
|
||||
import { SmartPopup, useConflict, useSmartPopup } from "_components/SmartPopup";
|
||||
import { Mission, MissionState } from "@repo/db";
|
||||
import FMSStatusHistory from "./_components/MissionMarkerTabs";
|
||||
|
||||
export const MISSION_STATUS_COLORS: Record<MissionState, string> = {
|
||||
draft: "#0092b8",
|
||||
@@ -21,10 +29,38 @@ export const MISSION_STATUS_TEXT_COLORS: Record<MissionState, string> = {
|
||||
};
|
||||
|
||||
const MissionPopupContent = ({ mission }: { mission: Mission }) => {
|
||||
const setMissionTab = useMapStore((state) => state.setMissionTab);
|
||||
const currentTab = useMapStore(
|
||||
(state) => state.missionTabs[mission.id] || "home",
|
||||
);
|
||||
|
||||
const handleTabChange = useCallback(
|
||||
(tab: "home" | "details" | "chat") => {
|
||||
if (currentTab !== tab) {
|
||||
setMissionTab(mission.id, tab);
|
||||
}
|
||||
},
|
||||
[currentTab, mission.id, setMissionTab],
|
||||
);
|
||||
|
||||
const renderTabContent = useMemo(() => {
|
||||
switch (currentTab) {
|
||||
case "home":
|
||||
return <FMSStatusHistory />;
|
||||
case "details":
|
||||
return <div>Details Content</div>;
|
||||
case "chat":
|
||||
return <div>Chat Content</div>;
|
||||
default:
|
||||
return <span className="text-gray-100">Error</span>;
|
||||
}
|
||||
}, [currentTab]);
|
||||
|
||||
const setOpenMissionMarker = useMapStore(
|
||||
(state) => state.setOpenMissionMarker,
|
||||
);
|
||||
const { anchor } = useSmartPopup();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -36,7 +72,7 @@ const MissionPopupContent = ({ mission }: { mission: Mission }) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Minimize2 className="text-white " size={15} />
|
||||
<Minimize2 className="text-white" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -68,40 +104,47 @@ const MissionPopupContent = ({ mission }: { mission: Mission }) => {
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="p-2 flex justify-center items-center"
|
||||
className="p-2 px-3 flex justify-center items-center cursor-pointer"
|
||||
style={{
|
||||
backgroundColor: `${MISSION_STATUS_TEXT_COLORS[mission.state]}`,
|
||||
backgroundColor: `${MISSION_STATUS_COLORS[mission.state]}`,
|
||||
borderBottom:
|
||||
currentTab === "home"
|
||||
? `5px solid ${MISSION_STATUS_TEXT_COLORS[mission.state]}`
|
||||
: "5px solid transparent",
|
||||
}}
|
||||
onClick={() => handleTabChange("home")}
|
||||
>
|
||||
<House className="text-sm " />
|
||||
<House className="text-sm" />
|
||||
</div>
|
||||
<div
|
||||
className="p-2 flex justify-center items-center"
|
||||
className="p-2 px-4 flex justify-center items-center cursor-pointer"
|
||||
style={{
|
||||
backgroundColor: `${MISSION_STATUS_TEXT_COLORS[mission.state]}`,
|
||||
backgroundColor: `${MISSION_STATUS_COLORS[mission.state]}`,
|
||||
borderBottom:
|
||||
currentTab === "details"
|
||||
? `5px solid ${MISSION_STATUS_TEXT_COLORS[mission.state]}`
|
||||
: "5px solid transparent",
|
||||
}}
|
||||
onClick={() => handleTabChange("details")}
|
||||
>
|
||||
<Route className="text-sm " />
|
||||
<Route className="text-sm" />
|
||||
</div>
|
||||
<div
|
||||
className="flex justify-center items-center text-2xl p-2"
|
||||
className="p-2 px-4 flex justify-center items-center cursor-pointer"
|
||||
style={{
|
||||
backgroundColor: `${MISSION_STATUS_TEXT_COLORS[mission.state]}`,
|
||||
color: `${MISSION_STATUS_TEXT_COLORS[mission.state]}`,
|
||||
backgroundColor: `${MISSION_STATUS_COLORS[mission.state]}`,
|
||||
borderBottom:
|
||||
currentTab === "chat"
|
||||
? `5px solid ${MISSION_STATUS_TEXT_COLORS[mission.state]}`
|
||||
: "5px solid transparent",
|
||||
}}
|
||||
onClick={() => handleTabChange("chat")}
|
||||
>
|
||||
{mission.state}
|
||||
</div>
|
||||
<div
|
||||
className="p-2 flex-1 flex justify-center items-center"
|
||||
style={{
|
||||
backgroundColor: `${MISSION_STATUS_TEXT_COLORS[mission.state]}`,
|
||||
}}
|
||||
>
|
||||
<span className="text-sm text-white">Einsatz 250411</span>
|
||||
<Cross className="text-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>{renderTabContent}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -231,9 +274,11 @@ const MissionMarker = ({ mission }: { mission: Mission }) => {
|
||||
closeOnClick={false}
|
||||
autoPan={false}
|
||||
wrapperClassName="relative"
|
||||
className="w-[300px] h-[150px]"
|
||||
className="w-[502px]"
|
||||
>
|
||||
<MissionPopupContent mission={mission} />
|
||||
<div style={{ height: "auto", maxHeight: "90vh", overflowY: "auto" }}>
|
||||
<MissionPopupContent mission={mission} />
|
||||
</div>
|
||||
</SmartPopup>
|
||||
)}
|
||||
</Fragment>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import { FMS_STATUS_TEXT_COLORS } from "../AircraftMarker";
|
||||
|
||||
const FMSStatusHistory = () => {
|
||||
const dummyData = [
|
||||
{ status: "3", time: "12:00", unit: "RTW", unitshort: "RTW" },
|
||||
{ status: "3", time: "12:01", unit: "Christoph 31", unitshort: "CHX31" },
|
||||
{ status: "4", time: "12:09", unit: "RTW", unitshort: "RTW" },
|
||||
{ status: "4", time: "12:11", unit: "Christoph 31", unitshort: "CHX31" },
|
||||
{ status: "7", time: "12:34", unit: "RTW", unitshort: "RTW" },
|
||||
{ status: "1", time: "12:38", unit: "Christoph 31", unitshort: "CHX31" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
{[
|
||||
...new Map(dummyData.map((entry) => [entry.unit, entry])).values(),
|
||||
].map((entry, index, array) => (
|
||||
<React.Fragment key={index}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className="font-bold text-base"
|
||||
style={{
|
||||
color: FMS_STATUS_TEXT_COLORS[entry.status],
|
||||
}}
|
||||
>
|
||||
{entry.status}
|
||||
</span>
|
||||
<span className="text-base-content">{entry.unitshort}</span>
|
||||
</div>
|
||||
{index < array.length - 1 && <span className="mx-1">|</span>}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
<div className="divider m-0" />
|
||||
<ul className="space-y-2">
|
||||
{dummyData.map((entry, index) => (
|
||||
<li key={index} className="flex items-center gap-2">
|
||||
<span className="text-base-content">{entry.time}</span>
|
||||
<span
|
||||
className="font-bold text-base"
|
||||
style={{
|
||||
color: FMS_STATUS_TEXT_COLORS[entry.status],
|
||||
}}
|
||||
>
|
||||
{entry.status}
|
||||
</span>
|
||||
<span className="text-base-content">{entry.unit}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FMSStatusHistory;
|
||||
Reference in New Issue
Block a user