feat: modules, products, services, services kits
This commit is contained in:
@ -3,11 +3,13 @@ import { IconMoodSad } from "@tabler/icons-react";
|
||||
import { Group, Pagination, Stack, Text } from "@mantine/core";
|
||||
import useDealsTableColumns from "@/app/deals/components/desktop/DealsTable/useDealsTableColumns";
|
||||
import { useDealsContext } from "@/app/deals/contexts/DealsContext";
|
||||
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
|
||||
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
||||
import { useDrawersContext } from "@/drawers/DrawersContext";
|
||||
import { DealSchema } from "@/lib/client";
|
||||
|
||||
const DealsTable: FC = () => {
|
||||
const { selectedProject } = useProjectsContext();
|
||||
const { deals, paginationInfo, page, setPage, sortingForm, dealsCrud } =
|
||||
useDealsContext();
|
||||
const { openDrawer } = useDrawersContext();
|
||||
@ -20,6 +22,7 @@ const DealsTable: FC = () => {
|
||||
value: deal,
|
||||
onChange: deal => dealsCrud.onUpdate(deal.id, deal),
|
||||
onDelete: dealsCrud.onDelete,
|
||||
project: selectedProject,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@ -35,7 +35,7 @@ const TopToolPanel: FC<Props> = ({ view, setView }) => {
|
||||
title: "Создание проекта",
|
||||
withCloseButton: true,
|
||||
innerProps: {
|
||||
onChange: values => projectsCrud.onCreate(values.name),
|
||||
onChange: projectsCrud.onCreate,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -11,7 +11,7 @@ const CreateBoardButton = () => {
|
||||
<Flex style={{ borderBottom: "2px solid gray" }}>
|
||||
<InPlaceInput
|
||||
placeholder={"Название доски"}
|
||||
onChange={boardsCrud.onCreate}
|
||||
onChange={name => boardsCrud.onCreate({ name })}
|
||||
getChildren={startEditing => (
|
||||
<Box
|
||||
onClick={startEditing}
|
||||
|
||||
@ -11,7 +11,7 @@ const CreateCardButton = () => {
|
||||
const { dealsCrud } = useDealsContext();
|
||||
|
||||
const onSubmit = (values: CreateDealForm) => {
|
||||
dealsCrud.onCreate(values.name);
|
||||
dealsCrud.onCreate(values);
|
||||
setIsCreating(prevState => !prevState);
|
||||
setIsTransitionEnded(false);
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@ const CreateStatusButton = () => {
|
||||
className={styles["inner-container"]}>
|
||||
<InPlaceInput
|
||||
placeholder={"Название колонки"}
|
||||
onChange={statusesCrud.onCreate}
|
||||
onChange={name => statusesCrud.onCreate({ name })}
|
||||
getChildren={startEditing => (
|
||||
<Center
|
||||
p={"sm"}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Box, Card, Group, Pill, Stack, Text } from "@mantine/core";
|
||||
import { useDealsContext } from "@/app/deals/contexts/DealsContext";
|
||||
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
|
||||
import { useDrawersContext } from "@/drawers/DrawersContext";
|
||||
import { DealSchema } from "@/lib/client";
|
||||
import styles from "./DealCard.module.css";
|
||||
@ -9,6 +10,7 @@ type Props = {
|
||||
};
|
||||
|
||||
const DealCard = ({ deal }: Props) => {
|
||||
const { selectedProject } = useProjectsContext();
|
||||
const { dealsCrud } = useDealsContext();
|
||||
const { openDrawer } = useDrawersContext();
|
||||
|
||||
@ -19,6 +21,7 @@ const DealCard = ({ deal }: Props) => {
|
||||
value: deal,
|
||||
onChange: deal => dealsCrud.onUpdate(deal.id, deal),
|
||||
onDelete: dealsCrud.onDelete,
|
||||
project: selectedProject,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -2,9 +2,10 @@ import { FC } from "react";
|
||||
import { IconPlus } from "@tabler/icons-react";
|
||||
import { Box, Group, Text } from "@mantine/core";
|
||||
import { modals } from "@mantine/modals";
|
||||
import { CreateBoardSchema } from "@/lib/client";
|
||||
|
||||
type Props = {
|
||||
onCreateBoard: (name: string) => void;
|
||||
onCreateBoard: (data: Partial<CreateBoardSchema>) => void;
|
||||
};
|
||||
|
||||
const CreateBoardButton: FC<Props> = ({ onCreateBoard }) => {
|
||||
@ -14,7 +15,7 @@ const CreateBoardButton: FC<Props> = ({ onCreateBoard }) => {
|
||||
title: "Создание доски",
|
||||
withCloseButton: true,
|
||||
innerProps: {
|
||||
onChange: values => onCreateBoard(values.name),
|
||||
onChange: values => onCreateBoard(values),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -6,12 +6,13 @@ import DealEditorBody from "@/app/deals/drawers/DealEditorDrawer/components/Deal
|
||||
import Header from "@/app/deals/drawers/DealEditorDrawer/components/Header";
|
||||
import { DrawerProps } from "@/drawers/types";
|
||||
import useIsMobile from "@/hooks/utils/useIsMobile";
|
||||
import { DealSchema } from "@/lib/client";
|
||||
import { DealSchema, ProjectSchema } from "@/lib/client";
|
||||
|
||||
type Props = {
|
||||
value: DealSchema;
|
||||
onChange: (deal: DealSchema) => void;
|
||||
onDelete: (deal: DealSchema, onSuccess: () => void) => void;
|
||||
project: ProjectSchema | null;
|
||||
};
|
||||
|
||||
const DealEditorDrawer: FC<DrawerProps<Props>> = ({
|
||||
@ -24,7 +25,7 @@ const DealEditorDrawer: FC<DrawerProps<Props>> = ({
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
size={isMobile ? "100%" : "40%"}
|
||||
size={isMobile ? "100%" : "60%"}
|
||||
position={"right"}
|
||||
onClose={onClose}
|
||||
removeScrollProps={{ allowPinchZoom: true }}
|
||||
@ -49,6 +50,7 @@ const DealEditorDrawer: FC<DrawerProps<Props>> = ({
|
||||
props.onChange(deal);
|
||||
}}
|
||||
onDelete={value => props.onDelete(value, onClose)}
|
||||
project={props.project}
|
||||
/>
|
||||
</Drawer>
|
||||
);
|
||||
|
||||
@ -1,17 +1,55 @@
|
||||
import React, { FC } from "react";
|
||||
import { IconCircleDotted, IconEdit } from "@tabler/icons-react";
|
||||
import { Tabs, Text } from "@mantine/core";
|
||||
import React, { FC, ReactNode } from "react";
|
||||
import { IconEdit } from "@tabler/icons-react";
|
||||
import { motion } from "framer-motion";
|
||||
import { Box, Tabs } from "@mantine/core";
|
||||
import GeneralTab from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab";
|
||||
import { DealSchema } from "@/lib/client";
|
||||
import { DealSchema, ProjectSchema } from "@/lib/client";
|
||||
import { MODULES } from "@/modules/modules";
|
||||
import styles from "../DealEditorDrawer.module.css";
|
||||
|
||||
type Props = {
|
||||
value: DealSchema;
|
||||
onChange: (deal: DealSchema) => void;
|
||||
onDelete: (deal: DealSchema) => void;
|
||||
project: ProjectSchema | null;
|
||||
};
|
||||
|
||||
const DealEditorBody: FC<Props> = props => {
|
||||
const getTabPanel = (value: string, component: ReactNode): ReactNode => (
|
||||
<Tabs.Panel
|
||||
key={value}
|
||||
value={value}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2 }}>
|
||||
<Box
|
||||
h={"100%"}
|
||||
w={"100%"}>
|
||||
{component}
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Tabs.Panel>
|
||||
);
|
||||
|
||||
const getModuleTabs = () =>
|
||||
props.project?.builtInModules.map(module => {
|
||||
const moduleRender = MODULES[module.key].renderInfo;
|
||||
return (
|
||||
<Tabs.Tab
|
||||
key={moduleRender.key}
|
||||
value={moduleRender.key}
|
||||
leftSection={moduleRender.icon}>
|
||||
{moduleRender.label}
|
||||
</Tabs.Tab>
|
||||
);
|
||||
});
|
||||
|
||||
const getModuleTabPanels = () =>
|
||||
props.project?.builtInModules.map(module =>
|
||||
getTabPanel(module.key, MODULES[module.key]?.getTab?.(props))
|
||||
);
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
defaultValue="general"
|
||||
@ -22,19 +60,11 @@ const DealEditorBody: FC<Props> = props => {
|
||||
leftSection={<IconEdit />}>
|
||||
Общая информация
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
value="mock"
|
||||
leftSection={<IconCircleDotted />}>
|
||||
Mock
|
||||
</Tabs.Tab>
|
||||
{getModuleTabs()}
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="general">
|
||||
<GeneralTab {...props} />
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="mock">
|
||||
<Text>mock</Text>
|
||||
</Tabs.Panel>
|
||||
{getTabPanel("general", <GeneralTab {...props} />)}
|
||||
{getModuleTabPanels()}
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { FC } from "react";
|
||||
import { Stack, Text, TextInput } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import Footer from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/Footer";
|
||||
import Footer from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/components/Footer";
|
||||
import BoardSelect from "@/components/selects/BoardSelect/BoardSelect";
|
||||
import StatusSelect from "@/components/selects/StatusSelect/StatusSelect";
|
||||
import { BoardSchema, DealSchema, StatusSchema } from "@/lib/client";
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { FC } from "react";
|
||||
import { IconEdit } from "@tabler/icons-react";
|
||||
import { IconBlocks, IconEdit } from "@tabler/icons-react";
|
||||
import { Tabs } from "@mantine/core";
|
||||
import GeneralTab from "@/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/GeneralTab";
|
||||
import {
|
||||
GeneralTab,
|
||||
ModulesTab,
|
||||
} from "@/app/deals/drawers/ProjectEditorDrawer/tabs";
|
||||
import { ProjectSchema } from "@/lib/client";
|
||||
import styles from "../ProjectEditorDrawer.module.css";
|
||||
|
||||
@ -22,10 +25,18 @@ const ProjectEditorBody: FC<Props> = props => {
|
||||
leftSection={<IconEdit />}>
|
||||
Общая информация
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
value="modules"
|
||||
leftSection={<IconBlocks />}>
|
||||
Модули
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
<Tabs.Panel value="general">
|
||||
<GeneralTab {...props} />
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="modules">
|
||||
<ModulesTab {...props} />
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { FC } from "react";
|
||||
import { Stack, TextInput } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import Footer from "@/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/Footer";
|
||||
import Footer from "@/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/components/Footer";
|
||||
import { ProjectSchema } from "@/lib/client";
|
||||
|
||||
type Props = {
|
||||
@ -10,7 +10,7 @@ type Props = {
|
||||
onDelete: (value: ProjectSchema) => void;
|
||||
};
|
||||
|
||||
const GeneralTab: FC<Props> = ({ value, onChange, onDelete }) => {
|
||||
export const GeneralTab: FC<Props> = ({ value, onChange, onDelete }) => {
|
||||
const form = useForm<ProjectSchema>({
|
||||
initialValues: value,
|
||||
validate: {
|
||||
@ -38,5 +38,3 @@ const GeneralTab: FC<Props> = ({ value, onChange, onDelete }) => {
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default GeneralTab;
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
import { FC } from "react";
|
||||
import { isEqual } from "lodash";
|
||||
import { Button, Stack } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { ProjectSchema } from "@/lib/client";
|
||||
import ModulesTable from "./components/ModulesTable";
|
||||
|
||||
type Props = {
|
||||
value: ProjectSchema;
|
||||
onChange: (value: ProjectSchema) => void;
|
||||
};
|
||||
|
||||
export const ModulesTab: FC<Props> = ({ value, onChange }) => {
|
||||
const form = useForm<ProjectSchema>({
|
||||
initialValues: value,
|
||||
});
|
||||
|
||||
const onSubmit = (values: ProjectSchema) => {
|
||||
onChange(values);
|
||||
form.setInitialValues(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={form.onSubmit(onSubmit)}>
|
||||
<Stack p={"md"}>
|
||||
<ModulesTable
|
||||
selectedRecords={form.values.builtInModules}
|
||||
onSelectedRecordsChange={modules =>
|
||||
form.setFieldValue("builtInModules", modules)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
type={"submit"}
|
||||
variant={"default"}
|
||||
disabled={isEqual(value, form.values)}>
|
||||
Сохранить
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,32 @@
|
||||
import { FC, useRef } from "react";
|
||||
import { Divider, Stack } from "@mantine/core";
|
||||
import useModulesTableColumns from "@/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns";
|
||||
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
||||
import { BuiltInModuleSchema } from "@/lib/client";
|
||||
import { MODULES } from "@/modules/modules";
|
||||
|
||||
type Props = {
|
||||
selectedRecords: BuiltInModuleSchema[];
|
||||
onSelectedRecordsChange: (records: BuiltInModuleSchema[]) => void;
|
||||
};
|
||||
|
||||
const ModulesTable: FC<Props> = props => {
|
||||
const columns = useModulesTableColumns();
|
||||
const modules = useRef(
|
||||
Object.values(MODULES).map(module => module.modelData)
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack gap={0}>
|
||||
<Divider />
|
||||
<BaseTable
|
||||
records={modules.current}
|
||||
columns={columns}
|
||||
verticalSpacing={"md"}
|
||||
{...props}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModulesTable;
|
||||
@ -0,0 +1,24 @@
|
||||
import { useMemo } from "react";
|
||||
import { DataTableColumn } from "mantine-datatable";
|
||||
import { BuiltInModuleSchema } from "@/lib/client";
|
||||
|
||||
const useModulesTableColumns = () => {
|
||||
return useMemo(
|
||||
() =>
|
||||
[
|
||||
{
|
||||
accessor: "label",
|
||||
title: "Название",
|
||||
width: "30%",
|
||||
},
|
||||
{
|
||||
title: "Описание",
|
||||
accessor: "description",
|
||||
width: "70%",
|
||||
},
|
||||
] as DataTableColumn<BuiltInModuleSchema>[],
|
||||
[]
|
||||
);
|
||||
};
|
||||
|
||||
export default useModulesTableColumns;
|
||||
2
src/app/deals/drawers/ProjectEditorDrawer/tabs/index.ts
Normal file
2
src/app/deals/drawers/ProjectEditorDrawer/tabs/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export { GeneralTab } from "./GeneralTab/GeneralTab";
|
||||
export { ModulesTab } from "./ModulesTab/ModulesTab";
|
||||
@ -13,7 +13,7 @@ const CreateProjectButton: FC = () => {
|
||||
title: "Создание проекта",
|
||||
withCloseButton: true,
|
||||
innerProps: {
|
||||
onChange: values => projectsCrud.onCreate(values.name),
|
||||
onChange: projectsCrud.onCreate,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -13,7 +13,7 @@ const CreateStatusButton: FC = () => {
|
||||
title: "Создание колонки",
|
||||
withCloseButton: true,
|
||||
innerProps: {
|
||||
onChange: values => statusesCrud.onCreate(values.name),
|
||||
onChange: statusesCrud.onCreate,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user