import { useCallback, useEffect, useState } from 'react'; import { SubmitHandler, useForm } from 'react-hook-form'; import { useDropzone } from 'react-dropzone'; import { useNavigate } from 'react-router-dom'; import clsx from 'clsx'; import { ReactFCC } from '../../utils/ReactFCC'; import { Heading, HeadingSize } from '../../components/Heading'; import { ETextVariants, Text } from '../../components/Text'; import { Button, ButtonSize, ButtonVariant } from '../../components/Button'; import { Divider } from '../../components/Divider'; import { Textarea } from '../../components/Textarea'; import { useCreateProcess } from '../../api/process'; import { useProcess } from '../../api/process/getProcess'; import { useSingleTimeout } from '../../hooks/useSingleTimeout'; import { Upload } from '../../components/Upload'; import { Attachment } from '../../components/Attachment'; import { Loader } from '../../components/Loader'; import { PathBuilder } from '../../app/routes'; import { ReactComponent as PlusIcon } from './assets/plus.svg'; import s from './HomePage.module.scss'; export type FormFields = { text?: string; files: File[]; }; export const PROCESS_POLLING_MS = 500; export const HomePage: ReactFCC = () => { const { register, handleSubmit, watch, setValue, formState: { errors } } = useForm({ defaultValues: { files: [] } }); // const [processId, setProcessId] = useState(null); const { data: createProcessResponse, mutateAsync: createProcess, isLoading: createProcessLoading } = useCreateProcess(); const processId = createProcessResponse?.id; const { data: process, refetch: refetchProcess, isFetching: processFetching } = useProcess({ processId: processId || '', config: { enabled: !!processId } }); const timeout = useSingleTimeout(); const onSubmit: SubmitHandler = useCallback( async (data) => { await createProcess({ text: data.text, files: data.files }); }, [createProcess] ); useEffect(() => { if (processId) { const startPolling = () => { timeout.set(async () => { const { data: process } = await refetchProcess(); if (process && process.current < process.total) { startPolling(); } }, PROCESS_POLLING_MS); }; if (processId) { startPolling(); } } }, [processId, refetchProcess, timeout]); const navigate = useNavigate(); useEffect(() => { if (processId && process && process.current === process.total) { navigate(PathBuilder.getProcessPath(processId)); } }, [navigate, process, processId]); // ------ Обработка DnD ------ const currentText = watch('text'); const currentFiles = watch('files'); const onDrop = useCallback( (acceptedFiles: File[]) => { setValue('text', ''); setValue('files', [...currentFiles, ...acceptedFiles]); }, [currentFiles, setValue] ); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, noClick: true // todo подумать насчет валидации на фронте (нужна ли?) // accept: { // 'application/msword': ['.doc'], // 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'], // 'application/vnd.ms-excel': ['.xls'], // 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'] // } }); // ------ Логика UI ------ const isLoading = createProcessLoading || !!processId || processFetching || !!(process && process.current < process.total); const isDisabled = !currentText && currentFiles.length === 0; return (
{!isLoading ? (
Анализ текстовых пресс-релизов Позволяет оценить кредитный рейтинг компании на основе пресс-релиза с выделением в тексте меток по различным метрикам.
{currentFiles.length === 0 ? (