Group flights by date in list view
This commit is contained in:
parent
a600cff6e6
commit
8c0a0955b3
@ -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,15 +143,17 @@ export default function App({ pageProps }) {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<MantineProvider theme={{ primaryColor: "violet" }}>
|
<HydrationBoundary state={dehydratedState}>
|
||||||
<AuthProvider>
|
<MantineProvider theme={{ primaryColor: "violet" }}>
|
||||||
<Outlet />
|
<AuthProvider>
|
||||||
<ScrollRestoration />
|
<Outlet />
|
||||||
<Scripts />
|
<ScrollRestoration />
|
||||||
<LiveReload />
|
<Scripts />
|
||||||
</AuthProvider>
|
<LiveReload />
|
||||||
</MantineProvider>
|
</AuthProvider>
|
||||||
<ReactQueryDevtools initialIsOpen={false} />
|
</MantineProvider>
|
||||||
|
<ReactQueryDevtools initialIsOpen={false} />
|
||||||
|
</HydrationBoundary>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -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"
|
||||||
|
@ -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
12
web/package-lock.json
generated
@ -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",
|
||||||
|
@ -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",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user