Finish flight information display
This commit is contained in:
parent
352172487a
commit
8bc3639d89
@ -1,3 +1,4 @@
|
|||||||
|
import CollapsibleFieldset from "@/ui/display/collapsible-fieldset";
|
||||||
import { VerticalLogItem } from "@/ui/display/log-item";
|
import { VerticalLogItem } from "@/ui/display/log-item";
|
||||||
import ErrorDisplay from "@/ui/error-display";
|
import ErrorDisplay from "@/ui/error-display";
|
||||||
import { useApi } from "@/util/api";
|
import { useApi } from "@/util/api";
|
||||||
@ -15,10 +16,18 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
Modal,
|
Modal,
|
||||||
Button,
|
Button,
|
||||||
|
Badge,
|
||||||
|
Fieldset,
|
||||||
|
Collapse,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useDisclosure } from "@mantine/hooks";
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
import { useNavigate, useParams } from "@remix-run/react";
|
import { useNavigate, useParams } from "@remix-run/react";
|
||||||
import { IconPencil, IconTrash } from "@tabler/icons-react";
|
import {
|
||||||
|
IconPencil,
|
||||||
|
IconPlaneTilt,
|
||||||
|
IconPlus,
|
||||||
|
IconTrash,
|
||||||
|
} from "@tabler/icons-react";
|
||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
export default function Flight() {
|
export default function Flight() {
|
||||||
@ -87,9 +96,11 @@ export default function Flight() {
|
|||||||
) : flight.data ? (
|
) : flight.data ? (
|
||||||
<>
|
<>
|
||||||
<Group justify="space-between" px="xl">
|
<Group justify="space-between" px="xl">
|
||||||
<Title order={2} py="lg" style={{ textAlign: "center" }}>
|
<Group>
|
||||||
Flight Log
|
<Title order={2} py="lg" style={{ textAlign: "center" }}>
|
||||||
</Title>
|
Flight Log
|
||||||
|
</Title>
|
||||||
|
</Group>
|
||||||
<Group>
|
<Group>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
label="Edit Flight"
|
label="Edit Flight"
|
||||||
@ -116,212 +127,233 @@ export default function Flight() {
|
|||||||
<ScrollArea h="calc(100vh - 95px - 110px)" m="0" p="0">
|
<ScrollArea h="calc(100vh - 95px - 110px)" m="0" p="0">
|
||||||
<Container h="100%">
|
<Container h="100%">
|
||||||
<Grid justify="center">
|
<Grid justify="center">
|
||||||
<Grid.Col span={6}>
|
<CollapsibleFieldset legend="About" mt="sm" w="100%">
|
||||||
<VerticalLogItem label="Date" content={log.date} date />
|
<Group grow>
|
||||||
</Grid.Col>
|
<VerticalLogItem label="Date" content={log.date} date />
|
||||||
<Grid.Col span={6}>
|
<VerticalLogItem
|
||||||
<VerticalLogItem
|
label="Aircraft"
|
||||||
label="Aircraft"
|
content={log.aircraft}
|
||||||
content={log.aircraft}
|
/>
|
||||||
/>
|
</Group>
|
||||||
</Grid.Col>
|
{(log.pax || log.crew) &&
|
||||||
{log.waypoint_from || log.waypoint_to ? (
|
(log.pax.length > 0 || log.crew.length > 0) ? (
|
||||||
<>
|
<Group grow mt="sm">
|
||||||
<Grid.Col span={6}>
|
<VerticalLogItem label="Pax" content={log.pax} list />
|
||||||
<VerticalLogItem
|
<VerticalLogItem
|
||||||
label="Waypoint From"
|
label="Crew"
|
||||||
content={log.waypoint_from}
|
content={log.crew}
|
||||||
|
list
|
||||||
/>
|
/>
|
||||||
</Grid.Col>
|
</Group>
|
||||||
<Grid.Col span={6}>
|
) : null}
|
||||||
|
{log.tags && log.tags.length > 0 ? (
|
||||||
|
<Group grow mt="sm">
|
||||||
<VerticalLogItem
|
<VerticalLogItem
|
||||||
label="Waypoint To"
|
label="Tags"
|
||||||
content={log.waypoint_to}
|
content={log.tags}
|
||||||
|
list
|
||||||
/>
|
/>
|
||||||
</Grid.Col>
|
</Group>
|
||||||
</>
|
) : null}
|
||||||
|
{log.comments?.length > 0 ? (
|
||||||
|
<Group grow mt="sm">
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Comments"
|
||||||
|
content={log.comments}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
) : null}
|
||||||
|
</CollapsibleFieldset>
|
||||||
|
{log.waypoint_from || log.waypoint_to || log.route ? (
|
||||||
|
<CollapsibleFieldset legend="Route" w="100%" mt="sm">
|
||||||
|
{log.waypoint_from || log.waypoint_to ? (
|
||||||
|
<Group grow>
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Waypoint From"
|
||||||
|
content={log.waypoint_from}
|
||||||
|
/>
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Waypoint To"
|
||||||
|
content={log.waypoint_to}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
) : null}
|
||||||
|
{log.route ? (
|
||||||
|
<Group grow>
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Route"
|
||||||
|
content={log.route}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
) : null}
|
||||||
|
</CollapsibleFieldset>
|
||||||
) : null}
|
) : null}
|
||||||
{log.route ? (
|
{log.hobbs_start ||
|
||||||
<>
|
log.hobbs_end ||
|
||||||
<Grid.Col span={12}>
|
log.tach_start ||
|
||||||
<VerticalLogItem label="Route" content={log.route} />
|
log.tach_end ? (
|
||||||
</Grid.Col>
|
<CollapsibleFieldset legend="Times" w="100%" mt="sm">
|
||||||
</>
|
{log.hobbs_start || log.hobbs_end ? (
|
||||||
|
<Group grow>
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Hobbs Start"
|
||||||
|
content={log.hobbs_start}
|
||||||
|
hours
|
||||||
|
/>
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Hobbs End"
|
||||||
|
content={log.hobbs_end}
|
||||||
|
hours
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
) : null}
|
||||||
|
{log.tach_start || log.tach_end ? (
|
||||||
|
<Group grow mt="sm">
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Tach Start"
|
||||||
|
content={log.tach_start}
|
||||||
|
hours
|
||||||
|
/>
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Tach End"
|
||||||
|
content={log.tach_end}
|
||||||
|
hours
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
) : null}
|
||||||
|
</CollapsibleFieldset>
|
||||||
) : null}
|
) : null}
|
||||||
{log.hobbs_start || log.hobbs_end ? (
|
{log.time_start ||
|
||||||
<>
|
log.time_off ||
|
||||||
<Grid.Col span={6}>
|
log.time_down ||
|
||||||
<VerticalLogItem
|
log.time_stop ? (
|
||||||
label="Hobbs Start"
|
<CollapsibleFieldset legend="Start/Stop" w="100%" mt="sm">
|
||||||
content={log.hobbs_start}
|
{log.time_start || log.time_off ? (
|
||||||
hours
|
<Group grow>
|
||||||
/>
|
<VerticalLogItem
|
||||||
</Grid.Col>
|
label="Time Start"
|
||||||
<Grid.Col span={6}>
|
content={log.time_start}
|
||||||
<VerticalLogItem
|
time
|
||||||
label="Hobbs End"
|
/>
|
||||||
content={log.hobbs_end}
|
<VerticalLogItem
|
||||||
hours
|
label="Time Off"
|
||||||
/>
|
content={log.time_off}
|
||||||
</Grid.Col>
|
time
|
||||||
</>
|
/>
|
||||||
|
</Group>
|
||||||
|
) : null}
|
||||||
|
{log.time_down || log.time_stop ? (
|
||||||
|
<Group grow mt="sm">
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Time Down"
|
||||||
|
content={log.time_down}
|
||||||
|
time
|
||||||
|
/>
|
||||||
|
<VerticalLogItem
|
||||||
|
label="Time Stop"
|
||||||
|
content={log.time_stop}
|
||||||
|
time
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
) : null}
|
||||||
|
</CollapsibleFieldset>
|
||||||
) : null}
|
) : null}
|
||||||
{log.tach_start || log.tach_end ? (
|
<CollapsibleFieldset legend="Hours" w="100%" mt="sm">
|
||||||
<>
|
<Group grow>
|
||||||
<Grid.Col span={6}>
|
<VerticalLogItem
|
||||||
<VerticalLogItem
|
label="Total Time"
|
||||||
label="Tach Start"
|
content={log.time_total}
|
||||||
content={log.tach_start}
|
hours
|
||||||
hours
|
/>
|
||||||
/>
|
<VerticalLogItem
|
||||||
</Grid.Col>
|
label="Time Solo"
|
||||||
<Grid.Col span={6}>
|
content={log.time_solo}
|
||||||
<VerticalLogItem
|
hours
|
||||||
label="Tach End"
|
/>
|
||||||
content={log.tach_end}
|
<VerticalLogItem
|
||||||
hours
|
label="Time Night"
|
||||||
/>
|
content={log.time_night}
|
||||||
</Grid.Col>
|
hours
|
||||||
</>
|
/>
|
||||||
) : null}
|
</Group>
|
||||||
{log.time_start || log.time_off ? (
|
<Group grow mt="sm">
|
||||||
<>
|
<VerticalLogItem
|
||||||
<Grid.Col span={6}>
|
label="Time PIC"
|
||||||
<VerticalLogItem
|
content={log.time_pic}
|
||||||
label="Time Start"
|
hours
|
||||||
content={log.time_start}
|
/>
|
||||||
time
|
<VerticalLogItem
|
||||||
/>
|
label="Time SIC"
|
||||||
</Grid.Col>
|
content={log.time_sic}
|
||||||
<Grid.Col span={6}>
|
hours
|
||||||
<VerticalLogItem
|
/>
|
||||||
label="Time Off"
|
</Group>
|
||||||
content={log.time_off}
|
</CollapsibleFieldset>
|
||||||
time
|
{log.time_xc || log.dist_xc ? (
|
||||||
/>
|
<CollapsibleFieldset
|
||||||
</Grid.Col>
|
legend="Cross-Country"
|
||||||
</>
|
w="100%"
|
||||||
) : null}
|
mt="sm"
|
||||||
{log.time_down || log.time_stop ? (
|
>
|
||||||
<>
|
<Group grow>
|
||||||
<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
|
<VerticalLogItem
|
||||||
label="Time Cross-Country"
|
label="Time Cross-Country"
|
||||||
content={log.time_xc}
|
content={log.time_xc}
|
||||||
hours
|
hours
|
||||||
/>
|
/>
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<VerticalLogItem
|
<VerticalLogItem
|
||||||
label="Cross-Country Distance"
|
label="Cross-Country Distance"
|
||||||
content={log.dist_xc}
|
content={log.dist_xc}
|
||||||
decimal={2}
|
decimal={2}
|
||||||
/>
|
/>
|
||||||
</Grid.Col>
|
</Group>
|
||||||
</>
|
</CollapsibleFieldset>
|
||||||
) : null}
|
) : null}
|
||||||
<Grid.Col span={6}>
|
<CollapsibleFieldset
|
||||||
<VerticalLogItem
|
legend="Takeoffs/Landings"
|
||||||
label="Takeoffs (Day)"
|
w="100%"
|
||||||
content={log.takeoffs_day}
|
mt="sm"
|
||||||
/>
|
>
|
||||||
</Grid.Col>
|
<Group grow>
|
||||||
<Grid.Col span={6}>
|
<VerticalLogItem
|
||||||
<VerticalLogItem
|
label="Takeoffs (Day)"
|
||||||
label="Landings (Day)"
|
content={log.takeoffs_day}
|
||||||
content={log.landings_day}
|
/>
|
||||||
/>
|
<VerticalLogItem
|
||||||
</Grid.Col>
|
label="Landings (Day)"
|
||||||
<Grid.Col span={6}>
|
content={log.landings_day}
|
||||||
<VerticalLogItem
|
/>
|
||||||
label="Takeoffs (Night)"
|
<VerticalLogItem
|
||||||
content={log.takeoffs_night}
|
label="Takeoffs (Night)"
|
||||||
/>
|
content={log.takeoffs_night}
|
||||||
</Grid.Col>
|
/>
|
||||||
<Grid.Col span={6}>
|
<VerticalLogItem
|
||||||
<VerticalLogItem
|
label="Landings (Night)"
|
||||||
label="Landings (Night)"
|
content={log.landings_night}
|
||||||
content={log.landings_night}
|
/>
|
||||||
/>
|
</Group>
|
||||||
</Grid.Col>
|
</CollapsibleFieldset>
|
||||||
{log.time_instrument ||
|
{log.time_instrument ||
|
||||||
log.time_sim_instrument ||
|
log.time_sim_instrument ||
|
||||||
log.holds_instrument ? (
|
log.holds_instrument ? (
|
||||||
<>
|
<CollapsibleFieldset legend="Instrument" mt="sm" w="100%">
|
||||||
<Grid.Col span={4}>
|
<Group grow>
|
||||||
<VerticalLogItem
|
<VerticalLogItem
|
||||||
label="Instrument Time"
|
label="Instrument Time"
|
||||||
content={log.time_instrument}
|
content={log.time_instrument}
|
||||||
hours
|
hours
|
||||||
/>
|
/>
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={4}>
|
|
||||||
<VerticalLogItem
|
<VerticalLogItem
|
||||||
label="Simulated Instrument Time"
|
label="Simulated Instrument Time"
|
||||||
content={log.time_sim_instrument}
|
content={log.time_sim_instrument}
|
||||||
hours
|
hours
|
||||||
/>
|
/>
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={4}>
|
|
||||||
<VerticalLogItem
|
<VerticalLogItem
|
||||||
label="Instrument Holds"
|
label="Instrument Holds"
|
||||||
content={log.holds_instrument}
|
content={log.holds_instrument}
|
||||||
/>
|
/>
|
||||||
</Grid.Col>
|
</Group>
|
||||||
</>
|
</CollapsibleFieldset>
|
||||||
) : null}
|
) : null}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</Container>
|
||||||
|
35
web/app/ui/display/collapsible-fieldset.tsx
Normal file
35
web/app/ui/display/collapsible-fieldset.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { ActionIcon, Collapse, Fieldset, Group, Text } from "@mantine/core";
|
||||||
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
|
import { IconMinus, IconPlus } from "@tabler/icons-react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
export default function CollapsibleFieldset({
|
||||||
|
children,
|
||||||
|
legend,
|
||||||
|
w = "",
|
||||||
|
mt = "",
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
legend?: string;
|
||||||
|
w?: string;
|
||||||
|
mt?: string;
|
||||||
|
}) {
|
||||||
|
const [open, { toggle }] = useDisclosure(true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fieldset
|
||||||
|
legend={
|
||||||
|
<Group gap="xs">
|
||||||
|
{legend ? <Text>{legend}</Text> : null}
|
||||||
|
<ActionIcon variant="transparent" onClick={toggle} color="gray">
|
||||||
|
{open ? <IconMinus /> : <IconPlus />}
|
||||||
|
</ActionIcon>
|
||||||
|
</Group>
|
||||||
|
}
|
||||||
|
w={w}
|
||||||
|
mt={mt}
|
||||||
|
>
|
||||||
|
<Collapse in={open}>{children}</Collapse>
|
||||||
|
</Fieldset>
|
||||||
|
);
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { Card, Group, Stack, Text } from "@mantine/core";
|
import { Badge, Card, Group, Stack, Text } from "@mantine/core";
|
||||||
|
import { randomId } from "@mantine/hooks";
|
||||||
import { IconX } from "@tabler/icons-react";
|
import { IconX } from "@tabler/icons-react";
|
||||||
|
|
||||||
export function LogItem({
|
export function LogItem({
|
||||||
@ -25,36 +26,48 @@ export function VerticalLogItem({
|
|||||||
hours = false,
|
hours = false,
|
||||||
time = false,
|
time = false,
|
||||||
date = false,
|
date = false,
|
||||||
|
list = false,
|
||||||
}: {
|
}: {
|
||||||
label: string;
|
label: string;
|
||||||
content: string | null;
|
content: string | string[] | null;
|
||||||
decimal?: number;
|
decimal?: number;
|
||||||
hours?: boolean;
|
hours?: boolean;
|
||||||
time?: boolean;
|
time?: boolean;
|
||||||
date?: boolean;
|
date?: boolean;
|
||||||
|
list?: boolean;
|
||||||
}) {
|
}) {
|
||||||
if (content === null) content = "";
|
if (content === null) content = "";
|
||||||
if (decimal > 0) content = Number(content).toFixed(decimal);
|
if (decimal > 0) content = Number(content).toFixed(decimal);
|
||||||
if (hours) content = Number(content).toFixed(1);
|
if (hours) content = Number(content).toFixed(1);
|
||||||
if (time) {
|
if (time) {
|
||||||
const time = content.split("T")[1].split(":");
|
const time = (content as string).split("T")[1].split(":");
|
||||||
content = `${time[0]}:${time[1]}`;
|
content = `${time[0]}:${time[1]}`;
|
||||||
}
|
}
|
||||||
if (date) content = content.split("T")[0];
|
if (date) content = (content as string).split("T")[0];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card shadow="sm" withBorder>
|
||||||
<Stack gap="xs" align="center" h="100%">
|
<Stack gap="xs" align="center" h="100%">
|
||||||
<Text c="dimmed" style={{ textalign: "center" }}>
|
<Text c="dimmed" style={{ textalign: "center" }}>
|
||||||
{label}
|
{label}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
{list ? (
|
||||||
size="lg"
|
<Group>
|
||||||
style={{ textalign: "center" }}
|
{(content as string[]).map((item) => (
|
||||||
c={content === "" ? "dimmed" : ""}
|
<Badge key={randomId()} size="lg">
|
||||||
>
|
{item}
|
||||||
{content === "" ? <IconX /> : content}
|
</Badge>
|
||||||
</Text>
|
))}
|
||||||
|
</Group>
|
||||||
|
) : (
|
||||||
|
<Text
|
||||||
|
size="lg"
|
||||||
|
style={{ textalign: "center" }}
|
||||||
|
c={content === "" ? "dimmed" : ""}
|
||||||
|
>
|
||||||
|
{content === "" ? <IconX /> : content}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user