feat: removed price categories

This commit is contained in:
2025-02-12 15:28:17 +04:00
parent 648fffeb46
commit cc3e72bf94
34 changed files with 10 additions and 575 deletions

View File

@@ -174,14 +174,6 @@ const Content: FC<Props> = ({ deal }) => {
{...form.getInputProps("status")}
label={"Статус"}
/>
{deal.category && (
<TextInput
disabled
placeholder={"Категория"}
label={"Категория"}
value={deal.category.name}
/>
)}
<Textarea
h={rem(150)}
styles={{

View File

@@ -1,15 +1,8 @@
import { ContextModalProps } from "@mantine/modals";
import BaseFormModal, {
CreateEditFormProps,
} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
import { DealServiceSchema, ServicePriceCategorySchema } from "../../../client";
import BaseFormModal, { CreateEditFormProps } from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
import { DealServiceSchema } from "../../../client";
import { useForm } from "@mantine/form";
import {
ComboboxItem,
ComboboxItemGroup,
NumberInput,
OptionsFilter,
} from "@mantine/core";
import { ComboboxItem, ComboboxItemGroup, NumberInput, OptionsFilter } from "@mantine/core";
import ServiceWithPriceInput from "../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
import { ServiceType } from "../../../shared/enums/ServiceType.ts";
import { useSelector } from "react-redux";
@@ -17,7 +10,6 @@ import { RootState } from "../../../redux/store.ts";
type RestProps = {
serviceIds?: number[];
category?: ServicePriceCategorySchema;
};
type Props = CreateEditFormProps<Partial<DealServiceSchema>> & RestProps;
const AddDealServiceModal = ({
@@ -26,7 +18,6 @@ const AddDealServiceModal = ({
innerProps,
}: ContextModalProps<Props>) => {
const authState = useSelector((state: RootState) => state.auth);
console.log(innerProps.category);
const isEditing = "element" in innerProps;
const form = useForm<Partial<DealServiceSchema>>({
initialValues: isEditing
@@ -77,7 +68,6 @@ const AddDealServiceModal = ({
<BaseFormModal.Body>
<>
<ServiceWithPriceInput
category={innerProps.category}
serviceProps={{
...form.getInputProps("service"),
label: "Услуга",

View File

@@ -3,7 +3,6 @@ import BaseFormModal, {
} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
import {
DealProductServiceSchema,
ServicePriceCategorySchema,
ServiceSchema,
} from "../../../client";
import { ContextModalProps } from "@mantine/modals";
@@ -18,7 +17,6 @@ import { RootState } from "../../../redux/store.ts";
type RestProps = {
quantity: number;
serviceIds: number[];
category?: ServicePriceCategorySchema;
};
type Props = CreateEditFormProps<DealProductServiceSchema> & RestProps;
@@ -60,7 +58,6 @@ const ProductServiceFormModal = ({
<>
<Flex w={"100%"} direction={"column"} gap={rem(10)}>
<ServiceWithPriceInput
category={innerProps.category}
serviceProps={{
...form.getInputProps("service"),
label: "Услуга",

View File

@@ -50,7 +50,6 @@ const DealServicesTable: FC<Props> = ({
innerProps: {
onCreate: onCreate,
serviceIds,
category: dealState.deal?.category || undefined,
},
withCloseButton: false,
});

View File

@@ -48,7 +48,6 @@ const ProductServicesTable: FC<Props> = ({
onCreate: onCreate,
serviceIds,
quantity,
category: dealState.deal?.category || undefined,
},
withCloseButton: false,
});
@@ -63,7 +62,6 @@ const ProductServicesTable: FC<Props> = ({
onChange,
serviceIds,
quantity,
category: dealState.deal?.category || undefined,
},
withCloseButton: false,
});

View File

@@ -1,53 +0,0 @@
import { CRUDTableProps } from "../../../../types/CRUDTable.tsx";
import { ServicePriceCategorySchema } from "../../../../client";
import { FC } from "react";
import { BaseTable } from "../../../../components/BaseTable/BaseTable.tsx";
import useServicePriceCategoryTableColumns from "./columns.tsx";
import { MRT_TableOptions } from "mantine-react-table";
import { ActionIcon, Flex, Tooltip } from "@mantine/core";
import { IconEdit, IconTrash } from "@tabler/icons-react";
type Props = CRUDTableProps<ServicePriceCategorySchema>;
const ServicePriceCategoryTable: FC<Props> = ({
items,
onChange,
onDelete,
}) => {
const columns = useServicePriceCategoryTableColumns();
return (
<BaseTable
data={items}
columns={columns}
restProps={
{
enableRowActions: true,
renderRowActions: ({ row }) => (
<Flex gap="md">
<Tooltip label="Редактировать">
<ActionIcon
onClick={() =>
onChange && onChange(row.original)
}
variant={"default"}>
<IconEdit />
</ActionIcon>
</Tooltip>
<Tooltip label="Удалить">
<ActionIcon
onClick={() =>
onDelete && onDelete(row.original)
}
variant={"default"}>
<IconTrash />
</ActionIcon>
</Tooltip>
</Flex>
),
} as MRT_TableOptions<ServicePriceCategorySchema>
}
/>
);
};
export default ServicePriceCategoryTable;

View File

@@ -1,19 +0,0 @@
import { useMemo } from "react";
import { MRT_ColumnDef } from "mantine-react-table";
import { ServicePriceCategorySchema } from "../../../../client";
const useServicePriceCategoryTableColumns = () => {
return useMemo<MRT_ColumnDef<ServicePriceCategorySchema>[]>(
() => [
{
accessorKey: "name",
header: "Название",
enableColumnActions: false,
enableSorting: false,
},
],
[]
);
};
export default useServicePriceCategoryTableColumns;

View File

@@ -1,70 +0,0 @@
import { BaseFormInputProps } from "../../../../types/utils.ts";
import type {
ServiceCategoryPriceSchema,
ServicePriceCategorySchema,
} from "../../../../client";
import { FC, useEffect, useState } from "react";
import { Flex, NumberInput, rem } from "@mantine/core";
import ServicePriceCategorySelect from "../../../../components/Selects/ServicePriceCategorySelect/ServicePriceCategorySelect.tsx";
export type PriceCategoryInputProps = BaseFormInputProps<
ServiceCategoryPriceSchema[]
>;
const PriceCategoryInput: FC<PriceCategoryInputProps> = (
props: PriceCategoryInputProps
) => {
const [innerState, setInnerState] = useState<ServiceCategoryPriceSchema[]>(
props.value || []
);
const [category, setCategory] = useState<
ServicePriceCategorySchema | undefined
>(undefined);
const getValue = (): number | undefined | string => {
if (category === undefined) return undefined;
const value = innerState.find(item => item.category.id === category.id);
return value?.price || "";
};
const handleChange = (value: number | string) => {
// remove value if is string
if (typeof value === "string") {
setInnerState(
innerState.filter(item => item.category.id !== category?.id)
);
return;
}
const newValue = {
category: category as ServicePriceCategorySchema,
price: value,
};
const newInnerState = innerState.filter(
item => item.category.id !== category?.id
);
setInnerState([...newInnerState, newValue]);
};
useEffect(() => {
if (props.value === innerState) return;
props.onChange(innerState);
}, [innerState]);
return (
<Flex
direction={"column"}
gap={rem(10)}>
<ServicePriceCategorySelect
label={"Категория цены"}
placeholder={"Выберите категорию цены"}
onChange={setCategory}
/>
<NumberInput
label={"Цена"}
placeholder={"Введите цену"}
value={getValue()}
onChange={handleChange}
/>
</Flex>
);
};
export default PriceCategoryInput;

View File

@@ -5,7 +5,6 @@ import { omit } from "lodash";
export enum ServicePriceType {
DEFAULT,
BY_RANGE,
BY_CATEGORY,
}
type RestProps = {
@@ -26,10 +25,6 @@ const ServicePriceTypeSegmentedControl: FC<Props> = props => {
label: "По диапазону",
value: ServicePriceType.BY_RANGE.toString(),
},
{
label: "По категории",
value: ServicePriceType.BY_CATEGORY.toString(),
},
];
const handleChange = (value: string) => {
onChange(Number(value));

View File

@@ -5,7 +5,6 @@ export enum ServicesTab {
DEAL_SERVICE,
PRODUCT_SERVICE,
SERVICES_KITS,
SERVICES_PRICE_CATEGORIES,
}
type Props = Omit<SegmentedControlProps, "data">;
@@ -22,10 +21,6 @@ const data = [
label: "Наборы услуг",
value: ServicesTab.SERVICES_KITS.toString(),
},
{
label: "Категории цен",
value: ServicesTab.SERVICES_PRICE_CATEGORIES.toString(),
},
];
const ServiceTypeSegmentedControl: FC<Props> = props => {
return (

View File

@@ -1,11 +0,0 @@
import ObjectList from "../../../hooks/objectList.tsx";
import { ServiceService } from "../../../client";
const useServicePriceCategoriesList = () =>
ObjectList({
queryFn: ServiceService.getAllPriceCategories,
getObjectsFn: response => response.priceCategories,
queryKey: "getAllPriceCategories",
});
export default useServicePriceCategoriesList;

View File

@@ -1,83 +0,0 @@
import UseObjectState from "../../../types/UseObjectState.ts";
import {
type ServicePriceCategorySchema,
ServiceService,
} from "../../../client";
import useServicePriceCategoriesList from "./useServicePriceCategoriesList.tsx";
import { modals } from "@mantine/modals";
import { notifications } from "../../../shared/lib/notifications.ts";
const useServicePriceCategoryState =
(): UseObjectState<ServicePriceCategorySchema> => {
const { objects, refetch } = useServicePriceCategoriesList();
const onCreateClick = () => {
modals.openContextModal({
modal: "servicePriceCategoryForm",
title: "Создание категории цен",
withCloseButton: false,
innerProps: {
onCreate,
},
});
};
const onCreate = (values: ServicePriceCategorySchema) => {
console.log(ServiceService);
ServiceService.createPriceCategory({
requestBody: {
name: values.name,
},
}).then(async ({ ok, message }) => {
notifications.guess(ok, { message: message });
if (!ok) return;
await refetch();
});
};
const onDelete = (item: ServicePriceCategorySchema) => {
modals.openConfirmModal({
title: "Удаление категории",
children: "Вы уверены, что хотите удалить категорию?",
onConfirm: () => {
ServiceService.deletePriceCategory({
requestBody: {
id: item.id,
},
}).then(async ({ ok, message }) => {
notifications.guess(ok, { message: message });
if (!ok) return;
await refetch();
});
},
});
};
const onChange = (item: ServicePriceCategorySchema) => {
modals.openContextModal({
modal: "servicePriceCategoryForm",
title: "Изменение категории цен",
withCloseButton: false,
innerProps: {
onChange: (values: ServicePriceCategorySchema) => {
ServiceService.updatePriceCategory({
requestBody: {
id: item.id,
name: values.name,
},
}).then(async ({ ok, message }) => {
notifications.guess(ok, { message: message });
if (!ok) return;
await refetch();
});
},
element: item,
},
});
};
return {
onCreateClick,
onCreate,
onDelete,
onChange,
objects,
};
};
export default useServicePriceCategoryState;

View File

@@ -1,9 +1,7 @@
import { ServicePriceRangeSchema, ServiceSchema } from "../../../client";
import { useForm } from "@mantine/form";
import { ContextModalProps } from "@mantine/modals";
import BaseFormModal, {
CreateEditFormProps,
} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
import BaseFormModal, { CreateEditFormProps } from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
import { Fieldset, Flex, rem, TextInput } from "@mantine/core";
import ServiceCategorySelect from "../components/ServiceCategorySelect/ServiceCategorySelect.tsx";
import ServiceTypeSelect from "../components/ServiceTypeSelect/ServiceTypeSelect.tsx";
@@ -11,13 +9,8 @@ import ServicePriceTypeSegmentedControl, {
ServicePriceType,
} from "../components/ServicePriceTypeSegmentedControl/ServicePriceTypeSegmentedControl.tsx";
import { useEffect, useState } from "react";
import RangePriceInput, {
PriceRangeInputType,
} from "../components/ServicePriceInput/RangePriceInput.tsx";
import RangePriceInput, { PriceRangeInputType } from "../components/ServicePriceInput/RangePriceInput.tsx";
import SinglePriceInput from "../components/ServicePriceInput/SinglePriceInput.tsx";
import PriceCategoryInput, {
PriceCategoryInputProps,
} from "../components/ServicePriceInput/PriceCategoryInput.tsx";
type Props = CreateEditFormProps<ServiceSchema>;
const CreateServiceModal = ({
@@ -44,7 +37,6 @@ const CreateServiceModal = ({
serviceType: -1,
priceRanges: [] as ServicePriceRangeSchema[],
cost: null,
categoryPrices: [],
rank: "",
};
@@ -89,14 +81,6 @@ const CreateServiceModal = ({
) as PriceRangeInputType)}
/>
);
case ServicePriceType.BY_CATEGORY:
return (
<PriceCategoryInput
{...(form.getInputProps(
"categoryPrices",
) as PriceCategoryInputProps)}
/>
);
}
};
const onCancelClick = () => {

View File

@@ -1,44 +0,0 @@
import { ServicePriceCategorySchema } from "../../../client";
import BaseFormModal, {
CreateEditFormProps,
} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
import { ContextModalProps } from "@mantine/modals";
import { TextInput } from "@mantine/core";
import { useForm } from "@mantine/form";
type Props = CreateEditFormProps<ServicePriceCategorySchema>;
const ServicePriceCategoryForm = ({
context,
id,
innerProps,
}: ContextModalProps<Props>) => {
const isEditing = "element" in innerProps;
const initialValues: Partial<ServicePriceCategorySchema> = isEditing
? innerProps.element
: {
name: "",
};
const form = useForm<Partial<ServicePriceCategorySchema>>({
initialValues,
});
return (
<BaseFormModal
{...innerProps}
form={form}
closeOnSubmit
onClose={() => context.closeContextModal(id)}>
<BaseFormModal.Body>
<>
<TextInput
label={"Название"}
placeholder={"Введите название категории"}
{...form.getInputProps("name")}
/>
</>
</BaseFormModal.Body>
</BaseFormModal>
);
};
export default ServicePriceCategoryForm;

View File

@@ -7,11 +7,8 @@ import ServiceTypeSegmentedControl, {
ServicesTab,
} from "../components/ServiceTypeSegmentedControl/ServiceTypeSegmentedControl.tsx";
import ServicesKitsTable from "../components/ServicesKitsTable/ServicesKitsTable.tsx";
import ServicePriceCategoryTable from "../components/ServicePriceCategoryTable/ServicePriceCategoryTable.tsx";
import useServicesState from "../hooks/useServicesState.tsx";
import useServicesKitsState from "../hooks/useServicesKitsState.tsx";
import useServicePriceCategoryState from "../hooks/useServicePriceCategoryState.tsx";
import { ObjectStateToTableProps } from "../../../types/utils.ts";
import { IconDownload, IconFileExcel, IconFileTypePdf } from "@tabler/icons-react";
import FileSaver from "file-saver";
import { getCurrentDateTimeForFilename } from "../../../shared/lib/date.ts";
@@ -28,10 +25,6 @@ export const ServicesPage: FC = () => {
} = useServicesState();
const { servicesKits, onKitUpdate, onKitCreateClick } =
useServicesKitsState();
const {
onCreateClick: onCreatePriceCategoryClick,
...priceCategoryRestProps
} = useServicePriceCategoryState();
const getBody = () => {
switch (serviceType) {
case ServicesTab.SERVICES_KITS:
@@ -60,12 +53,6 @@ export const ServicesPage: FC = () => {
/>
);
}
case ServicesTab.SERVICES_PRICE_CATEGORIES:
return (
<ServicePriceCategoryTable
{...ObjectStateToTableProps(priceCategoryRestProps)}
/>
);
}
};
const getControls = () => {
@@ -141,18 +128,6 @@ export const ServicesPage: FC = () => {
/>
</Flex>
);
case ServicesTab.SERVICES_PRICE_CATEGORIES:
return (
<Button
variant={"default"}
onClick={() => {
if (onCreatePriceCategoryClick) {
onCreatePriceCategoryClick();
}
}}>
Создать категорию
</Button>
);
}
};