This commit is contained in:
2024-04-28 04:55:19 +03:00
parent c4e106576e
commit d0a32b938c
25 changed files with 274 additions and 58 deletions

View File

@@ -21,6 +21,7 @@ const DealStatusChangeTable: FC<Props> = (props: Props) => {
enableBottomToolbar: false,
enableColumnFilters: false,
enableColumnVisibilityToggle: false,
layoutMode:"grid"
}}
/>
);

View File

@@ -2,6 +2,7 @@ import {useMemo} from "react";
import {MRT_ColumnDef} from "mantine-react-table";
import {DealStatusHistorySchema} from "../../../../client";
import {DealStatus, DealStatusDictionary} from "../../../../shared/enums/DealStatus.ts";
import {Spoiler, Text} from "@mantine/core";
export const useDealStatusChangeTableColumns = () => {
return useMemo<MRT_ColumnDef<DealStatusHistorySchema>[]>(() => [
@@ -23,6 +24,17 @@ export const useDealStatusChangeTableColumns = () => {
accessorKey: "toStatus",
header: "В статус",
accessorFn: (row) => DealStatusDictionary[row.toStatus as DealStatus],
},
{
accessorKey: "comment",
header: "Комментарий",
Cell: ({row}) =>
<Spoiler onDoubleClick={()=>{console.log("double click")}} maxHeight={80} showLabel={"Показать весь"} hideLabel={"Скрыть"}>
<Text style={{wordWrap: "break-word", wordBreak: "break-all", whiteSpace: "normal"}} span>
{row.original.comment}<br/>
</Text>
</Spoiler>
,
}
], []);

View File

@@ -1,8 +1,8 @@
import {useQuery} from "@tanstack/react-query";
import {DealService, DealSummary} from "../../../client";
import {DealService} from "../../../client";
export const useDealSummaries = (): DealSummary[] => {
const {data: summaries = []} = useQuery({
export const useDealSummaries = () => {
const {data: summariesRaw = [], refetch} = useQuery({
queryKey: ['getDealSummaries'],
queryFn: DealService.getDealSummaries,
select: data => data.summaries || [] // Трансформируем полученные данные
@@ -11,5 +11,5 @@ export const useDealSummaries = (): DealSummary[] => {
// Теперь summaries будет содержать либо трансформированные данные, либо пустой массив по умолчанию
// isLoading и isError могут быть использованы для отображения индикаторов загрузки или ошибки
return summaries;
return {summariesRaw, refetch};
}

View File

@@ -20,3 +20,22 @@
padding-right: 5%;
padding-left: 5%;
}
.delete {
@mixin light {
border-color: var(--mantine-color-gray-1);
}
@mixin dark {
border-color: var(--mantine-color-dark-5);
}
border: dashed var(--item-border-size) var(--mantine-color-default-border);
border-radius: var(--item-border-radius);
padding: rem(30);
text-align: center;
}
.delete-hidden {
border: none;
}

View File

@@ -1,31 +1,77 @@
import {FC, useEffect, useState} from "react";
import styles from './LeadsPage.module.css';
import Board from "../../../components/Dnd/Board/Board.tsx";
import {DragDropContext, DropResult, OnDragEndResponder, ResponderProvided} from "@hello-pangea/dnd";
import {DragDropContext, Droppable, DropResult} from "@hello-pangea/dnd";
import {useDealSummaries} from "../hooks/useDealSummaries.tsx";
import {DealStatus} from "../../../shared/enums/DealStatus.ts";
import {DealStatus, getDealStatusByName} from "../../../shared/enums/DealStatus.ts";
import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
import DealEditDrawer from "../drawers/DealEditDrawer/DealEditDrawer.tsx";
import {DealPageContextProvider} from "../contexts/DealPageContext.tsx";
import {modals} from "@mantine/modals";
import {DealSummaryReorderRequest} from "../../../client";
import {DealService, DealSummaryReorderRequest} from "../../../client";
import {Flex} from "@mantine/core";
import classNames from "classnames";
import {notifications} from "../../../shared/lib/notifications.ts";
export const LeadsPage: FC = () => {
const summariesRaw = useDealSummaries();
const {summariesRaw, refetch} = useDealSummaries();
const [summaries, setSummaries] = useState(summariesRaw);
const [isDragEnded, setIsDragEnded] = useState(true);
useEffect(() => {
setSummaries(summariesRaw);
}, [summariesRaw]);
const onDragEnd = async (result: DropResult, provided: ResponderProvided) => {
const onDelete = (dealId: number) => {
const summary = summaries.find(summary => summary.id == dealId);
if (!summary) return;
modals.openConfirmModal({
title: "Удаление сделки",
children:
<Flex>
Вы действительно хотите удалить сделку {summary.name}?
</Flex>,
onConfirm: () => {
DealService.deleteDeal({requestBody: {dealId: dealId}})
.then(async ({ok, message}) => {
notifications.guess(ok, {message});
if (!ok) return;
await refetch();
})
},
labels: {
confirm: "Удалить",
cancel: "Отмена"
}
});
}
const onDragEnd = async (result: DropResult) => {
setIsDragEnded(true);
if (!result.destination || result.destination == result.source) return;
const dealId = parseInt(result.draggableId);
const request: DealSummaryReorderRequest = {}
if (isNaN(dealId)) return;
const droppableId = result.destination.droppableId;
if (droppableId === 'DELETE') {
onDelete(dealId);
return;
}
const request: Partial<DealSummaryReorderRequest> = {
dealId: dealId,
index: result.destination.index,
status: getDealStatusByName(droppableId)
}
modals.openContextModal({
modal: 'enterDeadline',
title: "Необходимо указать дедлайн",
innerProps: {
onSubmit: (event) => console.log(event)
onSubmit: (event) => DealService.reorderDealSummaries({requestBody: event})
.then(async response => {
setSummaries(response.summaries);
await refetch();
}),
request: request
}
});
@@ -34,43 +80,89 @@ export const LeadsPage: FC = () => {
<>
<DealPageContextProvider>
<PageBlock>
<PageBlock fullHeight>
<div className={styles['container']}>
<div className={styles['boards']}>
<DragDropContext onDragEnd={onDragEnd}>
<DragDropContext
onDragStart={() => {
setIsDragEnded(false);
}}
onDragEnd={onDragEnd}>
<div className={styles['boards']}>
<Board
withCreateButton
summaries={summaries
.filter(summary => summary.status == DealStatus.AWAITING_ACCEPTANCE)}
title={"Ожидает приемки"}
droppableId={"AWAITING_ACCEPTANCE"}
color={'#4A90E2'}
/>
<Board
summaries={summaries
.filter(summary => summary.status == DealStatus.PACKAGING)}
title={"Упаковка"}
droppableId={"PACKAGING"}
color={'#F5A623'}
/>
<Board
summaries={summaries
.filter(summary => summary.status == DealStatus.AWAITING_SHIPMENT)}
title={"Ожидает отгрузки"}
droppableId={"AWAITING_SHIPMENT"}
color={'#7ED321'}
/>
<Board
summaries={summaries
.filter(summary => summary.status == DealStatus.AWAITING_PAYMENT)}
title={"Ожидает оплаты"}
droppableId={"AWAITING_PAYMENT"}
color={'#D0021B'}
/>
<Board
summaries={summaries
.filter(summary => summary.status == DealStatus.COMPLETED)}
title={"Завершена"}
droppableId={"COMPLETED"}
color={'#417505'}
/>
</DragDropContext>
</div>
</div>
<Flex justify={"flex-end"}>
<div
className={
classNames(
styles['delete'],
isDragEnded && styles['delete-hidden']
)
}
>
<Droppable droppableId={"DELETE"}>
{(provided) => (
<>
<div
{...provided.droppableProps}
ref={provided.innerRef}
>
{!isDragEnded &&
<span>
Удалить
</span>
}
</div>
{provided.placeholder}
</>
)}
</Droppable>
</div>
</Flex>
</DragDropContext>
</div>
</PageBlock>
<DealEditDrawer