1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36:40 +07:00

#34 made error handling and resetting

This commit is contained in:
Fedor Katurov 2021-02-27 18:29:05 +07:00
parent dad416e6e2
commit 29e5aef01b
6 changed files with 136 additions and 43 deletions

View file

@ -1,9 +1,10 @@
@import "~/styles/variables.scss";
@import '~/styles/variables.scss';
.wrap {
display: flex;
flex-wrap: wrap;
height: 32px;
flex: 1;
@media(max-width: 480px) {
display: none;

View file

@ -1,4 +1,4 @@
import React, { FC, useState } from 'react';
import React, { FC, useCallback, useState } from 'react';
import { useCommentFormFormik } from '~/utils/hooks/useCommentFormFormik';
import { FormikProvider } from 'formik';
import { LocalCommentFormTextarea } from '~/components/comment/LocalCommentFormTextarea';
@ -11,6 +11,10 @@ import { LocalCommentFormAttaches } from '~/components/comment/LocalCommentFormA
import { LoaderCircle } from '~/components/input/LoaderCircle';
import { IComment, INode } from '~/redux/types';
import { EMPTY_COMMENT } from '~/redux/node/constants';
import { CommentFormDropzone } from '~/components/comment/CommentFormDropzone';
import styles from './styles.module.scss';
import { ERROR_LITERAL } from '~/constants/errors';
import { Group } from '~/components/containers/Group';
interface IProps {
comment?: IComment;
@ -20,41 +24,73 @@ interface IProps {
const LocalCommentForm: FC<IProps> = ({ comment, nodeId, onCancelEdit }) => {
const [textarea, setTextarea] = useState<HTMLTextAreaElement>();
const uploader = useFileUploader(UPLOAD_SUBJECTS.COMMENT, UPLOAD_TARGETS.COMMENTS);
const uploader = useFileUploader(
UPLOAD_SUBJECTS.COMMENT,
UPLOAD_TARGETS.COMMENTS,
comment?.files
);
const formik = useCommentFormFormik(comment || EMPTY_COMMENT, nodeId, uploader, onCancelEdit);
const isLoading = formik.isSubmitting || uploader.isUploading;
const isEditing = !!comment?.id;
const clearError = useCallback(() => {
if (formik.status) {
formik.setStatus('');
}
if (formik.errors.text) {
formik.setErrors({
...formik.errors,
text: '',
});
}
}, [formik]);
const error = formik.status || formik.errors.text;
return (
<form onSubmit={formik.handleSubmit}>
<FormikProvider value={formik}>
<FileUploaderProvider value={uploader}>
<LocalCommentFormTextarea setRef={setTextarea} />
<CommentFormDropzone onUpload={uploader.uploadFiles}>
<form onSubmit={formik.handleSubmit} className={styles.wrap}>
<FormikProvider value={formik}>
<FileUploaderProvider value={uploader}>
<div className={styles.input}>
<LocalCommentFormTextarea setRef={setTextarea} />
<CommentFormAttachButtons onUpload={uploader.uploadFiles} />
<CommentFormFormatButtons element={textarea} handler={formik.handleChange('text')} />
<LocalCommentFormAttaches />
{!!error && (
<div className={styles.error} onClick={clearError}>
{ERROR_LITERAL[error] || error}
</div>
)}
</div>
{isLoading && <LoaderCircle size={20} />}
<LocalCommentFormAttaches />
{isEditing && (
<Button size="small" color="link" type="button" onClick={onCancelEdit}>
Отмена
</Button>
)}
<Group horizontal className={styles.buttons}>
<CommentFormAttachButtons onUpload={uploader.uploadFiles} />
<CommentFormFormatButtons element={textarea} handler={formik.handleChange('text')} />
<Button
type="submit"
size="small"
color="gray"
iconRight={!isEditing ? 'enter' : 'check'}
disabled={isLoading}
>
{!isEditing ? 'Сказать' : 'Сохранить'}
</Button>
</FileUploaderProvider>
</FormikProvider>
</form>
{isLoading && <LoaderCircle size={20} />}
{isEditing && (
<Button size="small" color="link" type="button" onClick={onCancelEdit}>
Отмена
</Button>
)}
<Button
type="submit"
size="small"
color="gray"
iconRight={!isEditing ? 'enter' : 'check'}
disabled={isLoading}
>
{!isEditing ? 'Сказать' : 'Сохранить'}
</Button>
</Group>
</FileUploaderProvider>
</FormikProvider>
</form>
</CommentFormDropzone>
);
};

View file

@ -0,0 +1,57 @@
@import "src/styles/variables";
.wrap {
display: flex;
flex-direction: column;
textarea {
min-height: 62px !important;
}
}
.input {
@include outer_shadow();
position: relative;
flex: 1;
padding: ($gap / 2) ($gap / 2 + 1px);
}
.buttons {
@include outer_shadow();
position: relative;
z-index: 1;
display: flex;
flex-direction: row;
background: transparentize(black, 0.8);
padding: $gap / 2;
border-radius: 0 0 $radius $radius;
flex-wrap: wrap;
}
.uploads {
padding: ($gap / 2);
display: grid;
grid-column-gap: $gap / 2;
grid-row-gap: $gap / 2;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
.attaches {
@include outer_shadow();
}
.error {
position: absolute;
bottom: 0;
left: 50%;
background: $red;
z-index: 10;
font: $font_12_regular;
box-sizing: border-box;
padding: 0 $gap;
border-radius: 4px 4px 0 0;
transform: translate(-50%, 0);
cursor: pointer;
}

View file

@ -178,17 +178,6 @@
fill: white;
}
}
> * {
margin: 0 5px;
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
}
}
.micro {

View file

@ -10,12 +10,13 @@ import { selectUploads } from '~/redux/uploads/selectors';
export const useFileUploader = (
subject: typeof UPLOAD_SUBJECTS[keyof typeof UPLOAD_SUBJECTS],
target: typeof UPLOAD_TARGETS[keyof typeof UPLOAD_TARGETS]
target: typeof UPLOAD_TARGETS[keyof typeof UPLOAD_TARGETS],
initialFiles?: IFile[]
) => {
const dispatch = useDispatch();
const { files: uploadedFiles, statuses } = useShallowSelect(selectUploads);
const [files, setFiles] = useState<IFile[]>([]);
const [files, setFiles] = useState<IFile[]>(initialFiles || []);
const [pendingIDs, setPendingIDs] = useState<string[]>([]);
const uploadFiles = useCallback(

View file

@ -1,5 +1,5 @@
import { IComment, INode } from '~/redux/types';
import { useCallback, useRef } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { FormikHelpers, useFormik, useFormikContext } from 'formik';
import { array, object, string } from 'yup';
import { FileUploader } from '~/utils/hooks/fileUploader';
@ -58,13 +58,22 @@ export const useCommentFormFormik = (
if (stopEditing) stopEditing();
}, [uploader, stopEditing]);
return useFormik({
const formik = useFormik({
initialValues,
validationSchema,
onSubmit,
initialStatus: '',
onReset,
validateOnChange: true,
});
useEffect(() => {
if (formik.status) {
formik.setStatus('');
}
}, [formik.values.text]);
return formik;
};
export const useCommentFormContext = () => useFormikContext<IComment>();