mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 05:25:41 +00:00
ui on new contrat page
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { useState } from "react";
|
||||
import { Button, FileButton, Group, Select, Stack, Text } from "@mantine/core";
|
||||
import { FileUp, Upload } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Box, Button, FileButton, Group, Select, Stack, Text } from "@mantine/core";
|
||||
import { Eye, FileText, FileUp, Upload } from "lucide-react";
|
||||
import { isViewable } from "@edr/ui-common";
|
||||
|
||||
import { useUploadGlDocuments } from "@/hooks/contracts/useContracts";
|
||||
import { useFileViewer } from "@/hooks/useFileViewer";
|
||||
import { ActionShell } from "./ActionShell";
|
||||
|
||||
/**
|
||||
@@ -23,6 +25,7 @@ export function GlDocumentUploadCard({ bookingId }: { bookingId: string }) {
|
||||
const upload = useUploadGlDocuments(bookingId);
|
||||
const [slot, setSlot] = useState<string | null>(GL_DOC_SLOTS[0].value);
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const { view, viewer } = useFileViewer();
|
||||
|
||||
const submit = () => {
|
||||
if (!slot || !file) return;
|
||||
@@ -69,12 +72,108 @@ export function GlDocumentUploadCard({ bookingId }: { bookingId: string }) {
|
||||
Upload
|
||||
</Button>
|
||||
</Group>
|
||||
{!file ? (
|
||||
{file ? (
|
||||
<StagedFilePreview file={file} onPreview={view} />
|
||||
) : (
|
||||
<Text size="xs" c="dimmed">
|
||||
PDF or image. The matching milestone completes on upload.
|
||||
</Text>
|
||||
) : null}
|
||||
)}
|
||||
</Stack>
|
||||
{viewer}
|
||||
</ActionShell>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A compact preview chip for the GL file staged for upload: an image thumbnail
|
||||
* (or a glyph) and a Preview button that opens the file in the shared viewer via
|
||||
* a local object URL (minted once, revoked on unmount).
|
||||
*/
|
||||
function StagedFilePreview({
|
||||
file,
|
||||
onPreview,
|
||||
}: {
|
||||
file: File;
|
||||
onPreview: (f: { name: string; url: string; mimeType?: string | null }) => void;
|
||||
}) {
|
||||
const url = useMemo(() => URL.createObjectURL(file), [file]);
|
||||
useEffect(() => () => URL.revokeObjectURL(url), [url]);
|
||||
|
||||
const isImage =
|
||||
file.type.startsWith("image/") ||
|
||||
["png", "jpg", "jpeg", "webp", "gif", "bmp", "svg"].includes(
|
||||
file.name.split(".").pop()?.toLowerCase() ?? "",
|
||||
);
|
||||
const canPreview = isViewable({ name: file.name, url, mimeType: file.type });
|
||||
|
||||
return (
|
||||
<Group
|
||||
gap={10}
|
||||
wrap="nowrap"
|
||||
p={8}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
border: "1px dashed var(--mantine-color-edr-green-5)",
|
||||
background: "var(--mantine-color-edr-green-0)",
|
||||
minWidth: 0,
|
||||
}}
|
||||
>
|
||||
{isImage ? (
|
||||
<Box
|
||||
onClick={() => onPreview({ name: file.name, url, mimeType: file.type })}
|
||||
style={{
|
||||
width: 38,
|
||||
height: 38,
|
||||
flexShrink: 0,
|
||||
borderRadius: 8,
|
||||
overflow: "hidden",
|
||||
cursor: "pointer",
|
||||
border: "1px solid var(--mantine-color-gray-3)",
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={url}
|
||||
alt=""
|
||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<Box
|
||||
c="edr-green"
|
||||
style={{
|
||||
width: 38,
|
||||
height: 38,
|
||||
flexShrink: 0,
|
||||
borderRadius: 8,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
background: "var(--mantine-color-edr-green-1)",
|
||||
}}
|
||||
>
|
||||
<FileText size={17} />
|
||||
</Box>
|
||||
)}
|
||||
<Box style={{ minWidth: 0, flex: 1 }}>
|
||||
<Text size="xs" fw={700} c="edr-green">
|
||||
Ready to upload
|
||||
</Text>
|
||||
<Text size="xs" truncate>
|
||||
{file.name}
|
||||
</Text>
|
||||
</Box>
|
||||
{canPreview && (
|
||||
<Button
|
||||
size="compact-xs"
|
||||
variant="subtle"
|
||||
color="edr-green"
|
||||
leftSection={<Eye size={13} />}
|
||||
onClick={() => onPreview({ name: file.name, url, mimeType: file.type })}
|
||||
>
|
||||
Preview
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user