feat: add a name and phone change from the Masters (#62)
This commit is contained in:
parent
3ea501161c
commit
4f92125e6d
@ -73,6 +73,10 @@
|
||||
"dry-wash.arm.master.table.header.phone": "Phone",
|
||||
"dry-wash.arm.master.table.header.actions": "Actions",
|
||||
"dry-wash.arm.master.table.actionsMenu.delete": "Delete Master",
|
||||
"dry-wash.arm.master.schedule.empty": "free",
|
||||
"dry-wash.arm.master.editable.aria.cancel": "Undo changes",
|
||||
"dry-wash.arm.master.editable.aria.save": "Save changes ",
|
||||
"dry-wash.arm.master.editable.aria.edit": "Edit",
|
||||
"dry-wash.arm.master.drawer.title": "Add New Master",
|
||||
"dry-wash.arm.master.drawer.inputName.label": "Full Name",
|
||||
"dry-wash.arm.master.drawer.inputName.placeholder": "Enter Full Name",
|
||||
|
@ -24,6 +24,10 @@
|
||||
"dry-wash.arm.master.table.header.phone": "Телефон",
|
||||
"dry-wash.arm.master.table.header.actions": "Действия",
|
||||
"dry-wash.arm.master.table.actionsMenu.delete": "Удалить мастера",
|
||||
"dry-wash.arm.master.schedule.empty": "Свободен",
|
||||
"dry-wash.arm.master.editable.aria.cancel": "Отменить изменения",
|
||||
"dry-wash.arm.master.editable.aria.save": "Сохранить изменения",
|
||||
"dry-wash.arm.master.editable.aria.edit": "Редактировать",
|
||||
"dry-wash.arm.master.drawer.title": "Добавить нового мастера",
|
||||
"dry-wash.arm.master.drawer.inputName.label": "ФИО",
|
||||
"dry-wash.arm.master.drawer.inputName.placeholder": "Введите ФИО",
|
||||
|
@ -68,7 +68,33 @@ const armService = () => {
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
return { fetchOrders, fetchMasters, addMaster, deleteMaster };
|
||||
const updateMaster = async ({
|
||||
id,
|
||||
name,
|
||||
phone,
|
||||
}: {
|
||||
id: string;
|
||||
name?: string;
|
||||
phone?: string;
|
||||
}) => {
|
||||
const body = JSON.stringify({ name, phone });
|
||||
|
||||
const response = await fetch(`${endpoint}${ArmEndpoints.MASTERS}/${id}`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch update masters: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
return { fetchOrders, fetchMasters, addMaster, deleteMaster, updateMaster };
|
||||
};
|
||||
|
||||
export { armService, ArmEndpoints };
|
||||
|
119
src/components/Editable/Editable.tsx
Normal file
119
src/components/Editable/Editable.tsx
Normal file
@ -0,0 +1,119 @@
|
||||
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;
|
@ -1,8 +1,11 @@
|
||||
import React from 'react';
|
||||
import { Badge, Link, Stack, Td, Tr } from '@chakra-ui/react';
|
||||
import { Badge, Stack, Td, Tr, Text } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import MasterActionsMenu from '../MasterActionsMenu';
|
||||
import { getTimeSlot } from '../../lib';
|
||||
import EditableWrapper from '../Editable/Editable';
|
||||
import { armService } from '../../api/arm';
|
||||
|
||||
export interface Schedule {
|
||||
id: string;
|
||||
@ -18,20 +21,41 @@ export type MasterProps = {
|
||||
};
|
||||
|
||||
const MasterItem = ({ name, phone, id, schedule }) => {
|
||||
const { updateMaster } = armService();
|
||||
const { t } = useTranslation('~', {
|
||||
keyPrefix: 'dry-wash.arm.master',
|
||||
});
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
<Td>{name}</Td>
|
||||
<Td>
|
||||
<Stack direction='row'>
|
||||
{schedule?.map(({ startWashTime, endWashTime }, index) => (
|
||||
<Badge colorScheme={'green'} key={index}>
|
||||
{getTimeSlot(startWashTime, endWashTime)}
|
||||
</Badge>
|
||||
))}
|
||||
</Stack>
|
||||
<EditableWrapper
|
||||
id={id}
|
||||
as={'name'}
|
||||
value={name}
|
||||
onSubmit={updateMaster}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<Link href='tel:'>{phone}</Link>
|
||||
{schedule?.length > 0 ? (
|
||||
<Stack direction='row'>
|
||||
{schedule?.map(({ startWashTime, endWashTime }, index: number) => (
|
||||
<Badge colorScheme={'green'} key={index}>
|
||||
{getTimeSlot(startWashTime, endWashTime)}
|
||||
</Badge>
|
||||
))}
|
||||
</Stack>
|
||||
) : (
|
||||
<Text color='gray.500'>{t('schedule.empty')}</Text>
|
||||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
<EditableWrapper
|
||||
id={id}
|
||||
as={'phone'}
|
||||
value={phone}
|
||||
onSubmit={updateMaster}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<MasterActionsMenu id={id} />
|
||||
|
@ -2,22 +2,12 @@
|
||||
"success": true,
|
||||
"body": [
|
||||
{
|
||||
"id": "masters1",
|
||||
"id": "4545423234",
|
||||
"name": "Иван Иванов",
|
||||
"schedule": [ {
|
||||
"id": "order1",
|
||||
"startWashTime": "2024-11-24T10:30:00.000Z",
|
||||
"endWashTime": "2024-11-24T16:30:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "order2",
|
||||
"startWashTime": "2024-11-24T11:30:00.000Z",
|
||||
"endWashTime": "2024-11-24T17:30:00.000Z"
|
||||
}],
|
||||
"phone": "+7 900 123 45 67"
|
||||
},
|
||||
{
|
||||
"id": "masters12",
|
||||
"id": "345354234",
|
||||
"name": "Иван Иванов",
|
||||
"schedule": [ {
|
||||
"id": "order1",
|
||||
|
Loading…
Reference in New Issue
Block a user