From b50d333677478db0f0e3f83d4c450c2b287307eb Mon Sep 17 00:00:00 2001 From: april Date: Thu, 11 Jan 2024 11:30:10 -0600 Subject: [PATCH] Implement aircraft values in flight creation/updating --- web/app/routes/logbook.aircraft/route.tsx | 19 +- .../routes/logbook.flights.edit.$id/route.tsx | 37 +- web/app/routes/logbook.flights.new/route.tsx | 2 + web/app/routes/logbook/route.tsx | 2 +- web/app/ui/form/aircraft-form.tsx | 2 +- web/app/ui/form/flight-form.tsx | 589 ++++++++++++------ web/app/util/hooks.ts | 13 + 7 files changed, 449 insertions(+), 215 deletions(-) create mode 100644 web/app/util/hooks.ts 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 ( -
onSubmit(values))}> - - - {/* Date and Aircraft */} + <> + + + + onSubmit(values))}> + + + {/* Date and Aircraft */} -
- - - - -
+
+ + +