Improve flight view appearance

This commit is contained in:
april 2024-01-04 16:55:12 -06:00
parent 887f83119f
commit 04813bfd76
4 changed files with 322 additions and 25 deletions

View File

@ -1,8 +1,17 @@
import { LogItem, VerticalLogItem } from "@/ui/display/log-item";
import ErrorDisplay from "@/ui/error-display"; import ErrorDisplay from "@/ui/error-display";
import { client } from "@/util/api"; import { client } from "@/util/api";
import { Center, Container, List, Loader, Stack, Text } from "@mantine/core"; import {
Center,
Container,
Divider,
Grid,
Loader,
ScrollAreaAutosize,
Stack,
Title,
} from "@mantine/core";
import { useParams } from "@remix-run/react"; import { useParams } from "@remix-run/react";
import { IconAlertTriangle } from "@tabler/icons-react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
export default function Flight() { export default function Flight() {
@ -14,30 +23,239 @@ export default function Flight() {
await client.get(`/flights/${params.id}`).then((res) => res.data), await client.get(`/flights/${params.id}`).then((res) => res.data),
}); });
const log = flight.data;
return ( return (
<Container> <Container>
<Stack h="calc(100vh - 95px)"> <Stack>
{flight.isError ? ( {flight.isError ? (
<ErrorDisplay error="Error Fetching Flight" /> <Center h="calc(100vh - 95px)">
<ErrorDisplay error="Error Fetching Flight" />
</Center>
) : flight.isPending ? ( ) : flight.isPending ? (
<Center h="100%"> <Center h="calc(100vh - 95px)">
<Loader /> <Loader />
</Center> </Center>
) : flight.data ? (
<>
<Title order={3} py="lg" style={{ textAlign: "center" }}>
Flight Log
</Title>
<ScrollAreaAutosize mah="calc(100vh - 95px - 110px)" m="0" p="0">
<Container h="100%">
<Grid justify="center">
<Grid.Col span={6}>
<VerticalLogItem label="Date" content={log.date} date />
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem label="Aircraft" content={log.aircraft} />
</Grid.Col>
{log.waypoint_from || log.waypoint_to ? (
<>
<Grid.Col span={6}>
<VerticalLogItem
label="Waypoint From"
content={log.waypoint_from}
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Waypoint To"
content={log.waypoint_to}
/>
</Grid.Col>
</>
) : null}
{log.route ? (
<>
<Grid.Col span={12}>
<VerticalLogItem label="Route" content={log.route} />
</Grid.Col>
</>
) : null}
{log.hobbs_start || log.hobbs_end ? (
<>
<Grid.Col span={6}>
<VerticalLogItem
label="Hobbs Start"
content={log.hobbs_start}
hours
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Hobbs End"
content={log.hobbs_end}
hours
/>
</Grid.Col>
</>
) : null}
{log.tach_start || log.tach_end ? (
<>
<Grid.Col span={6}>
<VerticalLogItem
label="Tach Start"
content={log.tach_start}
hours
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Tach End"
content={log.tach_end}
hours
/>
</Grid.Col>
</>
) : null}
{log.time_start || log.time_off ? (
<>
<Grid.Col span={6}>
<VerticalLogItem
label="Time Start"
content={log.time_start}
time
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Time Off"
content={log.time_off}
time
/>
</Grid.Col>
</>
) : null}
{log.time_down || log.time_stop ? (
<>
<Grid.Col span={6}>
<VerticalLogItem
label="Time Down"
content={log.time_down}
time
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Time Stop"
content={log.time_stop}
time
/>
</Grid.Col>
</>
) : null}
<Grid.Col span={4}>
<VerticalLogItem
label="Total Time"
content={log.time_total}
hours
/>
</Grid.Col>
<Grid.Col span={4}>
<VerticalLogItem
label="Time Solo"
content={log.time_solo}
hours
/>
</Grid.Col>
<Grid.Col span={4}>
<VerticalLogItem
label="Time Night"
content={log.time_night}
hours
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Time PIC"
content={log.time_pic}
hours
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Time SIC"
content={log.time_sic}
hours
/>
</Grid.Col>
{log.time_xc && log.dist_xc ? (
<>
<Grid.Col span={6}>
<VerticalLogItem
label="Time Cross-Country"
content={log.time_xc}
hours
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Cross-Country Distance"
content={log.dist_xc}
decimal={2}
/>
</Grid.Col>
</>
) : null}
<Grid.Col span={6}>
<VerticalLogItem
label="Takeoffs (Day)"
content={log.takeoffs_day}
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Landings (Day)"
content={log.landings_day}
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Takeoffs (Night)"
content={log.takeoffs_night}
/>
</Grid.Col>
<Grid.Col span={6}>
<VerticalLogItem
label="Landings (Night)"
content={log.landings_night}
/>
</Grid.Col>
{log.time_instrument ||
log.time_sim_instrument ||
log.holds_instrument ? (
<>
<Grid.Col span={4}>
<VerticalLogItem
label="Instrument Time"
content={log.time_instrument}
hours
/>
</Grid.Col>
<Grid.Col span={4}>
<VerticalLogItem
label="Simulated Instrument Time"
content={log.time_sim_instrument}
hours
/>
</Grid.Col>
<Grid.Col span={4}>
<VerticalLogItem
label="Instrument Holds"
content={log.holds_instrument}
/>
</Grid.Col>
</>
) : null}
</Grid>
</Container>
</ScrollAreaAutosize>
</>
) : ( ) : (
<List> <Center h="calc(100vh - 95px)">
{Object.entries(flight.data).map(([key, value]) => <ErrorDisplay error="Unknown Error" />
value && value.length !== 0 ? ( </Center>
<List.Item key={key}>
<Text span>
<Text span fw={700}>
{key}
</Text>
: <Text span>{value}</Text>
</Text>
</List.Item>
) : null
)}
</List>
)} )}
</Stack> </Stack>
</Container> </Container>

View File

@ -111,7 +111,7 @@ export default function NewFlight() {
<Title order={2}>New Flight</Title> <Title order={2}>New Flight</Title>
<form onSubmit={form.onSubmit((values) => createFlight.mutate(values))}> <form onSubmit={form.onSubmit((values) => createFlight.mutate(values))}>
<ScrollAreaAutosize mah="calc(100vh - 95px - 110px"> <ScrollAreaAutosize mah="calc(100vh - 95px - 110px)">
<Container> <Container>
{/* Date and Aircraft */} {/* Date and Aircraft */}

View File

@ -0,0 +1,53 @@
import { Card, Group, Stack, Text } from "@mantine/core";
export function LogItem({
label,
content,
}: {
label: string;
content: string | null;
}) {
if (content === null) content = "";
return (
<Group justify="space-between" px="sm">
<Text>{label}</Text>
<Text>{content}</Text>
</Group>
);
}
export function VerticalLogItem({
label,
content,
decimal = 0,
hours = false,
time = false,
date = false,
}: {
label: string;
content: string | null;
decimal?: number;
hours?: boolean;
time?: boolean;
date?: boolean;
}) {
if (content === null) content = "";
if (decimal > 0) content = Number(content).toFixed(decimal);
if (hours) content = Number(content).toFixed(1);
if (time) content = content.split("T")[1];
if (date) content = content.split("T")[0];
return (
<Card>
<Stack gap="xs" align="center">
<Text c="dimmed" style={{ textalign: "center" }}>
{label}
</Text>
<Text size="lg" style={{ textalign: "center" }}>
{content}
</Text>
</Stack>
</Card>
);
}

View File

@ -14,11 +14,6 @@ type FlightBaseSchema = {
tach_start: number | null; tach_start: number | null;
tach_end: number | null; tach_end: number | null;
time_start: number | null;
time_off: number | null;
time_down: number | null;
time_stop: number | null;
time_total: number; time_total: number;
time_pic: number; time_pic: number;
time_sic: number; time_sic: number;
@ -52,16 +47,31 @@ type FlightBaseSchema = {
type FlightFormSchema = FlightBaseSchema & { type FlightFormSchema = FlightBaseSchema & {
date: dayjs.Dayjs; date: dayjs.Dayjs;
time_start: number | null;
time_off: number | null;
time_down: number | null;
time_stop: number | null;
}; };
type FlightCreateSchema = FlightBaseSchema & { type FlightCreateSchema = FlightBaseSchema & {
date: string; date: string;
time_start: dayjs.Dayjs;
time_off: dayjs.Dayjs;
time_down: dayjs.Dayjs;
time_stop: dayjs.Dayjs;
}; };
type FlightDisplaySchema = FlightBaseSchema & { type FlightDisplaySchema = FlightBaseSchema & {
id: string; id: string;
user: string; user: string;
date: dayjs.Dayjs; date: dayjs.Dayjs;
time_start: number | null;
time_off: number | null;
time_down: number | null;
time_stop: number | null;
}; };
type FlightConciseSchema = { type FlightConciseSchema = {
@ -86,6 +96,22 @@ const flightCreateHelper = (values: FlightFormSchema): FlightCreateSchema => {
hobbs_end: Number(values.hobbs_end), hobbs_end: Number(values.hobbs_end),
tach_start: Number(values.tach_start), tach_start: Number(values.tach_start),
tach_end: Number(values.tach_end), tach_end: Number(values.tach_end),
time_start: values.date
.utc()
.hour(values.time_start ?? 0 / 100)
.minute(values.time_start ?? 0 % 100),
time_off: values.date
.utc()
.hour(values.time_off ?? 0 / 100)
.minute(values.time_off ?? 0 % 100),
time_down: values.date
.utc()
.hour(values.time_down ?? 0 / 100)
.minute(values.time_down ?? 0 % 100),
time_stop: values.date
.utc()
.hour(values.time_stop ?? 0 / 100)
.minute(values.time_stop ?? 0 % 100),
}; };
}; };