feat: change sidebar to header, fix wizard update, delete unnecessary statuses
Some checks failed
it-academy/dry-wash-pl/pipeline/head There was a failure building this commit
it-academy/dry-wash-pl/pipeline/pr-main This commit looks good

This commit is contained in:
Ильназ 2025-02-24 23:07:10 +03:00
parent c9c17340c6
commit d312445bf2
12 changed files with 111 additions and 83 deletions

View File

@ -58,7 +58,7 @@
"dry-wash.arm.order.status.complete": "Completed", "dry-wash.arm.order.status.complete": "Completed",
"dry-wash.arm.order.status.pending": "Pending", "dry-wash.arm.order.status.pending": "Pending",
"dry-wash.arm.order.status.working": "Working", "dry-wash.arm.order.status.working": "Working",
"dry-wash.arm.order.status.canceled": "Canceled", "dry-wash.arm.order.status.cancelled": "Canceled",
"dry-wash.arm.order.status.placeholder": "Select status", "dry-wash.arm.order.status.placeholder": "Select status",
"dry-wash.arm.order.master.placeholder": "Select master", "dry-wash.arm.order.master.placeholder": "Select master",
"dry-wash.arm.order.table.header.carNumber": "Car Number", "dry-wash.arm.order.table.header.carNumber": "Car Number",

View File

@ -5,7 +5,7 @@
"dry-wash.arm.order.status.complete": "Завершено", "dry-wash.arm.order.status.complete": "Завершено",
"dry-wash.arm.order.status.pending": "В ожидании", "dry-wash.arm.order.status.pending": "В ожидании",
"dry-wash.arm.order.status.working": "В работе", "dry-wash.arm.order.status.working": "В работе",
"dry-wash.arm.order.status.canceled": "Отменено", "dry-wash.arm.order.status.cancelled": "Отменено",
"dry-wash.arm.order.status.placeholder": "Выберите статус", "dry-wash.arm.order.status.placeholder": "Выберите статус",
"dry-wash.arm.order.master.placeholder": "Выберите мастера", "dry-wash.arm.order.master.placeholder": "Выберите мастера",
"dry-wash.arm.order.table.header.carNumber": "Номер машины", "dry-wash.arm.order.table.header.carNumber": "Номер машины",

View File

@ -0,0 +1,51 @@
import { Box, Button, Heading, HStack, Divider, Flex } from '@chakra-ui/react';
import React from 'react';
import { useLocation, Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { URLs } from '../../__data__/urls';
const Header = () => {
const location = useLocation();
const isActive = (keyword: string) => location.pathname.includes(keyword);
const { t } = useTranslation('~', {
keyPrefix: 'dry-wash.arm.master.sideBar',
});
return (
<Box as='header' bg='gray.50' boxShadow='md' px={6} py={4} w='100%'>
<Flex gap={50} align='center'>
<Heading color='green' size='lg'>
{t('title')}
</Heading>
<HStack spacing={4}>
{URLs.armOrder.isOn && (
<Button
as={Link}
to={URLs.armOrder.url}
colorScheme={isActive(URLs.armOrder.url) ? 'green' : 'blue'}
variant={isActive(URLs.armOrder.url) ? 'outline' : 'ghost'}
>
{t('orders')}
</Button>
)}
<Divider orientation='vertical' height='30px' />
{URLs.armMaster.isOn && (
<Button
as={Link}
to={URLs.armMaster.url}
colorScheme={isActive(URLs.armMaster.url) ? 'green' : 'blue'}
variant={isActive(URLs.armMaster.url) ? 'outline' : 'ghost'}
data-testid='master-button'
>
{t('master')}
</Button>
)}
</HStack>
</Flex>
</Box>
);
};
export default Header;

View File

@ -0,0 +1 @@
export { default } from './Header';

View File

@ -2,10 +2,10 @@ import { Box, Flex } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { Navigate, Route, Routes } from 'react-router-dom'; import { Navigate, Route, Routes } from 'react-router-dom';
import Sidebar from '../Sidebar';
import Orders from '../Orders'; import Orders from '../Orders';
import Masters from '../Masters'; import Masters from '../Masters';
import { URLs } from '../../__data__/urls'; import { URLs } from '../../__data__/urls';
import Header from '../Header';
const LayoutArm = () => { const LayoutArm = () => {
let defaultRedirect = null; let defaultRedirect = null;
@ -17,8 +17,8 @@ const LayoutArm = () => {
} }
return ( return (
<Flex h='100vh'> <Flex flexDirection='column' h='100vh'>
<Sidebar /> <Header />
<Box flex='1' bg='gray.50'> <Box flex='1' bg='gray.50'>
<Routes> <Routes>
<Route index element={<Navigate to={defaultRedirect} replace />} /> <Route index element={<Navigate to={defaultRedirect} replace />} />

View File

@ -2,16 +2,17 @@ import React, { ChangeEvent, useState } from 'react';
import { Td, Tr, Link, Select } from '@chakra-ui/react'; import { Td, Tr, Link, Select } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { ViewIcon } from '@chakra-ui/icons';
import { getTimeSlot } from '../../lib'; import { getTimeSlot } from '../../lib';
import { useUpdateOrdersMutation } from '../../__data__/service/api'; import { useUpdateOrdersMutation } from '../../__data__/service/api';
import { OrderArm, Status, statuses } from '../../models/api'; import { OrderArm, Status, statuses } from '../../models/api';
import PopoverTemplate from '../PopoverTemplate';
const statusColors: Record<Status, string> = { const statusColors: Record<Status, string> = {
pending: 'yellow.100', pending: 'yellow.100',
progress: 'blue.100', progress: 'blue.100',
working: 'orange.100', cancelled: 'red.100',
canceled: 'red.100',
complete: 'green.100', complete: 'green.100',
}; };
@ -34,7 +35,7 @@ const OrderItem = ({
const [statusSelect, setStatus] = useState(status); const [statusSelect, setStatus] = useState(status);
const bgColor = statusColors[statusSelect]; const bgColor = statusColors[statusSelect];
const [masterSelect, setMaster] = useState(master?.name); const [masterSelectId, setMasterSelectId] = useState(master);
const handelChangeMasters = (e: ChangeEvent<HTMLSelectElement>) => { const handelChangeMasters = (e: ChangeEvent<HTMLSelectElement>) => {
const masterName = e.target.value; const masterName = e.target.value;
@ -43,7 +44,7 @@ const OrderItem = ({
); );
if (selectedMaster) { if (selectedMaster) {
setMaster(masterName); setMasterSelectId(selectedMaster.id);
updateOrders({ id, master: selectedMaster.id }); updateOrders({ id, master: selectedMaster.id });
} else { } else {
console.error('Master not found'); console.error('Master not found');
@ -56,6 +57,10 @@ const OrderItem = ({
setStatus(status); setStatus(status);
}; };
const masterSelectChange = allMasters.find(
(master) => master.id === masterSelectId,
);
return ( return (
<Tr> <Tr>
<Td>{carNumber}</Td> <Td>{carNumber}</Td>
@ -79,7 +84,7 @@ const OrderItem = ({
</Td> </Td>
<Td> <Td>
<Select <Select
value={masterSelect} value={masterSelectChange?.name}
onChange={handelChangeMasters} onChange={handelChangeMasters}
placeholder={t(`master.placeholder`)} placeholder={t(`master.placeholder`)}
> >
@ -93,7 +98,9 @@ const OrderItem = ({
<Td> <Td>
<Link href='tel:'>{phone}</Link> <Link href='tel:'>{phone}</Link>
</Td> </Td>
<Td>{location}</Td> <Td>
<PopoverTemplate trigger={<ViewIcon />} description={location} />
</Td>
</Tr> </Tr>
); );
}; };

View File

@ -0,0 +1,35 @@
import React from 'react';
import {
Button,
Popover,
PopoverArrow,
PopoverBody,
PopoverCloseButton,
PopoverContent,
PopoverHeader,
PopoverTrigger,
} from '@chakra-ui/react';
interface Props {
title?: string;
description: string;
trigger?: React.ReactNode;
}
const PopoverTemplate = ({ title, description, trigger }: Props) => {
return (
<Popover>
<PopoverTrigger>
<Button>{trigger}</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
{title && <PopoverHeader>{title}!</PopoverHeader>}
<PopoverBody mr={5}>{description}</PopoverBody>
</PopoverContent>
</Popover>
);
};
export default PopoverTemplate;

View File

@ -0,0 +1 @@
export { default } from './PopoverTemplate';

View File

@ -1,61 +0,0 @@
import { Box, Button, Heading, VStack, Divider } from '@chakra-ui/react';
import React from 'react';
import { useLocation, Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { URLs } from '../../__data__/urls';
const Sidebar = () => {
const location = useLocation();
const isActive = (keyword: string) => location.pathname.includes(keyword);
const { t } = useTranslation('~', {
keyPrefix: 'dry-wash.arm.master.sideBar',
});
return (
<Box
borderRight='1px solid black'
bg='gray.50'
color='white'
w='250px'
p='5'
pt='8'
>
<Heading color='green' size='lg' mb='5'>
{t('title')}
</Heading>
<VStack align='start' spacing='4'>
<Divider />
{URLs.armOrder.isOn && (
<Button
as={Link}
to={URLs.armOrder.url}
w='100%'
colorScheme={isActive(URLs.armOrder.url) ? 'green' : 'blue'}
variant={isActive(URLs.armOrder.url) ? 'solid' : 'ghost'}
>
{t('orders')}
</Button>
)}
<Divider />
{URLs.armMaster.isOn && (
<Button
as={Link}
to={URLs.armMaster.url}
w='100%'
colorScheme={isActive(URLs.armMaster.url) ? 'green' : 'blue'}
variant={isActive(URLs.armMaster.url) ? 'solid' : 'ghost'}
data-testid='master-button'
>
{t('master')}
</Button>
)}
<Divider />
</VStack>
</Box>
);
};
export default Sidebar;

View File

@ -1 +0,0 @@
export { default } from './Sidebar';

View File

@ -27,8 +27,7 @@ type GetArrItemType<ArrType> =
export const statuses = [ export const statuses = [
'pending' as const, 'pending' as const,
'progress' as const, 'progress' as const,
'working' as const, 'cancelled' as const,
'canceled' as const,
'complete' as const, 'complete' as const,
]; ];
@ -42,7 +41,7 @@ export type OrderArm = {
status?: GetArrItemType<typeof statuses>; status?: GetArrItemType<typeof statuses>;
phone?: string; phone?: string;
location?: string; location?: string;
master: Master; master: string | [];
notes: ''; notes: '';
allMasters: Master[]; allMasters: Master[];
id: string; id: string;

View File

@ -9,12 +9,8 @@
"orderDate": "2024-11-24T08:41:46.366Z", "orderDate": "2024-11-24T08:41:46.366Z",
"status": "pending", "status": "pending",
"phone": "79001234563", "phone": "79001234563",
"location": "Казань, ул. Баумана, 1", "location": "55.779905316526424,49.12446113769528 Республика Татарстан (Татарстан),н Казань, ул. Баумана, 1",
"master": { "master": "4545423234",
"name": "Олег Макаров",
"phone": "79001234567",
"id": "23423442"
},
"notes": "" "notes": ""
}, },
{ {
@ -25,7 +21,7 @@
"orderDate": "2024-11-24T07:40:46.366Z", "orderDate": "2024-11-24T07:40:46.366Z",
"status": "progress", "status": "progress",
"phone": "79001234567", "phone": "79001234567",
"location": "Казань, ул. Баумана, 43", "location": "55.779905316526424,49.12446113769528 Республика Татарстан (Татарстан), Казань, озеро Нижний Кабан",
"master": [], "master": [],
"notes": "" "notes": ""
} }