feat: a few tabs for module, deal services tab for mobiles
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
@media (max-width: 48em) {
|
@media (max-width: 48em) {
|
||||||
|
width: 100%;
|
||||||
border-bottom-width: 3px;
|
border-bottom-width: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,12 @@ import React, { FC, ReactNode } from "react";
|
|||||||
import { IconEdit, IconHistory } from "@tabler/icons-react";
|
import { IconEdit, IconHistory } from "@tabler/icons-react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { Box, Tabs, Text } from "@mantine/core";
|
import { Box, Tabs, Text } from "@mantine/core";
|
||||||
|
import TabsList from "@/app/deals/drawers/DealEditorDrawer/components/TabsList";
|
||||||
import DealStatusHistoryTab from "@/app/deals/drawers/DealEditorDrawer/tabs/DealStatusHistoryTab/DealStatusHistoryTab";
|
import DealStatusHistoryTab from "@/app/deals/drawers/DealEditorDrawer/tabs/DealStatusHistoryTab/DealStatusHistoryTab";
|
||||||
import GeneralTab from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab";
|
import GeneralTab from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab";
|
||||||
import useIsMobile from "@/hooks/utils/useIsMobile";
|
import useIsMobile from "@/hooks/utils/useIsMobile";
|
||||||
import { DealSchema, ProjectSchema } from "@/lib/client";
|
import { DealSchema, ProjectSchema } from "@/lib/client";
|
||||||
import { MODULES } from "@/modules/modules";
|
import MODULES from "@/modules/modules";
|
||||||
import styles from "../DealEditorDrawer.module.css";
|
import styles from "../DealEditorDrawer.module.css";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -50,29 +51,58 @@ const DealEditorBody: FC<Props> = props => {
|
|||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
);
|
);
|
||||||
|
|
||||||
const getModuleTabs = () =>
|
const getModuleTabs = (): ReactNode[] => {
|
||||||
props.project?.builtInModules.map(module => {
|
if (!props.project) return [];
|
||||||
const info = MODULES[module.key].renderInfo;
|
const tabs: ReactNode[] = [];
|
||||||
return getTab(info.key, info.label, info.icon);
|
|
||||||
});
|
|
||||||
|
|
||||||
const getModuleTabPanels = () =>
|
for (const module of props.project.builtInModules) {
|
||||||
props.project?.builtInModules.map(module =>
|
const moduleInfo = MODULES[module.key];
|
||||||
getTabPanel(module.key, MODULES[module.key]?.getTab?.(props))
|
for (const tab of moduleInfo.tabs) {
|
||||||
);
|
if (
|
||||||
|
(tab.device === "desktop" && isMobile) ||
|
||||||
|
(tab.device === "mobile" && !isMobile)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tabs.push(getTab(tab.key, tab.label, tab.icon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabs;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getModuleTabPanels = () => {
|
||||||
|
if (!props.project) return [];
|
||||||
|
const tabPanels: ReactNode[] = [];
|
||||||
|
|
||||||
|
for (const module of props.project.builtInModules) {
|
||||||
|
const moduleInfo = MODULES[module.key];
|
||||||
|
for (const tab of moduleInfo.tabs) {
|
||||||
|
if (
|
||||||
|
(tab.device === "desktop" && isMobile) ||
|
||||||
|
(tab.device === "mobile" && !isMobile)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tabPanels.push(getTabPanel(tab.key, tab.tab(props)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabPanels;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue="general"
|
defaultValue="general"
|
||||||
orientation={isMobile ? "horizontal" : "vertical"}
|
orientation={isMobile ? "horizontal" : "vertical"}
|
||||||
h={"97vh"}
|
h={isMobile ? "min-content" : "97vh"}
|
||||||
mih={"97vh"}
|
mih={isMobile ? "min-content" : "97vh"}
|
||||||
classNames={{ tab: styles.tab }}>
|
classNames={{ tab: styles.tab }}>
|
||||||
<Tabs.List>
|
<TabsList>
|
||||||
{getTab("general", "Общая информация", <IconEdit />)}
|
{getTab("general", "Общая информация", <IconEdit />)}
|
||||||
{getTab("history", "История", <IconHistory />)}
|
{getTab("history", "История", <IconHistory />)}
|
||||||
{getModuleTabs()}
|
{getModuleTabs()}
|
||||||
</Tabs.List>
|
</TabsList>
|
||||||
|
|
||||||
{getTabPanel("general", <GeneralTab {...props} />)}
|
{getTabPanel("general", <GeneralTab {...props} />)}
|
||||||
{getTabPanel("history", <DealStatusHistoryTab {...props} />)}
|
{getTabPanel("history", <DealStatusHistoryTab {...props} />)}
|
||||||
|
|||||||
@ -0,0 +1,30 @@
|
|||||||
|
import { FC, ReactNode } from "react";
|
||||||
|
import { ScrollArea, Tabs } from "@mantine/core";
|
||||||
|
import useIsMobile from "@/hooks/utils/useIsMobile";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TabsList: FC<Props> = ({ children }) => {
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
|
if (!isMobile) {
|
||||||
|
return <Tabs.List>{children}</Tabs.List>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ScrollArea scrollbarSize={0}>
|
||||||
|
<Tabs.List
|
||||||
|
style={{
|
||||||
|
flexWrap: "nowrap",
|
||||||
|
minWidth: "100%",
|
||||||
|
width: "max-content",
|
||||||
|
}}>
|
||||||
|
{children}
|
||||||
|
</Tabs.List>
|
||||||
|
</ScrollArea>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TabsList;
|
||||||
24
src/components/ui/InlineButton/InlineButton.tsx
Normal file
24
src/components/ui/InlineButton/InlineButton.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
import { Button, ButtonProps, Group } from "@mantine/core";
|
||||||
|
|
||||||
|
interface Props extends ButtonProps {
|
||||||
|
children?: ReactNode;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InlineButton = ({ children, onClick, ...props }: Props) => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
onClick={onClick}
|
||||||
|
{...props}>
|
||||||
|
<Group
|
||||||
|
gap="sm"
|
||||||
|
wrap={"nowrap"}>
|
||||||
|
{children}
|
||||||
|
</Group>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InlineButton;
|
||||||
@ -38,10 +38,6 @@ export type BuiltInModuleSchemaInput = {
|
|||||||
* Label
|
* Label
|
||||||
*/
|
*/
|
||||||
label: string;
|
label: string;
|
||||||
/**
|
|
||||||
* Iconname
|
|
||||||
*/
|
|
||||||
iconName: string;
|
|
||||||
/**
|
/**
|
||||||
* Description
|
* Description
|
||||||
*/
|
*/
|
||||||
@ -50,6 +46,10 @@ export type BuiltInModuleSchemaInput = {
|
|||||||
* Dependson
|
* Dependson
|
||||||
*/
|
*/
|
||||||
dependsOn: Array<BuiltInModuleSchemaInput>;
|
dependsOn: Array<BuiltInModuleSchemaInput>;
|
||||||
|
/**
|
||||||
|
* Tabs
|
||||||
|
*/
|
||||||
|
tabs: Array<BuiltInModuleTabSchema>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,10 +68,6 @@ export type BuiltInModuleSchemaOutput = {
|
|||||||
* Label
|
* Label
|
||||||
*/
|
*/
|
||||||
label: string;
|
label: string;
|
||||||
/**
|
|
||||||
* Iconname
|
|
||||||
*/
|
|
||||||
iconName: string;
|
|
||||||
/**
|
/**
|
||||||
* Description
|
* Description
|
||||||
*/
|
*/
|
||||||
@ -80,6 +76,32 @@ export type BuiltInModuleSchemaOutput = {
|
|||||||
* Dependson
|
* Dependson
|
||||||
*/
|
*/
|
||||||
dependsOn: Array<BuiltInModuleSchemaOutput>;
|
dependsOn: Array<BuiltInModuleSchemaOutput>;
|
||||||
|
/**
|
||||||
|
* Tabs
|
||||||
|
*/
|
||||||
|
tabs: Array<BuiltInModuleTabSchema>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BuiltInModuleTabSchema
|
||||||
|
*/
|
||||||
|
export type BuiltInModuleTabSchema = {
|
||||||
|
/**
|
||||||
|
* Id
|
||||||
|
*/
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* Label
|
||||||
|
*/
|
||||||
|
label: string;
|
||||||
|
/**
|
||||||
|
* Iconname
|
||||||
|
*/
|
||||||
|
iconName: string;
|
||||||
|
/**
|
||||||
|
* Device
|
||||||
|
*/
|
||||||
|
device: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -12,6 +12,16 @@ export const zBoardSchema = z.object({
|
|||||||
projectId: z.int(),
|
projectId: z.int(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BuiltInModuleTabSchema
|
||||||
|
*/
|
||||||
|
export const zBuiltInModuleTabSchema = z.object({
|
||||||
|
id: z.int(),
|
||||||
|
label: z.string(),
|
||||||
|
iconName: z.string(),
|
||||||
|
device: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BuiltInModuleSchema
|
* BuiltInModuleSchema
|
||||||
*/
|
*/
|
||||||
@ -19,7 +29,6 @@ export const zBuiltInModuleSchemaInput = z.object({
|
|||||||
id: z.int(),
|
id: z.int(),
|
||||||
key: z.string(),
|
key: z.string(),
|
||||||
label: z.string(),
|
label: z.string(),
|
||||||
iconName: z.string(),
|
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
get dependsOn() {
|
get dependsOn() {
|
||||||
return z.array(
|
return z.array(
|
||||||
@ -28,6 +37,7 @@ export const zBuiltInModuleSchemaInput = z.object({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
tabs: z.array(zBuiltInModuleTabSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +47,6 @@ export const zBuiltInModuleSchemaOutput = z.object({
|
|||||||
id: z.int(),
|
id: z.int(),
|
||||||
key: z.string(),
|
key: z.string(),
|
||||||
label: z.string(),
|
label: z.string(),
|
||||||
iconName: z.string(),
|
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
get dependsOn() {
|
get dependsOn() {
|
||||||
return z.array(
|
return z.array(
|
||||||
@ -46,6 +55,7 @@ export const zBuiltInModuleSchemaOutput = z.object({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
tabs: z.array(zBuiltInModuleTabSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -2,12 +2,14 @@ import DealsBoardFiltersModal from "@/app/deals/modals/DealsBoardFiltersModal/De
|
|||||||
import DealsScheduleFiltersModal from "@/app/deals/modals/DealsScheduleFiltersModal/DealsScheduleFiltersModal";
|
import DealsScheduleFiltersModal from "@/app/deals/modals/DealsScheduleFiltersModal/DealsScheduleFiltersModal";
|
||||||
import DealsTableFiltersModal from "@/app/deals/modals/DealsTableFiltersModal/DealsTableFiltersModal";
|
import DealsTableFiltersModal from "@/app/deals/modals/DealsTableFiltersModal/DealsTableFiltersModal";
|
||||||
import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal";
|
import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal";
|
||||||
import DealProductEditorModal from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/DealProductEditorModal/DealProductEditorModal";
|
import {
|
||||||
import DealServiceEditorModal from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/DealServiceEditorModal/DealServiceEditorModal";
|
DealProductEditorModal,
|
||||||
import DuplicateServicesModal from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/DuplicateServicesModal/DuplicateServicesModal";
|
DealServiceEditorModal,
|
||||||
import ProductEditorModal from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/ProductEditorModal/ProductEditorModal";
|
DuplicateServicesModal,
|
||||||
import ProductServiceEditorModal from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/ProductServiceEditorModal/ProductServiceEditorModal";
|
ProductEditorModal,
|
||||||
import ServicesKitSelectModal from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/ServicesKitSelectModal/ServicesKitSelectModal";
|
ProductServiceEditorModal,
|
||||||
|
ServicesKitSelectModal,
|
||||||
|
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals";
|
||||||
|
|
||||||
export const modals = {
|
export const modals = {
|
||||||
enterNameModal: EnterNameModal,
|
enterNameModal: EnterNameModal,
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
import FulfillmentBaseTab from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab";
|
|
||||||
import { ModuleNames } from "./modules";
|
|
||||||
import ModulesType from "./types";
|
|
||||||
|
|
||||||
const connectModules = (modules: ModulesType) => {
|
|
||||||
modules[ModuleNames.FULFILLMENT_BASE].getTab = props => (
|
|
||||||
<FulfillmentBaseTab {...props} />
|
|
||||||
);
|
|
||||||
|
|
||||||
return modules;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connectModules;
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { DealSchema } from "@/lib/client";
|
import { DealSchema } from "@/lib/client";
|
||||||
import FulfillmentBaseTabBody from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/FulfillmentBaseTabBody/FulfillmentBaseTabBody";
|
import { FulfillmentBaseContextProvider } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
import { FulfillmentBaseContextProvider } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import FulfillmentBaseTabBody from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/FulfillmentBaseTabBody/FulfillmentBaseTabBody";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
value: DealSchema;
|
value: DealSchema;
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { Flex, Stack } from "@mantine/core";
|
import { Flex, Stack } from "@mantine/core";
|
||||||
import DealServicesTable from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/DealInfoView/components/DealServicesTable/DealServicesTable";
|
import ProductsActions from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/components/ProductsActions/ProductsActions";
|
||||||
import ProductsActions from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/DealInfoView/components/ProductsActions/ProductsActions";
|
import TotalPriceLabel from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/components/TotalPriceLabel/TotalPriceLabel";
|
||||||
import TotalPriceLabel from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/DealInfoView/components/TotalPriceLabel/TotalPriceLabel";
|
import DealServicesTable from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealServicesTable/DealServicesTable";
|
||||||
import styles from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.module.css";
|
import styles from "@/modules/dealModularEditorTabs/FulfillmentBase/FulfillmentBase.module.css";
|
||||||
|
|
||||||
const DealInfoView = () => (
|
const DealInfoView = () => (
|
||||||
<Stack
|
<Stack
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { Button, Flex } from "@mantine/core";
|
import { Button, Flex } from "@mantine/core";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
const ProductsActions: FC = () => {
|
const ProductsActions: FC = () => {
|
||||||
const { deal, dealProductsList, productsCrud, dealProductsCrud } =
|
const { deal, dealProductsList, productsCrud, dealProductsCrud } =
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { Flex, Title } from "@mantine/core";
|
import { Flex, Title } from "@mantine/core";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
import styles from "../../../../FulfillmentBaseTab.module.css";
|
import styles from "../../../../../FulfillmentBase.module.css";
|
||||||
|
|
||||||
const TotalPriceLabel = () => {
|
const TotalPriceLabel = () => {
|
||||||
const {
|
const {
|
||||||
@ -1,16 +1,14 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { Flex, ScrollArea } from "@mantine/core";
|
import { Flex, ScrollArea } from "@mantine/core";
|
||||||
import DealServicesTitle from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/DealInfoView/components/DealServicesTable/components/DealServicesTitle";
|
import DealServiceRow from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealServicesTable/components/DealServiceRow";
|
||||||
import DealServicesTotalLabel from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/DealInfoView/components/DealServicesTable/components/DealServicesTotalLabel";
|
import DealServicesTitle from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealServicesTable/components/DealServicesTitle";
|
||||||
import ServicesActions from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/DealInfoView/components/DealServicesTable/components/ServicesActions";
|
import ServicesActions from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealServicesTable/components/ServicesActions";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import DealServicesTotalLabel from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/components/DealServicesTotalLabel/DealServicesTotalLabel";
|
||||||
import DealServiceRow from "./components/DealServiceRow";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
const DealServicesTable: FC = () => {
|
const DealServicesTable: FC = () => {
|
||||||
const { dealServicesList, dealServicesCrud } = useFulfillmentBaseContext();
|
const { dealServicesList, dealServicesCrud } = useFulfillmentBaseContext();
|
||||||
|
|
||||||
// const isLocked = isDealLocked(deal); // TODO bills
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
direction={"column"}
|
direction={"column"}
|
||||||
@ -20,7 +18,7 @@ const DealServicesTable: FC = () => {
|
|||||||
<ScrollArea
|
<ScrollArea
|
||||||
flex={1}
|
flex={1}
|
||||||
scrollbars={"y"}
|
scrollbars={"y"}
|
||||||
offsetScrollbars={"y"}>
|
offsetScrollbars={"present"}>
|
||||||
<Flex
|
<Flex
|
||||||
direction={"column"}
|
direction={"column"}
|
||||||
gap={"sm"}>
|
gap={"sm"}>
|
||||||
@ -34,7 +32,7 @@ const DealServicesTable: FC = () => {
|
|||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
<DealServicesTotalLabel />
|
<DealServicesTotalLabel mt={"sm"} />
|
||||||
<ServicesActions />
|
<ServicesActions />
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { IconTrash } from "@tabler/icons-react";
|
import { IconTrash } from "@tabler/icons-react";
|
||||||
import { isNumber } from "lodash";
|
import { isNumber } from "lodash";
|
||||||
import { Divider, Group, NumberInput, Stack, Text } from "@mantine/core";
|
import { Divider, Group, NumberInput, rem, Stack, Text } from "@mantine/core";
|
||||||
import { useDebouncedCallback } from "@mantine/hooks";
|
import { useDebouncedCallback } from "@mantine/hooks";
|
||||||
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
||||||
import { DealServiceSchema } from "@/lib/client";
|
import { DealServiceSchema } from "@/lib/client";
|
||||||
import LockCheckbox from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/LockCheckbox/LockCheckbox";
|
import LockCheckbox from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/LockCheckbox/LockCheckbox";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
value: DealServiceSchema;
|
value: DealServiceSchema;
|
||||||
@ -64,6 +64,7 @@ const DealServiceRow: FC<Props> = ({ value, onChange, onDelete }) => {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
|
paddingRight: rem(10),
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
rightSection={
|
rightSection={
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { Button, Flex } from "@mantine/core";
|
import { Button, Flex } from "@mantine/core";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import { addKitToDeal, ServicesKitSchema } from "@/lib/client";
|
import { addKitToDeal, ServicesKitSchema } from "@/lib/client";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/types/service";
|
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
|
||||||
|
|
||||||
const ServicesActions = () => {
|
const ServicesActions = () => {
|
||||||
const { dealServicesList, dealServicesCrud, deal } =
|
const { dealServicesList, dealServicesCrud, deal } =
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { Flex, ScrollArea, Stack } from "@mantine/core";
|
import { Flex, ScrollArea, Stack } from "@mantine/core";
|
||||||
import DealInfoView from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/DealInfoView/DealInfoView";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
import ProductView from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView";
|
import DealInfoView from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/DealInfoView";
|
||||||
import { useFulfillmentBaseContext } from "../../contexts/FulfillmentBaseContext";
|
import ProductView from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/ProductView";
|
||||||
|
|
||||||
const FulfillmentBaseTabBody = () => {
|
const FulfillmentBaseTabBody = () => {
|
||||||
const { dealProductsList } = useFulfillmentBaseContext();
|
const { dealProductsList } = useFulfillmentBaseContext();
|
||||||
@ -6,7 +6,7 @@ import ObjectSelect, {
|
|||||||
ObjectSelectProps,
|
ObjectSelectProps,
|
||||||
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
||||||
import { ProductSchema } from "@/lib/client";
|
import { ProductSchema } from "@/lib/client";
|
||||||
import useProductsList from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/hooks/lists/useProductsList";
|
import useProductsList from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useProductsList";
|
||||||
import renderProductOption from "./utils/renderProductOption";
|
import renderProductOption from "./utils/renderProductOption";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
@ -5,7 +5,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { ProductSchema } from "@/lib/client";
|
import { ProductSchema } from "@/lib/client";
|
||||||
import ProductFieldsList from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductFieldsList";
|
import ProductFieldsList from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/components/ProductFieldsList";
|
||||||
|
|
||||||
const renderProductOption = (
|
const renderProductOption = (
|
||||||
products: ProductSchema[]
|
products: ProductSchema[]
|
||||||
@ -16,12 +16,12 @@ import {
|
|||||||
duplicateProductServices,
|
duplicateProductServices,
|
||||||
ServicesKitSchema,
|
ServicesKitSchema,
|
||||||
} from "@/lib/client";
|
} from "@/lib/client";
|
||||||
import ProductFieldsList from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductFieldsList";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
import ProductViewActions from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductViewActions";
|
import ProductFieldsList from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/components/ProductFieldsList";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import ProductViewActions from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/components/ProductViewActions";
|
||||||
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/types/service";
|
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
|
||||||
import ProductServicesTable from "./components/ProductServicesTable";
|
import ProductServicesTable from "./components/ProductServicesTable";
|
||||||
import styles from "../../FulfillmentBaseTab.module.css";
|
import styles from "../../../FulfillmentBase.module.css";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dealProduct: DealProductSchema;
|
dealProduct: DealProductSchema;
|
||||||
@ -5,8 +5,8 @@ import { modals } from "@mantine/modals";
|
|||||||
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
||||||
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
||||||
import { DealProductSchema, ProductServiceSchema } from "@/lib/client";
|
import { DealProductSchema, ProductServiceSchema } from "@/lib/client";
|
||||||
import useProductServicesTableColumns from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/ProductView/hooks/useProductServicesTableColumns";
|
import useProductServicesTableColumns from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/hooks/useProductServicesTableColumns";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dealProduct: DealProductSchema;
|
dealProduct: DealProductSchema;
|
||||||
@ -4,7 +4,7 @@ import { Flex } from "@mantine/core";
|
|||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
||||||
import { DealProductSchema } from "@/lib/client";
|
import { DealProductSchema } from "@/lib/client";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dealProduct: DealProductSchema;
|
dealProduct: DealProductSchema;
|
||||||
@ -9,8 +9,8 @@ import ObjectSelect, {
|
|||||||
ObjectSelectProps,
|
ObjectSelectProps,
|
||||||
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
||||||
import { ServiceSchema } from "@/lib/client";
|
import { ServiceSchema } from "@/lib/client";
|
||||||
import useServicesList from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/hooks/lists/useServicesList";
|
import useServicesList from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useServicesList";
|
||||||
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/types/service";
|
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
filterType?: ServiceType;
|
filterType?: ServiceType;
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { DealSchema } from "@/lib/client";
|
||||||
|
import { FulfillmentBaseContextProvider } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
import DealServicesTable from "@/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/DealServiceTable/DealServicesTable";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: DealSchema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CommonServicesTab: FC<Props> = ({ value }) => {
|
||||||
|
return (
|
||||||
|
<FulfillmentBaseContextProvider deal={value}>
|
||||||
|
<DealServicesTable />
|
||||||
|
</FulfillmentBaseContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CommonServicesTab;
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { DealSchema } from "@/lib/client";
|
||||||
|
import { FulfillmentBaseContextProvider } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: DealSchema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProductsTab: FC<Props> = ({ value }) => {
|
||||||
|
return (
|
||||||
|
<FulfillmentBaseContextProvider deal={value}>
|
||||||
|
<></>
|
||||||
|
</FulfillmentBaseContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProductsTab;
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
|
import { ButtonProps, Text } from "@mantine/core";
|
||||||
|
import { modals } from "@mantine/modals";
|
||||||
|
import InlineButton from "@/components/ui/InlineButton/InlineButton";
|
||||||
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
|
type Props = ButtonProps;
|
||||||
|
|
||||||
|
const AddDealServiceButton: FC<Props> = props => {
|
||||||
|
const { dealServicesList, dealServicesCrud, deal } =
|
||||||
|
useFulfillmentBaseContext();
|
||||||
|
|
||||||
|
const onCreateClick = () => {
|
||||||
|
const serviceIdsToExclude = dealServicesList.dealServices.map(
|
||||||
|
service => service.service.id
|
||||||
|
);
|
||||||
|
modals.openContextModal({
|
||||||
|
modal: "dealServiceEditorModal",
|
||||||
|
innerProps: {
|
||||||
|
onCreate: values =>
|
||||||
|
dealServicesCrud.onCreate({ ...values, dealId: deal.id }),
|
||||||
|
serviceIdsToExclude,
|
||||||
|
isEditing: false,
|
||||||
|
},
|
||||||
|
withCloseButton: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InlineButton
|
||||||
|
{...props}
|
||||||
|
onClick={onCreateClick}>
|
||||||
|
<IconPlus />
|
||||||
|
<Text>Добавить услугу</Text>
|
||||||
|
</InlineButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddDealServiceButton;
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { Flex, ScrollArea, Stack } from "@mantine/core";
|
||||||
|
import { modals } from "@mantine/modals";
|
||||||
|
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
||||||
|
import { DealServiceSchema } from "@/lib/client";
|
||||||
|
import AddDealServiceButton from "@/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/AddDealServiceButton/AddDealServiceButton";
|
||||||
|
import useDealServicesTableColumns from "@/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/DealServiceTable/useDealServicesTableColumns";
|
||||||
|
import DealServicesTotalLabel from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/components/DealServicesTotalLabel/DealServicesTotalLabel";
|
||||||
|
import { useFulfillmentBaseContext } from "../../../shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
|
const DealServicesTable: FC = () => {
|
||||||
|
const { dealServicesList, dealServicesCrud } = useFulfillmentBaseContext();
|
||||||
|
|
||||||
|
const onChange = (item: DealServiceSchema) => {
|
||||||
|
const serviceIdsToExclude = dealServicesList.dealServices.map(
|
||||||
|
dealService => dealService.service.id
|
||||||
|
);
|
||||||
|
|
||||||
|
modals.openContextModal({
|
||||||
|
modal: "dealServiceEditorModal",
|
||||||
|
innerProps: {
|
||||||
|
entity: item,
|
||||||
|
onChange: values =>
|
||||||
|
dealServicesCrud.onUpdate(
|
||||||
|
item.dealId,
|
||||||
|
item.serviceId,
|
||||||
|
values
|
||||||
|
),
|
||||||
|
serviceIdsToExclude,
|
||||||
|
isEditing: true,
|
||||||
|
},
|
||||||
|
withCloseButton: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = useDealServicesTableColumns({
|
||||||
|
onDelete: dealServicesCrud.onDelete,
|
||||||
|
onChange,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ScrollArea
|
||||||
|
m={"xs"}
|
||||||
|
h={"calc(100vh - 140px)"}
|
||||||
|
scrollbars={"y"}
|
||||||
|
type={"scroll"}>
|
||||||
|
<Stack gap={"sm"}>
|
||||||
|
<Flex
|
||||||
|
p={"sm"}
|
||||||
|
bd={"1px solid var(--mantine-color-default-border)"}
|
||||||
|
bdrs={"lg"}>
|
||||||
|
<DealServicesTotalLabel order={5} />
|
||||||
|
</Flex>
|
||||||
|
<BaseTable
|
||||||
|
records={dealServicesList.dealServices}
|
||||||
|
columns={columns}
|
||||||
|
groups={undefined}
|
||||||
|
idAccessor={"serviceId"}
|
||||||
|
withTableBorder
|
||||||
|
/>
|
||||||
|
<AddDealServiceButton size={"lg"} />
|
||||||
|
</Stack>
|
||||||
|
</ScrollArea>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default DealServicesTable;
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
import { IconEdit, IconTrash } from "@tabler/icons-react";
|
||||||
|
import { DataTableColumn } from "mantine-datatable";
|
||||||
|
import { ActionIcon, Flex } from "@mantine/core";
|
||||||
|
import { DealServiceSchema } from "@/lib/client";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onChange: (dealService: DealServiceSchema) => void;
|
||||||
|
onDelete: (dealService: DealServiceSchema) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useDealServicesTableColumns = ({ onChange, onDelete }: Props) => {
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
[
|
||||||
|
{
|
||||||
|
accessor: "service.name",
|
||||||
|
title: "Название",
|
||||||
|
width: "53%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: "quantity",
|
||||||
|
title: "Кол-во",
|
||||||
|
width: "17%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: "price",
|
||||||
|
title: "Цена",
|
||||||
|
width: "30%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: "actions",
|
||||||
|
title: "Действия",
|
||||||
|
textAlign: "center",
|
||||||
|
width: "0%",
|
||||||
|
render: dealService => (
|
||||||
|
<Flex gap={"sm"}>
|
||||||
|
<ActionIcon
|
||||||
|
variant={"subtle"}
|
||||||
|
c={"red"}
|
||||||
|
onClick={() => onDelete(dealService)}>
|
||||||
|
<IconTrash />
|
||||||
|
</ActionIcon>
|
||||||
|
<ActionIcon
|
||||||
|
variant={"subtle"}
|
||||||
|
onClick={() => onChange(dealService)}>
|
||||||
|
<IconEdit />
|
||||||
|
</ActionIcon>
|
||||||
|
</Flex>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
] as DataTableColumn<DealServiceSchema>[],
|
||||||
|
[onChange, onDelete]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useDealServicesTableColumns;
|
||||||
@ -1,8 +1,10 @@
|
|||||||
import { useMemo } from "react";
|
import { FC, useMemo } from "react";
|
||||||
import { Title } from "@mantine/core";
|
import { Title, TitleProps } from "@mantine/core";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext";
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
const DealServicesTotalLabel = () => {
|
type Props = TitleProps;
|
||||||
|
|
||||||
|
const DealServicesTotalLabel: FC<Props> = ({ order = 3, ...props }) => {
|
||||||
const { dealServicesList } = useFulfillmentBaseContext();
|
const { dealServicesList } = useFulfillmentBaseContext();
|
||||||
const total = useMemo(
|
const total = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -16,9 +18,9 @@ const DealServicesTotalLabel = () => {
|
|||||||
return (
|
return (
|
||||||
<Title
|
<Title
|
||||||
style={{ textAlign: "end" }}
|
style={{ textAlign: "end" }}
|
||||||
mt={"sm"}
|
order={order}
|
||||||
order={3}>
|
{...props}>
|
||||||
Итог: {total.toFixed(2)}₽
|
Итог: {total.toLocaleString("ru")}₽
|
||||||
</Title>
|
</Title>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -3,22 +3,25 @@
|
|||||||
import { DealSchema } from "@/lib/client";
|
import { DealSchema } from "@/lib/client";
|
||||||
import { getProductsQueryKey } from "@/lib/client/@tanstack/react-query.gen";
|
import { getProductsQueryKey } from "@/lib/client/@tanstack/react-query.gen";
|
||||||
import makeContext from "@/lib/contextFactory/contextFactory";
|
import makeContext from "@/lib/contextFactory/contextFactory";
|
||||||
import useDealServicesCrud, {
|
|
||||||
DealServicesCrud,
|
|
||||||
} from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/hooks/cruds/useDealServiceCrud";
|
|
||||||
import useProductServiceCrud, {
|
|
||||||
DealProductServicesCrud,
|
|
||||||
} from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/hooks/cruds/useProductServiceCrud";
|
|
||||||
import useDealServicesList, {
|
|
||||||
DealServicesList,
|
|
||||||
} from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/hooks/lists/useDealServicesList";
|
|
||||||
import useDealProductCrud, {
|
import useDealProductCrud, {
|
||||||
DealProductsCrud,
|
DealProductsCrud,
|
||||||
} from "../hooks/cruds/useDealProductCrud";
|
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useDealProductCrud";
|
||||||
import { ProductsCrud, useProductsCrud } from "../hooks/cruds/useProductsCrud";
|
import useDealServicesCrud, {
|
||||||
|
DealServicesCrud,
|
||||||
|
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useDealServicesCrud";
|
||||||
|
import {
|
||||||
|
ProductsCrud,
|
||||||
|
useProductsCrud,
|
||||||
|
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useProductsCrud";
|
||||||
|
import useProductServiceCrud, {
|
||||||
|
DealProductServicesCrud,
|
||||||
|
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useProductServiceCrud";
|
||||||
import useDealProductsList, {
|
import useDealProductsList, {
|
||||||
DealProductsList,
|
DealProductsList,
|
||||||
} from "../hooks/lists/useDealProductsList";
|
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useDealProductsList";
|
||||||
|
import useDealServicesList, {
|
||||||
|
DealServicesList,
|
||||||
|
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useDealServicesList";
|
||||||
|
|
||||||
type FulfillmentBaseContextState = {
|
type FulfillmentBaseContextState = {
|
||||||
deal: DealSchema;
|
deal: DealSchema;
|
||||||
@ -29,7 +29,7 @@ export type DealServicesCrud = {
|
|||||||
onDelete: (data: DealServiceSchema, onSuccess?: () => void) => void;
|
onDelete: (data: DealServiceSchema, onSuccess?: () => void) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useDealServiceCrud = ({ dealId }: Props): DealServicesCrud => {
|
const useDealServicesCrud = ({ dealId }: Props): DealServicesCrud => {
|
||||||
const queryKey = getDealServicesQueryKey({ path: { dealId } });
|
const queryKey = getDealServicesQueryKey({ path: { dealId } });
|
||||||
const key = "getDealServices";
|
const key = "getDealServices";
|
||||||
const { queryClient, onError, onSettled } = getCommonQueryClient({
|
const { queryClient, onError, onSettled } = getCommonQueryClient({
|
||||||
@ -150,4 +150,4 @@ const useDealServiceCrud = ({ dealId }: Props): DealServicesCrud => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDealServiceCrud;
|
export default useDealServicesCrud;
|
||||||
@ -11,7 +11,8 @@ import {
|
|||||||
import BaseFormModal, {
|
import BaseFormModal, {
|
||||||
CreateEditFormProps,
|
CreateEditFormProps,
|
||||||
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
||||||
import ProductSelect from "../../components/ProductSelect/ProductSelect";
|
import ProductSelect
|
||||||
|
from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductSelect/ProductSelect";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
clientId: number;
|
clientId: number;
|
||||||
@ -11,7 +11,7 @@ import {
|
|||||||
import BaseFormModal, {
|
import BaseFormModal, {
|
||||||
CreateEditFormProps,
|
CreateEditFormProps,
|
||||||
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
||||||
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/types/service";
|
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
|
||||||
import ServiceWithPriceInput from "./components/ServiceWithPriceInput";
|
import ServiceWithPriceInput from "./components/ServiceWithPriceInput";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
@ -9,8 +9,8 @@ import {
|
|||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { ObjectSelectProps } from "@/components/selects/ObjectSelect/ObjectSelect";
|
import { ObjectSelectProps } from "@/components/selects/ObjectSelect/ObjectSelect";
|
||||||
import { ServiceSchema } from "@/lib/client";
|
import { ServiceSchema } from "@/lib/client";
|
||||||
import ServiceSelect from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/ServiceSelect/ServiceSelect";
|
import ServiceSelect from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ServiceSelect/ServiceSelect";
|
||||||
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/types/service";
|
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
|
||||||
|
|
||||||
type ServiceProps = Omit<ObjectSelectProps<ServiceSchema>, "data">;
|
type ServiceProps = Omit<ObjectSelectProps<ServiceSchema>, "data">;
|
||||||
type PriceProps = NumberInputProps;
|
type PriceProps = NumberInputProps;
|
||||||
@ -11,7 +11,7 @@ import {
|
|||||||
import BaseFormModal, {
|
import BaseFormModal, {
|
||||||
CreateEditFormProps,
|
CreateEditFormProps,
|
||||||
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
||||||
import ProductImageDropzone from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/ProductImageDropzone";
|
import ProductImageDropzone from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductImageDropzone/ProductImageDropzone";
|
||||||
import BaseFormInputProps from "@/utils/baseFormInputProps";
|
import BaseFormInputProps from "@/utils/baseFormInputProps";
|
||||||
|
|
||||||
type Props = CreateEditFormProps<
|
type Props = CreateEditFormProps<
|
||||||
@ -12,8 +12,8 @@ import {
|
|||||||
import BaseFormModal, {
|
import BaseFormModal, {
|
||||||
CreateEditFormProps,
|
CreateEditFormProps,
|
||||||
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
||||||
import ServiceWithPriceInput from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/DealServiceEditorModal/components/ServiceWithPriceInput";
|
import ServiceWithPriceInput from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals/DealServiceEditorModal/components/ServiceWithPriceInput";
|
||||||
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/types/service";
|
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
quantity: number;
|
quantity: number;
|
||||||
@ -5,7 +5,7 @@ import { useForm } from "@mantine/form";
|
|||||||
import { ContextModalProps } from "@mantine/modals";
|
import { ContextModalProps } from "@mantine/modals";
|
||||||
import { ServicesKitSchema } from "@/lib/client";
|
import { ServicesKitSchema } from "@/lib/client";
|
||||||
import BaseFormModalActions from "@/modals/base/BaseFormModal/BaseFormModalActions";
|
import BaseFormModalActions from "@/modals/base/BaseFormModal/BaseFormModalActions";
|
||||||
import ServicesKitSelect from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/modals/ServicesKitSelectModal/components/ServicesKitSelect";
|
import ServicesKitSelect from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals/ServicesKitSelectModal/components/ServicesKitSelect";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSelect: (kit: ServicesKitSchema) => void;
|
onSelect: (kit: ServicesKitSchema) => void;
|
||||||
@ -3,7 +3,7 @@ import ObjectSelect, {
|
|||||||
ObjectSelectProps,
|
ObjectSelectProps,
|
||||||
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
||||||
import { ServicesKitSchema } from "@/lib/client";
|
import { ServicesKitSchema } from "@/lib/client";
|
||||||
import useServicesKitsList from "@/modules/dealModularEditorTabs/FulfillmentBaseTab/hooks/lists/useServicesKitsList";
|
import useServicesKitsList from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useServicesKitsList";
|
||||||
|
|
||||||
type Props = Omit<ObjectSelectProps<ServicesKitSchema>, "data">;
|
type Props = Omit<ObjectSelectProps<ServicesKitSchema>, "data">;
|
||||||
|
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
export { default as ServicesKitSelectModal } from "./ServicesKitSelectModal/ServicesKitSelectModal";
|
||||||
|
export { default as ProductEditorModal } from "./ProductEditorModal/ProductEditorModal";
|
||||||
|
export { default as DuplicateServicesModal } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals/DuplicateServicesModal/DuplicateServicesModal";
|
||||||
|
export { default as DealServiceEditorModal } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals/DealServiceEditorModal/DealServiceEditorModal";
|
||||||
|
export { default as DealProductEditorModal } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals/DealProductEditorModal/DealProductEditorModal";
|
||||||
|
export { default as ProductServiceEditorModal } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals/ProductServiceEditorModal/ProductServiceEditorModal";
|
||||||
3
src/modules/dealModularEditorTabs/index.ts
Normal file
3
src/modules/dealModularEditorTabs/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export { default as CommonServicesTab } from "@/modules/dealModularEditorTabs/FulfillmentBase/mobile/CommonServicesTab";
|
||||||
|
export { default as FulfillmentBaseTab } from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/FulfillmentBaseTab";
|
||||||
|
export { default as ProductsTab } from "@/modules/dealModularEditorTabs/FulfillmentBase/mobile/ProductsTab";
|
||||||
@ -1,21 +1,48 @@
|
|||||||
import {
|
import {
|
||||||
|
IconColumns,
|
||||||
IconBox,
|
IconBox,
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
|
import {
|
||||||
|
CommonServicesTab,
|
||||||
|
ProductsTab,
|
||||||
|
FulfillmentBaseTab,
|
||||||
|
} from "./dealModularEditorTabs";
|
||||||
import ModulesType from "./types";
|
import ModulesType from "./types";
|
||||||
import connectModules from "./connectModules";
|
|
||||||
|
|
||||||
export enum ModuleNames {
|
export enum ModuleNames {
|
||||||
FULFILLMENT_BASE = "fulfillment_base",
|
FULFILLMENT_BASE = "fulfillment_base",
|
||||||
}
|
}
|
||||||
|
|
||||||
const modules: ModulesType = {
|
const MODULES: ModulesType = {
|
||||||
[ModuleNames.FULFILLMENT_BASE]: {
|
[ModuleNames.FULFILLMENT_BASE]: {
|
||||||
renderInfo: {
|
info: {
|
||||||
label: "Фулфиллмент",
|
|
||||||
key: "fulfillment_base",
|
key: "fulfillment_base",
|
||||||
icon: <IconBox />,
|
label: "Фулфиллмент",
|
||||||
},
|
},
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
label: "Услуги",
|
||||||
|
key: "common_services",
|
||||||
|
icon: <IconColumns />,
|
||||||
|
device: "mobile",
|
||||||
|
tab: (props: any) => <CommonServicesTab {...props} key={"common_services"} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Товары",
|
||||||
|
key: "products",
|
||||||
|
icon: <IconBox />,
|
||||||
|
device: "mobile",
|
||||||
|
tab: (props: any) => <ProductsTab {...props} key={"products"} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Фулфиллмент",
|
||||||
|
key: "fulfillment_base",
|
||||||
|
icon: <IconBox />,
|
||||||
|
device: "desktop",
|
||||||
|
tab: (props: any) => <FulfillmentBaseTab {...props} key={"fulfillment_base"} />,
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MODULES = connectModules(modules);
|
export default MODULES;
|
||||||
|
|||||||
@ -4,12 +4,19 @@ import axios, { AxiosResponse } from "axios";
|
|||||||
import * as handlebars from "handlebars";
|
import * as handlebars from "handlebars";
|
||||||
|
|
||||||
// region types
|
// region types
|
||||||
type Module = {
|
type ModuleTab = {
|
||||||
id: number;
|
id: number;
|
||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
iconName: string;
|
iconName: string;
|
||||||
|
moduleId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Module = {
|
||||||
|
id: number;
|
||||||
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
tabs: ModuleTab[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type ModulesResponse = {
|
type ModulesResponse = {
|
||||||
@ -59,10 +66,23 @@ handlebars.registerHelper("uppercase", text => {
|
|||||||
return text.replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase();
|
return text.replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function pascalcase(s: string): string {
|
||||||
|
return s.replace(/(?:^|_+)([a-zA-Z0-9])/g, (_, c) => c.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
handlebars.registerHelper("pascalcase", pascalcase);
|
||||||
|
|
||||||
const generateRows = (modules: Module[]) => {
|
const generateRows = (modules: Module[]) => {
|
||||||
try {
|
try {
|
||||||
|
const iconsToImport = new Set<string>();
|
||||||
|
for (const module of modules) {
|
||||||
|
for (const tab of module.tabs) {
|
||||||
|
iconsToImport.add(tab.iconName);
|
||||||
|
}
|
||||||
|
}
|
||||||
const data = {
|
const data = {
|
||||||
modules,
|
modules,
|
||||||
|
iconsToImport: Array.from(iconsToImport),
|
||||||
};
|
};
|
||||||
const tsxContent = template(data);
|
const tsxContent = template(data);
|
||||||
fs.writeFileSync(OUTPUT_PATH, tsxContent);
|
fs.writeFileSync(OUTPUT_PATH, tsxContent);
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
{{#each modules}}
|
{{#each iconsToImport}}
|
||||||
{{#if this.iconName}}{{this.iconName}},{{/if}}
|
{{this}},
|
||||||
{{/each}}
|
{{/each}}
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
|
import {
|
||||||
|
{{#each modules}}
|
||||||
|
{{#each this.tabs}}
|
||||||
|
{{pascalcase this.key}}Tab,
|
||||||
|
{{/each}}
|
||||||
|
{{/each}}
|
||||||
|
} from "./dealModularEditorTabs";
|
||||||
import ModulesType from "./types";
|
import ModulesType from "./types";
|
||||||
import connectModules from "./connectModules";
|
|
||||||
|
|
||||||
export enum ModuleNames {
|
export enum ModuleNames {
|
||||||
{{#each modules}}
|
{{#each modules}}
|
||||||
@ -12,16 +18,26 @@ export enum ModuleNames {
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
}
|
}
|
||||||
|
|
||||||
const modules: ModulesType = {
|
const MODULES: ModulesType = {
|
||||||
{{#each modules}}
|
{{#each modules}}
|
||||||
[ModuleNames.{{uppercase this.key}}]: {
|
[ModuleNames.{{uppercase this.key}}]: {
|
||||||
renderInfo: {
|
info: {
|
||||||
label: "{{this.label}}",
|
|
||||||
key: "{{this.key}}",
|
key: "{{this.key}}",
|
||||||
icon: {{#if this.iconName}}<{{this.iconName}} />{{else}}None{{/if}},
|
label: "{{this.label}}",
|
||||||
},
|
},
|
||||||
|
tabs: [
|
||||||
|
{{#each this.tabs}}
|
||||||
|
{
|
||||||
|
label: "{{this.label}}",
|
||||||
|
key: "{{this.key}}",
|
||||||
|
icon: {{#if this.iconName}}<{{this.iconName}} />{{else}}None{{/if}},
|
||||||
|
device: "{{this.device}}",
|
||||||
|
tab: (props: any) => <{{pascalcase this.key}}Tab {...props} key={"{{this.key}}"} />,
|
||||||
|
},
|
||||||
|
{{/each}}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{{/each}}
|
{{/each}}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MODULES = connectModules(modules);
|
export default MODULES;
|
||||||
|
|||||||
@ -1,12 +1,24 @@
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
type GetTab = (props: any) => ReactNode[] | ReactNode;
|
||||||
|
|
||||||
|
export type ModuleTab = {
|
||||||
|
label: string;
|
||||||
|
key: string;
|
||||||
|
icon: ReactNode;
|
||||||
|
device: "mobile" | "desktop" | "both";
|
||||||
|
tab: (props: any) => ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
export type Module = {
|
export type Module = {
|
||||||
renderInfo: {
|
info: {
|
||||||
label: string;
|
label: string;
|
||||||
key: string;
|
key: string;
|
||||||
icon: ReactNode;
|
|
||||||
};
|
};
|
||||||
getTab?: (props: any) => ReactNode;
|
tabs: ModuleTab[];
|
||||||
|
getTabs?: GetTab;
|
||||||
|
getMobileTabs?: GetTab;
|
||||||
|
getDesktopTabs?: GetTab;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ModulesType = {
|
type ModulesType = {
|
||||||
|
|||||||
Reference in New Issue
Block a user