feat: total services amount and recalculating
This commit is contained in:
@@ -10,7 +10,7 @@ import { ContextModalProps } from "@mantine/modals";
|
||||
import { useForm, UseFormReturnType } from "@mantine/form";
|
||||
import { isNil, isNumber } from "lodash";
|
||||
import ServiceWithPriceInput from "../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
|
||||
import { Flex } from "@mantine/core";
|
||||
import { Checkbox, Flex, rem } from "@mantine/core";
|
||||
import { ServiceType } from "../../../shared/enums/ServiceType.ts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../../redux/store.ts";
|
||||
@@ -23,20 +23,21 @@ type RestProps = {
|
||||
type Props = CreateEditFormProps<DealProductServiceSchema> & RestProps;
|
||||
|
||||
const ProductServiceFormModal = ({
|
||||
context,
|
||||
id,
|
||||
innerProps,
|
||||
}: ContextModalProps<Props>) => {
|
||||
context,
|
||||
id,
|
||||
innerProps,
|
||||
}: ContextModalProps<Props>) => {
|
||||
const authState = useSelector((state: RootState) => state.auth);
|
||||
|
||||
const isEditing = "onChange" in innerProps;
|
||||
const initialValues: Partial<DealProductServiceSchema> = isEditing
|
||||
? innerProps.element
|
||||
: {
|
||||
service: undefined,
|
||||
price: undefined,
|
||||
employees: [],
|
||||
};
|
||||
service: undefined,
|
||||
price: undefined,
|
||||
employees: [],
|
||||
isFixedPrice: false,
|
||||
};
|
||||
const form = useForm<Partial<DealProductServiceSchema>>({
|
||||
initialValues,
|
||||
validate: {
|
||||
@@ -57,7 +58,7 @@ const ProductServiceFormModal = ({
|
||||
closeOnSubmit>
|
||||
<BaseFormModal.Body>
|
||||
<>
|
||||
<Flex w={"100%"}>
|
||||
<Flex w={"100%"} direction={"column"} gap={rem(10)}>
|
||||
<ServiceWithPriceInput
|
||||
category={innerProps.category}
|
||||
serviceProps={{
|
||||
@@ -85,6 +86,11 @@ const ProductServiceFormModal = ({
|
||||
lockOnEdit={isEditing}
|
||||
quantity={innerProps.quantity}
|
||||
/>
|
||||
<Checkbox
|
||||
{...form.getInputProps("isFixedPrice", { type: "checkbox" })}
|
||||
label={"Зафиксировать цену"}
|
||||
placeholder={"Зафиксировать цену"}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
</BaseFormModal.Body>
|
||||
|
||||
@@ -1,21 +1,7 @@
|
||||
import { CRUDTableProps } from "../../../../../../types/CRUDTable.tsx";
|
||||
import {
|
||||
DealServiceSchema,
|
||||
GetServiceKitSchema,
|
||||
UserSchema,
|
||||
} from "../../../../../../client";
|
||||
import { DealServiceSchema, GetServiceKitSchema, UserSchema } from "../../../../../../client";
|
||||
import { FC, useState } from "react";
|
||||
import {
|
||||
ActionIcon,
|
||||
Button,
|
||||
Flex,
|
||||
Modal,
|
||||
NumberInput,
|
||||
rem,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import { ActionIcon, Button, Flex, Modal, NumberInput, rem, Text, Title, Tooltip } from "@mantine/core";
|
||||
import { IconTrash, IconUsersGroup } from "@tabler/icons-react";
|
||||
import { modals } from "@mantine/modals";
|
||||
import { isNumber } from "lodash";
|
||||
@@ -24,18 +10,19 @@ import { ServiceType } from "../../../../../../shared/enums/ServiceType.ts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../../../../../redux/store.ts";
|
||||
import useDealProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
||||
import LockCheckbox from "../../../../../../components/LockCheckbox/LockCheckbox.tsx";
|
||||
|
||||
type RestProps = {
|
||||
onKitAdd?: (kit: GetServiceKitSchema) => void;
|
||||
};
|
||||
type Props = CRUDTableProps<DealServiceSchema> & RestProps;
|
||||
const DealServicesTable: FC<Props> = ({
|
||||
items,
|
||||
onDelete,
|
||||
onCreate,
|
||||
onChange,
|
||||
onKitAdd,
|
||||
}) => {
|
||||
items,
|
||||
onDelete,
|
||||
onCreate,
|
||||
onChange,
|
||||
onKitAdd,
|
||||
}) => {
|
||||
const authState = useSelector((state: RootState) => state.auth);
|
||||
|
||||
const { dealState } = useDealProductAndServiceTabState();
|
||||
@@ -78,7 +65,13 @@ const DealServicesTable: FC<Props> = ({
|
||||
price,
|
||||
});
|
||||
};
|
||||
|
||||
const onLockChange = (item: DealServiceSchema, isLocked: boolean) => {
|
||||
if (!onChange) return;
|
||||
onChange({
|
||||
...item,
|
||||
isFixedPrice: isLocked,
|
||||
});
|
||||
};
|
||||
const onEmployeeClick = (item: DealServiceSchema) => {
|
||||
if (!onChange) return;
|
||||
setCurrentService(item);
|
||||
@@ -91,7 +84,7 @@ const DealServicesTable: FC<Props> = ({
|
||||
const getCurrentEmployees = (): UserSchema[] => {
|
||||
if (!currentService) return [];
|
||||
const item = items.find(
|
||||
i => i.service.id === currentService.service.id
|
||||
i => i.service.id === currentService.service.id,
|
||||
);
|
||||
if (!item) return [];
|
||||
return item.employees;
|
||||
@@ -169,7 +162,9 @@ const DealServicesTable: FC<Props> = ({
|
||||
isNumber(event) &&
|
||||
onQuantityChange(service, event)
|
||||
}
|
||||
|
||||
value={service.quantity}
|
||||
|
||||
/>
|
||||
<NumberInput
|
||||
flex={1}
|
||||
@@ -179,7 +174,22 @@ const DealServicesTable: FC<Props> = ({
|
||||
}
|
||||
suffix={"₽"}
|
||||
value={service.price}
|
||||
disabled={authState.isGuest || isLocked}
|
||||
disabled={authState.isGuest || isLocked || service.isFixedPrice}
|
||||
rightSectionProps={{
|
||||
style: {
|
||||
display: "flex",
|
||||
cursor: "pointer",
|
||||
pointerEvents: "auto",
|
||||
},
|
||||
}}
|
||||
rightSection={
|
||||
<LockCheckbox
|
||||
label={"Зафиксировать цену"}
|
||||
variant={"default"}
|
||||
value={service.isFixedPrice}
|
||||
onChange={value => onLockChange(service, value)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
))}
|
||||
@@ -192,7 +202,7 @@ const DealServicesTable: FC<Props> = ({
|
||||
Итог:{" "}
|
||||
{items.reduce(
|
||||
(acc, item) => acc + item.price * item.quantity,
|
||||
0
|
||||
0,
|
||||
)}
|
||||
₽
|
||||
</Title>
|
||||
|
||||
@@ -8,13 +8,24 @@ import { useDealPageContext } from "../../../contexts/DealPageContext.tsx";
|
||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||
|
||||
const useDealState = () => {
|
||||
|
||||
const { selectedDeal, setSelectedDeal } = useDealPageContext();
|
||||
const recalculate = async () => {
|
||||
|
||||
return DealService.recalculateDealPrice({
|
||||
requestBody: {
|
||||
dealId: selectedDeal?.id || -1,
|
||||
},
|
||||
});
|
||||
};
|
||||
const refetch = async () => {
|
||||
if (!selectedDeal) return;
|
||||
const { ok, message } = await recalculate();
|
||||
if (!ok) notifications.guess(ok, { message });
|
||||
return DealService.getDealById({ dealId: selectedDeal.id }).then(
|
||||
deal => {
|
||||
setSelectedDeal(deal);
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
return {
|
||||
@@ -25,6 +36,9 @@ const useDealState = () => {
|
||||
|
||||
const useDealServicesState = (): CRUDTableProps<DealServiceSchema> => {
|
||||
const { deal, refetch } = useDealState();
|
||||
const refetchAndRecalculate = async () => {
|
||||
await refetch();
|
||||
};
|
||||
const onCreate = (item: DealServiceSchema) => {
|
||||
if (!deal) return;
|
||||
DealService.addDealService({
|
||||
@@ -36,7 +50,7 @@ const useDealServicesState = (): CRUDTableProps<DealServiceSchema> => {
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) notifications.guess(ok, { message });
|
||||
if (ok) await refetch();
|
||||
if (ok) await refetchAndRecalculate();
|
||||
});
|
||||
};
|
||||
const onDelete = (item: DealServiceSchema) => {
|
||||
@@ -48,7 +62,7 @@ const useDealServicesState = (): CRUDTableProps<DealServiceSchema> => {
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) notifications.guess(ok, { message });
|
||||
if (ok) await refetch();
|
||||
if (ok) await refetchAndRecalculate();
|
||||
});
|
||||
};
|
||||
const onChange = (item: DealServiceSchema) => {
|
||||
@@ -60,7 +74,7 @@ const useDealServicesState = (): CRUDTableProps<DealServiceSchema> => {
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) notifications.guess(ok, { message });
|
||||
if (ok) await refetch();
|
||||
if (ok) await refetchAndRecalculate();
|
||||
});
|
||||
};
|
||||
return {
|
||||
@@ -73,6 +87,9 @@ const useDealServicesState = (): CRUDTableProps<DealServiceSchema> => {
|
||||
|
||||
const useDealProductsState = (): CRUDTableProps<DealProductSchema> => {
|
||||
const { deal, refetch } = useDealState();
|
||||
const refetchAndRecalculate = async () => {
|
||||
await refetch();
|
||||
};
|
||||
const onCreate = (item: DealProductSchema) => {
|
||||
if (!deal) return;
|
||||
DealService.addDealProduct({
|
||||
@@ -82,7 +99,7 @@ const useDealProductsState = (): CRUDTableProps<DealProductSchema> => {
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) notifications.guess(ok, { message });
|
||||
if (ok) await refetch();
|
||||
if (ok) await refetchAndRecalculate();
|
||||
});
|
||||
};
|
||||
const onDelete = (item: DealProductSchema) => {
|
||||
@@ -94,7 +111,7 @@ const useDealProductsState = (): CRUDTableProps<DealProductSchema> => {
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) notifications.guess(ok, { message });
|
||||
if (ok) await refetch();
|
||||
if (ok) await refetchAndRecalculate();
|
||||
});
|
||||
};
|
||||
const onChange = (item: DealProductSchema) => {
|
||||
@@ -106,7 +123,7 @@ const useDealProductsState = (): CRUDTableProps<DealProductSchema> => {
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) notifications.guess(ok, { message });
|
||||
if (ok) await refetch();
|
||||
if (ok) await refetchAndRecalculate();
|
||||
});
|
||||
};
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user