Implement flight log creation

This commit is contained in:
april
2024-01-03 15:27:58 -06:00
parent 8e03e3dccf
commit a52eab9105
12 changed files with 742 additions and 54 deletions

View File

@@ -1,4 +1,5 @@
import "@mantine/core/styles.css";
import "@mantine/dates/styles.css";
import { cssBundleHref } from "@remix-run/css-bundle";
import type { LinksFunction } from "@remix-run/node";

View File

@@ -0,0 +1,344 @@
import {
Button,
CloseButton,
Container,
Fieldset,
Group,
NumberInput,
ScrollArea,
ScrollAreaAutosize,
Stack,
TextInput,
Textarea,
Title,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { DatePickerInput } from "@mantine/dates";
import dayjs from "dayjs";
import { IconPencil } from "@tabler/icons-react";
import TimeInput from "@/ui/form/time-input";
import { FlightFormSchema, flightCreateHelper } from "@/util/types";
import { HourInput, ZeroHourInput } from "@/ui/form/hour-input";
import { ZeroIntInput } from "@/ui/form/int-input";
import ListInput from "@/ui/form/list-input";
import { useMutation } from "@tanstack/react-query";
import { client } from "@/util/api";
import { useNavigate } from "@remix-run/react";
export default function NewFlight() {
const form = useForm<FlightFormSchema>({
initialValues: {
date: dayjs(),
aircraft: "",
waypoint_from: "",
waypoint_to: "",
route: "",
hobbs_start: null,
hobbs_end: null,
tach_start: null,
tach_end: null,
time_start: null,
time_off: null,
time_down: null,
time_stop: null,
time_total: 0.0,
time_pic: 0.0,
time_sic: 0.0,
time_night: 0.0,
time_solo: 0.0,
time_xc: 0.0,
dist_xc: 0.0,
takeoffs_day: 0,
landings_day: 0,
takeoffs_night: 0,
landings_night: 0,
time_instrument: 0.0,
time_sim_instrument: 0.0,
holds_instrument: 0,
dual_given: 0.0,
dual_recvd: 0.0,
time_sim: 0.0,
time_ground: 0.0,
tags: [],
pax: [],
crew: [],
comments: "",
},
});
const navigate = useNavigate();
const createFlight = useMutation({
mutationFn: async (values: FlightFormSchema) => {
const newFlight = flightCreateHelper(values);
const res = await client.post("/flights", newFlight);
navigate(`/logbook/flights/${res.data.id}`);
},
onError: (error) => {
console.log(error);
},
});
return (
<Container>
<Stack>
<Title order={2}>New Flight</Title>
<form onSubmit={form.onSubmit((values) => createFlight.mutate(values))}>
<ScrollAreaAutosize mah="calc(100vh - 95px - 110px">
<Container>
{/* Date and Aircraft */}
<Fieldset>
<Group justify="center" grow>
<DatePickerInput
label="Date"
{...form.getInputProps("date")}
/>
<TextInput
label="Aircraft"
{...form.getInputProps("aircraft")}
/>
</Group>
</Fieldset>
{/* Route */}
<Fieldset legend="Route" mt="lg">
<Group justify="center" grow>
<TextInput
label="Waypoint From"
{...form.getInputProps("waypoint_from")}
/>
<TextInput
label="Waypoint To"
{...form.getInputProps("waypoint_to")}
/>
</Group>
<TextInput
label="Route"
{...form.getInputProps("route")}
mt="md"
/>
</Fieldset>
{/* Times */}
<Fieldset legend="Times" mt="md">
<Group justify="center" grow>
<HourInput
form={form}
field="hobbs_start"
label="Hobbs Start"
/>
<HourInput form={form} field="hobbs_end" label="Hobbs End" />
</Group>
<Group justify="center" grow mt="md">
<HourInput
form={form}
field="tach_start"
label="Tach Start"
/>
<HourInput form={form} field="tach_end" label="Tach End" />
</Group>
</Fieldset>
{/* Start/Stop */}
<Fieldset legend="Start/Stop" mt="md">
<Group justify="center" grow>
<TimeInput
form={form}
field="time_start"
label="Start Time"
/>
<TimeInput form={form} field="time_stop" label="Stop Time" />
</Group>
<Group justify="center" grow mt="md">
<TimeInput form={form} field="time_off" label="Time Off" />
<TimeInput form={form} field="time_down" label="Time Down" />
</Group>
</Fieldset>
{/* Hours */}
<Fieldset legend="Hours" mt="md">
<Group justify="center" grow>
<ZeroHourInput
form={form}
field="time_total"
label="Time Total"
/>
<ZeroHourInput
form={form}
field="time_pic"
label="Time PIC"
/>
<ZeroHourInput
form={form}
field="time_sic"
label="Time SIC"
/>
</Group>
<Group justify="center" grow mt="md">
<ZeroHourInput
form={form}
field="time_night"
label="Time Night"
/>
<ZeroHourInput
form={form}
field="time_solo"
label="Time Solo"
/>
</Group>
</Fieldset>
{/* Cross-Country */}
<Fieldset legend="Cross-Country" mt="md">
<Group justify="center" grow>
<ZeroHourInput
form={form}
field="time_xc"
label="Time Cross-Country"
/>
<NumberInput
label="Distance Cross-Country"
decimalScale={2}
min={0}
fixedDecimalScale
leftSection={
<CloseButton
aria-label="Clear input"
onClick={() => form.setFieldValue("dist_xc", 0)}
style={{
display:
form.getTransformedValues().dist_xc == 0
? "none"
: undefined,
}}
/>
}
{...form.getInputProps("dist_xc")}
/>
</Group>
</Fieldset>
{/* Takeoffs and Landings */}
<Fieldset legend="Takeoffs and Landings" mt="md">
<Group justify="center" grow>
<ZeroIntInput
form={form}
field="takeoffs_day"
label="Day Takeoffs"
/>
<ZeroIntInput
form={form}
field="landings_day"
label="Day Landings"
/>
</Group>
<Group justify="center" grow mt="md">
<ZeroIntInput
form={form}
field="takeoffs_night"
label="Night Takeoffs"
/>
<ZeroIntInput
form={form}
field="landings_night"
label="Night Landings"
/>
</Group>
</Fieldset>
{/* Instrument */}
<Fieldset legend="Instrument" mt="md">
<Group justify="center" grow>
<ZeroHourInput
form={form}
field="time_instrument"
label="Time Instrument"
/>
<ZeroHourInput
form={form}
field="time_sim_instrument"
label="Time Sim Instrument"
/>
<ZeroIntInput
form={form}
field="holds_instrument"
label="Instrument Holds"
/>
</Group>
</Fieldset>
{/* Instruction */}
<Fieldset legend="Instruction" mt="md">
<Group justify="center" grow>
<ZeroHourInput
form={form}
field="dual_given"
label="Dual Given"
/>
<ZeroHourInput
form={form}
field="dual_recvd"
label="Dual Received"
/>
<ZeroHourInput
form={form}
field="time_sim"
label="Sim Time"
/>
<ZeroHourInput
form={form}
field="time_ground"
label="Ground Time"
/>
</Group>
</Fieldset>
{/* About the Flight */}
<Fieldset legend="About" mt="md">
<ListInput form={form} field="tags" label="Tags" />
<Group justify="center" grow mt="md">
<ListInput form={form} field="pax" label="Pax" />
<ListInput form={form} field="crew" label="Crew" />
</Group>
<Textarea
label="Comments"
mt="md"
autosize
minRows={4}
{...form.getInputProps("comments")}
/>
</Fieldset>
</Container>
</ScrollAreaAutosize>
<Group justify="flex-end" mt="md">
<Button type="submit" leftSection={<IconPencil />}>
Create
</Button>
</Group>
</form>
</Stack>
</Container>
);
}

View File

@@ -1,7 +1,7 @@
import { client } from "@/util/api";
import { Flight } from "@/util/types";
import { FlightConciseSchema } from "@/util/types";
import { NavLink, Text, Button, ScrollArea, Stack } from "@mantine/core";
import { Link, useLocation } from "@remix-run/react";
import { Link, useLocation, useNavigate } from "@remix-run/react";
import { IconPlus } from "@tabler/icons-react";
import { useQuery } from "@tanstack/react-query";
@@ -14,14 +14,21 @@ export function FlightsList() {
const location = useLocation();
const page = location.pathname.split("/")[3];
const navigate = useNavigate();
return (
<Stack p="0" m="0" gap="0">
<Button variant="outline" leftSection={<IconPlus />} mb="md">
<Button
variant="outline"
leftSection={<IconPlus />}
mb="md"
onClick={() => navigate("/logbook/flights/new")}
>
Add
</Button>
<ScrollArea>
{flights.data ? (
flights.data.map((flight: Flight, index: number) => (
flights.data.map((flight: FlightConciseSchema, index: number) => (
<NavLink
key={index}
component={Link}
@@ -47,11 +54,13 @@ export function MobileFlightsList() {
const location = useLocation();
const page = location.pathname.split("/")[3];
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: Flight, index: number) => (
flights.data.map((flight: FlightConciseSchema, index: number) => (
<NavLink
key={index}
component={Link}
@@ -64,7 +73,12 @@ export function MobileFlightsList() {
<Text p="sm">No Flights</Text>
)}
</ScrollArea>
<Button variant="outline" leftSection={<IconPlus />} mt="md">
<Button
variant="outline"
leftSection={<IconPlus />}
mt="md"
onClick={() => navigate("/logbook/flights/new")}
>
Add
</Button>
</Stack>

View File

@@ -1,4 +1,4 @@
import { Divider, Grid, Container } from "@mantine/core";
import { Divider, Grid, Container, ScrollAreaAutosize } from "@mantine/core";
import { Outlet } from "@remix-run/react";
import { FlightsList } from "./flights-list";
@@ -11,7 +11,9 @@ export default function FlightsLayout() {
</Grid.Col>
<Divider orientation="vertical" m="sm" />
<Grid.Col span="auto">
<Outlet />
<ScrollAreaAutosize mah="calc(100vh - 95px)">
<Outlet />
</ScrollAreaAutosize>
</Grid.Col>
</Grid>
<Container hiddenFrom="md">

View File

@@ -0,0 +1,77 @@
import { FlightFormSchema } from "@/util/types";
import { CloseButton, NumberInput } from "@mantine/core";
import { UseFormReturnType } from "@mantine/form";
function HourInput({
form,
field,
label,
}: {
form: UseFormReturnType<
FlightFormSchema,
(values: FlightFormSchema) => FlightFormSchema
>;
field: string;
label: string;
}) {
const field_key = field as keyof typeof form.getTransformedValues;
return (
<NumberInput
label={label}
decimalScale={1}
min={0}
fixedDecimalScale
leftSection={
<CloseButton
aria-label="Clear input"
onClick={() => form.setFieldValue(field, "")}
style={{
display:
["", null].indexOf(form.getTransformedValues()[field_key]) > -1
? "none"
: undefined,
}}
/>
}
{...form.getInputProps(field)}
/>
);
}
function ZeroHourInput({
form,
field,
label,
}: {
form: UseFormReturnType<
FlightFormSchema,
(values: FlightFormSchema) => FlightFormSchema
>;
field: string;
label: string;
}) {
const field_key = field as keyof typeof form.getTransformedValues;
return (
<NumberInput
label={label}
decimalScale={1}
min={0}
fixedDecimalScale
leftSection={
<CloseButton
aria-label="Clear input"
onClick={() => form.setFieldValue(field, 0)}
style={{
display:
form.getTransformedValues()[field_key] === 0 ? "none" : undefined,
}}
/>
}
{...form.getInputProps(field)}
/>
);
}
export { HourInput, ZeroHourInput };

View File

@@ -0,0 +1,75 @@
import { FlightFormSchema } from "@/util/types";
import { CloseButton, NumberInput } from "@mantine/core";
import { UseFormReturnType } from "@mantine/form";
function IntInput({
form,
field,
label,
}: {
form: UseFormReturnType<
FlightFormSchema,
(values: FlightFormSchema) => FlightFormSchema
>;
field: string;
label: string;
}) {
const field_key = field as keyof typeof form.getTransformedValues;
return (
<NumberInput
label={label}
min={0}
allowDecimal={false}
leftSection={
<CloseButton
aria-label="Clear input"
onClick={() => form.setFieldValue(field, "")}
style={{
display:
["", null].indexOf(form.getTransformedValues()[field_key]) > -1
? "none"
: undefined,
}}
/>
}
{...form.getInputProps(field)}
/>
);
}
function ZeroIntInput({
form,
field,
label,
}: {
form: UseFormReturnType<
FlightFormSchema,
(values: FlightFormSchema) => FlightFormSchema
>;
field: string;
label: string;
}) {
const field_key = field as keyof typeof form.getTransformedValues;
return (
<NumberInput
label={label}
min={0}
allowDecimal={false}
leftSection={
<CloseButton
aria-label="Clear input"
onClick={() => form.setFieldValue(field, 0)}
style={{
display:
form.getTransformedValues()[field_key] > 0 ? "none" : undefined,
}}
/>
}
{...form.getInputProps(field)}
/>
);
}
export { IntInput, ZeroIntInput };

View File

@@ -0,0 +1,69 @@
import { FlightFormSchema } from "@/util/types";
import { Pill, PillsInput } from "@mantine/core";
import { UseFormReturnType } from "@mantine/form";
import { useState } from "react";
export default function ListInput({
form,
field,
label,
}: {
form: UseFormReturnType<
FlightFormSchema,
(values: FlightFormSchema) => FlightFormSchema
>;
field: string;
label: string;
}) {
const field_key = field as keyof typeof form.getTransformedValues;
const [inputValue, setInputValue] = useState<string>("");
const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === "Enter" || event.key === ",") {
event.preventDefault();
const values = form.getTransformedValues()[field_key] as string[];
const newItem = inputValue.trim();
if (newItem && values.indexOf(newItem) == -1) {
form.setFieldValue(field, [...values, newItem]);
setInputValue("");
}
} else if (event.key === "Backspace") {
const values = form.getTransformedValues()[field_key] as string[];
const newItem = inputValue.trim();
if (newItem === "") {
form.setFieldValue(field, values.slice(0, -1));
}
}
};
return (
<PillsInput label={label}>
<Pill.Group>
{(form.getTransformedValues()[field_key] as string[]).map(
(item: string) => (
<Pill
radius="sm"
key={item}
withRemoveButton
onRemove={() =>
form.setFieldValue(
field,
(form.getTransformedValues()[field_key] as string[]).filter(
(value: string) => value !== item
)
)
}
>
{item}
</Pill>
)
)}
<PillsInput.Field
value={inputValue}
onChange={(event) => setInputValue(event.currentTarget.value)}
onKeyDown={handleKeyDown}
/>
</Pill.Group>
</PillsInput>
);
}

View File

@@ -0,0 +1,52 @@
import { FlightFormSchema } from "@/util/types";
import { ActionIcon, CloseButton, NumberInput, Tooltip } from "@mantine/core";
import { UseFormReturnType } from "@mantine/form";
import { IconClock } from "@tabler/icons-react";
import dayjs from "dayjs";
export default function TimeInput({
form,
label,
field,
}: {
form: UseFormReturnType<FlightFormSchema>;
field: string;
label: string;
}) {
const field_key = field as keyof typeof form.getTransformedValues;
return (
<NumberInput
label={label}
allowDecimal={false}
min={0}
max={2359}
leftSection={
<CloseButton
aria-label="Clear input"
onClick={() => form.setFieldValue(field, "")}
style={{
display:
["", null].indexOf(form.getTransformedValues()[field_key]) > -1
? "none"
: undefined,
}}
/>
}
rightSection={
<Tooltip label="Now">
<ActionIcon
variant="transparent"
mr="sm"
onClick={() => {
form.setFieldValue(field, dayjs().format("HHmm"));
}}
>
<IconClock style={{ width: "70%", height: "70%" }} />
</ActionIcon>
</Tooltip>
}
{...form.getInputProps(field)}
/>
);
}

View File

@@ -91,6 +91,7 @@ function useProvideAuth() {
.get("/users/me")
.then((response) => handleUser(response.data.username))
.catch(() => handleUser(null));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return {

View File

@@ -1,8 +1,9 @@
type Flight = {
id: string;
user: string;
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc.js";
date: string;
dayjs.extend(utc);
type FlightBaseSchema = {
aircraft: string | null;
waypoint_from: string | null;
waypoint_to: string | null;
@@ -49,4 +50,49 @@ type Flight = {
comments: string;
};
export { type Flight };
type FlightFormSchema = FlightBaseSchema & {
date: dayjs.Dayjs;
};
type FlightCreateSchema = FlightBaseSchema & {
date: string;
};
type FlightDisplaySchema = FlightBaseSchema & {
id: string;
user: string;
date: dayjs.Dayjs;
};
type FlightConciseSchema = {
user: string;
id: string;
date: dayjs.Dayjs;
aircraft: string;
waypoint_from: string;
waypoint_to: string;
time_total: number;
comments: string;
};
const flightCreateHelper = (values: FlightFormSchema): FlightCreateSchema => {
return {
...values,
date: values.date.utc().startOf("day").toISOString(),
hobbs_start: Number(values.hobbs_start),
hobbs_end: Number(values.hobbs_end),
tach_start: Number(values.tach_start),
tach_end: Number(values.tach_end),
};
};
export {
flightCreateHelper,
type FlightFormSchema,
type FlightCreateSchema,
type FlightDisplaySchema,
type FlightConciseSchema,
};

76
web/package-lock.json generated
View File

@@ -5,12 +5,12 @@
"packages": {
"": {
"dependencies": {
"@mantine/core": "^7.3.2",
"@mantine/dates": "^7.3.2",
"@mantine/dropzone": "^7.3.2",
"@mantine/form": "^7.3.2",
"@mantine/hooks": "^7.3.2",
"@mantine/notifications": "^7.3.2",
"@mantine/core": "^7.4.0",
"@mantine/dates": "^7.4.0",
"@mantine/dropzone": "^7.4.0",
"@mantine/form": "^7.4.0",
"@mantine/hooks": "^7.4.0",
"@mantine/notifications": "^7.4.0",
"@remix-run/css-bundle": "^2.4.1",
"@remix-run/node": "^2.4.1",
"@remix-run/react": "^2.4.1",
@@ -20,6 +20,7 @@
"@tanstack/react-query-devtools": "^5.17.0",
"axios": "^1.6.3",
"dayjs": "^1.11.10",
"dayjs-plugin-utc": "^0.1.2",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
@@ -1426,9 +1427,9 @@
"dev": true
},
"node_modules/@mantine/core": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.3.2.tgz",
"integrity": "sha512-CwAuQogVLcLR7O9e1eOgi3gtk4XX6cnaqevAxzJJpIOIyCnHiQ3cEGINVXyUUjUUipBlvK3sqz3NPGJ2ekLFDQ==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.4.0.tgz",
"integrity": "sha512-wnQOz1aSpqVlCpdyY4XyJKRqlW87mexMADQrbCTwg/5BbxKp8XU6sTcnk1piwyR0mM6SI1uo0Yik2qYNGFlyWw==",
"dependencies": {
"@floating-ui/react": "^0.24.8",
"clsx": "2.0.0",
@@ -1438,44 +1439,44 @@
"type-fest": "^3.13.1"
},
"peerDependencies": {
"@mantine/hooks": "7.3.2",
"@mantine/hooks": "7.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
},
"node_modules/@mantine/dates": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.3.2.tgz",
"integrity": "sha512-mmP0PYpM9GYTXRhEL4Ulb+170vgW8fpGwRdVNuCCE/cyzIKHPJzaI2pEGR/i+sboH+RC1InCy/JaiDkPY6Fzlg==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.4.0.tgz",
"integrity": "sha512-KNRVMSUW4sIk8U5SM2+4PRLqndWNaMtTabENPZUVA/Zl99yk6tDsNsu/CuinE1K5LQo9H6RJho0FRGzmzEsTwA==",
"dependencies": {
"clsx": "2.0.0"
},
"peerDependencies": {
"@mantine/core": "7.3.2",
"@mantine/hooks": "7.3.2",
"@mantine/core": "7.4.0",
"@mantine/hooks": "7.4.0",
"dayjs": ">=1.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
},
"node_modules/@mantine/dropzone": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-7.3.2.tgz",
"integrity": "sha512-SqeBARkfS/x8UkxTc8qup7oWF1NDXP2WsbzllsLpjnlH7A/MpNgEUHs/y6oUF0Sxnc3g5Z0cvzHlZpFiWDGCmg==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-7.4.0.tgz",
"integrity": "sha512-vMX9vrYBl9A/0frIcvgHjCLAdZ0hSI79VMQfMoWQ9GpOG15auQGtleT04JEgmB83I0mChSdS1I+8rV9erTBlhQ==",
"dependencies": {
"react-dropzone-esm": "15.0.1"
},
"peerDependencies": {
"@mantine/core": "7.3.2",
"@mantine/hooks": "7.3.2",
"@mantine/core": "7.4.0",
"@mantine/hooks": "7.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
},
"node_modules/@mantine/form": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.3.2.tgz",
"integrity": "sha512-/qa1KQKVC46XWgIU190r3XM3Xld8Lsvz4L/an//TO67RnAGEdC5OCvr2JCb+fprZZi3YdxaKOkVNvP20W23qkg==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.4.0.tgz",
"integrity": "sha512-JI/o2nECWct/Kvn3GF6VplHyJeaLy0q/jGNEB/F4yt12mAYBsux6vPfAhpWrKKZ8Jt31RI+ikn6R4UcY1HGIAw==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"klona": "^2.0.6"
@@ -1485,32 +1486,32 @@
}
},
"node_modules/@mantine/hooks": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.3.2.tgz",
"integrity": "sha512-xgumuuI3PBWXff5N02HCI7PEy25mDEdyXDQklUYK93J6FKwpcosyZnGVitoUrV1gLtYYa9ZudeAWdhHuh/CpOg==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.4.0.tgz",
"integrity": "sha512-Swv23D8XmZqE2hohPBcff+ITwv5l8UlwiiEGMhL+ceUvJLnPzdwlW21qnLBtRtZWyQQ59TAav4M0GFGd93JS8Q==",
"peerDependencies": {
"react": "^18.2.0"
}
},
"node_modules/@mantine/notifications": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.3.2.tgz",
"integrity": "sha512-XOzgm4pm4XszavVN0QUjN+IP0xiG2IochxJSz/FduTI0r3u1WxdpvDYlOvEJpHhtWvyqI8W8rx6cPJaD2HdAwQ==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.4.0.tgz",
"integrity": "sha512-nRXYIcJpqqKxwYs2r17IBZ8uQZK57x6K2hkzOQ+ZFviO5rejxl4ip+fC+LUhIi3P7D1YSxyoZwumT73gSPz9Xw==",
"dependencies": {
"@mantine/store": "7.3.2",
"@mantine/store": "7.4.0",
"react-transition-group": "4.4.5"
},
"peerDependencies": {
"@mantine/core": "7.3.2",
"@mantine/hooks": "7.3.2",
"@mantine/core": "7.4.0",
"@mantine/hooks": "7.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
},
"node_modules/@mantine/store": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.3.2.tgz",
"integrity": "sha512-M1eWHzTRCeCFvrpFhXKIM9zblrlIT5/XrMue/fP2HrkA43dpkgq+ArnZkN3LhG9lWR/EKbRwQWDhDIvdLtfD7w==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.4.0.tgz",
"integrity": "sha512-sSaBj6qVU0e5ml70/8e3A9pwAMBL5yKWNdnhw20b+74j85+FUDhDy8bEGZfyS0BtYPGVoxj5yF8/uZhxnDXpbg==",
"peerDependencies": {
"react": "^18.2.0"
}
@@ -4210,6 +4211,11 @@
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
"integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
},
"node_modules/dayjs-plugin-utc": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/dayjs-plugin-utc/-/dayjs-plugin-utc-0.1.2.tgz",
"integrity": "sha512-ExERH5o3oo6jFOdkvMP3gytTCQ9Ksi5PtylclJWghr7k7m3o2U5QrwtdiJkOxLOH4ghr0EKhpqGefzGz1VvVJg=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",

View File

@@ -11,12 +11,12 @@
"typecheck": "tsc"
},
"dependencies": {
"@mantine/core": "^7.3.2",
"@mantine/dates": "^7.3.2",
"@mantine/dropzone": "^7.3.2",
"@mantine/form": "^7.3.2",
"@mantine/hooks": "^7.3.2",
"@mantine/notifications": "^7.3.2",
"@mantine/core": "^7.4.0",
"@mantine/dates": "^7.4.0",
"@mantine/dropzone": "^7.4.0",
"@mantine/form": "^7.4.0",
"@mantine/hooks": "^7.4.0",
"@mantine/notifications": "^7.4.0",
"@remix-run/css-bundle": "^2.4.1",
"@remix-run/node": "^2.4.1",
"@remix-run/react": "^2.4.1",
@@ -26,6 +26,7 @@
"@tanstack/react-query-devtools": "^5.17.0",
"axios": "^1.6.3",
"dayjs": "^1.11.10",
"dayjs-plugin-utc": "^0.1.2",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"