Added DB integration for missions
This commit is contained in:
@@ -29,6 +29,7 @@ export const useMissionsStore = create<MissionStore>((set) => ({
|
|||||||
missionPatientInfo: "Test",
|
missionPatientInfo: "Test",
|
||||||
missionStationIds: [],
|
missionStationIds: [],
|
||||||
createdUserId: "1",
|
createdUserId: "1",
|
||||||
|
hpgMissionString: null,
|
||||||
missionLog: [],
|
missionLog: [],
|
||||||
missionStationUserIds: [],
|
missionStationUserIds: [],
|
||||||
hpgLocationLat: 52.520008,
|
hpgLocationLat: 52.520008,
|
||||||
@@ -49,7 +50,7 @@ export const useMissionsStore = create<MissionStore>((set) => ({
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(mission),
|
body: JSON.stringify(mission),
|
||||||
});
|
});
|
||||||
if (!res.ok) return undefined;
|
if (!res.ok) return new Error("Failed to create mission");
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
set((state) => ({ missions: [...state.missions, data] }));
|
set((state) => ({ missions: [...state.missions, data] }));
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export const ContextMenu = () => {
|
|||||||
road: string;
|
road: string;
|
||||||
state: string;
|
state: string;
|
||||||
city: string;
|
city: string;
|
||||||
|
town: string;
|
||||||
};
|
};
|
||||||
display_name: string;
|
display_name: string;
|
||||||
importance: number;
|
importance: number;
|
||||||
@@ -71,11 +72,12 @@ export const ContextMenu = () => {
|
|||||||
place_rank: number;
|
place_rank: number;
|
||||||
type: string;
|
type: string;
|
||||||
};
|
};
|
||||||
|
console.log(data);
|
||||||
setMissionFormValues({
|
setMissionFormValues({
|
||||||
addressLat: contextMenu.lat,
|
addressLat: contextMenu.lat,
|
||||||
addressLng: contextMenu.lng,
|
addressLng: contextMenu.lng,
|
||||||
addressCity: data.address.city,
|
addressCity: data.address.city || data.address.town,
|
||||||
addressStreet: `${data.address.road}, ${data.address.house_number}`,
|
addressStreet: `${data.address.road}, ${data.address.house_number || "keine HN"}`,
|
||||||
addressZip: data.address.postcode,
|
addressZip: data.address.postcode,
|
||||||
state: "draft",
|
state: "draft",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Audio } from "./_components/Audio";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ExitIcon, ExternalLinkIcon } from "@radix-ui/react-icons";
|
import { ExitIcon, ExternalLinkIcon } from "@radix-ui/react-icons";
|
||||||
import { Chat } from "./_components/Chat";
|
import { Chat } from "./_components/Chat";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
const [isDark, setIsDark] = useState(false);
|
const [isDark, setIsDark] = useState(false);
|
||||||
@@ -42,9 +43,11 @@ export default function Navbar() {
|
|||||||
<button className="btn btn-ghost">
|
<button className="btn btn-ghost">
|
||||||
<ExternalLinkIcon className="w-4 h-4" /> HUB
|
<ExternalLinkIcon className="w-4 h-4" /> HUB
|
||||||
</button>
|
</button>
|
||||||
|
<Link href={"/logout"}>
|
||||||
<button className="btn btn-ghost">
|
<button className="btn btn-ghost">
|
||||||
<ExitIcon className="w-4 h-4" />
|
<ExitIcon className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,25 +1,49 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import React, { use, useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { BellRing, BookmarkPlus, Trash2 } from "lucide-react";
|
import { BellRing, BookmarkPlus } from "lucide-react";
|
||||||
import { Select } from "_components/Select";
|
import { Select } from "_components/Select";
|
||||||
import { Keyword, Station } from "@repo/db";
|
import { Keyword, KEYWORD_CATEGORY, missionType, Station } from "@repo/db";
|
||||||
import { getKeywords, getStations } from "dispatch/_components/pannel/action";
|
import { getKeywords, getStations } from "dispatch/_components/pannel/action";
|
||||||
import {
|
import {
|
||||||
MissionOptionalDefaults,
|
MissionOptionalDefaults,
|
||||||
MissionOptionalDefaultsSchema,
|
MissionOptionalDefaultsSchema,
|
||||||
} from "@repo/db/zod";
|
} from "@repo/db/zod";
|
||||||
import { usePannelStore } from "_store/pannelStore";
|
import { usePannelStore } from "_store/pannelStore";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
import { toast } from "react-hot-toast";
|
||||||
|
import { useMissionsStore } from "_store/missionsStore";
|
||||||
|
|
||||||
export const MissionForm = () => {
|
export const MissionForm = () => {
|
||||||
|
const createMission = useMissionsStore((state) => state.createMission);
|
||||||
|
const session = useSession();
|
||||||
|
const defaultFormValues = React.useMemo(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
createdUserId: session.data?.user.id,
|
||||||
|
type: "primär",
|
||||||
|
addressOSMways: [],
|
||||||
|
hpgFireEngineState: null,
|
||||||
|
hpgAmbulanceState: null,
|
||||||
|
hpgPoliceState: null,
|
||||||
|
hpgMissionString: null,
|
||||||
|
missionLog: [],
|
||||||
|
}) as Partial<MissionOptionalDefaults>,
|
||||||
|
[session.data?.user.id],
|
||||||
|
);
|
||||||
|
|
||||||
const form = useForm<MissionOptionalDefaults>({
|
const form = useForm<MissionOptionalDefaults>({
|
||||||
resolver: zodResolver(MissionOptionalDefaultsSchema),
|
resolver: zodResolver(MissionOptionalDefaultsSchema),
|
||||||
defaultValues: {},
|
defaultValues: defaultFormValues,
|
||||||
});
|
});
|
||||||
const { missionFormValues, setMissionFormValues } = usePannelStore(
|
const { missionFormValues } = usePannelStore((state) => state);
|
||||||
(state) => state,
|
|
||||||
);
|
useEffect(() => {
|
||||||
|
if (session.data?.user.id) {
|
||||||
|
form.setValue("createdUserId", session.data.user.id);
|
||||||
|
}
|
||||||
|
}, [session.data?.user.id, form]);
|
||||||
|
|
||||||
/* const formValues = form.watch();
|
/* const formValues = form.watch();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -30,9 +54,12 @@ export const MissionForm = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (missionFormValues) {
|
if (missionFormValues) {
|
||||||
form.reset(missionFormValues);
|
form.reset({
|
||||||
|
...missionFormValues,
|
||||||
|
...defaultFormValues,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [missionFormValues, form]);
|
}, [missionFormValues, form, defaultFormValues]);
|
||||||
|
|
||||||
const [stations, setStations] = useState<Station[]>([]);
|
const [stations, setStations] = useState<Station[]>([]);
|
||||||
const [keywords, setKeywords] = useState<Keyword[]>([]);
|
const [keywords, setKeywords] = useState<Keyword[]>([]);
|
||||||
@@ -46,12 +73,10 @@ export const MissionForm = () => {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onSubmit = (data: MissionOptionalDefaults) => {
|
console.log(
|
||||||
console.log({
|
form.watch("missionKeywordName"),
|
||||||
...data,
|
form.watch("missionKeywordAbbreviation"),
|
||||||
});
|
);
|
||||||
};
|
|
||||||
|
|
||||||
console.log(form.formState.errors);
|
console.log(form.formState.errors);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -127,6 +152,12 @@ export const MissionForm = () => {
|
|||||||
<select
|
<select
|
||||||
{...form.register("type")}
|
{...form.register("type")}
|
||||||
className="select select-primary select-bordered w-full mb-4"
|
className="select select-primary select-bordered w-full mb-4"
|
||||||
|
onChange={(e) => {
|
||||||
|
form.setValue("type", e.target.value as missionType);
|
||||||
|
form.setValue("missionKeywordName", null);
|
||||||
|
form.setValue("missionKeywordAbbreviation", null);
|
||||||
|
form.setValue("hpgMissionString", null);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<option value="primär">PRIMÄR</option>
|
<option value="primär">PRIMÄR</option>
|
||||||
<option value="sekundär">SEKUNDÄR</option>
|
<option value="sekundär">SEKUNDÄR</option>
|
||||||
@@ -134,14 +165,52 @@ export const MissionForm = () => {
|
|||||||
{form.watch("type") === "primär" && (
|
{form.watch("type") === "primär" && (
|
||||||
<>
|
<>
|
||||||
<select
|
<select
|
||||||
{...form.register("missionKeyword")}
|
{...form.register("missionKeywordCategory")}
|
||||||
className="select select-primary select-bordered w-full mb-4"
|
className="select select-primary select-bordered w-full mb-4"
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
form.setValue("missionKeyword", e.target.value as string)
|
form.setValue(
|
||||||
}
|
"missionKeywordCategory",
|
||||||
|
e.target.value as string,
|
||||||
|
);
|
||||||
|
form.setValue("missionKeywordName", null);
|
||||||
|
form.setValue("missionKeywordAbbreviation", null);
|
||||||
|
form.setValue("hpgMissionString", null);
|
||||||
|
}}
|
||||||
|
defaultValue="default"
|
||||||
>
|
>
|
||||||
{keywords.map((keyword) => (
|
<option disabled value="default">
|
||||||
<option key={keyword.id} value={keyword.name}>
|
Einsatz Kathegorie auswählen...
|
||||||
|
</option>
|
||||||
|
{Object.keys(KEYWORD_CATEGORY).map((use) => (
|
||||||
|
<option key={use} value={use}>
|
||||||
|
{use}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<select
|
||||||
|
{...form.register("missionKeywordAbbreviation")}
|
||||||
|
className="select select-primary select-bordered w-full mb-4"
|
||||||
|
onChange={(e) => {
|
||||||
|
const keyword = keywords.find(
|
||||||
|
(k) => k.abreviation === e.target.value,
|
||||||
|
);
|
||||||
|
form.setValue("missionKeywordName", keyword?.name || null);
|
||||||
|
form.setValue(
|
||||||
|
"missionKeywordAbbreviation",
|
||||||
|
keyword?.abreviation || null,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
defaultValue="default"
|
||||||
|
>
|
||||||
|
<option disabled value="default">
|
||||||
|
Einsatzstichwort auswählen...
|
||||||
|
</option>
|
||||||
|
{keywords
|
||||||
|
.filter(
|
||||||
|
(k) => k.category === form.watch("missionKeywordCategory"),
|
||||||
|
)
|
||||||
|
.map((keyword) => (
|
||||||
|
<option key={keyword.id} value={keyword.abreviation}>
|
||||||
{keyword.name}
|
{keyword.name}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
@@ -150,15 +219,23 @@ export const MissionForm = () => {
|
|||||||
/* {...form.register("missionKeyword")} */
|
/* {...form.register("missionKeyword")} */
|
||||||
className="select select-primary select-bordered w-full mb-4"
|
className="select select-primary select-bordered w-full mb-4"
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
form.setValue("missionKeyword", e.target.value as string)
|
form.setValue("hpgMissionString", e.target.value as string)
|
||||||
}
|
}
|
||||||
|
defaultValue="default"
|
||||||
>
|
>
|
||||||
<option defaultChecked disabled value="">
|
<option disabled value="default">
|
||||||
Einsatz Szenerie auswählen...
|
Einsatz Szenerie auswählen...
|
||||||
</option>
|
</option>
|
||||||
<option value="typ1">typ1</option>
|
{keywords
|
||||||
<option value="typ2">typ2</option>
|
.find((k) => k.name === form.watch("missionKeywordName"))
|
||||||
<option value="typ3">typ3</option>
|
?.hpgMissionTypes?.map((missionString) => {
|
||||||
|
const [name, code] = missionString.split(":");
|
||||||
|
return (
|
||||||
|
<option key={missionString} value={missionString}>
|
||||||
|
{name}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</select>
|
</select>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -195,9 +272,19 @@ export const MissionForm = () => {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-warning"
|
className="btn btn-warning"
|
||||||
onClick={form.handleSubmit(() => {
|
onClick={form.handleSubmit(
|
||||||
console.log("Alarmieren");
|
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
|
<BellRing className="h-4 w-4" /> Alarmieren
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Binary file not shown.
@@ -16,6 +16,7 @@ model Mission {
|
|||||||
missionStationIds String[] @default([])
|
missionStationIds String[] @default([])
|
||||||
missionStationUserIds String[] @default([])
|
missionStationUserIds String[] @default([])
|
||||||
missionLog Json[] @default([])
|
missionLog Json[] @default([])
|
||||||
|
hpgMissionString String?
|
||||||
hpgAmbulanceState HpgState?
|
hpgAmbulanceState HpgState?
|
||||||
hpgFireEngineState HpgState?
|
hpgFireEngineState HpgState?
|
||||||
hpgPoliceState HpgState?
|
hpgPoliceState HpgState?
|
||||||
|
|||||||
Reference in New Issue
Block a user