# @ws-serenity/react-attachments

[Repository](https://gitlab.thewhite.ru/ws-projects/frontend-library/ws-serenity/-/tree/master/packages/react/attachments)

## TODO
В общем. Поместить запросы в либу. И сделать сетап для них подобный тому,
как работают api-requests. Его один раз делаешь и все. Нужно будет передать просто api туда,
а возвращаем мы уже `AttachmentApi` с `getAll(ids)`. 

А в компоненте мы все же не будем по умолчанию использовать их.
Пусть пропсом передается `initial` с промисом:

```JS
<AttachmentContainer
    customDragComponent={<CustomActiveDrag />}
    className={'sample-attachment-container'}
    showAttachedFiles={true}
    uploadComponent={CustomUploadComponent}
    handleSubmit={filesRef}
    initialAttachments={attachmentApi.getAll(ids)}
    // интерфейсом мы ограничим наличие "getAll", здесь он нам больше не нужен будет
    attachmentApi={attachmentsApi}
    downloadComponent={DownloadButton}
    deleteComponent={DeleteButton}
/>;
```

```JS
// inside useAttachmentDataHandler
useEffect(()=>{
    initialAttachments.then(resp=>setApiAttachments(resp.items))
},[])
```

## About

Концепция - максимально настраиваемый без лишних стилей. <br>
Не подходит по дизайну? Используй вспомогательные хуки и настрой самостоятельно!

Компонент не создает самостоятельно аттачменты. Но удаляет существующие
(над этим стоит еще подумать). Поэтому можно сказать, что им полностью управляет внешняя форма.

Иными словами, всегда хранится два состояния:

1. Что пришло с API
2. Что добавил пользователь, но еще не отправил

Если это необходимо, можно будет создать настройку этого поведения.

## Отправка формы аттачментов

Необходимо выполнять "вручную". Это сделано, чтобы лишний раз не нагружать сеть при
удалении/добавлении элементов. Запросы отправляются параллельно.

Пример:

```JSX
export function SomeFormWithAttachments(){
    const filesRef = useExtractApiData();

    async function handleSubmit(e: any) {
        e.preventDefault();
        if (!filesRef.current) return;
        
        // make component send create requests
        const files = await filesRef.current.extract();
        // now u can submit form with attachmentIds
    }

    return (
        <form
            action={'#'}
            className={'test-container'}
            onSubmit={handleSubmit}
        >
            <AttachmentContainer
                customDragComponent={<CustomActiveDrag/>}
                className={'sample-attachment-container'}
                showAttachedFiles={true}
                handleSubmit={filesRef}
                uploadComponent={CustomUploadComponent}
                attachmentApi={attachmentsApi}
                downloadComponent={DownloadButton}
                deleteComponent={DeleteButton}
            />
            <button className={'test-container__submit'}>
                Submit
            </button>
        </form>
    );
}

// You can override default Component on active drag (if it's enabled)
const CustomActiveDrag = () => (
    <div className={'custom-active-drop'}>
        <p>Drop your files here</p>
        <UploadIcon/>
    </div>
);

// You must define buttons to delete and remove attachment if u want to use built-in AttachmentItem-component
// You can define your own behaviour using "AttachmentCustomItem" type
const DownloadButton = (props: ActionProps) => (
    <button
        type={'button'}
        onClick={props.onClick}
        className={clsx(props.className, 'sample-attachment-container__attachment-button')}
    >
        <DownloadIcon/>
    </button>
);

const DeleteButton = (props: ActionProps) => (
    <button
        type={'button'}
        onClick={props.onClick}
        className={clsx(props.className, 'sample-attachment-container__attachment-button')}
    >
        <DeleteIcon/>
    </button>
);

// U can also define custom component to upload files. 
// It's displayed when component is empty or user can upload more files
// You can manage It's behaviour using css-styling. Component has to state-classes (read further)
const CustomUploadComponent = (props:UploadComponentProps) => (
    <div onClick={props.handleUploadClick} className={props.className}>
        <p>Drop your files here</p>
    </div>
)

```

## State-styles

1. Когда компонент не содержит вложений, он имеет стиль: `ws-attachment-container--empty`
2. При активном drag-and-drop добавляется `ws-attachments-container--drag-active`

В большинстве случаев, следует добавлять классы, передаваемые в пропсы к кастомным компонентам. Они
могут содержать важные стили для состояния.

## Limitations

Пока что все кастомные JSX-элементы (`JSXElementConstructor<Props>`) не могут иметь каких-либо
дополнительных пропсов, что сильно ограничивает их функционал. Вскоре планируется добавить
