Heliport Search, Station connection history table, reworked mission close functionality
This commit is contained in:
@@ -2,20 +2,26 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { StationOptionalDefaultsSchema } from "@repo/db/zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { BosUse, Country, Station } from "@repo/db";
|
||||
import { FileText, LocateIcon, PlaneIcon } from "lucide-react";
|
||||
import { BosUse, ConnectedAircraft, Country, Station, User } from "@repo/db";
|
||||
import { FileText, LocateIcon, PlaneIcon, UserIcon } from "lucide-react";
|
||||
import { Input } from "../../../../_components/ui/Input";
|
||||
import { useState } from "react";
|
||||
import { deleteStation, upsertStation } from "../action";
|
||||
import { Button } from "../../../../_components/ui/Button";
|
||||
import { redirect } from "next/navigation";
|
||||
import toast from "react-hot-toast";
|
||||
import { PaginatedTable, PaginatedTableRef } from "_components/PaginatedTable";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import Link from "next/link";
|
||||
import { deletePilotHistory } from "(app)/admin/user/action";
|
||||
import { useRef } from "react";
|
||||
import { cn } from "@repo/shared-components";
|
||||
|
||||
export const StationForm = ({ station }: { station?: Station }) => {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(StationOptionalDefaultsSchema),
|
||||
defaultValues: station,
|
||||
});
|
||||
const dispoTableRef = useRef<PaginatedTableRef>(null);
|
||||
// const [deleteLoading, setDeleteLoading] = useState(false);
|
||||
return (
|
||||
<>
|
||||
@@ -27,10 +33,10 @@ export const StationForm = ({ station }: { station?: Station }) => {
|
||||
})}
|
||||
className="grid grid-cols-6 gap-3"
|
||||
>
|
||||
<div className="card bg-base-200 shadow-xl col-span-2 max-xl:col-span-6">
|
||||
<div className="card bg-base-200 col-span-2 shadow-xl max-xl:col-span-6">
|
||||
<div className="card-body">
|
||||
<h2 className="card-title">
|
||||
<FileText className="w-5 h-5" /> Allgemeines
|
||||
<FileText className="h-5 w-5" /> Allgemeines
|
||||
</h2>
|
||||
<Input form={form} label="BOS Rufname" name="bosCallsign" className="input-sm" />
|
||||
<Input
|
||||
@@ -55,7 +61,7 @@ export const StationForm = ({ station }: { station?: Station }) => {
|
||||
/>
|
||||
|
||||
<label className="form-control w-full">
|
||||
<span className="label-text text-lg flex items-center gap-2">BOS Nutzung</span>
|
||||
<span className="label-text flex items-center gap-2 text-lg">BOS Nutzung</span>
|
||||
<select
|
||||
className="input-sm select select-bordered select-sm"
|
||||
{...form.register("bosUse")}
|
||||
@@ -69,13 +75,13 @@ export const StationForm = ({ station }: { station?: Station }) => {
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card bg-base-200 shadow-xl col-span-2 max-xl:col-span-6">
|
||||
<div className="card bg-base-200 col-span-2 shadow-xl max-xl:col-span-6">
|
||||
<div className="card-body">
|
||||
<h2 className="card-title">
|
||||
<LocateIcon className="w-5 h-5" /> Standort + Ausrüstung
|
||||
<LocateIcon className="h-5 w-5" /> Standort + Ausrüstung
|
||||
</h2>
|
||||
<label className="form-control w-full">
|
||||
<span className="label-text text-lg flex items-center gap-2">Land</span>
|
||||
<span className="label-text flex items-center gap-2 text-lg">Land</span>
|
||||
<select
|
||||
className="input-sm select select-bordered select-sm"
|
||||
{...form.register("country", {})}
|
||||
@@ -94,21 +100,21 @@ export const StationForm = ({ station }: { station?: Station }) => {
|
||||
name="locationStateShort"
|
||||
className="input-sm"
|
||||
/>
|
||||
<span className="label-text text-lg flex items-center gap-2">Ausgerüstet mit:</span>
|
||||
<span className="label-text flex items-center gap-2 text-lg">Ausgerüstet mit:</span>
|
||||
<div className="form-control space-y-2">
|
||||
<label className="label cursor-pointer flex">
|
||||
<label className="label flex cursor-pointer">
|
||||
<span className="flex-1 text-left">Winde</span>
|
||||
<input type="checkbox" className="toggle" {...form.register("hasWinch")} />
|
||||
</label>
|
||||
<label className="label cursor-pointer flex">
|
||||
<label className="label flex cursor-pointer">
|
||||
<span className="flex-1 text-left">Nachtsicht-Gerät</span>
|
||||
<input type="checkbox" className="toggle" {...form.register("hasNvg")} />
|
||||
</label>
|
||||
<label className="label cursor-pointer flex">
|
||||
<label className="label flex cursor-pointer">
|
||||
<span className="flex-1 text-left">24-Stunden Einsatzfähig</span>
|
||||
<input type="checkbox" className="toggle" {...form.register("is24h")} />
|
||||
</label>
|
||||
<label className="label cursor-pointer flex">
|
||||
<label className="label flex cursor-pointer">
|
||||
<span className="flex-1 text-left">Bergetau</span>
|
||||
<input type="checkbox" className="toggle" {...form.register("hasRope")} />
|
||||
</label>
|
||||
@@ -132,16 +138,16 @@ export const StationForm = ({ station }: { station?: Station }) => {
|
||||
type="number"
|
||||
step="any"
|
||||
/>
|
||||
<label className="label cursor-pointer flex">
|
||||
<span className="text-lg flex-1 text-left">Reichweiten ausblenden</span>
|
||||
<label className="label flex cursor-pointer">
|
||||
<span className="flex-1 text-left text-lg">Reichweiten ausblenden</span>
|
||||
<input type="checkbox" className="toggle" {...form.register("hideRangeRings")} />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card bg-base-200 shadow-xl col-span-2 max-xl:col-span-6">
|
||||
<div className="card bg-base-200 col-span-2 shadow-xl max-xl:col-span-6">
|
||||
<div className="card-body">
|
||||
<h2 className="card-title">
|
||||
<PlaneIcon className="w-5 h-5" /> Hubschrauber
|
||||
<PlaneIcon className="h-5 w-5" /> Hubschrauber
|
||||
</h2>
|
||||
<Input form={form} label="Hubschrauber Typ" name="aircraft" className="input-sm" />
|
||||
<Input
|
||||
@@ -160,8 +166,8 @@ export const StationForm = ({ station }: { station?: Station }) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card bg-base-200 shadow-xl col-span-6">
|
||||
<div className="card-body ">
|
||||
<div className="card bg-base-200 col-span-6 shadow-xl">
|
||||
<div className="card-body">
|
||||
<div className="flex w-full gap-4">
|
||||
<Button
|
||||
isLoading={form.formState.isSubmitting}
|
||||
@@ -184,6 +190,93 @@ export const StationForm = ({ station }: { station?: Station }) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card bg-base-200 col-span-6 shadow-xl">
|
||||
<PaginatedTable
|
||||
leftOfSearch={
|
||||
<div className="flex items-center gap-2 text-lg font-bold">
|
||||
<UserIcon className="h-5 w-5" />
|
||||
Verbundene Piloten
|
||||
</div>
|
||||
}
|
||||
filter={{
|
||||
stationId: station?.id,
|
||||
}}
|
||||
searchFields={["User.firstname", "User.lastname", "User.publicId"]}
|
||||
prismaModel={"connectedAircraft"}
|
||||
include={{ Station: true, User: true }}
|
||||
columns={
|
||||
[
|
||||
{
|
||||
accessorKey: "User.firstname",
|
||||
header: "Nutzer",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Link
|
||||
className="link link-hover"
|
||||
href={`/admin/user/${row.original.User.id}`}
|
||||
>
|
||||
{row.original.User.firstname} {row.original.User.lastname} (
|
||||
{row.original.User.publicId})
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "loginTime",
|
||||
header: "Login",
|
||||
cell: ({ row }) => {
|
||||
return new Date(row.getValue("loginTime")).toLocaleString("de-DE");
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "logoutTime",
|
||||
header: "Logout",
|
||||
cell: ({ row }) => {
|
||||
return new Date(row.getValue("logoutTime")).toLocaleString("de-DE");
|
||||
},
|
||||
},
|
||||
{
|
||||
header: "Time Online",
|
||||
cell: ({ row }) => {
|
||||
if (!row.original.logoutTime) {
|
||||
return <span className="text-success">Online</span>;
|
||||
}
|
||||
const loginTime = new Date(row.original.loginTime).getTime();
|
||||
const logoutTime = new Date(row.original.logoutTime).getTime();
|
||||
const timeOnline = logoutTime - loginTime;
|
||||
|
||||
const hours = Math.floor(timeOnline / 1000 / 60 / 60);
|
||||
const minutes = Math.floor((timeOnline / 1000 / 60) % 60);
|
||||
|
||||
return (
|
||||
<span className={cn(hours > 2 && "text-error")}>
|
||||
{hours}h {minutes}min
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
header: "Aktionen",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
className="btn btn-sm btn-error"
|
||||
onClick={async () => {
|
||||
await deletePilotHistory(row.original.id);
|
||||
dispoTableRef.current?.refresh();
|
||||
}}
|
||||
>
|
||||
löschen
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
] as ColumnDef<ConnectedAircraft & { Station: Station; User: User }>[]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user