feat: deal group and stuff
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
"globals": "^15.8.0",
|
"globals": "^15.8.0",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"mantine-contextmenu": "^7.12.2",
|
||||||
"mantine-form-zod-resolver": "^1.1.0",
|
"mantine-form-zod-resolver": "^1.1.0",
|
||||||
"mantine-react-table": "^2.0.0-beta.5",
|
"mantine-react-table": "^2.0.0-beta.5",
|
||||||
"phone": "^3.1.49",
|
"phone": "^3.1.49",
|
||||||
|
|||||||
@@ -71,11 +71,15 @@ export type { DealAddServiceRequest } from './models/DealAddServiceRequest';
|
|||||||
export type { DealAddServiceResponse } from './models/DealAddServiceResponse';
|
export type { DealAddServiceResponse } from './models/DealAddServiceResponse';
|
||||||
export type { DealAddServicesRequest } from './models/DealAddServicesRequest';
|
export type { DealAddServicesRequest } from './models/DealAddServicesRequest';
|
||||||
export type { DealAddServicesResponse } from './models/DealAddServicesResponse';
|
export type { DealAddServicesResponse } from './models/DealAddServicesResponse';
|
||||||
|
export type { DealAddToGroupRequest } from './models/DealAddToGroupRequest';
|
||||||
|
export type { DealAddToGroupResponse } from './models/DealAddToGroupResponse';
|
||||||
export type { DealBillRequestSchema } from './models/DealBillRequestSchema';
|
export type { DealBillRequestSchema } from './models/DealBillRequestSchema';
|
||||||
export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
|
export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
|
||||||
export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
|
export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
|
||||||
export type { DealCompleteRequest } from './models/DealCompleteRequest';
|
export type { DealCompleteRequest } from './models/DealCompleteRequest';
|
||||||
export type { DealCompleteResponse } from './models/DealCompleteResponse';
|
export type { DealCompleteResponse } from './models/DealCompleteResponse';
|
||||||
|
export type { DealCreateGroupRequest } from './models/DealCreateGroupRequest';
|
||||||
|
export type { DealCreateGroupResponse } from './models/DealCreateGroupResponse';
|
||||||
export type { DealCreateGuestUrlRequest } from './models/DealCreateGuestUrlRequest';
|
export type { DealCreateGuestUrlRequest } from './models/DealCreateGuestUrlRequest';
|
||||||
export type { DealCreateGuestUrlResponse } from './models/DealCreateGuestUrlResponse';
|
export type { DealCreateGuestUrlResponse } from './models/DealCreateGuestUrlResponse';
|
||||||
export type { DealCreateRequest } from './models/DealCreateRequest';
|
export type { DealCreateRequest } from './models/DealCreateRequest';
|
||||||
@@ -91,6 +95,11 @@ export type { DealDeleteServicesRequest } from './models/DealDeleteServicesReque
|
|||||||
export type { DealDeleteServicesResponse } from './models/DealDeleteServicesResponse';
|
export type { DealDeleteServicesResponse } from './models/DealDeleteServicesResponse';
|
||||||
export type { DealGeneralInfoSchema } from './models/DealGeneralInfoSchema';
|
export type { DealGeneralInfoSchema } from './models/DealGeneralInfoSchema';
|
||||||
export type { DealGetAllResponse } from './models/DealGetAllResponse';
|
export type { DealGetAllResponse } from './models/DealGetAllResponse';
|
||||||
|
export type { DealGroupChangeStatusRequest } from './models/DealGroupChangeStatusRequest';
|
||||||
|
export type { DealGroupChangeStatusResponse } from './models/DealGroupChangeStatusResponse';
|
||||||
|
export type { DealGroupSchema } from './models/DealGroupSchema';
|
||||||
|
export type { DealGroupUpdateRequest } from './models/DealGroupUpdateRequest';
|
||||||
|
export type { DealGroupUpdateResponse } from './models/DealGroupUpdateResponse';
|
||||||
export type { DealPrefillRequest } from './models/DealPrefillRequest';
|
export type { DealPrefillRequest } from './models/DealPrefillRequest';
|
||||||
export type { DealPrefillResponse } from './models/DealPrefillResponse';
|
export type { DealPrefillResponse } from './models/DealPrefillResponse';
|
||||||
export type { DealProductAddKitRequest } from './models/DealProductAddKitRequest';
|
export type { DealProductAddKitRequest } from './models/DealProductAddKitRequest';
|
||||||
@@ -101,6 +110,8 @@ export type { DealQuickCreateRequest } from './models/DealQuickCreateRequest';
|
|||||||
export type { DealQuickCreateResponse } from './models/DealQuickCreateResponse';
|
export type { DealQuickCreateResponse } from './models/DealQuickCreateResponse';
|
||||||
export type { DealRecalculatePriceRequest } from './models/DealRecalculatePriceRequest';
|
export type { DealRecalculatePriceRequest } from './models/DealRecalculatePriceRequest';
|
||||||
export type { DealRecalculatePriceResponse } from './models/DealRecalculatePriceResponse';
|
export type { DealRecalculatePriceResponse } from './models/DealRecalculatePriceResponse';
|
||||||
|
export type { DealRemoveFromGroupRequest } from './models/DealRemoveFromGroupRequest';
|
||||||
|
export type { DealRemoveFromGroupResponse } from './models/DealRemoveFromGroupResponse';
|
||||||
export type { DealSchema } from './models/DealSchema';
|
export type { DealSchema } from './models/DealSchema';
|
||||||
export type { DealServiceSchema } from './models/DealServiceSchema';
|
export type { DealServiceSchema } from './models/DealServiceSchema';
|
||||||
export type { DealServicesCopyRequest } from './models/DealServicesCopyRequest';
|
export type { DealServicesCopyRequest } from './models/DealServicesCopyRequest';
|
||||||
|
|||||||
9
src/client/models/DealAddToGroupRequest.ts
Normal file
9
src/client/models/DealAddToGroupRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealAddToGroupRequest = {
|
||||||
|
dealId: number;
|
||||||
|
groupId: number;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealAddToGroupResponse.ts
Normal file
9
src/client/models/DealAddToGroupResponse.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealAddToGroupResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealCreateGroupRequest.ts
Normal file
9
src/client/models/DealCreateGroupRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealCreateGroupRequest = {
|
||||||
|
draggingDealId: number;
|
||||||
|
hoveredDealId: number;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealCreateGroupResponse.ts
Normal file
9
src/client/models/DealCreateGroupResponse.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealCreateGroupResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealGroupChangeStatusRequest.ts
Normal file
9
src/client/models/DealGroupChangeStatusRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealGroupChangeStatusRequest = {
|
||||||
|
groupId: number;
|
||||||
|
newStatus: number;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealGroupChangeStatusResponse.ts
Normal file
9
src/client/models/DealGroupChangeStatusResponse.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealGroupChangeStatusResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
10
src/client/models/DealGroupSchema.ts
Normal file
10
src/client/models/DealGroupSchema.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealGroupSchema = {
|
||||||
|
id: number;
|
||||||
|
name?: (string | null);
|
||||||
|
lexorank: string;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealGroupUpdateRequest.ts
Normal file
9
src/client/models/DealGroupUpdateRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type { DealGroupSchema } from './DealGroupSchema';
|
||||||
|
export type DealGroupUpdateRequest = {
|
||||||
|
data: DealGroupSchema;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealGroupUpdateResponse.ts
Normal file
9
src/client/models/DealGroupUpdateResponse.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealGroupUpdateResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
8
src/client/models/DealRemoveFromGroupRequest.ts
Normal file
8
src/client/models/DealRemoveFromGroupRequest.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealRemoveFromGroupRequest = {
|
||||||
|
dealId: number;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/DealRemoveFromGroupResponse.ts
Normal file
9
src/client/models/DealRemoveFromGroupResponse.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type DealRemoveFromGroupResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
@@ -4,13 +4,14 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import type { BaseMarketplaceSchema } from './BaseMarketplaceSchema';
|
import type { BaseMarketplaceSchema } from './BaseMarketplaceSchema';
|
||||||
import type { DealBillRequestSchema } from './DealBillRequestSchema';
|
import type { DealBillRequestSchema } from './DealBillRequestSchema';
|
||||||
|
import type { DealGroupSchema } from './DealGroupSchema';
|
||||||
export type DealSummary = {
|
export type DealSummary = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
clientName: string;
|
clientName: string;
|
||||||
changedAt: string;
|
changedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
deadline: string;
|
deadline?: (string | null);
|
||||||
status: number;
|
status: number;
|
||||||
totalPrice: number;
|
totalPrice: number;
|
||||||
rank: number;
|
rank: number;
|
||||||
@@ -21,5 +22,6 @@ export type DealSummary = {
|
|||||||
deliveryDate?: (string | null);
|
deliveryDate?: (string | null);
|
||||||
receivingSlotDate?: (string | null);
|
receivingSlotDate?: (string | null);
|
||||||
billRequest?: (DealBillRequestSchema | null);
|
billRequest?: (DealBillRequestSchema | null);
|
||||||
|
group?: (DealGroupSchema | null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,14 @@ import type { DealAddServiceRequest } from '../models/DealAddServiceRequest';
|
|||||||
import type { DealAddServiceResponse } from '../models/DealAddServiceResponse';
|
import type { DealAddServiceResponse } from '../models/DealAddServiceResponse';
|
||||||
import type { DealAddServicesRequest } from '../models/DealAddServicesRequest';
|
import type { DealAddServicesRequest } from '../models/DealAddServicesRequest';
|
||||||
import type { DealAddServicesResponse } from '../models/DealAddServicesResponse';
|
import type { DealAddServicesResponse } from '../models/DealAddServicesResponse';
|
||||||
|
import type { DealAddToGroupRequest } from '../models/DealAddToGroupRequest';
|
||||||
|
import type { DealAddToGroupResponse } from '../models/DealAddToGroupResponse';
|
||||||
import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
|
import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
|
||||||
import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
|
import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
|
||||||
import type { DealCompleteRequest } from '../models/DealCompleteRequest';
|
import type { DealCompleteRequest } from '../models/DealCompleteRequest';
|
||||||
import type { DealCompleteResponse } from '../models/DealCompleteResponse';
|
import type { DealCompleteResponse } from '../models/DealCompleteResponse';
|
||||||
|
import type { DealCreateGroupRequest } from '../models/DealCreateGroupRequest';
|
||||||
|
import type { DealCreateGroupResponse } from '../models/DealCreateGroupResponse';
|
||||||
import type { DealCreateGuestUrlRequest } from '../models/DealCreateGuestUrlRequest';
|
import type { DealCreateGuestUrlRequest } from '../models/DealCreateGuestUrlRequest';
|
||||||
import type { DealCreateGuestUrlResponse } from '../models/DealCreateGuestUrlResponse';
|
import type { DealCreateGuestUrlResponse } from '../models/DealCreateGuestUrlResponse';
|
||||||
import type { DealCreateRequest } from '../models/DealCreateRequest';
|
import type { DealCreateRequest } from '../models/DealCreateRequest';
|
||||||
@@ -28,6 +32,10 @@ import type { DealDeleteServiceResponse } from '../models/DealDeleteServiceRespo
|
|||||||
import type { DealDeleteServicesRequest } from '../models/DealDeleteServicesRequest';
|
import type { DealDeleteServicesRequest } from '../models/DealDeleteServicesRequest';
|
||||||
import type { DealDeleteServicesResponse } from '../models/DealDeleteServicesResponse';
|
import type { DealDeleteServicesResponse } from '../models/DealDeleteServicesResponse';
|
||||||
import type { DealGetAllResponse } from '../models/DealGetAllResponse';
|
import type { DealGetAllResponse } from '../models/DealGetAllResponse';
|
||||||
|
import type { DealGroupChangeStatusRequest } from '../models/DealGroupChangeStatusRequest';
|
||||||
|
import type { DealGroupChangeStatusResponse } from '../models/DealGroupChangeStatusResponse';
|
||||||
|
import type { DealGroupUpdateRequest } from '../models/DealGroupUpdateRequest';
|
||||||
|
import type { DealGroupUpdateResponse } from '../models/DealGroupUpdateResponse';
|
||||||
import type { DealPrefillRequest } from '../models/DealPrefillRequest';
|
import type { DealPrefillRequest } from '../models/DealPrefillRequest';
|
||||||
import type { DealPrefillResponse } from '../models/DealPrefillResponse';
|
import type { DealPrefillResponse } from '../models/DealPrefillResponse';
|
||||||
import type { DealProductAddKitRequest } from '../models/DealProductAddKitRequest';
|
import type { DealProductAddKitRequest } from '../models/DealProductAddKitRequest';
|
||||||
@@ -36,6 +44,8 @@ import type { DealQuickCreateRequest } from '../models/DealQuickCreateRequest';
|
|||||||
import type { DealQuickCreateResponse } from '../models/DealQuickCreateResponse';
|
import type { DealQuickCreateResponse } from '../models/DealQuickCreateResponse';
|
||||||
import type { DealRecalculatePriceRequest } from '../models/DealRecalculatePriceRequest';
|
import type { DealRecalculatePriceRequest } from '../models/DealRecalculatePriceRequest';
|
||||||
import type { DealRecalculatePriceResponse } from '../models/DealRecalculatePriceResponse';
|
import type { DealRecalculatePriceResponse } from '../models/DealRecalculatePriceResponse';
|
||||||
|
import type { DealRemoveFromGroupRequest } from '../models/DealRemoveFromGroupRequest';
|
||||||
|
import type { DealRemoveFromGroupResponse } from '../models/DealRemoveFromGroupResponse';
|
||||||
import type { DealSchema } from '../models/DealSchema';
|
import type { DealSchema } from '../models/DealSchema';
|
||||||
import type { DealServicesCopyRequest } from '../models/DealServicesCopyRequest';
|
import type { DealServicesCopyRequest } from '../models/DealServicesCopyRequest';
|
||||||
import type { DealServicesCopyResponse } from '../models/DealServicesCopyResponse';
|
import type { DealServicesCopyResponse } from '../models/DealServicesCopyResponse';
|
||||||
@@ -652,4 +662,104 @@ export class DealService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Add To Group
|
||||||
|
* @returns DealAddToGroupResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static addDealToGroup({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: DealAddToGroupRequest,
|
||||||
|
}): CancelablePromise<DealAddToGroupResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/deal/add-to-group',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create Group
|
||||||
|
* @returns DealCreateGroupResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static createDealGroup({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: DealCreateGroupRequest,
|
||||||
|
}): CancelablePromise<DealCreateGroupResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/deal/create-group',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove From Group
|
||||||
|
* @returns DealRemoveFromGroupResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static removeDealFromGroup({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: DealRemoveFromGroupRequest,
|
||||||
|
}): CancelablePromise<DealRemoveFromGroupResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/deal/remove-from-group',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Update Group
|
||||||
|
* @returns DealGroupUpdateResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static updateDealGroup({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: DealGroupUpdateRequest,
|
||||||
|
}): CancelablePromise<DealGroupUpdateResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/deal/group/update',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Change Group Status
|
||||||
|
* @returns DealGroupChangeStatusResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static changeDealGroupStatus({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: DealGroupChangeStatusRequest,
|
||||||
|
}): CancelablePromise<DealGroupChangeStatusResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/deal/group/change-status',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import styles from "./Board.module.css";
|
|||||||
import { Divider, Text, Title } from "@mantine/core";
|
import { Divider, Text, Title } from "@mantine/core";
|
||||||
import { Draggable, Droppable } from "@hello-pangea/dnd";
|
import { Draggable, Droppable } from "@hello-pangea/dnd";
|
||||||
import CreateDealButton from "../CreateDealButton/CreateDealButton.tsx";
|
import CreateDealButton from "../CreateDealButton/CreateDealButton.tsx";
|
||||||
import { DealSummary } from "../../../client";
|
import { DealGroupSchema, DealSummary } from "../../../client";
|
||||||
import DealSummaryCard from "../DealSummaryCard/DealSummaryCard.tsx";
|
import DealSummaryCard from "../DealSummaryCard/DealSummaryCard.tsx";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { getPluralForm } from "../../../shared/lib/utils.ts";
|
import { getPluralForm } from "../../../shared/lib/utils.ts";
|
||||||
import { sum } from "lodash";
|
import { groupBy, has, sum, uniq } from "lodash";
|
||||||
|
import { DealGroupView } from "../DealGroupView/DealGroupView.tsx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
droppableId: string;
|
droppableId: string;
|
||||||
@@ -16,6 +17,7 @@ type Props = {
|
|||||||
summaries: DealSummary[];
|
summaries: DealSummary[];
|
||||||
color: string;
|
color: string;
|
||||||
};
|
};
|
||||||
|
type GroupWithDeals = { group: DealGroupSchema, deals: DealSummary[] }
|
||||||
|
|
||||||
export const Board: FC<Props> = ({
|
export const Board: FC<Props> = ({
|
||||||
droppableId,
|
droppableId,
|
||||||
@@ -29,11 +31,113 @@ export const Board: FC<Props> = ({
|
|||||||
summaries.length,
|
summaries.length,
|
||||||
"сделка",
|
"сделка",
|
||||||
"сделки",
|
"сделки",
|
||||||
"сделок"
|
"сделок",
|
||||||
);
|
);
|
||||||
return `${summaries.length} ${pluralForm}: ${sum(summaries.map(summary => summary.totalPrice)).toLocaleString("ru-RU")}₽`;
|
return `${summaries.length} ${pluralForm}: ${sum(summaries.map(summary => summary.totalPrice)).toLocaleString("ru-RU")}₽`;
|
||||||
};
|
};
|
||||||
|
const isGroup = (obj: GroupWithDeals | DealSummary): obj is GroupWithDeals => {
|
||||||
|
return has(obj, "deals");
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDateFromDealOrGroup = (obj: GroupWithDeals | DealSummary) => {
|
||||||
|
// if is group get group with the delivery earliest date
|
||||||
|
if (isGroup(obj)) {
|
||||||
|
const dates = obj.deals.map(d => d.deliveryDate || d.createdAt).filter(Boolean);
|
||||||
|
if (dates.length === 0) return null;
|
||||||
|
return new Date(Math.min(...dates.map(d => {
|
||||||
|
return new Date(d).getTime();
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
// if is deal get deal delivery date
|
||||||
|
return new Date(obj.deliveryDate || obj.createdAt);
|
||||||
|
};
|
||||||
|
const getDealGroups = (): GroupWithDeals[] => {
|
||||||
|
const groups = uniq<DealGroupSchema>(summaries.filter(s => s.group).map(summary => summary.group) as DealGroupSchema[]);
|
||||||
|
if (groups.length === 0) return [];
|
||||||
|
const groupedSummaries = groupBy(summaries, "group.id");
|
||||||
|
const groupDict = groups.reduce((acc, group) => {
|
||||||
|
acc[group.id] = group;
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
, {} as { [key: number]: DealGroupSchema });
|
||||||
|
return Object.entries(groupedSummaries).reduce((acc, [groupId, deals]) => {
|
||||||
|
if (!groupId) return acc;
|
||||||
|
const group = groupDict[parseInt(groupId)];
|
||||||
|
if (!group) return acc;
|
||||||
|
acc.push({
|
||||||
|
group,
|
||||||
|
deals,
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
}, [] as { group: DealGroupSchema; deals: DealSummary[] }[]);
|
||||||
|
};
|
||||||
|
const getDealsAndGroups = (): (GroupWithDeals | DealSummary)[] => {
|
||||||
|
const groups = getDealGroups();
|
||||||
|
const deals = summaries.filter(s => !s.group);
|
||||||
|
const data = [...groups, ...deals];
|
||||||
|
return data.sort((a, b) => {
|
||||||
|
const aDate = getDateFromDealOrGroup(a);
|
||||||
|
const bDate = getDateFromDealOrGroup(b);
|
||||||
|
if (!aDate || !bDate) return 0;
|
||||||
|
return aDate.getTime() - bDate.getTime();
|
||||||
|
}).map((obj, index) => {
|
||||||
|
if (isGroup(obj)) {
|
||||||
|
obj.deals[0].rank = index;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
obj.rank = index;
|
||||||
|
return obj;
|
||||||
|
}) as (GroupWithDeals | DealSummary)[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderDeal = (deal: DealSummary) => {
|
||||||
|
return (<Draggable
|
||||||
|
|
||||||
|
draggableId={deal.id.toString()}
|
||||||
|
index={deal.rank}
|
||||||
|
key={deal.id}>
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<div
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
ref={provided.innerRef}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transition: "transform 0.1s ease-in-out",
|
||||||
|
transform: snapshot.combineWith ? "scale(0.85)" : "none",
|
||||||
|
color: snapshot.combineWith ? "red" : "black",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DealSummaryCard
|
||||||
|
dealSummary={deal}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>);
|
||||||
|
};
|
||||||
|
const renderGroup = (obj: GroupWithDeals) => {
|
||||||
|
const { deals, group } = obj;
|
||||||
|
return (<Draggable
|
||||||
|
draggableId={"group-" + group.id}
|
||||||
|
index={deals[0].rank}
|
||||||
|
key={"group-" + group.id}
|
||||||
|
>
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
>
|
||||||
|
<DealGroupView
|
||||||
|
deals={deals}
|
||||||
|
group={group}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className={styles["container"]}>
|
<div className={styles["container"]}>
|
||||||
<div className={styles["header"]}>
|
<div className={styles["header"]}>
|
||||||
@@ -45,7 +149,9 @@ export const Board: FC<Props> = ({
|
|||||||
color={color}
|
color={color}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Droppable droppableId={droppableId}>
|
<Droppable
|
||||||
|
isCombineEnabled
|
||||||
|
droppableId={droppableId}>
|
||||||
{(provided, snapshot) => (
|
{(provided, snapshot) => (
|
||||||
<div
|
<div
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
@@ -53,30 +159,19 @@ export const Board: FC<Props> = ({
|
|||||||
styles["items-list"],
|
styles["items-list"],
|
||||||
snapshot.isDraggingOver &&
|
snapshot.isDraggingOver &&
|
||||||
!snapshot.draggingFromThisWith &&
|
!snapshot.draggingFromThisWith &&
|
||||||
styles["items-list-drag-over"]
|
styles["items-list-drag-over"],
|
||||||
)}
|
)}
|
||||||
{...provided.droppableProps}>
|
{...provided.droppableProps}>
|
||||||
{withCreateButton && (
|
{withCreateButton && (
|
||||||
<CreateDealButton onClick={() => {}} />
|
<CreateDealButton onClick={() => {
|
||||||
|
}} />
|
||||||
)}
|
)}
|
||||||
{summaries.map(summary => (
|
{getDealsAndGroups().map(obj => {
|
||||||
<Draggable
|
if (isGroup(obj)) {
|
||||||
draggableId={summary.id.toString()}
|
return renderGroup(obj);
|
||||||
index={summary.rank}
|
}
|
||||||
key={summary.id}>
|
return renderDeal(obj);
|
||||||
{provided => (
|
})}
|
||||||
<div
|
|
||||||
{...provided.draggableProps}
|
|
||||||
{...provided.dragHandleProps}
|
|
||||||
ref={provided.innerRef}>
|
|
||||||
<DealSummaryCard
|
|
||||||
dealSummary={summary}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Draggable>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -86,3 +181,4 @@ export const Board: FC<Props> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default Board;
|
export default Board;
|
||||||
|
|
||||||
|
|||||||
88
src/components/Dnd/DealGroupView/DealGroupView.tsx
Normal file
88
src/components/Dnd/DealGroupView/DealGroupView.tsx
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import { DealGroupSchema, DealService, DealSummary } from "../../../client";
|
||||||
|
import { FC, useEffect, useMemo, useState } from "react";
|
||||||
|
import DealSummaryCard from "../DealSummaryCard/DealSummaryCard.tsx";
|
||||||
|
import { Flex, rem, Text, TextInput, useMantineColorScheme } from "@mantine/core";
|
||||||
|
import { IconGripHorizontal } from "@tabler/icons-react";
|
||||||
|
import { useDebouncedValue } from "@mantine/hooks";
|
||||||
|
import { notifications } from "../../../shared/lib/notifications.ts";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
deals: DealSummary[];
|
||||||
|
group: DealGroupSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DealGroupView: FC<Props> = ({ deals, group }) => {
|
||||||
|
const theme = useMantineColorScheme();
|
||||||
|
const [name, setName] = useState<string>(group.name || "");
|
||||||
|
const [debouncedName] = useDebouncedValue(name, 200);
|
||||||
|
const totalPrice = useMemo(() => deals.reduce((acc, deal) => acc + deal.totalPrice, 0), [deals]);
|
||||||
|
const totalProducts = useMemo(() => deals.reduce((acc, deal) => acc + deal.totalProducts, 0), [deals]);
|
||||||
|
const updateName = () => {
|
||||||
|
if (debouncedName === group.name) return;
|
||||||
|
DealService.updateDealGroup({
|
||||||
|
requestBody: {
|
||||||
|
data: {
|
||||||
|
...group,
|
||||||
|
name: debouncedName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) return;
|
||||||
|
setName(group.name || "");
|
||||||
|
notifications.guess(response.ok, { message: response.message });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateName();
|
||||||
|
}, [debouncedName]);
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
style={{
|
||||||
|
border: "dashed var(--item-border-size) var(--mantine-color-default-border)",
|
||||||
|
borderRadius: "0.5rem",
|
||||||
|
}}
|
||||||
|
|
||||||
|
p={rem(5)}
|
||||||
|
py={rem(10)}
|
||||||
|
bg={theme.colorScheme === "dark" ? "var(--mantine-color-dark-5)" : "var(--mantine-color-gray-1)"}
|
||||||
|
gap={rem(10)}
|
||||||
|
direction={"column"}>
|
||||||
|
<Flex
|
||||||
|
justify={"space-between"}
|
||||||
|
align={"center"}
|
||||||
|
gap={rem(10)}
|
||||||
|
px={rem(10)}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
value={name}
|
||||||
|
onChange={event => setName(event.currentTarget.value)}
|
||||||
|
variant={"unstyled"}
|
||||||
|
/>
|
||||||
|
<IconGripHorizontal />
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={"column"} gap={rem(10)}>
|
||||||
|
{deals.map(deal => (
|
||||||
|
<DealSummaryCard
|
||||||
|
color={theme.colorScheme === "dark" ? "var(--mantine-color-dark-6)" : "var(--mantine-color-gray-2)"}
|
||||||
|
key={deal.id}
|
||||||
|
dealSummary={deal}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
p={rem(10)}
|
||||||
|
direction={"column"}
|
||||||
|
bg={theme.colorScheme === "dark" ? "var(--mantine-color-dark-6)" : "var(--mantine-color-gray-2)"}
|
||||||
|
style={{ borderRadius: "0.5rem" }}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
c={"gray.6"}
|
||||||
|
size={"xs"}>Сумма: {totalPrice.toLocaleString("ru-RU")} руб.</Text>
|
||||||
|
<Text
|
||||||
|
c={"gray.6"}
|
||||||
|
size={"xs"}>Всего товаров: {totalProducts.toLocaleString("ru-RU")} шт.</Text>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -13,20 +13,27 @@ import {
|
|||||||
Popover,
|
Popover,
|
||||||
rem,
|
rem,
|
||||||
Text,
|
Text,
|
||||||
|
ThemeIcon,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx";
|
import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { DealStatus } from "../../../shared/enums/DealStatus.ts";
|
import { DealStatus } from "../../../shared/enums/DealStatus.ts";
|
||||||
import { IconCheck } from "@tabler/icons-react";
|
import { IconCheck, IconLayoutGridRemove, IconTrash } from "@tabler/icons-react";
|
||||||
|
import { useContextMenu } from "mantine-contextmenu";
|
||||||
|
import useDealSummaryState from "./useDealSummaryState.tsx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dealSummary: DealSummary;
|
dealSummary: DealSummary;
|
||||||
|
color?: string
|
||||||
};
|
};
|
||||||
|
|
||||||
const DealSummaryCard: FC<Props> = ({ dealSummary }) => {
|
const DealSummaryCard: FC<Props> = ({ dealSummary, color }) => {
|
||||||
|
const { showContextMenu } = useContextMenu();
|
||||||
const { setSelectedDeal } = useDealPageContext();
|
const { setSelectedDeal } = useDealPageContext();
|
||||||
|
const { onDelete, onComplete, onDeleteFromGroup } = useDealSummaryState();
|
||||||
|
|
||||||
const onDealSummaryClick = () => {
|
const onDealSummaryClick = () => {
|
||||||
DealService.getDealById({ dealId: dealSummary.id }).then(deal => {
|
DealService.getDealById({ dealId: dealSummary.id }).then(deal => {
|
||||||
setSelectedDeal(deal);
|
setSelectedDeal(deal);
|
||||||
@@ -63,12 +70,36 @@ const DealSummaryCard: FC<Props> = ({ dealSummary }) => {
|
|||||||
<Indicator
|
<Indicator
|
||||||
position={"top-end"}
|
position={"top-end"}
|
||||||
withBorder
|
withBorder
|
||||||
|
size={15}
|
||||||
|
processing
|
||||||
{...getIndicatorProps()}
|
{...getIndicatorProps()}
|
||||||
>
|
>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
onContextMenu={showContextMenu([
|
||||||
|
...dealSummary.group ? [{
|
||||||
|
key: "removeFromGroup",
|
||||||
|
onClick: () => onDeleteFromGroup(dealSummary),
|
||||||
|
title: "Убрать из группы",
|
||||||
|
icon: <IconLayoutGridRemove />,
|
||||||
|
}] : [],
|
||||||
|
{
|
||||||
|
key: "complete",
|
||||||
|
onClick: () => onComplete(dealSummary),
|
||||||
|
title: "Завершить",
|
||||||
|
icon: <IconCheck />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "delete",
|
||||||
|
onClick: () => onDelete(dealSummary),
|
||||||
|
title: "Удалить",
|
||||||
|
icon: <IconTrash />,
|
||||||
|
},
|
||||||
|
])}
|
||||||
onClick={() => onDealSummaryClick()}
|
onClick={() => onDealSummaryClick()}
|
||||||
className={styles["container"]}>
|
className={styles["container"]}
|
||||||
|
style={{ backgroundColor: color }}
|
||||||
|
>
|
||||||
<Flex direction={"column"} flex={1} gap={rem(3)}>
|
<Flex direction={"column"} flex={1} gap={rem(3)}>
|
||||||
<Flex justify={"space-between"}>
|
<Flex justify={"space-between"}>
|
||||||
|
|
||||||
@@ -81,7 +112,9 @@ const DealSummaryCard: FC<Props> = ({ dealSummary }) => {
|
|||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Text c={"blue.5"} size={"sm"}>
|
<Text
|
||||||
|
c={"blue.5"}
|
||||||
|
size={"sm"}>
|
||||||
{dealSummary.name}
|
{dealSummary.name}
|
||||||
</Text>
|
</Text>
|
||||||
<Flex
|
<Flex
|
||||||
@@ -109,14 +142,14 @@ const DealSummaryCard: FC<Props> = ({ dealSummary }) => {
|
|||||||
<Flex direction={"column"}>
|
<Flex direction={"column"}>
|
||||||
{dealSummary.deliveryDate && (
|
{dealSummary.deliveryDate && (
|
||||||
<Text
|
<Text
|
||||||
c={"gray.6"}
|
c={"blue.5"}
|
||||||
size={"sm"}>
|
size={"sm"}>
|
||||||
Доставка: {(new Date(dealSummary.deliveryDate)).toLocaleDateString("ru-RU")}
|
Доставка: {(new Date(dealSummary.deliveryDate)).toLocaleDateString("ru-RU")}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
{dealSummary.receivingSlotDate && (
|
{dealSummary.receivingSlotDate && (
|
||||||
<Text
|
<Text
|
||||||
c={"gray.6"}
|
c={"blue.5"}
|
||||||
size={"sm"}>
|
size={"sm"}>
|
||||||
Слот: {(new Date(dealSummary.receivingSlotDate)).toLocaleDateString("ru-RU")}
|
Слот: {(new Date(dealSummary.receivingSlotDate)).toLocaleDateString("ru-RU")}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -163,8 +196,11 @@ const DealSummaryCard: FC<Props> = ({ dealSummary }) => {
|
|||||||
</CopyButton>
|
</CopyButton>
|
||||||
{dealSummary.billRequest?.paid && (
|
{dealSummary.billRequest?.paid && (
|
||||||
<Tooltip label={"Оплачен"}>
|
<Tooltip label={"Оплачен"}>
|
||||||
|
<ThemeIcon variant={"transparent"}>
|
||||||
<IconCheck />
|
<IconCheck />
|
||||||
|
</ThemeIcon>
|
||||||
|
|
||||||
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
|
|||||||
101
src/components/Dnd/DealSummaryCard/useDealSummaryState.tsx
Normal file
101
src/components/Dnd/DealSummaryCard/useDealSummaryState.tsx
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import { DealService, DealSummary } from "../../../client";
|
||||||
|
import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx";
|
||||||
|
import { modals } from "@mantine/modals";
|
||||||
|
import { Text } from "@mantine/core";
|
||||||
|
import { notifications } from "../../../shared/lib/notifications.ts";
|
||||||
|
|
||||||
|
const useDealSummaryState = () => {
|
||||||
|
const { refetchDeals } = useDealPageContext();
|
||||||
|
|
||||||
|
const recalculate = async (dealId: number) => {
|
||||||
|
return DealService.recalculateDealPrice({
|
||||||
|
requestBody: {
|
||||||
|
dealId: dealId,
|
||||||
|
},
|
||||||
|
}).then(({ ok, message }) => {
|
||||||
|
notifications.guess(ok, { message });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDelete = (summary: DealSummary) => {
|
||||||
|
modals.openConfirmModal({
|
||||||
|
title: "Удаление сделки",
|
||||||
|
children: (
|
||||||
|
<Text>
|
||||||
|
Вы уверены что хотите удалить сделку "{summary.name}"?
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
labels: { confirm: "Да", cancel: "Нет" },
|
||||||
|
confirmProps: { color: "red" },
|
||||||
|
onConfirm: () => {
|
||||||
|
DealService.deleteDeal({
|
||||||
|
requestBody: {
|
||||||
|
dealId: summary.id,
|
||||||
|
},
|
||||||
|
}).then(async (response) => {
|
||||||
|
notifications.guess(response.ok, { message: response.message });
|
||||||
|
if (response.ok) await refetchDeals();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onComplete = (summary: DealSummary) => {
|
||||||
|
modals.openConfirmModal({
|
||||||
|
title: "Удаление сделки",
|
||||||
|
children: (
|
||||||
|
<Text>
|
||||||
|
Вы уверены что хотите завершить сделку "{summary.name}"?
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
labels: { confirm: "Да", cancel: "Нет" },
|
||||||
|
confirmProps: { color: "green" },
|
||||||
|
onConfirm: () => {
|
||||||
|
DealService.completeDeal({
|
||||||
|
requestBody: {
|
||||||
|
dealId: summary.id,
|
||||||
|
},
|
||||||
|
}).then(async (response) => {
|
||||||
|
notifications.guess(response.ok, { message: response.message });
|
||||||
|
if (response.ok) await refetchDeals();
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteFromGroup = (summary: DealSummary) => {
|
||||||
|
modals.openConfirmModal({
|
||||||
|
title: "Удаление сделки",
|
||||||
|
children: (
|
||||||
|
<Text>
|
||||||
|
Вы уверены что хотите удалить сделку "{summary.name}" из группы?
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
labels: { confirm: "Да", cancel: "Нет" },
|
||||||
|
confirmProps: { color: "red" },
|
||||||
|
onConfirm: () => {
|
||||||
|
DealService.removeDealFromGroup({
|
||||||
|
requestBody: {
|
||||||
|
dealId: summary.id,
|
||||||
|
},
|
||||||
|
}).then(async (response) => {
|
||||||
|
notifications.guess(response.ok, { message: response.message });
|
||||||
|
if (response.ok) await refetchDeals();
|
||||||
|
await recalculate(summary.id);
|
||||||
|
if (response.ok) await refetchDeals();
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
onDelete,
|
||||||
|
onComplete,
|
||||||
|
onDeleteFromGroup,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useDealSummaryState;
|
||||||
10
src/main.tsx
10
src/main.tsx
@@ -1,5 +1,5 @@
|
|||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import { RouterProvider, createRouter } from "@tanstack/react-router";
|
import { createRouter, RouterProvider } from "@tanstack/react-router";
|
||||||
import { routeTree } from "./routeTree.gen";
|
import { routeTree } from "./routeTree.gen";
|
||||||
import { MantineProvider } from "@mantine/core";
|
import { MantineProvider } from "@mantine/core";
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
@@ -10,6 +10,8 @@ import "@mantine/core/styles.css";
|
|||||||
import "@mantine/notifications/styles.css";
|
import "@mantine/notifications/styles.css";
|
||||||
import "@mantine/dates/styles.css";
|
import "@mantine/dates/styles.css";
|
||||||
import "mantine-react-table/styles.css";
|
import "mantine-react-table/styles.css";
|
||||||
|
import "mantine-contextmenu/styles.css";
|
||||||
|
|
||||||
|
|
||||||
import "dayjs/locale/ru";
|
import "dayjs/locale/ru";
|
||||||
|
|
||||||
@@ -20,6 +22,7 @@ import { OpenAPI } from "./client";
|
|||||||
import { DatesProvider } from "@mantine/dates";
|
import { DatesProvider } from "@mantine/dates";
|
||||||
import { modals } from "./modals/modals.ts";
|
import { modals } from "./modals/modals.ts";
|
||||||
import TasksProvider from "./providers/TasksProvider/TasksProvider.tsx";
|
import TasksProvider from "./providers/TasksProvider/TasksProvider.tsx";
|
||||||
|
import { ContextMenuProvider } from "mantine-contextmenu";
|
||||||
|
|
||||||
// Configuring router
|
// Configuring router
|
||||||
const router = createRouter({ routeTree });
|
const router = createRouter({ routeTree });
|
||||||
@@ -47,6 +50,8 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
|||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<MantineProvider defaultColorScheme={"dark"}>
|
<MantineProvider defaultColorScheme={"dark"}>
|
||||||
|
<ContextMenuProvider>
|
||||||
|
|
||||||
<ModalsProvider
|
<ModalsProvider
|
||||||
labels={{ confirm: "Да", cancel: "Нет" }}
|
labels={{ confirm: "Да", cancel: "Нет" }}
|
||||||
modals={modals}>
|
modals={modals}>
|
||||||
@@ -57,7 +62,8 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
|||||||
</TasksProvider>
|
</TasksProvider>
|
||||||
</DatesProvider>
|
</DatesProvider>
|
||||||
</ModalsProvider>
|
</ModalsProvider>
|
||||||
|
</ContextMenuProvider>
|
||||||
</MantineProvider>
|
</MantineProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</Provider>
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { useMemo } from "react";
|
|||||||
import { DealServiceSchema } from "../../../../client";
|
import { DealServiceSchema } from "../../../../client";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
// onChange: (service: DealServiceSchema, quantity: number) => void;
|
|
||||||
data: DealServiceSchema[];
|
data: DealServiceSchema[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,11 +30,6 @@ export const useDealServicesTableColumns = (props: Props) => {
|
|||||||
accessorKey: "price",
|
accessorKey: "price",
|
||||||
header: "Цена",
|
header: "Цена",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
enableGrouping: false,
|
|
||||||
accessorKey: "service.cost",
|
|
||||||
header: "Себестоимость",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
enableGrouping: false,
|
enableGrouping: false,
|
||||||
accessorKey: "quantity",
|
accessorKey: "quantity",
|
||||||
|
|||||||
@@ -4,30 +4,40 @@ import { DealSchema } from "../../../client";
|
|||||||
type DealPageContextState = {
|
type DealPageContextState = {
|
||||||
selectedDeal?: DealSchema;
|
selectedDeal?: DealSchema;
|
||||||
setSelectedDeal: (deal: DealSchema | undefined) => void;
|
setSelectedDeal: (deal: DealSchema | undefined) => void;
|
||||||
|
refetchDeals: () => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DealPageContext = createContext<DealPageContextState | undefined>(
|
const DealPageContext = createContext<DealPageContextState | undefined>(
|
||||||
undefined
|
undefined,
|
||||||
);
|
);
|
||||||
const useDealPageContextState = () => {
|
|
||||||
|
type DealPageContextStateProps = {
|
||||||
|
refetchDeals: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useDealPageContextState = (props: DealPageContextStateProps) => {
|
||||||
|
const { refetchDeals } = props;
|
||||||
const [selectedDeal, setSelectedDeal] = useState<DealSchema | undefined>(
|
const [selectedDeal, setSelectedDeal] = useState<DealSchema | undefined>(
|
||||||
undefined
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedDeal,
|
selectedDeal,
|
||||||
setSelectedDeal,
|
setSelectedDeal,
|
||||||
|
refetchDeals,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type DealPageContextProviderProps = {
|
type DealPageContextProviderProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
refetchDeals: () => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DealPageContextProvider: FC<DealPageContextProviderProps> = ({
|
export const DealPageContextProvider: FC<DealPageContextProviderProps> = ({
|
||||||
children,
|
children,
|
||||||
|
refetchDeals,
|
||||||
}) => {
|
}) => {
|
||||||
const state = useDealPageContextState();
|
const state = useDealPageContextState({ refetchDeals });
|
||||||
return (
|
return (
|
||||||
<DealPageContext.Provider value={state}>
|
<DealPageContext.Provider value={state}>
|
||||||
{children}
|
{children}
|
||||||
@@ -39,7 +49,7 @@ export const useDealPageContext = () => {
|
|||||||
const context = useContext(DealPageContext);
|
const context = useContext(DealPageContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"useDealPageContext must be used within a DealPageContextProvider"
|
"useDealPageContext must be used within a DealPageContextProvider",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { useSelector } from "react-redux";
|
|||||||
import { RootState } from "../../../../../../redux/store.ts";
|
import { RootState } from "../../../../../../redux/store.ts";
|
||||||
import useDealProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
import useDealProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
||||||
import LockCheckbox from "../../../../../../components/LockCheckbox/LockCheckbox.tsx";
|
import LockCheckbox from "../../../../../../components/LockCheckbox/LockCheckbox.tsx";
|
||||||
|
import { useDebouncedCallback } from "@mantine/hooks";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
onKitAdd?: (kit: GetServiceKitSchema) => void;
|
onKitAdd?: (kit: GetServiceKitSchema) => void;
|
||||||
@@ -23,6 +24,10 @@ const DealServicesTable: FC<Props> = ({
|
|||||||
onChange,
|
onChange,
|
||||||
onKitAdd,
|
onKitAdd,
|
||||||
}) => {
|
}) => {
|
||||||
|
const debouncedOnChange = useDebouncedCallback(async (item: DealServiceSchema) => {
|
||||||
|
if (!onChange) return;
|
||||||
|
onChange(item);
|
||||||
|
}, 200);
|
||||||
const authState = useSelector((state: RootState) => state.auth);
|
const authState = useSelector((state: RootState) => state.auth);
|
||||||
|
|
||||||
const { dealState } = useDealProductAndServiceTabState();
|
const { dealState } = useDealProductAndServiceTabState();
|
||||||
@@ -39,7 +44,6 @@ const DealServicesTable: FC<Props> = ({
|
|||||||
};
|
};
|
||||||
const onCreateClick = () => {
|
const onCreateClick = () => {
|
||||||
if (!onCreate) return;
|
if (!onCreate) return;
|
||||||
console.log("228");
|
|
||||||
const serviceIds = items.map(service => service.service.id);
|
const serviceIds = items.map(service => service.service.id);
|
||||||
modals.openContextModal({
|
modals.openContextModal({
|
||||||
modal: "addDealService",
|
modal: "addDealService",
|
||||||
@@ -53,21 +57,21 @@ const DealServicesTable: FC<Props> = ({
|
|||||||
};
|
};
|
||||||
const onQuantityChange = (item: DealServiceSchema, quantity: number) => {
|
const onQuantityChange = (item: DealServiceSchema, quantity: number) => {
|
||||||
if (!onChange) return;
|
if (!onChange) return;
|
||||||
onChange({
|
debouncedOnChange({
|
||||||
...item,
|
...item,
|
||||||
quantity,
|
quantity,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const onPriceChange = (item: DealServiceSchema, price: number) => {
|
const onPriceChange = (item: DealServiceSchema, price: number) => {
|
||||||
if (!onChange) return;
|
if (!onChange) return;
|
||||||
onChange({
|
debouncedOnChange({
|
||||||
...item,
|
...item,
|
||||||
price,
|
price,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const onLockChange = (item: DealServiceSchema, isLocked: boolean) => {
|
const onLockChange = (item: DealServiceSchema, isLocked: boolean) => {
|
||||||
if (!onChange) return;
|
if (!onChange) return;
|
||||||
onChange({
|
debouncedOnChange({
|
||||||
...item,
|
...item,
|
||||||
isFixedPrice: isLocked,
|
isFixedPrice: isLocked,
|
||||||
});
|
});
|
||||||
@@ -91,7 +95,7 @@ const DealServicesTable: FC<Props> = ({
|
|||||||
};
|
};
|
||||||
const onEmployeesChange = (items: UserSchema[]) => {
|
const onEmployeesChange = (items: UserSchema[]) => {
|
||||||
if (!currentService || !onChange) return;
|
if (!currentService || !onChange) return;
|
||||||
onChange({
|
debouncedOnChange({
|
||||||
...currentService,
|
...currentService,
|
||||||
employees: items,
|
employees: items,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,14 +15,7 @@ const useProductServicesTableColumns = (props: Props) => {
|
|||||||
() => data.reduce((acc, row) => acc + row.price * quantity, 0),
|
() => data.reduce((acc, row) => acc + row.price * quantity, 0),
|
||||||
[data, quantity]
|
[data, quantity]
|
||||||
);
|
);
|
||||||
const totalCost = useMemo(
|
|
||||||
() =>
|
|
||||||
data.reduce(
|
|
||||||
(acc, row) => acc + (row.service.cost || 0) * quantity,
|
|
||||||
0
|
|
||||||
),
|
|
||||||
[data, quantity]
|
|
||||||
);
|
|
||||||
const hideGuestColumns = ["service.cost"];
|
const hideGuestColumns = ["service.cost"];
|
||||||
return useMemo<MRT_ColumnDef<DealProductServiceSchema>[]>(
|
return useMemo<MRT_ColumnDef<DealProductServiceSchema>[]>(
|
||||||
() => [
|
() => [
|
||||||
@@ -30,17 +23,6 @@ const useProductServicesTableColumns = (props: Props) => {
|
|||||||
accessorKey: "service.name",
|
accessorKey: "service.name",
|
||||||
header: "Услуга",
|
header: "Услуга",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
enableHiding: true,
|
|
||||||
accessorKey: "service.cost",
|
|
||||||
header: "Себестоимость",
|
|
||||||
Footer: () => (
|
|
||||||
<>
|
|
||||||
Итоговая себестоимость: {totalCost.toLocaleString("ru")}
|
|
||||||
₽
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accessorKey: "price",
|
accessorKey: "price",
|
||||||
header: "Цена",
|
header: "Цена",
|
||||||
|
|||||||
@@ -6,23 +6,14 @@ import {
|
|||||||
ProductSchema,
|
ProductSchema,
|
||||||
} from "../../../../../../client";
|
} from "../../../../../../client";
|
||||||
import styles from "./ProductView.module.css";
|
import styles from "./ProductView.module.css";
|
||||||
import {
|
import { ActionIcon, Box, Flex, Image, NumberInput, rem, Text, Title, Tooltip } from "@mantine/core";
|
||||||
ActionIcon,
|
|
||||||
Box,
|
|
||||||
Flex,
|
|
||||||
Image,
|
|
||||||
NumberInput,
|
|
||||||
rem,
|
|
||||||
Text,
|
|
||||||
Title,
|
|
||||||
Tooltip,
|
|
||||||
} from "@mantine/core";
|
|
||||||
import ProductServicesTable from "../ProductServicesTable/ProductServicesTable.tsx";
|
import ProductServicesTable from "../ProductServicesTable/ProductServicesTable.tsx";
|
||||||
import { isNil, isNumber } from "lodash";
|
import { isNil, isNumber } from "lodash";
|
||||||
import { IconBarcode, IconEdit, IconTrash } from "@tabler/icons-react";
|
import { IconBarcode, IconEdit, IconTrash } from "@tabler/icons-react";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import { ServiceType } from "../../../../../../shared/enums/ServiceType.ts";
|
import { ServiceType } from "../../../../../../shared/enums/ServiceType.ts";
|
||||||
import useDealProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
import useDealProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
||||||
|
import { useDebouncedCallback } from "@mantine/hooks";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
product: DealProductSchema;
|
product: DealProductSchema;
|
||||||
@@ -52,6 +43,10 @@ const ProductView: FC<Props> = ({
|
|||||||
onProductEdit,
|
onProductEdit,
|
||||||
}) => {
|
}) => {
|
||||||
const { dealState } = useDealProductAndServiceTabState();
|
const { dealState } = useDealProductAndServiceTabState();
|
||||||
|
const debouncedOnChange = useDebouncedCallback(async (item: DealProductSchema) => {
|
||||||
|
if (!onChange) return;
|
||||||
|
onChange(item);
|
||||||
|
}, 200);
|
||||||
const isLocked = Boolean(dealState.deal?.billRequest);
|
const isLocked = Boolean(dealState.deal?.billRequest);
|
||||||
const onDeleteClick = () => {
|
const onDeleteClick = () => {
|
||||||
if (!onDelete) return;
|
if (!onDelete) return;
|
||||||
@@ -87,7 +82,7 @@ const ProductView: FC<Props> = ({
|
|||||||
|
|
||||||
const onQuantityChange = (quantity: number) => {
|
const onQuantityChange = (quantity: number) => {
|
||||||
if (!onChange) return;
|
if (!onChange) return;
|
||||||
onChange({
|
debouncedOnChange({
|
||||||
...product,
|
...product,
|
||||||
quantity,
|
quantity,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
import { CRUDTableProps } from "../../../../../types/CRUDTable.tsx";
|
import { CRUDTableProps } from "../../../../../types/CRUDTable.tsx";
|
||||||
import {
|
import { DealProductSchema, DealService, DealServiceSchema } from "../../../../../client";
|
||||||
DealProductSchema,
|
|
||||||
DealService,
|
|
||||||
DealServiceSchema,
|
|
||||||
} from "../../../../../client";
|
|
||||||
import { useDealPageContext } from "../../../contexts/DealPageContext.tsx";
|
import { useDealPageContext } from "../../../contexts/DealPageContext.tsx";
|
||||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||||
|
|
||||||
@@ -11,23 +7,29 @@ const useDealState = () => {
|
|||||||
|
|
||||||
const { selectedDeal, setSelectedDeal } = useDealPageContext();
|
const { selectedDeal, setSelectedDeal } = useDealPageContext();
|
||||||
const recalculate = async () => {
|
const recalculate = async () => {
|
||||||
|
|
||||||
return DealService.recalculateDealPrice({
|
return DealService.recalculateDealPrice({
|
||||||
requestBody: {
|
requestBody: {
|
||||||
dealId: selectedDeal?.id || -1,
|
dealId: selectedDeal?.id || -1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const refetch = async () => {
|
const refetchDeal = async () => {
|
||||||
if (!selectedDeal) return;
|
if (!selectedDeal) return;
|
||||||
const { ok, message } = await recalculate();
|
|
||||||
if (!ok) notifications.guess(ok, { message });
|
|
||||||
return DealService.getDealById({ dealId: selectedDeal.id }).then(
|
return DealService.getDealById({ dealId: selectedDeal.id }).then(
|
||||||
deal => {
|
async deal => {
|
||||||
setSelectedDeal(deal);
|
setSelectedDeal(deal);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
const refetch = async () => {
|
||||||
|
if (!selectedDeal) return;
|
||||||
|
await refetchDeal();
|
||||||
|
const { ok, message } = await recalculate();
|
||||||
|
if (!ok) notifications.guess(ok, { message });
|
||||||
|
|
||||||
|
await refetchDeal();
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
deal: selectedDeal,
|
deal: selectedDeal,
|
||||||
refetch,
|
refetch,
|
||||||
|
|||||||
@@ -44,6 +44,16 @@ export const LeadsPage: FC = () => {
|
|||||||
setSummaries(summariesRaw);
|
setSummaries(summariesRaw);
|
||||||
}, [summariesRaw]);
|
}, [summariesRaw]);
|
||||||
|
|
||||||
|
const recalculate = async (dealId: number) => {
|
||||||
|
return DealService.recalculateDealPrice({
|
||||||
|
requestBody: {
|
||||||
|
dealId: dealId,
|
||||||
|
},
|
||||||
|
}).then(({ ok, message }) => {
|
||||||
|
notifications.guess(ok, { message });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onDelete = (dealId: number) => {
|
const onDelete = (dealId: number) => {
|
||||||
const summary = summaries.find(summary => summary.id == dealId);
|
const summary = summaries.find(summary => summary.id == dealId);
|
||||||
if (!summary) return;
|
if (!summary) return;
|
||||||
@@ -94,12 +104,79 @@ export const LeadsPage: FC = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const onCombine = async (result: DropResult) => {
|
||||||
|
if (!result.combine) return;
|
||||||
|
const destination = result.combine.draggableId;
|
||||||
|
const source = result.draggableId;
|
||||||
|
if (!destination || !source) return;
|
||||||
|
const sourceId = parseInt(source);
|
||||||
|
if (destination.includes("group")) {
|
||||||
|
const groupId = parseInt(destination.split("-")[1]);
|
||||||
|
DealService.addDealToGroup({
|
||||||
|
requestBody: {
|
||||||
|
dealId: sourceId,
|
||||||
|
groupId: groupId,
|
||||||
|
},
|
||||||
|
}).then(async response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
notifications.error({ message: response.message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await refetch();
|
||||||
|
await recalculate(sourceId);
|
||||||
|
await refetch();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const destinationId = parseInt(destination);
|
||||||
|
// creating new group
|
||||||
|
DealService.createDealGroup({
|
||||||
|
requestBody: {
|
||||||
|
draggingDealId: sourceId,
|
||||||
|
hoveredDealId: destinationId,
|
||||||
|
},
|
||||||
|
}).then(async response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
notifications.error({ message: response.message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await refetch();
|
||||||
|
await recalculate(sourceId);
|
||||||
|
await refetch();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const moveGroup = async (result: DropResult) => {
|
||||||
|
const groupId = parseInt(result.draggableId.split("-")[1]);
|
||||||
|
const destination = result.destination?.droppableId;
|
||||||
|
if (!destination) return;
|
||||||
|
const status = getDealStatusByName(destination);
|
||||||
|
DealService.changeDealGroupStatus({
|
||||||
|
requestBody: {
|
||||||
|
groupId: groupId,
|
||||||
|
newStatus: status,
|
||||||
|
},
|
||||||
|
}).then(async response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
notifications.error({ message: response.message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await refetch();
|
||||||
|
});
|
||||||
|
};
|
||||||
const onDragEnd = async (result: DropResult) => {
|
const onDragEnd = async (result: DropResult) => {
|
||||||
|
|
||||||
|
if (result.combine) {
|
||||||
|
return onCombine(result);
|
||||||
|
}
|
||||||
setIsDragEnded(true);
|
setIsDragEnded(true);
|
||||||
// If there is no changes
|
// If there is no changes
|
||||||
if (!result.destination || result.destination == result.source) return;
|
if (!result.destination || result.destination == result.source) return;
|
||||||
|
|
||||||
// Checking for valid dealId
|
// Checking for valid dealId
|
||||||
|
if (result.draggableId.includes("group")) {
|
||||||
|
return moveGroup(result);
|
||||||
|
}
|
||||||
const dealId = parseInt(result.draggableId);
|
const dealId = parseInt(result.draggableId);
|
||||||
if (isNaN(dealId)) return;
|
if (isNaN(dealId)) return;
|
||||||
|
|
||||||
@@ -317,7 +394,9 @@ export const LeadsPage: FC = () => {
|
|||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
boxShadow: "none",
|
boxShadow: "none",
|
||||||
}}>
|
}}>
|
||||||
<DealPageContextProvider>
|
<DealPageContextProvider refetchDeals={async () => {
|
||||||
|
await refetch();
|
||||||
|
}}>
|
||||||
<PrefillDealContextProvider>
|
<PrefillDealContextProvider>
|
||||||
<PageBlock style={{ flex: 0 }}>
|
<PageBlock style={{ flex: 0 }}>
|
||||||
<Flex
|
<Flex
|
||||||
|
|||||||
Reference in New Issue
Block a user