import toast from "react-hot-toast";
import { Upload } from "~/lib/storage_manager";
import { useTranslation } from "~/providers/I18nProvider";
import { api } from "~/utils/api";
import {
Credenza,
CredenzaBody,
CredenzaContent,
CredenzaDescription,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { Button } from "~/components/ui/button";
import { CloudUpload, UploadIcon, X } from "lucide-react";
import {
FileUpload,
FileUploadDropzone,
FileUploadItem,
FileUploadItemDelete,
FileUploadItemMetadata,
FileUploadItemPreview,
FileUploadItemProgress,
FileUploadList,
FileUploadTrigger,
} from "~/components/custom_ui/fileUpload";
import type { UsersId } from "~/schemas/public/Users";
import type { StorageindexId } from "~/schemas/public/Storageindex";
import { useCallback, useState } from "react";
type UploadModalProps = {
cb_onUpload?: () => void;
isAdmin?: boolean;
userId?: UsersId;
};
export const UploadModal = ({
cb_onUpload,
isAdmin,
userId,
}: UploadModalProps) => {
const { t } = useTranslation();
return (
{t.allegati.carica_nuovi}
Allegati modal
);
};
type UploadComponentProps = {
cb_onUpload?: () => void;
isAdmin?: boolean;
userId?: UsersId;
maxMB?: number;
maxFiles?: number;
};
export const UploadComponent = ({
cb_onUpload,
isAdmin,
userId,
maxMB = 5, // Default max size is 5MB
maxFiles,
}: UploadComponentProps) => {
const { t } = useTranslation();
const [files, setFiles] = useState([]);
const [isUploading, setIsUploading] = useState(false);
const { mutateAsync: getToken } = api.storage.getStorageTokenM.useMutation();
const { mutate: setUserStorage } = api.storage.addUserStorage.useMutation({
onMutate: () => {
toast(t.allegati.allegato_caricato, { icon: "📤" });
},
onSettled: async () => {
await utils.storage.getAll.invalidate();
await utils.storage.getUserStorage.invalidate({
userId,
});
},
});
const acceptedMimeTypes = [
"image/jpeg", // jpg, jpeg
"image/png", // png
"image/webp", // webp
"text/plain", // txt
"application/pdf", // pdf
"application/msword", // doc
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", // docx
"application/vnd.ms-excel", // xls
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // xlsx
"application/vnd.oasis.opendocument.text", // odt
"application/vnd.oasis.opendocument.spreadsheet", // ods
];
const utils = api.useUtils();
const onFileReject = useCallback((file: File, message: string) => {
toast(
`${message}\n\n"${file.name.length > 15 ? `${file.name.slice(0, 15)}...` : file.name}" ${t.allegati.file_rejected}`,
);
}, []);
const onFileValidate = useCallback(
(file: File): string | null => {
if (maxFiles) {
// Validate max files
if (files.length >= maxFiles) {
return `${t.allegati.file_too_many} ${maxFiles}`;
}
}
// Validate file type
if (!acceptedMimeTypes.includes(file.type)) {
return t.allegati.invalid_file_type;
}
if (maxMB) {
// Validate file size
const MAX_SIZE = maxMB * 1024 * 1024;
if (file.size > MAX_SIZE) {
return `${t.allegati.file_too_large} ${MAX_SIZE / (1024 * 1024)}MB`;
}
}
return null;
},
[files],
);
const onUpload = useCallback(
async (
files: File[],
{
onProgress,
}: {
onProgress: (file: File, progress: number) => void;
},
) => {
try {
setIsUploading(true);
const { status, attachments } = await Upload({
files: files,
getToken,
from_admin: isAdmin ?? true,
});
if (userId) {
for (const storageId of attachments) {
setUserStorage({
userId,
fileId: storageId as StorageindexId,
});
}
}
files.forEach((file) => {
const randomDelay = Math.random() * 1000 + 500; // Random delay between 500ms and 1500ms
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 10; // Increment progress randomly
if (progress >= 100) {
progress = 100;
clearInterval(interval);
}
onProgress(file, progress);
}, randomDelay / 1); // Adjust interval based on random delay
});
if (!status) {
toast.error(t.allegati.errore_caricamento, {
icon: "❌",
});
setIsUploading(false);
return;
}
toast.success(t.allegati.success_caricamento, {
icon: "✅",
});
} catch (error) {
setIsUploading(false);
toast.error(
error instanceof Error
? error.message
: t.allegati.errore_sconosciuto,
);
} finally {
setIsUploading(false);
setFiles([]);
cb_onUpload?.();
await utils.storage.getAll.invalidate();
}
},
[],
);
return (
{t.allegati.drag_drop}
{t.allegati.oppure}
{files.map((file, index) => (
))}
);
};