added mission fields

This commit is contained in:
PxlLoewe
2025-04-23 19:01:26 -07:00
parent 3761943cc2
commit f6e4449f68
12 changed files with 198 additions and 113 deletions

View File

@@ -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");
});

View File

@@ -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);
};

View File

@@ -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,30 +117,32 @@ 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>
<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) =>
setMissionKeyword(e.target.value as "AB_ATMUNG" | "C_BLUTUNG")
form.setValue("missionKeyword", e.target.value as string)
}
>
<option value="AB_ATMUNG">AB_ATMUNG</option>
<option value="C_BLUTUNG">C_BLUTUNG</option>
{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) =>
setMissionType(e.target.value as "typ1" | "typ2" | "typ3")
form.setValue("missionKeyword", e.target.value as string)
}
>
<option defaultChecked disabled value="">
@@ -172,12 +152,14 @@ export const MissionForm: React.FC = () => {
<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"

View 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.

View 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;

View File

@@ -0,0 +1,8 @@
export interface MissionVehicleLog {
wayID: string;
tags: string[];
nodes: {
lat: number;
lon: number;
};
}

View File

@@ -17,6 +17,6 @@ model Keyword {
abreviation String
name String
description String?
hpgMissionsType String[]
hpgMissionTypes String[]
// relations:
}

View File

@@ -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 {

View File

@@ -32,4 +32,6 @@ model Station {
longitude Float
atcCallsign String
hideRangeRings Boolean
MissionsOnStations MissionsOnStations[]
}

View File

@@ -43,6 +43,9 @@ model User {
EventAppointment EventAppointment[]
SentMessages ChatMessage[] @relation("SentMessages")
ReceivedMessages ChatMessage[] @relation("ReceivedMessages")
/**
* Missions Mission[]
*/
@@map(name: "users")
}

View File

@@ -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: [] }],
},
},
{