added mission fields
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Prisma } from "@repo/db";
|
||||
import { Mission, Prisma } from "@repo/db";
|
||||
import { MissionOptionalDefaults } from "@repo/db/zod";
|
||||
import { create } from "zustand";
|
||||
|
||||
@@ -6,29 +6,29 @@ interface MissionStore {
|
||||
missions: MissionOptionalDefaults[];
|
||||
setMissions: (missions: MissionOptionalDefaults[]) => void;
|
||||
getMissions: () => Promise<undefined>;
|
||||
createMission: (mission: MissionOptionalDefaults) => Promise<Mission>;
|
||||
setMission: (mission: MissionOptionalDefaults) => void;
|
||||
}
|
||||
|
||||
export const useMissionsStore = create<MissionStore>((set) => ({
|
||||
missions: [
|
||||
{
|
||||
state: "draft",
|
||||
id: "01250325",
|
||||
addressLat: 52.520008,
|
||||
addressLng: 13.404954,
|
||||
addressStreet: "Alexanderplatz",
|
||||
addressCity: "Berlin",
|
||||
addressZip: "10178",
|
||||
missionAdditionalInfo: "Additional info",
|
||||
missionCategory: "AB_Atmung",
|
||||
missionKeyword: "Zunehmende Beschwerden",
|
||||
missionSummary: "AB1_0",
|
||||
missionPatientInfo: "M/10",
|
||||
},
|
||||
],
|
||||
missions: [],
|
||||
setMissions: (missions) => set({ missions }),
|
||||
createMission: async (mission) => {
|
||||
const res = await fetch("/api/mission", {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(mission),
|
||||
});
|
||||
if (!res.ok) return undefined;
|
||||
const data = await res.json();
|
||||
set((state) => ({ missions: [...state.missions, data] }));
|
||||
return data;
|
||||
},
|
||||
getMissions: async () => {
|
||||
const res = await fetch("/api/mission", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
@@ -62,3 +62,10 @@ export const useMissionsStore = create<MissionStore>((set) => ({
|
||||
}
|
||||
}),
|
||||
}));
|
||||
|
||||
useMissionsStore
|
||||
.getState()
|
||||
.getMissions()
|
||||
.then(() => {
|
||||
console.log("Missions loaded");
|
||||
});
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
import { Prisma, prisma } from "@repo/db";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export const GET = (req: NextRequest) => {
|
||||
const filter = req.nextUrl.searchParams.get("filter") as
|
||||
| Prisma.MissionWhereInput
|
||||
| undefined;
|
||||
export const POST = async (req: NextRequest) => {
|
||||
console.log(req.body);
|
||||
const body = await req.json();
|
||||
console.log(body);
|
||||
|
||||
const missions = prisma.mission.findMany({
|
||||
where: filter,
|
||||
const missions = await prisma.mission.findMany({
|
||||
where: (body.filter as Prisma.MissionWhereInput) || {},
|
||||
});
|
||||
|
||||
return NextResponse.json(missions);
|
||||
};
|
||||
|
||||
export const PUT = async (req: NextRequest) => {
|
||||
const body = await req.json();
|
||||
|
||||
const newMission = await prisma.mission.create({
|
||||
data: body,
|
||||
});
|
||||
|
||||
return NextResponse.json(newMission);
|
||||
};
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import { MissionSchema } from "@repo/db/zod";
|
||||
import { BellRing, BookmarkPlus, Trash2 } from "lucide-react";
|
||||
import { Select } from "_components/Select";
|
||||
import { Keyword, Station } from "@repo/db";
|
||||
import { getKeywords, getStations } from "dispatch/_components/pannel/action";
|
||||
import { MissionCreateInputSchema } from "@repo/db/zod";
|
||||
|
||||
const clearBtn = () => {
|
||||
return (
|
||||
@@ -15,59 +17,35 @@ const clearBtn = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const missionFormSchema = MissionSchema.pick({
|
||||
addressLat: true,
|
||||
addressLng: true,
|
||||
addressStreet: true,
|
||||
addressCity: true,
|
||||
addressZip: true,
|
||||
missionCategory: true,
|
||||
missionKeyword: true,
|
||||
missionAdditionalInfo: true,
|
||||
missionPatientInfo: true,
|
||||
});
|
||||
export const MissionForm = () => {
|
||||
type MissionFormValues = z.infer<typeof MissionCreateInputSchema>;
|
||||
|
||||
type MissionFormValues = z.infer<typeof missionFormSchema>;
|
||||
|
||||
const dummyRettungsmittel = [
|
||||
"RTW",
|
||||
"Feuerwehr",
|
||||
"Polizei",
|
||||
"Christoph 31",
|
||||
"Christoph 100",
|
||||
"Christoph Berlin",
|
||||
"Christophorus 1",
|
||||
];
|
||||
|
||||
export const MissionForm: React.FC = () => {
|
||||
const [missionCategory, setMissionCategory] = useState<"PRIMÄR" | "SEKUNDÄR">(
|
||||
"PRIMÄR",
|
||||
);
|
||||
const [missionKeyword, setMissionKeyword] = useState<
|
||||
"AB_ATMUNG" | "C_BLUTUNG"
|
||||
>("AB_ATMUNG");
|
||||
const [missionType, setMissionType] = useState<"typ1" | "typ2" | "typ3">(
|
||||
"typ1",
|
||||
);
|
||||
const [selectedRettungsmittel, setSelectedRettungsmittel] = useState<
|
||||
{ label: string; value: string }[]
|
||||
>([]);
|
||||
const form = useForm<MissionFormValues>({
|
||||
resolver: zodResolver(missionFormSchema),
|
||||
defaultValues: {
|
||||
addressLat: 0,
|
||||
addressLng: 0,
|
||||
missionCategory: "PRIMÄR",
|
||||
},
|
||||
resolver: zodResolver(MissionCreateInputSchema),
|
||||
defaultValues: {},
|
||||
});
|
||||
|
||||
const [stations, setStations] = useState<Station[]>([]);
|
||||
const [keywords, setKeywords] = useState<Keyword[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("useEffect");
|
||||
getKeywords().then((data) => {
|
||||
setKeywords(data);
|
||||
});
|
||||
getStations().then((data) => {
|
||||
setStations(data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onSubmit = (data: MissionFormValues) => {
|
||||
console.log({
|
||||
...data,
|
||||
rettungsmittel: selectedRettungsmittel.map((item) => item.value),
|
||||
});
|
||||
};
|
||||
|
||||
console.log(form.formState.errors);
|
||||
|
||||
return (
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||
{/* Koorinaten Section */}
|
||||
@@ -78,13 +56,13 @@ export const MissionForm: React.FC = () => {
|
||||
type="text"
|
||||
{...form.register("addressLat")}
|
||||
className="input input-sm input-neutral input-bordered w-full"
|
||||
readOnly
|
||||
disabled
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
{...form.register("addressLng")}
|
||||
className="input input-sm input-neutral input-bordered w-full"
|
||||
readOnly
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,9 +106,9 @@ export const MissionForm: React.FC = () => {
|
||||
label={""}
|
||||
isMulti
|
||||
form={form}
|
||||
options={dummyRettungsmittel.map((key, val) => ({
|
||||
label: key,
|
||||
value: val,
|
||||
options={stations.map((s) => ({
|
||||
label: s.bosCallsign,
|
||||
value: s.id,
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
@@ -139,45 +117,49 @@ export const MissionForm: React.FC = () => {
|
||||
<div className="form-control">
|
||||
<h2 className="text-lg font-bold mb-2">Einsatzdaten</h2>
|
||||
<select
|
||||
{...form.register("missionCategory")}
|
||||
{...form.register("type")}
|
||||
className="select select-primary select-bordered w-full mb-4"
|
||||
onChange={(e) =>
|
||||
setMissionCategory(e.target.value as "PRIMÄR" | "SEKUNDÄR")
|
||||
}
|
||||
>
|
||||
<option value="PRIMÄR">PRIMÄR</option>
|
||||
<option value="SEKUNDÄR">SEKUNDÄR</option>
|
||||
</select>
|
||||
<select
|
||||
{...form.register("missionKeyword")}
|
||||
className="select select-primary select-bordered w-full mb-4"
|
||||
onChange={(e) =>
|
||||
setMissionKeyword(e.target.value as "AB_ATMUNG" | "C_BLUTUNG")
|
||||
}
|
||||
>
|
||||
<option value="AB_ATMUNG">AB_ATMUNG</option>
|
||||
<option value="C_BLUTUNG">C_BLUTUNG</option>
|
||||
</select>
|
||||
<select
|
||||
/* {...form.register("missionKeyword")} */
|
||||
className="select select-primary select-bordered w-full mb-4"
|
||||
onChange={(e) =>
|
||||
setMissionType(e.target.value as "typ1" | "typ2" | "typ3")
|
||||
}
|
||||
>
|
||||
<option defaultChecked disabled value="">
|
||||
Einsatz Szenerie auswählen...
|
||||
</option>
|
||||
<option value="typ1">typ1</option>
|
||||
<option value="typ2">typ2</option>
|
||||
<option value="typ3">typ3</option>
|
||||
<option value="primär">PRIMÄR</option>
|
||||
<option value="sekundär">SEKUNDÄR</option>
|
||||
</select>
|
||||
{form.watch("type") === "primär" && (
|
||||
<>
|
||||
<select
|
||||
{...form.register("missionKeyword")}
|
||||
className="select select-primary select-bordered w-full mb-4"
|
||||
onChange={(e) =>
|
||||
form.setValue("missionKeyword", e.target.value as string)
|
||||
}
|
||||
>
|
||||
{keywords.map((keyword) => (
|
||||
<option key={keyword.id} value={keyword.name}>
|
||||
{keyword.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<select
|
||||
/* {...form.register("missionKeyword")} */
|
||||
className="select select-primary select-bordered w-full mb-4"
|
||||
onChange={(e) =>
|
||||
form.setValue("missionKeyword", e.target.value as string)
|
||||
}
|
||||
>
|
||||
<option defaultChecked disabled value="">
|
||||
Einsatz Szenerie auswählen...
|
||||
</option>
|
||||
<option value="typ1">typ1</option>
|
||||
<option value="typ2">typ2</option>
|
||||
<option value="typ3">typ3</option>
|
||||
</select>
|
||||
</>
|
||||
)}
|
||||
<textarea
|
||||
{...form.register("missionAdditionalInfo")}
|
||||
placeholder="Einsatzinformationen"
|
||||
className="textarea textarea-primary textarea-bordered w-full mb-4"
|
||||
/>
|
||||
{missionCategory === "SEKUNDÄR" && (
|
||||
{form.watch("type") === "sekundär" && (
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Zielkrankenhaus"
|
||||
|
||||
15
apps/dispatch/app/dispatch/_components/pannel/action.ts
Normal file
15
apps/dispatch/app/dispatch/_components/pannel/action.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@repo/db";
|
||||
|
||||
export const getKeywords = async () => {
|
||||
const keywords = prisma.keyword.findMany();
|
||||
|
||||
return keywords;
|
||||
};
|
||||
|
||||
export const getStations = async () => {
|
||||
const stations = await prisma.station.findMany();
|
||||
console.log(stations);
|
||||
return stations;
|
||||
};
|
||||
Binary file not shown.
24
packages/database/prisma/json/MissionVehicleLog.ts
Normal file
24
packages/database/prisma/json/MissionVehicleLog.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Station, User } from "../../generated/client";
|
||||
|
||||
export interface MissionStationLog {
|
||||
type: "station-log";
|
||||
auto: true;
|
||||
data: {
|
||||
stationId: string;
|
||||
oldFMSstatus: string;
|
||||
newFMSstatus: string;
|
||||
station: Station;
|
||||
user: User;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MissionMessageLog {
|
||||
type: "message-log";
|
||||
auto: false;
|
||||
data: {
|
||||
message: string;
|
||||
user: User;
|
||||
};
|
||||
}
|
||||
|
||||
export type MissionLog = MissionStationLog | MissionMessageLog;
|
||||
8
packages/database/prisma/json/OSMway.ts
Normal file
8
packages/database/prisma/json/OSMway.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface MissionVehicleLog {
|
||||
wayID: string;
|
||||
tags: string[];
|
||||
nodes: {
|
||||
lat: number;
|
||||
lon: number;
|
||||
};
|
||||
}
|
||||
@@ -17,6 +17,6 @@ model Keyword {
|
||||
abreviation String
|
||||
name String
|
||||
description String?
|
||||
hpgMissionsType String[]
|
||||
hpgMissionTypes String[]
|
||||
// relations:
|
||||
}
|
||||
|
||||
@@ -1,21 +1,55 @@
|
||||
model Mission {
|
||||
id String @id @default(uuid())
|
||||
id Int @id @default(autoincrement())
|
||||
type missionType @default(primär)
|
||||
state MissionState @default(draft)
|
||||
addressLat Float
|
||||
addressLng Float
|
||||
addressStreet String
|
||||
addressCity String
|
||||
addressZip String
|
||||
missionCategory String
|
||||
missionKeyword String
|
||||
missionSummary String
|
||||
addressStreet String?
|
||||
addressCity String?
|
||||
addressZip String?
|
||||
addressOSMways Json[] @default([])
|
||||
missionCategory String?
|
||||
missionKeyword String?
|
||||
missionSummary String?
|
||||
missionPatientInfo String
|
||||
missionAdditionalInfo String
|
||||
missionStationIds String[]
|
||||
missionLog Json[] @default([])
|
||||
hpgAmbulanceState HpgState? @default(ready)
|
||||
hpgFireEngineState HpgState? @default(ready)
|
||||
hpgPoliceState HpgState? @default(ready)
|
||||
hpgLocationLat Float? @default(0)
|
||||
hpgLocationLng Float? @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdUserId String
|
||||
|
||||
// relations:
|
||||
/**
|
||||
* /**
|
||||
* /**
|
||||
* /**
|
||||
* /**
|
||||
* /**
|
||||
* createdUser User @relation(fields: [createdUserId], references: [id])
|
||||
*/
|
||||
MissionsOnStations MissionsOnStations[]
|
||||
}
|
||||
|
||||
model MissionsOnStations {
|
||||
missionId Int
|
||||
stationId Int
|
||||
|
||||
// relations:
|
||||
Mission Mission @relation(fields: [missionId], references: [id])
|
||||
Station Station @relation(fields: [stationId], references: [id])
|
||||
|
||||
@@id([missionId, stationId])
|
||||
}
|
||||
|
||||
enum missionType {
|
||||
primär
|
||||
sekundär
|
||||
}
|
||||
|
||||
enum MissionState {
|
||||
|
||||
@@ -32,4 +32,6 @@ model Station {
|
||||
longitude Float
|
||||
atcCallsign String
|
||||
hideRangeRings Boolean
|
||||
|
||||
MissionsOnStations MissionsOnStations[]
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ model User {
|
||||
EventAppointment EventAppointment[]
|
||||
SentMessages ChatMessage[] @relation("SentMessages")
|
||||
ReceivedMessages ChatMessage[] @relation("ReceivedMessages")
|
||||
/**
|
||||
* Missions Mission[]
|
||||
*/
|
||||
|
||||
@@map(name: "users")
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export const config = [
|
||||
turbo: turboPlugin,
|
||||
},
|
||||
rules: {
|
||||
"turbo/no-undeclared-env-vars": ["error", { allowList: true }],
|
||||
"turbo/no-undeclared-env-vars": ["error", { allowList: [] }],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user