Edit Draft Mission
This commit is contained in:
@@ -7,11 +7,18 @@ interface PannelStore {
|
||||
setOpen: (isOpen: boolean) => void;
|
||||
missionFormValues?: Partial<MissionOptionalDefaults>;
|
||||
setMissionFormValues: (values: Partial<MissionOptionalDefaults>) => void;
|
||||
isEditingMission: boolean;
|
||||
editingMissionId: string | null;
|
||||
setEditingMission: (isEditing: boolean, missionId: string | null) => void;
|
||||
}
|
||||
|
||||
export const usePannelStore = create<PannelStore>((set) => ({
|
||||
isOpen: false, // DEBUG, REMOVE LATER FOR PROD
|
||||
isOpen: false,
|
||||
setOpen: (isOpen) => set({ isOpen }),
|
||||
missionFormValues: undefined,
|
||||
setMissionFormValues: (values) => set({ missionFormValues: values }),
|
||||
isEditingMission: false,
|
||||
editingMissionId: null,
|
||||
setEditingMission: (isEditing, missionId) =>
|
||||
set({ isEditingMission: isEditing, editingMissionId: missionId }),
|
||||
}));
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useMissionsStore } from "_store/missionsStore";
|
||||
import { Marker, useMap } from "react-leaflet";
|
||||
import { DivIcon, Marker as LMarker, Popup as LPopup } from "leaflet";
|
||||
import { useMapStore } from "_store/mapStore";
|
||||
import { usePannelStore } from "_store/pannelStore";
|
||||
import {
|
||||
Fragment,
|
||||
useCallback,
|
||||
@@ -18,6 +19,7 @@ import {
|
||||
Minimize2,
|
||||
Route,
|
||||
SmartphoneNfc,
|
||||
PencilLine,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
calculateAnchor,
|
||||
@@ -35,6 +37,7 @@ export const MISSION_STATUS_COLORS: Record<MissionState, string> = {
|
||||
draft: "#0092b8",
|
||||
running: "#155dfc",
|
||||
finished: "#155dfc",
|
||||
attention: "rgb(186,105,0)",
|
||||
};
|
||||
|
||||
export const MISSION_STATUS_TEXT_COLORS: Record<MissionState, string> = {
|
||||
@@ -44,6 +47,7 @@ export const MISSION_STATUS_TEXT_COLORS: Record<MissionState, string> = {
|
||||
};
|
||||
|
||||
const MissionPopupContent = ({ mission }: { mission: Mission }) => {
|
||||
const { setEditingMission } = usePannelStore();
|
||||
const setMissionMarker = useMapStore((state) => state.setOpenMissionMarker);
|
||||
const currentTab = useMapStore(
|
||||
(state) =>
|
||||
@@ -85,6 +89,7 @@ const MissionPopupContent = ({ mission }: { mission: Mission }) => {
|
||||
(state) => state.setOpenMissionMarker,
|
||||
);
|
||||
const { anchor } = useSmartPopup();
|
||||
const { setMissionFormValues, setOpen } = usePannelStore((state) => state);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -167,8 +172,30 @@ const MissionPopupContent = ({ mission }: { mission: Mission }) => {
|
||||
>
|
||||
<SmartphoneNfc className="text-sm" />
|
||||
</div>
|
||||
{mission.state === "draft" && (
|
||||
<div
|
||||
className="p-2 px-4 flex justify-center items-center cursor-pointer ml-auto"
|
||||
style={{
|
||||
backgroundColor: `${MISSION_STATUS_COLORS["attention"]}`,
|
||||
borderBottom: "5px solid transparent",
|
||||
}}
|
||||
onClick={() => {
|
||||
setMissionFormValues({
|
||||
...mission,
|
||||
state: "draft",
|
||||
});
|
||||
setEditingMission(true, mission.id);
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
<PencilLine className="text-sm" />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="p-2 px-4 flex justify-center items-center cursor-pointer ml-auto"
|
||||
className={cn(
|
||||
"p-2 px-4 flex justify-center items-center cursor-pointer",
|
||||
mission.state !== "draft" && "ml-auto",
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: `${MISSION_STATUS_COLORS[mission.state]}`,
|
||||
borderBottom:
|
||||
|
||||
@@ -28,7 +28,7 @@ import { useSession } from "next-auth/react";
|
||||
|
||||
const Einsatzdetails = ({ mission }: { mission: Mission }) => {
|
||||
const { deleteMission } = useMissionsStore((state) => state);
|
||||
const { setMissionFormValues } = usePannelStore((state) => state);
|
||||
const { setMissionFormValues, setOpen } = usePannelStore((state) => state);
|
||||
return (
|
||||
<div className="p-4 text-base-content">
|
||||
<h2 className="flex items-center gap-2 text-lg font-bold mb-3">
|
||||
@@ -81,6 +81,7 @@ const Einsatzdetails = ({ mission }: { mission: Mission }) => {
|
||||
hpgLocationLng: undefined,
|
||||
state: "draft",
|
||||
});
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
<Repeat2 size={18} /> Daten übernehmen
|
||||
|
||||
@@ -16,7 +16,10 @@ import { toast } from "react-hot-toast";
|
||||
import { useMissionsStore } from "_store/missionsStore";
|
||||
|
||||
export const MissionForm = () => {
|
||||
const { isEditingMission, editingMissionId, setEditingMission } =
|
||||
usePannelStore();
|
||||
const createMission = useMissionsStore((state) => state.createMission);
|
||||
const { deleteMission } = useMissionsStore((state) => state);
|
||||
const session = useSession();
|
||||
const defaultFormValues = React.useMemo(
|
||||
() =>
|
||||
@@ -41,7 +44,7 @@ export const MissionForm = () => {
|
||||
resolver: zodResolver(MissionOptionalDefaultsSchema),
|
||||
defaultValues: defaultFormValues,
|
||||
});
|
||||
const { missionFormValues } = usePannelStore((state) => state);
|
||||
const { missionFormValues, setOpen } = usePannelStore((state) => state);
|
||||
|
||||
useEffect(() => {
|
||||
if (session.data?.user.id) {
|
||||
@@ -290,44 +293,75 @@ export const MissionForm = () => {
|
||||
|
||||
<div className="form-control min-h-[140px] max-w-[320px]">
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-warning"
|
||||
onClick={form.handleSubmit(
|
||||
async (mission: MissionOptionalDefaults) => {
|
||||
try {
|
||||
const newMission = await createMission(mission);
|
||||
toast.success(`Einsatz ${newMission.id} erstellt`);
|
||||
// TODO: Einsatz alarmieren
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
`Fehler beim Erstellen des Einsatzes: ${(error as Error).message}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
)}
|
||||
>
|
||||
<BellRing className="h-4 w-4" /> Alarmieren
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-block"
|
||||
onClick={form.handleSubmit(
|
||||
async (mission: MissionOptionalDefaults) => {
|
||||
try {
|
||||
const newMission = await createMission(mission);
|
||||
toast.success(`Einsatz ${newMission.id} erstellt`);
|
||||
form.reset();
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
`Fehler beim Erstellen des Einsatzes: ${(error as Error).message}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
)}
|
||||
>
|
||||
<BookmarkPlus className="h-5 w-5" /> Einsatz vorbereiten
|
||||
</button>
|
||||
{isEditingMission && editingMissionId ? (
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-block"
|
||||
onClick={form.handleSubmit(
|
||||
async (mission: MissionOptionalDefaults) => {
|
||||
try {
|
||||
deleteMission(editingMissionId);
|
||||
const newMission = await createMission(mission);
|
||||
toast.success(
|
||||
`Einsatz ${newMission.id} erfolgreich aktualisiert`,
|
||||
);
|
||||
setEditingMission(false, null); // Reset editing state
|
||||
form.reset(); // Reset the form
|
||||
setOpen(false);
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
`Fehler beim Aktualisieren des Einsatzes: ${(error as Error).message}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
)}
|
||||
>
|
||||
Änderungen speichern
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-warning"
|
||||
onClick={form.handleSubmit(
|
||||
async (mission: MissionOptionalDefaults) => {
|
||||
try {
|
||||
const newMission = await createMission(mission);
|
||||
toast.success(`Einsatz ${newMission.id} erstellt`);
|
||||
// TODO: Einsatz alarmieren
|
||||
setOpen(false);
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
`Fehler beim Erstellen des Einsatzes: ${(error as Error).message}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
)}
|
||||
>
|
||||
<BellRing className="h-4 w-4" /> Alarmieren
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary btn-block"
|
||||
onClick={form.handleSubmit(
|
||||
async (mission: MissionOptionalDefaults) => {
|
||||
try {
|
||||
const newMission = await createMission(mission);
|
||||
toast.success(`Einsatz ${newMission.id} erstellt`);
|
||||
form.reset();
|
||||
setOpen(false);
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
`Fehler beim Erstellen des Einsatzes: ${(error as Error).message}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
)}
|
||||
>
|
||||
<BookmarkPlus className="h-5 w-5" /> Einsatz vorbereiten
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -5,22 +5,34 @@ import { Rss, Trash2Icon } from "lucide-react";
|
||||
|
||||
export const Pannel = () => {
|
||||
const { setOpen, setMissionFormValues } = usePannelStore();
|
||||
const { isEditingMission, editingMissionId, setEditingMission } =
|
||||
usePannelStore();
|
||||
|
||||
return (
|
||||
<div className={cn("flex-1 max-w-[600px] z-9999999")}>
|
||||
<div className="bg-base-100 min-h-screen h-full max-h-screen w-full overflow-auto">
|
||||
<div className="flex flex-row justify-between items-center p-4">
|
||||
<h1 className="text-xl font-bold flex items-center gap-2">
|
||||
<Rss /> Neuer Einsatz
|
||||
<Rss /> {isEditingMission ? "Einsatz bearbeiten" : "Neuer Einsatz"}
|
||||
</h1>
|
||||
<div>
|
||||
<button
|
||||
className="btn btn-ghost btn-sm mr-2 btn-warning"
|
||||
onClick={() => setMissionFormValues({})}
|
||||
onClick={() => {
|
||||
setMissionFormValues({});
|
||||
setEditingMission(false, null);
|
||||
}}
|
||||
>
|
||||
<Trash2Icon size={18} />
|
||||
</button>
|
||||
<button className="btn" onClick={() => setOpen(false)}>
|
||||
<button
|
||||
className="btn"
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
setEditingMission(false, null);
|
||||
setMissionFormValues({});
|
||||
}}
|
||||
>
|
||||
Abbrechen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user