117 lines
3.1 KiB
TypeScript
117 lines
3.1 KiB
TypeScript
|
|
import { Check, ChevronsUpDown, ExternalLink } from "lucide-react";
|
||
|
|
import Link from "next/link";
|
||
|
|
import { useState } from "react";
|
||
|
|
import type { FileMetadataWithAdmin } from "~/server/services/storage.service";
|
||
|
|
import { api } from "~/utils/api";
|
||
|
|
import { ExtIcon } from "../area-riservata/allegati";
|
||
|
|
import { Button } from "../ui/button";
|
||
|
|
import {
|
||
|
|
Command,
|
||
|
|
CommandEmpty,
|
||
|
|
CommandGroup,
|
||
|
|
CommandInput,
|
||
|
|
CommandItem,
|
||
|
|
CommandList,
|
||
|
|
} from "../ui/command";
|
||
|
|
import { Label } from "../ui/label";
|
||
|
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
||
|
|
|
||
|
|
export const DocInfo = ({
|
||
|
|
storageId,
|
||
|
|
children,
|
||
|
|
}: {
|
||
|
|
storageId: string;
|
||
|
|
children: React.ReactNode;
|
||
|
|
}) => {
|
||
|
|
const { data: file_info } = api.storage.getFileInfos.useQuery({
|
||
|
|
storageId,
|
||
|
|
});
|
||
|
|
if (!file_info) return null;
|
||
|
|
return (
|
||
|
|
<div className="flex w-full flex-col gap-2">
|
||
|
|
<Label htmlFor="selected-file">File Selezionato: </Label>
|
||
|
|
<div className="flex w-full items-center gap-2 sm:max-w-[30rem]">
|
||
|
|
<div className="flex w-full flex-1">
|
||
|
|
<Link
|
||
|
|
aria-label="Open Selected File"
|
||
|
|
href={`/area-riservata/allegato-view/${storageId}`}
|
||
|
|
id="selected-file"
|
||
|
|
target="_blank"
|
||
|
|
>
|
||
|
|
<Button className="w-fit grow" variant="outline">
|
||
|
|
<ExtIcon mimeType={file_info.mimeType} />
|
||
|
|
<span className="max-w-40 truncate sm:max-w-80">
|
||
|
|
{file_info.originalName}
|
||
|
|
</span>
|
||
|
|
<ExternalLink className="size-4" />
|
||
|
|
</Button>
|
||
|
|
</Link>
|
||
|
|
</div>
|
||
|
|
{children}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export const DocCombo = ({
|
||
|
|
files,
|
||
|
|
onSelect,
|
||
|
|
current,
|
||
|
|
}: {
|
||
|
|
files: FileMetadataWithAdmin[];
|
||
|
|
onSelect: (file: FileMetadataWithAdmin) => void;
|
||
|
|
current: string | null;
|
||
|
|
}) => {
|
||
|
|
const [open, setOpen] = useState(false);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Popover onOpenChange={setOpen} open={open}>
|
||
|
|
<PopoverTrigger asChild>
|
||
|
|
<Button
|
||
|
|
aria-expanded={open}
|
||
|
|
aria-label="Select Existing File"
|
||
|
|
className="w-auto justify-between"
|
||
|
|
role="combobox"
|
||
|
|
variant="outline"
|
||
|
|
>
|
||
|
|
Seleziona file esistente...
|
||
|
|
<ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
|
||
|
|
</Button>
|
||
|
|
</PopoverTrigger>
|
||
|
|
<PopoverContent className="w-auto p-0">
|
||
|
|
<Command>
|
||
|
|
<CommandInput placeholder="Cerca Documento..." />
|
||
|
|
<CommandList>
|
||
|
|
<CommandEmpty>Nessun file.</CommandEmpty>
|
||
|
|
<CommandGroup>
|
||
|
|
{files.map((file) => (
|
||
|
|
<CommandItem
|
||
|
|
key={file.id}
|
||
|
|
onSelect={(currentValue) => {
|
||
|
|
if (currentValue !== current) {
|
||
|
|
// biome-ignore lint/style/noNonNullAssertion: <exists>
|
||
|
|
onSelect(files.find((f) => f.id === currentValue)!);
|
||
|
|
}
|
||
|
|
setOpen(false);
|
||
|
|
}}
|
||
|
|
value={file.id}
|
||
|
|
>
|
||
|
|
<span className="flex items-center gap-2">
|
||
|
|
<ExtIcon mimeType={file.mimeType} />
|
||
|
|
<span className="block font-medium">
|
||
|
|
{file.originalName}
|
||
|
|
</span>
|
||
|
|
{current === file.id && (
|
||
|
|
<Check className="size-4 text-accent-foreground" />
|
||
|
|
)}
|
||
|
|
</span>
|
||
|
|
</CommandItem>
|
||
|
|
))}
|
||
|
|
</CommandGroup>
|
||
|
|
</CommandList>
|
||
|
|
</Command>
|
||
|
|
</PopoverContent>
|
||
|
|
</Popover>
|
||
|
|
);
|
||
|
|
};
|