feat: deals table
This commit is contained in:
		@@ -8,6 +8,7 @@ export type DealSummary = {
 | 
				
			|||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
    clientName: string;
 | 
					    clientName: string;
 | 
				
			||||||
    changedAt: string;
 | 
					    changedAt: string;
 | 
				
			||||||
 | 
					    createdAt: string;
 | 
				
			||||||
    deadline: string;
 | 
					    deadline: string;
 | 
				
			||||||
    status: number;
 | 
					    status: number;
 | 
				
			||||||
    totalPrice: number;
 | 
					    totalPrice: number;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,10 +134,20 @@ export class DealService {
 | 
				
			|||||||
     * @returns DealSummaryResponse Successful Response
 | 
					     * @returns DealSummaryResponse Successful Response
 | 
				
			||||||
     * @throws ApiError
 | 
					     * @throws ApiError
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static getDealSummaries(): CancelablePromise<DealSummaryResponse> {
 | 
					    public static getDealSummaries({
 | 
				
			||||||
 | 
					        full,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        full: (boolean | null),
 | 
				
			||||||
 | 
					    }): CancelablePromise<DealSummaryResponse> {
 | 
				
			||||||
        return __request(OpenAPI, {
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
            method: 'GET',
 | 
					            method: 'GET',
 | 
				
			||||||
            url: '/deal/summaries',
 | 
					            url: '/deal/summaries',
 | 
				
			||||||
 | 
					            query: {
 | 
				
			||||||
 | 
					                'full': full,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,15 @@ import {Center, Flex, Image, rem, Stack, Tooltip, UnstyledButton, useMantineColo
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
    IconBarcode,
 | 
					    IconBarcode,
 | 
				
			||||||
    IconBox,
 | 
					    IconBox,
 | 
				
			||||||
    IconCash, IconDashboard,
 | 
					    IconCash,
 | 
				
			||||||
 | 
					    IconDashboard,
 | 
				
			||||||
    IconFileBarcode,
 | 
					    IconFileBarcode,
 | 
				
			||||||
    IconHome2,
 | 
					    IconHome2,
 | 
				
			||||||
    IconLogout,
 | 
					    IconLogout,
 | 
				
			||||||
    IconMan,
 | 
					    IconMan,
 | 
				
			||||||
    IconMoon,
 | 
					    IconMoon,
 | 
				
			||||||
    IconSun,
 | 
					    IconSun,
 | 
				
			||||||
 | 
					    IconTable,
 | 
				
			||||||
} from '@tabler/icons-react';
 | 
					} from '@tabler/icons-react';
 | 
				
			||||||
import classes from './Navbar.module.css';
 | 
					import classes from './Navbar.module.css';
 | 
				
			||||||
import {useAppDispatch} from "../../redux/store.ts";
 | 
					import {useAppDispatch} from "../../redux/store.ts";
 | 
				
			||||||
@@ -40,16 +42,17 @@ function NavbarLink(props: NavbarLinkProps) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mockdata = [
 | 
					const mockdata = [
 | 
				
			||||||
    // {
 | 
					
 | 
				
			||||||
    //     icon: IconHome2,
 | 
					 | 
				
			||||||
    //     label: 'Главная',
 | 
					 | 
				
			||||||
    //     href: '/'
 | 
					 | 
				
			||||||
    // },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        icon: IconCash,
 | 
					        icon: IconCash,
 | 
				
			||||||
        label: 'Сделки',
 | 
					        label: 'Сделки',
 | 
				
			||||||
        href: '/leads'
 | 
					        href: '/leads'
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        icon: IconTable,
 | 
				
			||||||
 | 
					        label: 'Таблица сделок',
 | 
				
			||||||
 | 
					        href: '/deals'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        icon: IconMan,
 | 
					        icon: IconMan,
 | 
				
			||||||
        label: 'Клиенты',
 | 
					        label: 'Клиенты',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,10 +26,12 @@ type RestProps<T> = {
 | 
				
			|||||||
    filterBy?: (item: SelectObjectType<T>) => boolean;
 | 
					    filterBy?: (item: SelectObjectType<T>) => boolean;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const defaultGetLabelFn = <T extends { name: string }>(item: T): string => {
 | 
					const defaultGetLabelFn = <T extends { name: string }>(item: T): string => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return item.name;
 | 
					    return item.name;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const defaultGetValueFn = <T extends { id: number }>(item: T): string => {
 | 
					const defaultGetValueFn = <T extends { id: number }>(item: T): string => {
 | 
				
			||||||
 | 
					    if (!item) return item;
 | 
				
			||||||
    return item.id.toString();
 | 
					    return item.id.toString();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export type ObjectSelectProps<T> =
 | 
					export type ObjectSelectProps<T> =
 | 
				
			||||||
@@ -85,6 +87,7 @@ const ObjectSelect = <T, >(props: ObjectSelectProps<T>) => {
 | 
				
			|||||||
        if (isControlled || !internalValue) return;
 | 
					        if (isControlled || !internalValue) return;
 | 
				
			||||||
        props.onChange(internalValue);
 | 
					        props.onChange(internalValue);
 | 
				
			||||||
    }, [internalValue]);
 | 
					    }, [internalValue]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const restProps = omit(props, ['filterBy', 'groupBy', 'getValueFn', 'getLabelFn']);
 | 
					    const restProps = omit(props, ['filterBy', 'groupBy', 'getValueFn', 'getLabelFn']);
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Select
 | 
					        <Select
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								src/components/Selects/ClientSelectNew/ClientSelectNew.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/components/Selects/ClientSelectNew/ClientSelectNew.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					import ObjectSelect, {ObjectSelectProps} from "../../ObjectSelect/ObjectSelect.tsx";
 | 
				
			||||||
 | 
					import {ClientSchema} from "../../../client";
 | 
				
			||||||
 | 
					import {FC} from "react";
 | 
				
			||||||
 | 
					import useClientsList from "../../../pages/ClientsPage/hooks/useClientsList.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = Omit<ObjectSelectProps<ClientSchema>, 'data'>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ClientSelectNew: FC<Props> = (props) => {
 | 
				
			||||||
 | 
					    const {clients} = useClientsList();
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <ObjectSelect
 | 
				
			||||||
 | 
					            data={clients}
 | 
				
			||||||
 | 
					            {...props}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export default ClientSelectNew;
 | 
				
			||||||
@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import ObjectSelect, {ObjectSelectProps} from "../../../../components/ObjectSelect/ObjectSelect.tsx";
 | 
				
			||||||
 | 
					import {FC} from "react";
 | 
				
			||||||
 | 
					import {DealStatuses} from "../../../../shared/enums/DealStatus.ts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DealStatus = {
 | 
				
			||||||
 | 
					    name: string;
 | 
				
			||||||
 | 
					    id: number
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type Props = Omit<ObjectSelectProps<DealStatus>, 'data'>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DealStatusSelect: FC<Props> = (props) => {
 | 
				
			||||||
 | 
					    const data: DealStatus[] = DealStatuses;
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <ObjectSelect
 | 
				
			||||||
 | 
					            data={data}
 | 
				
			||||||
 | 
					            {...props}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export default DealStatusSelect;
 | 
				
			||||||
							
								
								
									
										49
									
								
								src/pages/DealsPage/components/DealsTable/DealsTable.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/pages/DealsPage/components/DealsTable/DealsTable.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					import {CRUDTableProps} from "../../../../types/CRUDTable.tsx";
 | 
				
			||||||
 | 
					import {DealService, DealSummary} from "../../../../client";
 | 
				
			||||||
 | 
					import {FC} from "react";
 | 
				
			||||||
 | 
					import useDealsTableColumns from "./columns.tsx";
 | 
				
			||||||
 | 
					import {BaseTable} from "../../../../components/BaseTable/BaseTable.tsx";
 | 
				
			||||||
 | 
					import {ActionIcon, Flex, Tooltip} from "@mantine/core";
 | 
				
			||||||
 | 
					import {IconEdit} from "@tabler/icons-react";
 | 
				
			||||||
 | 
					import {MRT_TableOptions} from "mantine-react-table";
 | 
				
			||||||
 | 
					import {useDealPageContext} from "../../../LeadsPage/contexts/DealPageContext.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = CRUDTableProps<DealSummary>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DealsTable: FC<Props> = ({items}) => {
 | 
				
			||||||
 | 
					    const columns = useDealsTableColumns();
 | 
				
			||||||
 | 
					    const {setSelectedDeal} = useDealPageContext();
 | 
				
			||||||
 | 
					    const onEditClick = (dealSummary: DealSummary) => {
 | 
				
			||||||
 | 
					        DealService.getDealById({dealId: dealSummary.id})
 | 
				
			||||||
 | 
					            .then((deal) => {
 | 
				
			||||||
 | 
					                setSelectedDeal(deal);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <BaseTable
 | 
				
			||||||
 | 
					            data={items}
 | 
				
			||||||
 | 
					            columns={columns}
 | 
				
			||||||
 | 
					            restProps={{
 | 
				
			||||||
 | 
					                enableSorting: true,
 | 
				
			||||||
 | 
					                enableColumnActions: false,
 | 
				
			||||||
 | 
					                enablePagination: true,
 | 
				
			||||||
 | 
					                enableBottomToolbar: true,
 | 
				
			||||||
 | 
					                paginationDisplayMode: "pages",
 | 
				
			||||||
 | 
					                enableRowActions: true,
 | 
				
			||||||
 | 
					                renderRowActions: ({row}) => (
 | 
				
			||||||
 | 
					                    <Flex gap="md">
 | 
				
			||||||
 | 
					                        <Tooltip label="Редактировать">
 | 
				
			||||||
 | 
					                            <ActionIcon
 | 
				
			||||||
 | 
					                                onClick={() => onEditClick(row.original)}
 | 
				
			||||||
 | 
					                                variant={"default"}>
 | 
				
			||||||
 | 
					                                <IconEdit/>
 | 
				
			||||||
 | 
					                            </ActionIcon>
 | 
				
			||||||
 | 
					                        </Tooltip>
 | 
				
			||||||
 | 
					                    </Flex>
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            } as MRT_TableOptions<DealSummary>}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default DealsTable;
 | 
				
			||||||
							
								
								
									
										50
									
								
								src/pages/DealsPage/components/DealsTable/columns.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/pages/DealsPage/components/DealsTable/columns.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					import {useMemo} from "react";
 | 
				
			||||||
 | 
					import {MRT_ColumnDef} from "mantine-react-table";
 | 
				
			||||||
 | 
					import {DealSummary} from "../../../../client";
 | 
				
			||||||
 | 
					import {ActionIcon, Image} from "@mantine/core";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useDealsTableColumns = () => {
 | 
				
			||||||
 | 
					    return useMemo<MRT_ColumnDef<DealSummary>[]>(() => [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            header: "Маркетплейс",
 | 
				
			||||||
 | 
					            size: 10,
 | 
				
			||||||
 | 
					            Cell: ({row}) => (
 | 
				
			||||||
 | 
					                <ActionIcon variant={"transparent"}>
 | 
				
			||||||
 | 
					                    <Image src={row.original.baseMarketplace?.iconUrl || ""}/>
 | 
				
			||||||
 | 
					                </ActionIcon>
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            header: "Дата создания",
 | 
				
			||||||
 | 
					            accessorKey: "createdAt",
 | 
				
			||||||
 | 
					            Cell: ({row}) => (new Date(row.original.createdAt)).toLocaleString("ru-RU"),
 | 
				
			||||||
 | 
					            enableSorting: true,
 | 
				
			||||||
 | 
					            sortingFn: (rowA, rowB) => ((new Date(rowB.original.createdAt)).getTime() - (new Date(rowA.original.createdAt)).getTime())
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            accessorKey: "name",
 | 
				
			||||||
 | 
					            header: "Название",
 | 
				
			||||||
 | 
					            enableSorting: false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            accessorKey: "clientName",
 | 
				
			||||||
 | 
					            header: "Клиент",
 | 
				
			||||||
 | 
					            enableSorting: false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Cell: ({row}) => (new Date(row.original.deadline)).toLocaleString("ru-RU"),
 | 
				
			||||||
 | 
					            accessorKey: "deadline",
 | 
				
			||||||
 | 
					            header: "Дедлайн",
 | 
				
			||||||
 | 
					            sortingFn: (rowA, rowB) => ((new Date(rowB.original.deadline)).getTime() - (new Date(rowA.original.deadline)).getTime())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            header: "Общая стоимость",
 | 
				
			||||||
 | 
					            Cell: ({row}) => (row.original.totalPrice).toLocaleString("ru-RU") + '₽',
 | 
				
			||||||
 | 
					            accessorKey:"totalPrice"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ], [])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default useDealsTableColumns;
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/pages/DealsPage/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/pages/DealsPage/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					export {DealsPage} from './ui/DealsPage.tsx';
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/pages/DealsPage/ui/DealsPage.module.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/pages/DealsPage/ui/DealsPage.module.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					.container {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    flex: 1;
 | 
				
			||||||
 | 
					    gap: rem(10);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.body-container {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.top-panel {
 | 
				
			||||||
 | 
					    padding: rem(5);
 | 
				
			||||||
 | 
					    gap: rem(10);
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.table-container {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    gap: rem(10);
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.table-pagination {
 | 
				
			||||||
 | 
					    align-self: flex-end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										89
									
								
								src/pages/DealsPage/ui/DealsPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/pages/DealsPage/ui/DealsPage.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					import {FC, useEffect, useState} from "react";
 | 
				
			||||||
 | 
					import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
 | 
				
			||||||
 | 
					import styles from './DealsPage.module.css';
 | 
				
			||||||
 | 
					import DealStatusSelect from "../components/DealStatusSelect/DealStatusSelect.tsx";
 | 
				
			||||||
 | 
					import DealsTable from "../components/DealsTable/DealsTable.tsx";
 | 
				
			||||||
 | 
					import {useDealSummariesFull} from "../../LeadsPage/hooks/useDealSummaries.tsx";
 | 
				
			||||||
 | 
					import {DealStatusType} from "../../../shared/enums/DealStatus.ts";
 | 
				
			||||||
 | 
					import {BaseMarketplaceSchema, ClientSchema} from "../../../client";
 | 
				
			||||||
 | 
					import BaseMarketplaceSelect from "../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
 | 
				
			||||||
 | 
					import {useForm} from "@mantine/form";
 | 
				
			||||||
 | 
					import ClientSelectNew from "../../../components/Selects/ClientSelectNew/ClientSelectNew.tsx";
 | 
				
			||||||
 | 
					import {DealPageContextProvider} from "../../LeadsPage/contexts/DealPageContext.tsx";
 | 
				
			||||||
 | 
					import DealEditDrawer from "../../LeadsPage/drawers/DealEditDrawer/DealEditDrawer.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type State = {
 | 
				
			||||||
 | 
					    marketplace: BaseMarketplaceSchema | null;
 | 
				
			||||||
 | 
					    dealStatus: DealStatusType | null;
 | 
				
			||||||
 | 
					    client: ClientSchema | null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export const DealsPage: FC = () => {
 | 
				
			||||||
 | 
					    const {objects} = useDealSummariesFull();
 | 
				
			||||||
 | 
					    const form = useForm<State>({
 | 
				
			||||||
 | 
					        initialValues: {
 | 
				
			||||||
 | 
					            marketplace: null,
 | 
				
			||||||
 | 
					            dealStatus: null,
 | 
				
			||||||
 | 
					            client: null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const [data, setData] = useState(objects);
 | 
				
			||||||
 | 
					    const applyFilters = () => {
 | 
				
			||||||
 | 
					        let result = objects;
 | 
				
			||||||
 | 
					        if (form.values.marketplace) {
 | 
				
			||||||
 | 
					            result = result.filter(obj => obj.baseMarketplace?.key === form.values.marketplace?.key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (form.values.dealStatus) {
 | 
				
			||||||
 | 
					            result = result.filter(obj => obj.status === form.values.dealStatus?.id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (form.values.client) {
 | 
				
			||||||
 | 
					            result = result.filter(obj => obj.clientName === form.values.client?.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        setData(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        applyFilters();
 | 
				
			||||||
 | 
					    }, [form.values, objects])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <>
 | 
				
			||||||
 | 
					            <DealPageContextProvider>
 | 
				
			||||||
 | 
					                <div className={styles['container']}>
 | 
				
			||||||
 | 
					                    <PageBlock>
 | 
				
			||||||
 | 
					                        <div className={styles['top-panel']}>
 | 
				
			||||||
 | 
					                            <DealStatusSelect
 | 
				
			||||||
 | 
					                                onClear={() => form.setFieldValue("dealStatus", null)}
 | 
				
			||||||
 | 
					                                clearable
 | 
				
			||||||
 | 
					                                placeholder={"Выберите статус "}
 | 
				
			||||||
 | 
					                                {...form.getInputProps("dealStatus")}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                            <BaseMarketplaceSelect
 | 
				
			||||||
 | 
					                                onClear={() => form.setFieldValue("marketplace", null)}
 | 
				
			||||||
 | 
					                                clearable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                placeholder={"Выберите маркетплейс"}
 | 
				
			||||||
 | 
					                                {...form.getInputProps("marketplace")}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                            <ClientSelectNew
 | 
				
			||||||
 | 
					                                onClear={() => form.setFieldValue("client", null)}
 | 
				
			||||||
 | 
					                                clearable
 | 
				
			||||||
 | 
					                                searchable
 | 
				
			||||||
 | 
					                                placeholder={"Выберите клиента"}
 | 
				
			||||||
 | 
					                                {...form.getInputProps("client")}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </PageBlock>
 | 
				
			||||||
 | 
					                    <PageBlock>
 | 
				
			||||||
 | 
					                        <div className={styles['body-container']}>
 | 
				
			||||||
 | 
					                            <div className={styles['table-container']}>
 | 
				
			||||||
 | 
					                                <DealsTable items={data}/>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </PageBlock>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <DealEditDrawer
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </DealPageContextProvider>
 | 
				
			||||||
 | 
					        </>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
import {useQuery} from "@tanstack/react-query";
 | 
					import {useQuery} from "@tanstack/react-query";
 | 
				
			||||||
import {DealService} from "../../../client";
 | 
					import {DealService} from "../../../client";
 | 
				
			||||||
 | 
					import ObjectList from "../../../hooks/objectList.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useDealSummaries = () => {
 | 
					export const useDealSummaries = () => {
 | 
				
			||||||
    const {data: summariesRaw = [], refetch} = useQuery({
 | 
					    const {data: summariesRaw = [], refetch} = useQuery({
 | 
				
			||||||
        queryKey: ['getDealSummaries'],
 | 
					        queryKey: ['getDealSummaries'],
 | 
				
			||||||
        queryFn: DealService.getDealSummaries,
 | 
					        queryFn: () => DealService.getDealSummaries({full: false}),
 | 
				
			||||||
        select: data => data.summaries || [] // Трансформируем полученные данные
 | 
					        select: data => data.summaries || [] // Трансформируем полученные данные
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,3 +14,8 @@ export const useDealSummaries = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return {summariesRaw, refetch};
 | 
					    return {summariesRaw, refetch};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					export const useDealSummariesFull = () => ObjectList({
 | 
				
			||||||
 | 
					    queryFn: () => DealService.getDealSummaries({full: true}),
 | 
				
			||||||
 | 
					    queryKey: "getDealSummariesFull",
 | 
				
			||||||
 | 
					    getObjectsFn: response => response.summaries
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -22,6 +22,7 @@ const ServicesLazyImport = createFileRoute('/services')()
 | 
				
			|||||||
const ProductsLazyImport = createFileRoute('/products')()
 | 
					const ProductsLazyImport = createFileRoute('/products')()
 | 
				
			||||||
const LoginLazyImport = createFileRoute('/login')()
 | 
					const LoginLazyImport = createFileRoute('/login')()
 | 
				
			||||||
const LeadsLazyImport = createFileRoute('/leads')()
 | 
					const LeadsLazyImport = createFileRoute('/leads')()
 | 
				
			||||||
 | 
					const DealsLazyImport = createFileRoute('/deals')()
 | 
				
			||||||
const ClientsLazyImport = createFileRoute('/clients')()
 | 
					const ClientsLazyImport = createFileRoute('/clients')()
 | 
				
			||||||
const BarcodeLazyImport = createFileRoute('/barcode')()
 | 
					const BarcodeLazyImport = createFileRoute('/barcode')()
 | 
				
			||||||
const AdminLazyImport = createFileRoute('/admin')()
 | 
					const AdminLazyImport = createFileRoute('/admin')()
 | 
				
			||||||
@@ -54,6 +55,11 @@ const LeadsLazyRoute = LeadsLazyImport.update({
 | 
				
			|||||||
  getParentRoute: () => rootRoute,
 | 
					  getParentRoute: () => rootRoute,
 | 
				
			||||||
} as any).lazy(() => import('./routes/leads.lazy').then((d) => d.Route))
 | 
					} as any).lazy(() => import('./routes/leads.lazy').then((d) => d.Route))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DealsLazyRoute = DealsLazyImport.update({
 | 
				
			||||||
 | 
					  path: '/deals',
 | 
				
			||||||
 | 
					  getParentRoute: () => rootRoute,
 | 
				
			||||||
 | 
					} as any).lazy(() => import('./routes/deals.lazy').then((d) => d.Route))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ClientsLazyRoute = ClientsLazyImport.update({
 | 
					const ClientsLazyRoute = ClientsLazyImport.update({
 | 
				
			||||||
  path: '/clients',
 | 
					  path: '/clients',
 | 
				
			||||||
  getParentRoute: () => rootRoute,
 | 
					  getParentRoute: () => rootRoute,
 | 
				
			||||||
@@ -75,8 +81,8 @@ const IndexLazyRoute = IndexLazyImport.update({
 | 
				
			|||||||
} as any).lazy(() => import('./routes/index.lazy').then((d) => d.Route))
 | 
					} as any).lazy(() => import('./routes/index.lazy').then((d) => d.Route))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DealsDealIdRoute = DealsDealIdImport.update({
 | 
					const DealsDealIdRoute = DealsDealIdImport.update({
 | 
				
			||||||
  path: '/deals/$dealId',
 | 
					  path: '/$dealId',
 | 
				
			||||||
  getParentRoute: () => rootRoute,
 | 
					  getParentRoute: () => DealsLazyRoute,
 | 
				
			||||||
} as any)
 | 
					} as any)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Populate the FileRoutesByPath interface
 | 
					// Populate the FileRoutesByPath interface
 | 
				
			||||||
@@ -111,6 +117,13 @@ declare module '@tanstack/react-router' {
 | 
				
			|||||||
      preLoaderRoute: typeof ClientsLazyImport
 | 
					      preLoaderRoute: typeof ClientsLazyImport
 | 
				
			||||||
      parentRoute: typeof rootRoute
 | 
					      parentRoute: typeof rootRoute
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    '/deals': {
 | 
				
			||||||
 | 
					      id: '/deals'
 | 
				
			||||||
 | 
					      path: '/deals'
 | 
				
			||||||
 | 
					      fullPath: '/deals'
 | 
				
			||||||
 | 
					      preLoaderRoute: typeof DealsLazyImport
 | 
				
			||||||
 | 
					      parentRoute: typeof rootRoute
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    '/leads': {
 | 
					    '/leads': {
 | 
				
			||||||
      id: '/leads'
 | 
					      id: '/leads'
 | 
				
			||||||
      path: '/leads'
 | 
					      path: '/leads'
 | 
				
			||||||
@@ -148,10 +161,10 @@ declare module '@tanstack/react-router' {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    '/deals/$dealId': {
 | 
					    '/deals/$dealId': {
 | 
				
			||||||
      id: '/deals/$dealId'
 | 
					      id: '/deals/$dealId'
 | 
				
			||||||
      path: '/deals/$dealId'
 | 
					      path: '/$dealId'
 | 
				
			||||||
      fullPath: '/deals/$dealId'
 | 
					      fullPath: '/deals/$dealId'
 | 
				
			||||||
      preLoaderRoute: typeof DealsDealIdImport
 | 
					      preLoaderRoute: typeof DealsDealIdImport
 | 
				
			||||||
      parentRoute: typeof rootRoute
 | 
					      parentRoute: typeof DealsLazyImport
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -163,12 +176,12 @@ export const routeTree = rootRoute.addChildren({
 | 
				
			|||||||
  AdminLazyRoute,
 | 
					  AdminLazyRoute,
 | 
				
			||||||
  BarcodeLazyRoute,
 | 
					  BarcodeLazyRoute,
 | 
				
			||||||
  ClientsLazyRoute,
 | 
					  ClientsLazyRoute,
 | 
				
			||||||
 | 
					  DealsLazyRoute: DealsLazyRoute.addChildren({ DealsDealIdRoute }),
 | 
				
			||||||
  LeadsLazyRoute,
 | 
					  LeadsLazyRoute,
 | 
				
			||||||
  LoginLazyRoute,
 | 
					  LoginLazyRoute,
 | 
				
			||||||
  ProductsLazyRoute,
 | 
					  ProductsLazyRoute,
 | 
				
			||||||
  ServicesLazyRoute,
 | 
					  ServicesLazyRoute,
 | 
				
			||||||
  TestLazyRoute,
 | 
					  TestLazyRoute,
 | 
				
			||||||
  DealsDealIdRoute,
 | 
					 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* prettier-ignore-end */
 | 
					/* prettier-ignore-end */
 | 
				
			||||||
@@ -183,12 +196,12 @@ export const routeTree = rootRoute.addChildren({
 | 
				
			|||||||
        "/admin",
 | 
					        "/admin",
 | 
				
			||||||
        "/barcode",
 | 
					        "/barcode",
 | 
				
			||||||
        "/clients",
 | 
					        "/clients",
 | 
				
			||||||
 | 
					        "/deals",
 | 
				
			||||||
        "/leads",
 | 
					        "/leads",
 | 
				
			||||||
        "/login",
 | 
					        "/login",
 | 
				
			||||||
        "/products",
 | 
					        "/products",
 | 
				
			||||||
        "/services",
 | 
					        "/services",
 | 
				
			||||||
        "/test",
 | 
					        "/test"
 | 
				
			||||||
        "/deals/$dealId"
 | 
					 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "/": {
 | 
					    "/": {
 | 
				
			||||||
@@ -203,6 +216,12 @@ export const routeTree = rootRoute.addChildren({
 | 
				
			|||||||
    "/clients": {
 | 
					    "/clients": {
 | 
				
			||||||
      "filePath": "clients.lazy.tsx"
 | 
					      "filePath": "clients.lazy.tsx"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "/deals": {
 | 
				
			||||||
 | 
					      "filePath": "deals.lazy.tsx",
 | 
				
			||||||
 | 
					      "children": [
 | 
				
			||||||
 | 
					        "/deals/$dealId"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "/leads": {
 | 
					    "/leads": {
 | 
				
			||||||
      "filePath": "leads.lazy.tsx"
 | 
					      "filePath": "leads.lazy.tsx"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@@ -219,7 +238,8 @@ export const routeTree = rootRoute.addChildren({
 | 
				
			|||||||
      "filePath": "test.lazy.tsx"
 | 
					      "filePath": "test.lazy.tsx"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "/deals/$dealId": {
 | 
					    "/deals/$dealId": {
 | 
				
			||||||
      "filePath": "deals.$dealId.tsx"
 | 
					      "filePath": "deals.$dealId.tsx",
 | 
				
			||||||
 | 
					      "parent": "/deals"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								src/routes/deals.lazy.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/routes/deals.lazy.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					import {createLazyFileRoute} from '@tanstack/react-router'
 | 
				
			||||||
 | 
					import {DealsPage} from "../pages/DealsPage";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Route = createLazyFileRoute('/deals')({
 | 
				
			||||||
 | 
					    component: DealsPage
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -20,3 +20,10 @@ export const DealStatusDictionary = {
 | 
				
			|||||||
    [DealStatus.COMPLETED]: "Завершена",
 | 
					    [DealStatus.COMPLETED]: "Завершена",
 | 
				
			||||||
    [DealStatus.CANCELLED]: "Отменена",
 | 
					    [DealStatus.CANCELLED]: "Отменена",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					export type DealStatusType = {
 | 
				
			||||||
 | 
					    id: number,
 | 
				
			||||||
 | 
					    name: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export const DealStatuses: DealStatusType[] = Object.entries(DealStatusDictionary).map(([key, value]) => {
 | 
				
			||||||
 | 
					    return {id: parseInt(key), name: value}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Reference in New Issue
	
	Block a user