diff --git a/web/app/routes/logbook.aircraft/route.tsx b/web/app/routes/logbook.aircraft/route.tsx
index d205761..cb3f0a3 100644
--- a/web/app/routes/logbook.aircraft/route.tsx
+++ b/web/app/routes/logbook.aircraft/route.tsx
@@ -1,6 +1,7 @@
import ErrorDisplay from "@/ui/error-display";
import AircraftForm from "@/ui/form/aircraft-form";
import { useApi } from "@/util/api";
+import { useAircraft } from "@/util/hooks";
import { AircraftFormSchema, AircraftSchema } from "@/util/types";
import {
ActionIcon,
@@ -11,37 +12,19 @@ import {
Group,
Loader,
Modal,
- NumberInput,
ScrollArea,
- Select,
Stack,
Text,
- TextInput,
Title,
Tooltip,
} from "@mantine/core";
-import { useForm } from "@mantine/form";
import { randomId, useDisclosure } from "@mantine/hooks";
import { IconPencil, IconPlus, IconTrash, IconX } from "@tabler/icons-react";
import {
UseQueryResult,
useMutation,
- useQuery,
useQueryClient,
} from "@tanstack/react-query";
-import { AxiosError } from "axios";
-import { useState } from "react";
-
-function useAircraft() {
- const client = useApi();
-
- const aircraft = useQuery({
- queryKey: ["aircraft-list"],
- queryFn: async () => await client.get(`/aircraft`).then((res) => res.data),
- });
-
- return aircraft;
-}
function AircraftCard({ aircraft }: { aircraft: AircraftSchema }) {
const [deleteOpened, { open: openDelete, close: closeDelete }] =
diff --git a/web/app/routes/logbook.flights.edit.$id/route.tsx b/web/app/routes/logbook.flights.edit.$id/route.tsx
index 602a6e4..3b583ad 100644
--- a/web/app/routes/logbook.flights.edit.$id/route.tsx
+++ b/web/app/routes/logbook.flights.edit.$id/route.tsx
@@ -1,4 +1,4 @@
-import { Container, Stack, Title } from "@mantine/core";
+import { Center, Container, Loader, Stack, Title } from "@mantine/core";
import {
FlightFormSchema,
flightCreateHelper,
@@ -9,6 +9,7 @@ import { useApi } from "@/util/api";
import { useNavigate, useParams } from "@remix-run/react";
import { AxiosError } from "axios";
import FlightForm from "@/ui/form/flight-form";
+import ErrorDisplay from "@/ui/error-display";
export default function EditFlight() {
const params = useParams();
@@ -47,16 +48,30 @@ export default function EditFlight() {
Edit Flight
- navigate(`/logbook/flights/${params.id}`)}
- mah="calc(100vh - 95px - 110px)"
- />
+ {flight.isLoading ? (
+
+
+
+ ) : flight.isError ? (
+
+
+
+ ) : (
+ navigate(`/logbook/flights/${params.id}`)}
+ mah="calc(100vh - 95px - 110px)"
+ autofillHobbs={false}
+ />
+ )}
);
diff --git a/web/app/routes/logbook.flights.new/route.tsx b/web/app/routes/logbook.flights.new/route.tsx
index c9a0161..94aba45 100644
--- a/web/app/routes/logbook.flights.new/route.tsx
+++ b/web/app/routes/logbook.flights.new/route.tsx
@@ -33,9 +33,11 @@ export default function NewFlight() {
diff --git a/web/app/routes/logbook/route.tsx b/web/app/routes/logbook/route.tsx
index ea5dd8b..2128b4f 100644
--- a/web/app/routes/logbook/route.tsx
+++ b/web/app/routes/logbook/route.tsx
@@ -47,7 +47,7 @@ export default function Index() {
staleTime: 1000,
retry: (failureCount, error: Error) => {
return (
- failureCount < 5 &&
+ failureCount < 3 &&
(!error ||
(error instanceof AxiosError &&
error.response?.status !== 401 &&
diff --git a/web/app/ui/form/aircraft-form.tsx b/web/app/ui/form/aircraft-form.tsx
index 253cd17..5d439d3 100644
--- a/web/app/ui/form/aircraft-form.tsx
+++ b/web/app/ui/form/aircraft-form.tsx
@@ -12,7 +12,7 @@ import {
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { IconPencil, IconX } from "@tabler/icons-react";
-import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { useQuery, useQueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios";
import { useState } from "react";
diff --git a/web/app/ui/form/flight-form.tsx b/web/app/ui/form/flight-form.tsx
index 7afbf80..93f4a66 100644
--- a/web/app/ui/form/flight-form.tsx
+++ b/web/app/ui/form/flight-form.tsx
@@ -1,15 +1,23 @@
-import { FlightFormSchema } from "@/util/types";
import {
+ AircraftFormSchema,
+ AircraftSchema,
+ FlightFormSchema,
+} from "@/util/types";
+import {
+ ActionIcon,
Button,
CloseButton,
Container,
Fieldset,
Group,
+ Modal,
NumberInput,
ScrollArea,
+ Select,
Text,
TextInput,
Textarea,
+ Tooltip,
} from "@mantine/core";
import { DatePickerInput } from "@mantine/dates";
import { useForm } from "@mantine/form";
@@ -18,11 +26,18 @@ import { HourInput, ZeroHourInput } from "./hour-input";
import TimeInput from "./time-input";
import { ZeroIntInput } from "./int-input";
import ListInput from "./list-input";
-import { IconPencil } from "@tabler/icons-react";
+import { IconPencil, IconPlaneTilt, IconPlus } from "@tabler/icons-react";
import { AxiosError } from "axios";
+import { useDisclosure } from "@mantine/hooks";
+import AircraftForm from "./aircraft-form";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { useApi } from "@/util/api";
+import { useAircraft } from "@/util/hooks";
+import { useEffect, useState } from "react";
export default function FlightForm({
onSubmit,
+ isPending,
isError,
error,
initialValues,
@@ -30,8 +45,10 @@ export default function FlightForm({
submitButtonLabel,
withCancelButton,
cancelFunc,
+ autofillHobbs = false,
}: {
onSubmit: (values: FlightFormSchema) => void;
+ isPending: boolean;
isError: boolean;
error: Error | null;
initialValues?: FlightFormSchema | null;
@@ -39,6 +56,7 @@ export default function FlightForm({
submitButtonLabel?: string;
withCancelButton?: boolean;
cancelFunc?: () => void;
+ autofillHobbs?: boolean;
}) {
const form = useForm({
initialValues: initialValues ?? {
@@ -86,196 +104,399 @@ export default function FlightForm({
},
});
+ const [aircraftOpened, { open: openAircraft, close: closeAircraft }] =
+ useDisclosure(false);
+
+ const client = useApi();
+ const queryClient = useQueryClient();
+
+ const addAircraft = useMutation({
+ mutationFn: async (values: AircraftFormSchema) => {
+ const newAircraft = values;
+ if (newAircraft) {
+ const res = await client.post("/aircraft", newAircraft);
+ return res.data;
+ }
+ throw new Error("Aircraft creation failed");
+ },
+ onSuccess: async () => {
+ await queryClient.invalidateQueries({ queryKey: ["aircraft-list"] });
+ close();
+ },
+ });
+
+ const [aircraft, setAircraft] = useState(
+ initialValues?.aircraft ?? ""
+ );
+
+ const [hobbsTouched, setHobbsTouched] = useState(false);
+
+ const getHobbs = useQuery({
+ queryKey: ["hobbs", aircraft],
+ queryFn: async () =>
+ await client.get(`/aircraft/tail/${aircraft}`).then((res) => res.data),
+ enabled: !!aircraft && aircraft !== "",
+ });
+
+ const getAircraft = useAircraft();
+
+ useEffect(() => {
+ if (autofillHobbs && getHobbs.isFetched && getHobbs.data && !hobbsTouched) {
+ form.setFieldValue(
+ "hobbs_start",
+ getHobbs.data.hobbs ?? form.getTransformedValues()["hobbs_start"]
+ );
+ }
+ }, [getHobbs.data]);
+
return (
-
+
+
+ >
);
}
diff --git a/web/app/util/hooks.ts b/web/app/util/hooks.ts
new file mode 100644
index 0000000..11aece2
--- /dev/null
+++ b/web/app/util/hooks.ts
@@ -0,0 +1,13 @@
+import { useQuery } from "@tanstack/react-query";
+import { useApi } from "./api";
+
+export function useAircraft() {
+ const client = useApi();
+
+ const aircraft = useQuery({
+ queryKey: ["aircraft-list"],
+ queryFn: async () => await client.get(`/aircraft`).then((res) => res.data),
+ });
+
+ return aircraft;
+}