Group flights by date in list view

This commit is contained in:
april 2024-01-04 15:13:45 -06:00
parent a600cff6e6
commit 8c0a0955b3
5 changed files with 101 additions and 58 deletions

View File

@ -17,13 +17,15 @@ import {
} from "@remix-run/react"; } from "@remix-run/react";
import { import {
MutationCache, HydrationBoundary,
QueryCache, QueryCache,
QueryClient, QueryClient,
QueryClientProvider, QueryClientProvider,
} from "@tanstack/react-query"; } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { useDehydratedState } from "use-dehydrated-state";
import { import {
Button, Button,
ColorSchemeScript, ColorSchemeScript,
@ -102,7 +104,7 @@ export function ErrorBoundary() {
); );
} }
export default function App({ pageProps }) { export default function App() {
const navigate = useNavigate(); const navigate = useNavigate();
const [queryClient] = useState( const [queryClient] = useState(
() => () =>
@ -128,6 +130,8 @@ export default function App({ pageProps }) {
}) })
); );
const dehydratedState = useDehydratedState();
return ( return (
<html lang="en"> <html lang="en">
<head> <head>
@ -139,6 +143,7 @@ export default function App({ pageProps }) {
</head> </head>
<body> <body>
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<HydrationBoundary state={dehydratedState}>
<MantineProvider theme={{ primaryColor: "violet" }}> <MantineProvider theme={{ primaryColor: "violet" }}>
<AuthProvider> <AuthProvider>
<Outlet /> <Outlet />
@ -148,6 +153,7 @@ export default function App({ pageProps }) {
</AuthProvider> </AuthProvider>
</MantineProvider> </MantineProvider>
<ReactQueryDevtools initialIsOpen={false} /> <ReactQueryDevtools initialIsOpen={false} />
</HydrationBoundary>
</QueryClientProvider> </QueryClientProvider>
</body> </body>
</html> </html>

View File

@ -8,19 +8,82 @@ import {
Stack, Stack,
Loader, Loader,
Center, Center,
Divider,
} from "@mantine/core"; } from "@mantine/core";
import { Link, useLocation, useNavigate } from "@remix-run/react"; import { Link, useLocation, useNavigate } from "@remix-run/react";
import { IconPlus } from "@tabler/icons-react"; import { IconPlus } from "@tabler/icons-react";
import { useQuery } from "@tanstack/react-query"; import { UseQueryResult, useQuery } from "@tanstack/react-query";
function useFlights() {
const flights = useQuery({
queryKey: ["flights-list"],
queryFn: async () => {
const res = await client.get(`/flights`);
const groupedFlights: { [date: string]: FlightConciseSchema[] } = {};
res.data.map((log: FlightConciseSchema) => {
const dateStr = log.date;
if (!groupedFlights[dateStr]) {
groupedFlights[dateStr] = [];
}
groupedFlights[dateStr].push(log);
});
return groupedFlights;
},
});
return flights;
}
function FlightsListDisplay({
flights,
page,
}: {
flights: UseQueryResult<{ [date: string]: FlightConciseSchema[] }>;
page: string;
}) {
return (
<>
{flights.data ? (
Object.entries(flights.data).map(([date, logs], index: number) => (
<>
<Text key={date} mt="md" mb="xs" fw={700}>
{date}
</Text>
<Divider key={date + index} />
{logs.map((flight: FlightConciseSchema) => (
<NavLink
key={flight.id}
component={Link}
to={`/logbook/flights/${flight.id}`}
label={`${flight.waypoint_from ? flight.waypoint_from : ""} ${
flight.waypoint_to ? flight.waypoint_to : ""
}`}
description={`${flight.date}`}
active={page === flight.id}
/>
))}
</>
))
) : flights.isLoading ? (
<Center h="calc(100vh - 95px - 50px)">
<Loader />
</Center>
) : (
<Center h="calc(100vh - 95px - 50px)">
<Text p="sm">No Flights</Text>
</Center>
)}
</>
);
}
export function FlightsList() { export function FlightsList() {
const location = useLocation(); const location = useLocation();
const page = location.pathname.split("/")[3]; const page = location.pathname.split("/")[3];
const flights = useQuery({ const flights = useFlights();
queryKey: ["flights-list"],
queryFn: async () => await client.get(`/flights`).then((res) => res.data),
});
const navigate = useNavigate(); const navigate = useNavigate();
@ -35,23 +98,7 @@ export function FlightsList() {
Add Add
</Button> </Button>
<ScrollArea h="calc(100vh - 95px - 50px)"> <ScrollArea h="calc(100vh - 95px - 50px)">
{flights.data ? ( <FlightsListDisplay flights={flights} page={page} />
flights.data.map((flight: FlightConciseSchema, index: number) => (
<NavLink
key={index}
component={Link}
to={`/logbook/flights/${flight.id}`}
label={`${flight.date}`}
active={page === flight.id}
/>
))
) : flights.isLoading ? (
<Center h="calc(100vh - 95px - 50px)">
<Loader />
</Center>
) : (
<Text p="sm">No Flights</Text>
)}
</ScrollArea> </ScrollArea>
</Stack> </Stack>
); );
@ -61,33 +108,14 @@ export function MobileFlightsList() {
const location = useLocation(); const location = useLocation();
const page = location.pathname.split("/")[3]; const page = location.pathname.split("/")[3];
const flights = useQuery({ const flights = useFlights();
queryKey: ["flights-list"],
queryFn: async () => await client.get(`/flights`).then((res) => res.data),
});
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<Stack p="0" m="0" justify="space-between" h="calc(100vh - 95px)"> <Stack p="0" m="0" justify="space-between" h="calc(100vh - 95px)">
<ScrollArea h="calc(100vh - 95px - 50px"> <ScrollArea h="calc(100vh - 95px - 50px">
{flights.data ? ( <FlightsListDisplay flights={flights} page={page} />
flights.data.map((flight: FlightConciseSchema, index: number) => (
<NavLink
key={index}
component={Link}
to={`/logbook/flights/${flight.id}`}
label={`${flight.date}`}
active={page === flight.id}
/>
))
) : flights.isLoading ? (
<Center h="calc(100vh - 95px - 70px)">
<Loader />
</Center>
) : (
<Text p="sm">No Flights</Text>
)}
</ScrollArea> </ScrollArea>
<Button <Button
variant="outline" variant="outline"

View File

@ -68,7 +68,7 @@ type FlightConciseSchema = {
user: string; user: string;
id: string; id: string;
date: dayjs.Dayjs; date: string;
aircraft: string; aircraft: string;
waypoint_from: string; waypoint_from: string;
waypoint_to: string; waypoint_to: string;

12
web/package-lock.json generated
View File

@ -24,7 +24,8 @@
"dayjs-plugin-utc": "^0.1.2", "dayjs-plugin-utc": "^0.1.2",
"isbot": "^3.6.8", "isbot": "^3.6.8",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0",
"use-dehydrated-state": "^0.1.0"
}, },
"devDependencies": { "devDependencies": {
"@remix-run/dev": "^2.4.1", "@remix-run/dev": "^2.4.1",
@ -4274,7 +4275,6 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -11173,6 +11173,14 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0" "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
} }
}, },
"node_modules/use-dehydrated-state": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/use-dehydrated-state/-/use-dehydrated-state-0.1.0.tgz",
"integrity": "sha512-E2E1Mx9UeHiK1fxabnUULJEc7BNMmdsMy7hBGiDxDvxgP5/QIYJawQ2g2ZQvqvoXIkyzJA7wWG07hBWa5yuM9Q==",
"dependencies": {
"deepmerge": "^4.2.2"
}
},
"node_modules/use-isomorphic-layout-effect": { "node_modules/use-isomorphic-layout-effect": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",

View File

@ -30,7 +30,8 @@
"dayjs-plugin-utc": "^0.1.2", "dayjs-plugin-utc": "^0.1.2",
"isbot": "^3.6.8", "isbot": "^3.6.8",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0",
"use-dehydrated-state": "^0.1.0"
}, },
"devDependencies": { "devDependencies": {
"@remix-run/dev": "^2.4.1", "@remix-run/dev": "^2.4.1",