120 lines
2.7 KiB
TypeScript
120 lines
2.7 KiB
TypeScript
import React, { useState } from 'react';
|
||
import {
|
||
Editable,
|
||
EditableInput,
|
||
EditablePreview,
|
||
Flex,
|
||
IconButton,
|
||
Input,
|
||
useEditableControls,
|
||
ButtonGroup,
|
||
Stack,
|
||
useToast,
|
||
} from '@chakra-ui/react';
|
||
import { CheckIcon, CloseIcon, EditIcon } from '@chakra-ui/icons';
|
||
import { useTranslation } from 'react-i18next';
|
||
|
||
interface EditableWrapperProps {
|
||
value: string;
|
||
onSubmit: ({
|
||
id,
|
||
name,
|
||
phone,
|
||
}: {
|
||
id: string;
|
||
name?: string;
|
||
phone?: string;
|
||
}) => Promise<unknown>;
|
||
as: 'phone' | 'name';
|
||
id: string;
|
||
}
|
||
|
||
const EditableWrapper = ({ value, onSubmit, as, id }: EditableWrapperProps) => {
|
||
const { t } = useTranslation('~', {
|
||
keyPrefix: 'dry-wash.arm.master.editable',
|
||
});
|
||
|
||
const toast = useToast();
|
||
const [currentValue, setCurrentValue] = useState<string>(value);
|
||
|
||
const handleSubmit = async (newValue: string) => {
|
||
if (currentValue === newValue) return;
|
||
|
||
try {
|
||
await onSubmit({ id, [as]: newValue });
|
||
|
||
setCurrentValue(newValue);
|
||
|
||
toast({
|
||
title: 'Успешно!',
|
||
description: 'Данные обновлены.',
|
||
status: 'success',
|
||
duration: 2000,
|
||
isClosable: true,
|
||
position: 'top-right',
|
||
});
|
||
} catch (error) {
|
||
toast({
|
||
title: 'Ошибка!',
|
||
description: 'Не удалось обновить данные.',
|
||
status: 'error',
|
||
duration: 2000,
|
||
isClosable: true,
|
||
position: 'top-right',
|
||
});
|
||
console.error('Ошибка при обновлении данных:', error);
|
||
}
|
||
};
|
||
|
||
function EditableControls() {
|
||
const {
|
||
isEditing,
|
||
getSubmitButtonProps,
|
||
getCancelButtonProps,
|
||
getEditButtonProps,
|
||
} = useEditableControls();
|
||
|
||
return isEditing ? (
|
||
<ButtonGroup justifyContent='center' size='sm'>
|
||
<IconButton
|
||
aria-label={t('aria.save')}
|
||
icon={<CheckIcon />}
|
||
{...getSubmitButtonProps()}
|
||
/>
|
||
<IconButton
|
||
aria-label={t('aria.cancel')}
|
||
icon={<CloseIcon />}
|
||
{...getCancelButtonProps()}
|
||
/>
|
||
</ButtonGroup>
|
||
) : (
|
||
<Flex justifyContent='center'>
|
||
<IconButton
|
||
aria-label={t('aria.edit')}
|
||
size='sm'
|
||
icon={<EditIcon />}
|
||
{...getEditButtonProps()}
|
||
/>
|
||
</Flex>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<Editable
|
||
textAlign='center'
|
||
defaultValue={currentValue}
|
||
fontSize='2xl'
|
||
isPreviewFocusable={false}
|
||
onSubmit={handleSubmit}
|
||
>
|
||
<Stack direction={['column', 'row']} spacing='15px'>
|
||
<EditablePreview />
|
||
<Input as={EditableInput} />
|
||
<EditableControls />
|
||
</Stack>
|
||
</Editable>
|
||
);
|
||
};
|
||
|
||
export default EditableWrapper;
|