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";
|
||||
|
||||
import {
|
||||
MutationCache,
|
||||
HydrationBoundary,
|
||||
QueryCache,
|
||||
QueryClient,
|
||||
QueryClientProvider,
|
||||
} from "@tanstack/react-query";
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
|
||||
import { useDehydratedState } from "use-dehydrated-state";
|
||||
|
||||
import {
|
||||
Button,
|
||||
ColorSchemeScript,
|
||||
@ -102,7 +104,7 @@ export function ErrorBoundary() {
|
||||
);
|
||||
}
|
||||
|
||||
export default function App({ pageProps }) {
|
||||
export default function App() {
|
||||
const navigate = useNavigate();
|
||||
const [queryClient] = useState(
|
||||
() =>
|
||||
@ -128,6 +130,8 @@ export default function App({ pageProps }) {
|
||||
})
|
||||
);
|
||||
|
||||
const dehydratedState = useDehydratedState();
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
@ -139,15 +143,17 @@ export default function App({ pageProps }) {
|
||||
</head>
|
||||
<body>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<MantineProvider theme={{ primaryColor: "violet" }}>
|
||||
<AuthProvider>
|
||||
<Outlet />
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
<LiveReload />
|
||||
</AuthProvider>
|
||||
</MantineProvider>
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
<HydrationBoundary state={dehydratedState}>
|
||||
<MantineProvider theme={{ primaryColor: "violet" }}>
|
||||
<AuthProvider>
|
||||
<Outlet />
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
<LiveReload />
|
||||
</AuthProvider>
|
||||
</MantineProvider>
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
</HydrationBoundary>
|
||||
</QueryClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -8,19 +8,82 @@ import {
|
||||
Stack,
|
||||
Loader,
|
||||
Center,
|
||||
Divider,
|
||||
} from "@mantine/core";
|
||||
import { Link, useLocation, useNavigate } from "@remix-run/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() {
|
||||
const location = useLocation();
|
||||
const page = location.pathname.split("/")[3];
|
||||
|
||||
const flights = useQuery({
|
||||
queryKey: ["flights-list"],
|
||||
queryFn: async () => await client.get(`/flights`).then((res) => res.data),
|
||||
});
|
||||
const flights = useFlights();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -35,23 +98,7 @@ export function FlightsList() {
|
||||
Add
|
||||
</Button>
|
||||
<ScrollArea h="calc(100vh - 95px - 50px)">
|
||||
{flights.data ? (
|
||||
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>
|
||||
)}
|
||||
<FlightsListDisplay flights={flights} page={page} />
|
||||
</ScrollArea>
|
||||
</Stack>
|
||||
);
|
||||
@ -61,33 +108,14 @@ export function MobileFlightsList() {
|
||||
const location = useLocation();
|
||||
const page = location.pathname.split("/")[3];
|
||||
|
||||
const flights = useQuery({
|
||||
queryKey: ["flights-list"],
|
||||
queryFn: async () => await client.get(`/flights`).then((res) => res.data),
|
||||
});
|
||||
const flights = useFlights();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Stack p="0" m="0" justify="space-between" h="calc(100vh - 95px)">
|
||||
<ScrollArea h="calc(100vh - 95px - 50px">
|
||||
{flights.data ? (
|
||||
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>
|
||||
)}
|
||||
<FlightsListDisplay flights={flights} page={page} />
|
||||
</ScrollArea>
|
||||
<Button
|
||||
variant="outline"
|
||||
|
@ -68,7 +68,7 @@ type FlightConciseSchema = {
|
||||
user: string;
|
||||
id: string;
|
||||
|
||||
date: dayjs.Dayjs;
|
||||
date: string;
|
||||
aircraft: string;
|
||||
waypoint_from: 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",
|
||||
"isbot": "^3.6.8",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
"react-dom": "^18.2.0",
|
||||
"use-dehydrated-state": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^2.4.1",
|
||||
@ -4274,7 +4275,6 @@
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -11173,6 +11173,14 @@
|
||||
"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": {
|
||||
"version": "1.1.2",
|
||||
"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",
|
||||
"isbot": "^3.6.8",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
"react-dom": "^18.2.0",
|
||||
"use-dehydrated-state": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^2.4.1",
|
||||
|
Loading…
x
Reference in New Issue
Block a user