Display images on flight logs
This commit is contained in:
parent
a1b5332910
commit
4b80593aa3
@ -1,5 +1,6 @@
|
|||||||
import "@mantine/core/styles.css";
|
import "@mantine/core/styles.css";
|
||||||
import "@mantine/dates/styles.css";
|
import "@mantine/dates/styles.css";
|
||||||
|
import "@mantine/carousel/styles.css";
|
||||||
|
|
||||||
import { cssBundleHref } from "@remix-run/css-bundle";
|
import { cssBundleHref } from "@remix-run/css-bundle";
|
||||||
import type { LinksFunction } from "@remix-run/node";
|
import type { LinksFunction } from "@remix-run/node";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import CollapsibleFieldset from "@/ui/display/collapsible-fieldset";
|
import CollapsibleFieldset from "@/ui/display/collapsible-fieldset";
|
||||||
import { VerticalLogItem } from "@/ui/display/log-item";
|
import { VerticalLogItem } from "@/ui/display/log-item";
|
||||||
|
import SecureImage from "@/ui/display/secure-img";
|
||||||
import ErrorDisplay from "@/ui/error-display";
|
import ErrorDisplay from "@/ui/error-display";
|
||||||
import { useApi } from "@/util/api";
|
import { useApi } from "@/util/api";
|
||||||
import {
|
import {
|
||||||
@ -17,10 +18,12 @@ import {
|
|||||||
Modal,
|
Modal,
|
||||||
Button,
|
Button,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useDisclosure } from "@mantine/hooks";
|
import { Carousel } from "@mantine/carousel";
|
||||||
|
import { randomId, 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, IconTrash } from "@tabler/icons-react";
|
||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function Flight() {
|
export default function Flight() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@ -34,6 +37,14 @@ export default function Flight() {
|
|||||||
await client.get(`/flights/${params.id}`).then((res) => res.data),
|
await client.get(`/flights/${params.id}`).then((res) => res.data),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [imageIds, setImageIds] = useState<string[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (flight.data) {
|
||||||
|
setImageIds(flight.data.images ?? []);
|
||||||
|
}
|
||||||
|
}, [flight.data]);
|
||||||
|
|
||||||
const [deleteOpened, { open: openDelete, close: closeDelete }] =
|
const [deleteOpened, { open: openDelete, close: closeDelete }] =
|
||||||
useDisclosure(false);
|
useDisclosure(false);
|
||||||
|
|
||||||
@ -117,6 +128,25 @@ 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">
|
||||||
|
{imageIds.length > 0 ? (
|
||||||
|
<CollapsibleFieldset legend="Images" mt="sm" w="100%">
|
||||||
|
<Carousel
|
||||||
|
withIndicators
|
||||||
|
slideGap="sm"
|
||||||
|
slideSize={{ base: "100%", sm: "80%" }}
|
||||||
|
>
|
||||||
|
{imageIds.map((img) => (
|
||||||
|
<Carousel.Slide key={randomId()}>
|
||||||
|
<SecureImage
|
||||||
|
key={randomId()}
|
||||||
|
id={img}
|
||||||
|
radius="lg"
|
||||||
|
/>
|
||||||
|
</Carousel.Slide>
|
||||||
|
))}
|
||||||
|
</Carousel>
|
||||||
|
</CollapsibleFieldset>
|
||||||
|
) : null}
|
||||||
<CollapsibleFieldset legend="About" mt="sm" w="100%">
|
<CollapsibleFieldset legend="About" mt="sm" w="100%">
|
||||||
<Group grow>
|
<Group grow>
|
||||||
<VerticalLogItem label="Date" content={log.date} date />
|
<VerticalLogItem label="Date" content={log.date} date />
|
||||||
|
91
web/app/ui/display/secure-img.tsx
Normal file
91
web/app/ui/display/secure-img.tsx
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import { useApi } from "@/util/api";
|
||||||
|
import { Center, Image, Loader, Modal } from "@mantine/core";
|
||||||
|
import { UseQueryResult, useQuery } from "@tanstack/react-query";
|
||||||
|
import ErrorDisplay from "../error-display";
|
||||||
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
|
|
||||||
|
function blobToBase64(blob: Blob): Promise<string | null> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsBinaryString(blob);
|
||||||
|
reader.onloadend = function () {
|
||||||
|
if (typeof reader.result === "string") {
|
||||||
|
const base64 = btoa(reader.result);
|
||||||
|
resolve(base64);
|
||||||
|
} else {
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function useFetchImageAsBase64(
|
||||||
|
img_id: string
|
||||||
|
): UseQueryResult<{ blob: string | null; type: string }> {
|
||||||
|
const client = useApi();
|
||||||
|
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["image", img_id],
|
||||||
|
queryFn: async (): Promise<{
|
||||||
|
blob: string;
|
||||||
|
type: string;
|
||||||
|
}> => {
|
||||||
|
const response = await client.get(`/img/${img_id}`, {
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
});
|
||||||
|
|
||||||
|
const blob = (await blobToBase64(new Blob([response.data]))) as string;
|
||||||
|
const type = (response.headers["content-type"] as string) ?? "image/jpeg";
|
||||||
|
|
||||||
|
return { blob, type };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SecureImage({
|
||||||
|
id,
|
||||||
|
radius = "sm",
|
||||||
|
clickable = true,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
radius?: string;
|
||||||
|
clickable?: boolean;
|
||||||
|
}) {
|
||||||
|
const { isLoading, error, data } = useFetchImageAsBase64(id);
|
||||||
|
|
||||||
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
|
|
||||||
|
if (isLoading)
|
||||||
|
return (
|
||||||
|
<Center h="100%">
|
||||||
|
<Loader />
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) return <ErrorDisplay error="Failed to load image" />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{clickable ? (
|
||||||
|
<Modal
|
||||||
|
title="Image"
|
||||||
|
opened={opened}
|
||||||
|
onClose={close}
|
||||||
|
centered
|
||||||
|
size="auto"
|
||||||
|
>
|
||||||
|
<Image src={`data:${data?.type};base64,${data?.blob}`} />
|
||||||
|
</Modal>
|
||||||
|
) : null}
|
||||||
|
<Image
|
||||||
|
src={`data:${data?.type};base64,${data?.blob}`}
|
||||||
|
radius={radius}
|
||||||
|
onClick={() => {
|
||||||
|
if (clickable) {
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -337,12 +337,32 @@ export default function FlightForm({
|
|||||||
|
|
||||||
<Fieldset legend="Start/Stop" mt="md">
|
<Fieldset legend="Start/Stop" mt="md">
|
||||||
<Group justify="center" grow>
|
<Group justify="center" grow>
|
||||||
<TimeInput form={form} field="time_start" label="Start Time" />
|
<TimeInput
|
||||||
<TimeInput form={form} field="time_off" label="Time Off" />
|
form={form}
|
||||||
|
field="time_start"
|
||||||
|
label="Start Time"
|
||||||
|
allowLeadingZeros
|
||||||
|
/>
|
||||||
|
<TimeInput
|
||||||
|
form={form}
|
||||||
|
field="time_off"
|
||||||
|
label="Time Off"
|
||||||
|
allowLeadingZeros
|
||||||
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<Group justify="center" grow mt="md">
|
<Group justify="center" grow mt="md">
|
||||||
<TimeInput form={form} field="time_down" label="Time Down" />
|
<TimeInput
|
||||||
<TimeInput form={form} field="time_stop" label="Stop Time" />
|
form={form}
|
||||||
|
field="time_down"
|
||||||
|
label="Time Down"
|
||||||
|
allowLeadingZeros
|
||||||
|
/>
|
||||||
|
<TimeInput
|
||||||
|
form={form}
|
||||||
|
field="time_stop"
|
||||||
|
label="Stop Time"
|
||||||
|
allowLeadingZeros
|
||||||
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
|
|
||||||
|
@ -8,10 +8,12 @@ export default function TimeInput({
|
|||||||
form,
|
form,
|
||||||
label,
|
label,
|
||||||
field,
|
field,
|
||||||
|
allowLeadingZeros = false,
|
||||||
}: {
|
}: {
|
||||||
form: UseFormReturnType<FlightFormSchema>;
|
form: UseFormReturnType<FlightFormSchema>;
|
||||||
field: string;
|
field: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
allowLeadingZeros?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const field_key = field as keyof typeof form.getTransformedValues;
|
const field_key = field as keyof typeof form.getTransformedValues;
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ export default function TimeInput({
|
|||||||
allowDecimal={false}
|
allowDecimal={false}
|
||||||
min={0}
|
min={0}
|
||||||
max={2359}
|
max={2359}
|
||||||
|
allowLeadingZeros={allowLeadingZeros}
|
||||||
leftSection={
|
leftSection={
|
||||||
<CloseButton
|
<CloseButton
|
||||||
aria-label="Clear input"
|
aria-label="Clear input"
|
||||||
|
@ -70,6 +70,8 @@ type FlightDisplaySchema = FlightBaseSchema & {
|
|||||||
time_off: number | null;
|
time_off: number | null;
|
||||||
time_down: number | null;
|
time_down: number | null;
|
||||||
time_stop: number | null;
|
time_stop: number | null;
|
||||||
|
|
||||||
|
images: string[] | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FlightConciseSchema = {
|
type FlightConciseSchema = {
|
||||||
|
112
web/package-lock.json
generated
112
web/package-lock.json
generated
@ -6,13 +6,14 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "tailfin-web",
|
"name": "tailfin-web",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/core": "^7.4.0",
|
"@mantine/carousel": "^7.4.1",
|
||||||
"@mantine/dates": "^7.4.0",
|
"@mantine/core": "^7.4.1",
|
||||||
"@mantine/dropzone": "^7.4.0",
|
"@mantine/dates": "^7.4.1",
|
||||||
"@mantine/form": "^7.4.0",
|
"@mantine/dropzone": "^7.4.1",
|
||||||
"@mantine/hooks": "^7.4.0",
|
"@mantine/form": "^7.4.1",
|
||||||
"@mantine/modals": "^7.4.0",
|
"@mantine/hooks": "^7.4.1",
|
||||||
"@mantine/notifications": "^7.4.0",
|
"@mantine/modals": "^7.4.1",
|
||||||
|
"@mantine/notifications": "^7.4.1",
|
||||||
"@remix-run/css-bundle": "^2.4.1",
|
"@remix-run/css-bundle": "^2.4.1",
|
||||||
"@remix-run/node": "^2.4.1",
|
"@remix-run/node": "^2.4.1",
|
||||||
"@remix-run/react": "^2.4.1",
|
"@remix-run/react": "^2.4.1",
|
||||||
@ -23,6 +24,7 @@
|
|||||||
"axios": "^1.6.3",
|
"axios": "^1.6.3",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"dayjs-plugin-utc": "^0.1.2",
|
"dayjs-plugin-utc": "^0.1.2",
|
||||||
|
"embla-carousel-react": "^7.1.0",
|
||||||
"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",
|
||||||
@ -1429,10 +1431,22 @@
|
|||||||
"integrity": "sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==",
|
"integrity": "sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@mantine/carousel": {
|
||||||
|
"version": "7.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mantine/carousel/-/carousel-7.4.1.tgz",
|
||||||
|
"integrity": "sha512-BrLToAIazslXs78nvdfft2WAS4Ag/CHWkXi1SOa2kiRY9tTvqduhPbd168uERK3Vcrqk3t4VUHyaGNyek7l1jg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@mantine/core": "7.4.1",
|
||||||
|
"@mantine/hooks": "7.4.1",
|
||||||
|
"embla-carousel-react": ">=7.0.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mantine/core": {
|
"node_modules/@mantine/core": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.4.1.tgz",
|
||||||
"integrity": "sha512-wnQOz1aSpqVlCpdyY4XyJKRqlW87mexMADQrbCTwg/5BbxKp8XU6sTcnk1piwyR0mM6SI1uo0Yik2qYNGFlyWw==",
|
"integrity": "sha512-crz9BemmwR8V/h6db9FgznCp0Ssp6rCUYkBBO4JprpH8NDSEblHyWcZZo43IuA1vZptp8eyrhRNJ4nfe8CAYFQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/react": "^0.24.8",
|
"@floating-ui/react": "^0.24.8",
|
||||||
"clsx": "2.0.0",
|
"clsx": "2.0.0",
|
||||||
@ -1442,44 +1456,44 @@
|
|||||||
"type-fest": "^3.13.1"
|
"type-fest": "^3.13.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mantine/hooks": "7.4.0",
|
"@mantine/hooks": "7.4.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mantine/dates": {
|
"node_modules/@mantine/dates": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.4.1.tgz",
|
||||||
"integrity": "sha512-KNRVMSUW4sIk8U5SM2+4PRLqndWNaMtTabENPZUVA/Zl99yk6tDsNsu/CuinE1K5LQo9H6RJho0FRGzmzEsTwA==",
|
"integrity": "sha512-a7DNeJmLCgnFbd9NAEQ/LP998zLFPu8IWVjtJY/YJ4OUIDLEPi56OzuopA3epVzGkMcEvL4Ak78Z23KfZPJepg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clsx": "2.0.0"
|
"clsx": "2.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mantine/core": "7.4.0",
|
"@mantine/core": "7.4.1",
|
||||||
"@mantine/hooks": "7.4.0",
|
"@mantine/hooks": "7.4.1",
|
||||||
"dayjs": ">=1.0.0",
|
"dayjs": ">=1.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mantine/dropzone": {
|
"node_modules/@mantine/dropzone": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-7.4.1.tgz",
|
||||||
"integrity": "sha512-vMX9vrYBl9A/0frIcvgHjCLAdZ0hSI79VMQfMoWQ9GpOG15auQGtleT04JEgmB83I0mChSdS1I+8rV9erTBlhQ==",
|
"integrity": "sha512-VeexJtIDrqf22udZcnxhQSR0TXT1/n2EzoTTw5OCgo118UVDfjMkH0o+go8koN+9S8BthXisy5e+W4CYccqaoQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-dropzone-esm": "15.0.1"
|
"react-dropzone-esm": "15.0.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mantine/core": "7.4.0",
|
"@mantine/core": "7.4.1",
|
||||||
"@mantine/hooks": "7.4.0",
|
"@mantine/hooks": "7.4.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mantine/form": {
|
"node_modules/@mantine/form": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.4.1.tgz",
|
||||||
"integrity": "sha512-JI/o2nECWct/Kvn3GF6VplHyJeaLy0q/jGNEB/F4yt12mAYBsux6vPfAhpWrKKZ8Jt31RI+ikn6R4UcY1HGIAw==",
|
"integrity": "sha512-8oWD21ioJN0RYA+7D8WnJw+jyB9GufuvjuWIKGpG2sLpSVmHyIVLRQi0kqpttsx87K+JNPEJU1KmZbdtA8NuKg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"klona": "^2.0.6"
|
"klona": "^2.0.6"
|
||||||
@ -1489,43 +1503,43 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mantine/hooks": {
|
"node_modules/@mantine/hooks": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.4.1.tgz",
|
||||||
"integrity": "sha512-Swv23D8XmZqE2hohPBcff+ITwv5l8UlwiiEGMhL+ceUvJLnPzdwlW21qnLBtRtZWyQQ59TAav4M0GFGd93JS8Q==",
|
"integrity": "sha512-7gV9YR+xZ1L69MGVaSNwV0gaxIz4bCZuGxXTtnuaamDcO/4YiNDtmvdD7/jC/RTa1iJMnZ6YiYrcPXLOn+8saQ==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^18.2.0"
|
"react": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mantine/modals": {
|
"node_modules/@mantine/modals": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-7.4.1.tgz",
|
||||||
"integrity": "sha512-uXZuN5vCx0Wdu0gOmoDaGD8/GVpx7qCeyAAFCH94WPHl/aK3fzKSk4K63deWY5Ml9a5ktic/i5pYil3MUBEj5w==",
|
"integrity": "sha512-LNE7tge2FJfmaZpW/Ai+5wMW8rbZ0CN2O0BtCxXF4Ztpzdsb+d/RJ3Me92Cext3ykWljfCFaNDbsEirWxS2mZQ==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mantine/core": "7.4.0",
|
"@mantine/core": "7.4.1",
|
||||||
"@mantine/hooks": "7.4.0",
|
"@mantine/hooks": "7.4.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mantine/notifications": {
|
"node_modules/@mantine/notifications": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.4.1.tgz",
|
||||||
"integrity": "sha512-nRXYIcJpqqKxwYs2r17IBZ8uQZK57x6K2hkzOQ+ZFviO5rejxl4ip+fC+LUhIi3P7D1YSxyoZwumT73gSPz9Xw==",
|
"integrity": "sha512-tDp2le/CsX7l8X4Kgx7eUQ2tdC8Z8cscPjRv2RPlkXI6giFYp0agOvc3BhwxED8xFDNZC4BkC+uoOonB9XTmdg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/store": "7.4.0",
|
"@mantine/store": "7.4.1",
|
||||||
"react-transition-group": "4.4.5"
|
"react-transition-group": "4.4.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mantine/core": "7.4.0",
|
"@mantine/core": "7.4.1",
|
||||||
"@mantine/hooks": "7.4.0",
|
"@mantine/hooks": "7.4.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mantine/store": {
|
"node_modules/@mantine/store": {
|
||||||
"version": "7.4.0",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.4.1.tgz",
|
||||||
"integrity": "sha512-sSaBj6qVU0e5ml70/8e3A9pwAMBL5yKWNdnhw20b+74j85+FUDhDy8bEGZfyS0BtYPGVoxj5yF8/uZhxnDXpbg==",
|
"integrity": "sha512-BWU2b+t8Rnlc+GsPMEhGzU0hzZIuf58miZvxDXDnXr8NcBubSPhoR97bSFQ81UAvDAczI4xqOQi8vVUcoKa+ng==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^18.2.0"
|
"react": "^18.2.0"
|
||||||
}
|
}
|
||||||
@ -4474,6 +4488,22 @@
|
|||||||
"integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==",
|
"integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/embla-carousel": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-Bh8Pa8NWzgugLkf8sAGexQlBCNDFaej5BXiKgQdRJ1mUC9NWBrw9Z23YVPVGkguWoz5LMjZXXFVGCobl3UPt/Q=="
|
||||||
|
},
|
||||||
|
"node_modules/embla-carousel-react": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-tbYRPRZSDNd2QLNqYDcArAakGIxtUbhS7tkP0dGXktXHGgcX+3ji3VrOUTOftBiujZrMV8kRxtrRUe/1soloIQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"embla-carousel": "7.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.1 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "9.2.2",
|
"version": "9.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||||
|
@ -11,13 +11,14 @@
|
|||||||
"typecheck": "tsc"
|
"typecheck": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/core": "^7.4.0",
|
"@mantine/carousel": "^7.4.1",
|
||||||
"@mantine/dates": "^7.4.0",
|
"@mantine/core": "^7.4.1",
|
||||||
"@mantine/dropzone": "^7.4.0",
|
"@mantine/dates": "^7.4.1",
|
||||||
"@mantine/form": "^7.4.0",
|
"@mantine/dropzone": "^7.4.1",
|
||||||
"@mantine/hooks": "^7.4.0",
|
"@mantine/form": "^7.4.1",
|
||||||
"@mantine/modals": "^7.4.0",
|
"@mantine/hooks": "^7.4.1",
|
||||||
"@mantine/notifications": "^7.4.0",
|
"@mantine/modals": "^7.4.1",
|
||||||
|
"@mantine/notifications": "^7.4.1",
|
||||||
"@remix-run/css-bundle": "^2.4.1",
|
"@remix-run/css-bundle": "^2.4.1",
|
||||||
"@remix-run/node": "^2.4.1",
|
"@remix-run/node": "^2.4.1",
|
||||||
"@remix-run/react": "^2.4.1",
|
"@remix-run/react": "^2.4.1",
|
||||||
@ -28,6 +29,7 @@
|
|||||||
"axios": "^1.6.3",
|
"axios": "^1.6.3",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"dayjs-plugin-utc": "^0.1.2",
|
"dayjs-plugin-utc": "^0.1.2",
|
||||||
|
"embla-carousel-react": "^7.1.0",
|
||||||
"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",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user