From e151e4bc5e880bf7d0fed9ae815f108c0cdf6952 Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Sun, 2 Mar 2025 16:49:28 +0400 Subject: [PATCH] fix: projects editor to selected project editor, moved attributes editor --- src/client/index.ts | 1 + src/client/models/ProjectGeneralInfoSchema.ts | 9 ++ src/client/models/UpdateProjectRequest.ts | 4 +- .../Dnd/Boards/Boards/hooks/useBoards.tsx | 6 +- .../Cards/CardSummaryItem/CardSummaryItem.tsx | 4 +- .../Cards/CardsDndColumn/CardsDndColumn.tsx | 4 +- .../CreateCardButton/CreateCardButton.tsx | 4 +- .../Cards/CreateCardForm/CreateCardForm.tsx | 4 +- src/contexts/ProjectsContext.tsx | 68 +++++++++++ .../CardsPage => }/hooks/useProjects.tsx | 2 +- src/main.tsx | 12 +- src/modals/modals.ts | 4 +- src/pages/AdminPage/AdminPage.tsx | 11 +- .../tabs/Attributes/Attributes.tsx} | 16 +-- .../components/AttributeTypeSelect.tsx | 4 +- .../components/DefaultAttributeValueInput.tsx | 2 +- .../hooks/attributesTableColumns.tsx | 4 +- .../hooks/useAttributeTypesList.tsx | 4 +- .../Attributes}/modals/AttributeModal.tsx | 6 +- .../CardsPageHeader/CardsPageHeader.tsx | 42 +++++-- .../CardsPage/contexts/CardPageContext.tsx | 5 +- .../contexts/ProjectsEditorContext.tsx | 19 +-- .../ProjectEditDrawer.module.css} | 0 .../ProjectEditDrawer.tsx} | 27 +++-- .../tabs/Attributes/Attributes.tsx | 71 +++++++++++ .../hooks/attributesTableColumns.tsx | 0 .../tabs/General/General.tsx | 114 ++++++++++++++++++ .../General}/hooks/projectsTableColumns.tsx | 0 .../General}/modals/CreateProjectModal.tsx | 0 .../tabs/Modules/Modules.tsx | 70 +++++++++++ .../Modules}/hooks/modulesTableColumns.tsx | 0 .../tabs/Modules}/hooks/useModulesList.tsx | 0 .../utils/defaultValueToStr.ts | 0 .../utils/eqSet.ts | 0 .../utils/stringConverting.ts | 0 .../tabs/ProjectsTab/ProjectsTab.tsx | 43 ------- .../components/AttributesPicker.tsx | 79 ------------ .../ProjectsTab/components/ModulesPicker.tsx | 78 ------------ .../ProjectsTab/components/ProjectsEditor.tsx | 95 --------------- .../tabs/ProjectsTab/hooks/useProjectsTab.tsx | 83 ------------- src/pages/CardsPage/hooks/useBoards.tsx | 13 +- .../CardsPage/hooks/useCardsPageState.tsx | 17 +-- src/pages/CardsPage/ui/CardsPage.tsx | 62 +++++----- .../CardsPage/utils/isModuleInProject.ts | 1 + 44 files changed, 476 insertions(+), 512 deletions(-) create mode 100644 src/client/models/ProjectGeneralInfoSchema.ts create mode 100644 src/contexts/ProjectsContext.tsx rename src/{pages/CardsPage => }/hooks/useProjects.tsx (87%) rename src/pages/{CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/AttributesTab.tsx => AdminPage/tabs/Attributes/Attributes.tsx} (87%) rename src/pages/{CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab => AdminPage/tabs/Attributes}/components/AttributeTypeSelect.tsx (84%) rename src/pages/{CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab => AdminPage/tabs/Attributes}/components/DefaultAttributeValueInput.tsx (97%) rename src/pages/{CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab => AdminPage/tabs/Attributes}/hooks/attributesTableColumns.tsx (93%) rename src/pages/{CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab => AdminPage/tabs/Attributes}/hooks/useAttributeTypesList.tsx (64%) rename src/pages/{CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab => AdminPage/tabs/Attributes}/modals/AttributeModal.tsx (96%) rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer/ProjectsEditorDrawer.module.css => ProjectEditDrawer/ProjectEditDrawer.module.css} (100%) rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer/ProjectsEditorDrawer.tsx => ProjectEditDrawer/ProjectEditDrawer.tsx} (71%) create mode 100644 src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Attributes/Attributes.tsx rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer/tabs/ProjectsTab => ProjectEditDrawer/tabs/Attributes}/hooks/attributesTableColumns.tsx (100%) create mode 100644 src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/General.tsx rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer/tabs/ProjectsTab => ProjectEditDrawer/tabs/General}/hooks/projectsTableColumns.tsx (100%) rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer/tabs/ProjectsTab => ProjectEditDrawer/tabs/General}/modals/CreateProjectModal.tsx (100%) create mode 100644 src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/Modules.tsx rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer/tabs/ProjectsTab => ProjectEditDrawer/tabs/Modules}/hooks/modulesTableColumns.tsx (100%) rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer/tabs/ProjectsTab => ProjectEditDrawer/tabs/Modules}/hooks/useModulesList.tsx (100%) rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer => ProjectEditDrawer}/utils/defaultValueToStr.ts (100%) rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer => ProjectEditDrawer}/utils/eqSet.ts (100%) rename src/pages/CardsPage/drawers/{ProjectsEditorDrawer => ProjectEditDrawer}/utils/stringConverting.ts (100%) delete mode 100644 src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/ProjectsTab.tsx delete mode 100644 src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/AttributesPicker.tsx delete mode 100644 src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ModulesPicker.tsx delete mode 100644 src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ProjectsEditor.tsx delete mode 100644 src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/useProjectsTab.tsx diff --git a/src/client/index.ts b/src/client/index.ts index ddff108..b9b3fad 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -308,6 +308,7 @@ export type { ProductUploadImageResponse } from './models/ProductUploadImageResp export type { ProfitChartDataItem } from './models/ProfitChartDataItem'; export type { ProfitTableDataItem } from './models/ProfitTableDataItem'; export type { ProfitTableGroupBy } from './models/ProfitTableGroupBy'; +export type { ProjectGeneralInfoSchema } from './models/ProjectGeneralInfoSchema'; export type { ProjectSchema } from './models/ProjectSchema'; export type { ReceiptBoxSchema } from './models/ReceiptBoxSchema'; export type { ReceiptPalletSchema } from './models/ReceiptPalletSchema'; diff --git a/src/client/models/ProjectGeneralInfoSchema.ts b/src/client/models/ProjectGeneralInfoSchema.ts new file mode 100644 index 0000000..954d507 --- /dev/null +++ b/src/client/models/ProjectGeneralInfoSchema.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ProjectGeneralInfoSchema = { + name: string; + id: number; +}; + diff --git a/src/client/models/UpdateProjectRequest.ts b/src/client/models/UpdateProjectRequest.ts index eb9e41f..db3347e 100644 --- a/src/client/models/UpdateProjectRequest.ts +++ b/src/client/models/UpdateProjectRequest.ts @@ -2,8 +2,8 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { ProjectSchema } from './ProjectSchema'; +import type { ProjectGeneralInfoSchema } from './ProjectGeneralInfoSchema'; export type UpdateProjectRequest = { - project: ProjectSchema; + project: ProjectGeneralInfoSchema; }; diff --git a/src/components/Dnd/Boards/Boards/hooks/useBoards.tsx b/src/components/Dnd/Boards/Boards/hooks/useBoards.tsx index c89deef..d097cf8 100644 --- a/src/components/Dnd/Boards/Boards/hooks/useBoards.tsx +++ b/src/components/Dnd/Boards/Boards/hooks/useBoards.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { BoardSchema, BoardService } from "../../../../../client"; import { modals } from "@mantine/modals"; import { notifications } from "../../../../../shared/lib/notifications.ts"; -import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx"; +import { useProjectsContext } from "../../../../../contexts/ProjectsContext.tsx"; type Props = { boards: BoardSchema[]; @@ -11,7 +11,7 @@ type Props = { const useBoards = ({ boards, refetchBoards }: Props) => { const [selectedBoard, setSelectedBoard] = useState(null); - const { selectedProject: project } = useCardPageContext(); + const { selectedProject: project } = useProjectsContext(); useEffect(() => { if (boards.length > 0 && selectedBoard === null) { @@ -24,7 +24,7 @@ const useBoards = ({ boards, refetchBoards }: Props) => { let newBoard = boards.find(board => board.id === selectedBoard.id); if (!newBoard && boards.length > 0) { - newBoard = boards[0] + newBoard = boards[0]; } setSelectedBoard(newBoard ?? null); } diff --git a/src/components/Dnd/Cards/CardSummaryItem/CardSummaryItem.tsx b/src/components/Dnd/Cards/CardSummaryItem/CardSummaryItem.tsx index f70b1a8..e811f11 100644 --- a/src/components/Dnd/Cards/CardSummaryItem/CardSummaryItem.tsx +++ b/src/components/Dnd/Cards/CardSummaryItem/CardSummaryItem.tsx @@ -10,6 +10,7 @@ import { IconCheck, IconLayoutGridRemove, IconTrash } from "@tabler/icons-react" import { useContextMenu } from "mantine-contextmenu"; import useCardSummaryState from "./useCardSummaryState.tsx"; import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts"; +import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx"; type Props = { cardSummary: CardSummary; @@ -18,7 +19,8 @@ type Props = { const CardSummaryItem: FC = ({ cardSummary, color }) => { const { showContextMenu } = useContextMenu(); - const { selectedProject, setSelectedCard } = useCardPageContext(); + const { selectedProject } = useProjectsContext(); + const { setSelectedCard } = useCardPageContext(); const { onDelete, onComplete, onDeleteFromGroup } = useCardSummaryState(); const isServicesAndProductsIncluded = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedProject); diff --git a/src/components/Dnd/Cards/CardsDndColumn/CardsDndColumn.tsx b/src/components/Dnd/Cards/CardsDndColumn/CardsDndColumn.tsx index 8b2a8ea..365ebec 100644 --- a/src/components/Dnd/Cards/CardsDndColumn/CardsDndColumn.tsx +++ b/src/components/Dnd/Cards/CardsDndColumn/CardsDndColumn.tsx @@ -9,8 +9,8 @@ import { groupBy, has, uniq } from "lodash"; import { CardGroupView } from "../CardGroupView/CardGroupView.tsx"; import CreateDealsFromFileButton from "../CreateCardsFromFileButton/CreateDealsFromFileButton.tsx"; import DragState from "../../../../pages/CardsPage/enums/DragState.ts"; -import { useCardPageContext } from "../../../../pages/CardsPage/contexts/CardPageContext.tsx"; import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts"; +import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx"; type Props = { status: StatusSchema; @@ -27,7 +27,7 @@ export const CardsDndColumn: FC = ({ dragState, withCreateButton = false, }) => { - const { selectedProject } = useCardPageContext(); + const { selectedProject } = useProjectsContext(); const isCreatingDealFromFileEnabled = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedProject); const isDropDisabled = dragState === DragState.DRAG_STATUS; const droppableId = status.id.toString(); diff --git a/src/components/Dnd/Cards/CreateCardButton/CreateCardButton.tsx b/src/components/Dnd/Cards/CreateCardButton/CreateCardButton.tsx index bd9aa7e..5d9eeae 100644 --- a/src/components/Dnd/Cards/CreateCardButton/CreateCardButton.tsx +++ b/src/components/Dnd/Cards/CreateCardButton/CreateCardButton.tsx @@ -7,8 +7,8 @@ import { CardService, StatusSchema } from "../../../../client"; import { useQueryClient } from "@tanstack/react-query"; import { dateWithoutTimezone } from "../../../../shared/lib/date.ts"; import { usePrefillCardContext } from "../../../../pages/CardsPage/contexts/PrefillCardContext.tsx"; -import { useCardPageContext } from "../../../../pages/CardsPage/contexts/CardPageContext.tsx"; import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts"; +import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx"; type Props = { status: StatusSchema; @@ -20,7 +20,7 @@ const CreateCardButton = ({ status }: Props) => { const queryClient = useQueryClient(); const { prefillCard, setPrefillCard } = usePrefillCardContext(); - const { selectedProject } = useCardPageContext(); + const { selectedProject } = useProjectsContext(); const isPrefillingDealEnabled = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedProject); return ( diff --git a/src/components/Dnd/Cards/CreateCardForm/CreateCardForm.tsx b/src/components/Dnd/Cards/CreateCardForm/CreateCardForm.tsx index 4042c3d..09125fa 100644 --- a/src/components/Dnd/Cards/CreateCardForm/CreateCardForm.tsx +++ b/src/components/Dnd/Cards/CreateCardForm/CreateCardForm.tsx @@ -9,8 +9,8 @@ import ShippingWarehouseAutocomplete from "../../../Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx"; import BaseMarketplaceSelect from "../../../Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx"; import { usePrefillCardContext } from "../../../../pages/CardsPage/contexts/PrefillCardContext.tsx"; -import { useCardPageContext } from "../../../../pages/CardsPage/contexts/CardPageContext.tsx"; import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts"; +import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx"; type Props = { onSubmit: (quickDeal: QuickCard) => void; @@ -18,7 +18,7 @@ type Props = { }; const CreateCardForm: FC = ({ onSubmit, onCancel }) => { - const { selectedProject } = useCardPageContext(); + const { selectedProject } = useProjectsContext(); const isPrefillingEnabled = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedProject); const { prefillOnOpen, prefillCard } = usePrefillCardContext(); diff --git a/src/contexts/ProjectsContext.tsx b/src/contexts/ProjectsContext.tsx new file mode 100644 index 0000000..9f4ddfd --- /dev/null +++ b/src/contexts/ProjectsContext.tsx @@ -0,0 +1,68 @@ +import React, { createContext, FC, useContext, useEffect, useState } from "react"; +import { ProjectSchema } from "../client"; +import useProjects from "../hooks/useProjects.tsx"; + +type ProjectsContextState = { + selectedProject: ProjectSchema | null; + setSelectedProject: React.Dispatch>; + refetchProjects: () => void; + projects: ProjectSchema[]; +}; + +const ProjectsContext = createContext( + undefined, +); + +const useProjectsContextState = () => { + const { projects, refetchProjects } = useProjects(); + const [selectedProject, setSelectedProject] = useState(null); + + const refetch = () => { + refetchProjects(); + }; + + useEffect(() => { + if (projects.length > 0) { + if (selectedProject) { + setSelectedProject( + projects.find(project => project.id === selectedProject.id) ?? null, + ); + } else { + setSelectedProject(projects[0]); + } + } else { + setSelectedProject(null); + } + }, [projects]); + + return { + projects, + refetchProjects: refetch, + selectedProject, + setSelectedProject, + }; +}; + +type ProjectsContextProviderProps = { + children: React.ReactNode; +}; + +export const ProjectsContextProvider: FC = ({ children }) => { + const state = useProjectsContextState(); + + return ( + + {children} + + ); +}; + +export const useProjectsContext = () => { + const context = useContext(ProjectsContext); + if (!context) { + throw new Error( + "useProjectsContext must be used within a ProjectsContextProvider", + ); + } + return context; +}; diff --git a/src/pages/CardsPage/hooks/useProjects.tsx b/src/hooks/useProjects.tsx similarity index 87% rename from src/pages/CardsPage/hooks/useProjects.tsx rename to src/hooks/useProjects.tsx index c320edb..0fe0dc8 100644 --- a/src/pages/CardsPage/hooks/useProjects.tsx +++ b/src/hooks/useProjects.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { type FullProjectSchema, ProjectService } from "../../../client"; +import { type FullProjectSchema, ProjectService } from "../client"; const useProjects = () => { diff --git a/src/main.tsx b/src/main.tsx index 0493dad..f3c2d9b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -23,6 +23,7 @@ import { DatesProvider } from "@mantine/dates"; import { modals } from "./modals/modals.ts"; import TasksProvider from "./providers/TasksProvider/TasksProvider.tsx"; import { ContextMenuProvider } from "mantine-contextmenu"; +import { ProjectsContextProvider } from "./contexts/ProjectsContext.tsx"; // Configuring router const router = createRouter({ routeTree }); @@ -43,22 +44,21 @@ const queryClient = new QueryClient(); // Configuring OpenAPI OpenAPI.BASE = import.meta.env.VITE_API_URL; -OpenAPI.TOKEN = JSON.parse(localStorage.getItem("authState") || "{}")[ - "accessToken" - ]; +OpenAPI.TOKEN = JSON.parse(localStorage.getItem("authState") || "{}")["accessToken"]; ReactDOM.createRoot(document.getElementById("root")!).render( - - - + + + + diff --git a/src/modals/modals.ts b/src/modals/modals.ts index a68cfa8..a54a0a0 100644 --- a/src/modals/modals.ts +++ b/src/modals/modals.ts @@ -35,9 +35,9 @@ import ReceiptModal from "../pages/ReceiptPage/components/ReceiptEditing/modals/ import SelectScannedProductModal from "../pages/ReceiptPage/modals/SelectScannedProductModal.tsx"; import BoardModal from "../pages/CardsPage/modals/BoardModal/BoardModal.tsx"; import StatusModal from "../pages/CardsPage/modals/StatusModal/StatusModal.tsx"; -import AttributeModal from "../pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/modals/AttributeModal.tsx"; +import AttributeModal from "../pages/AdminPage/tabs/Attributes/modals/AttributeModal.tsx"; import CreateProjectModal - from "../pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/modals/CreateProjectModal.tsx"; + from "../pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/modals/CreateProjectModal.tsx"; export const modals = { enterDeadline: EnterDeadlineModal, diff --git a/src/pages/AdminPage/AdminPage.tsx b/src/pages/AdminPage/AdminPage.tsx index fdda5a8..654ac8c 100644 --- a/src/pages/AdminPage/AdminPage.tsx +++ b/src/pages/AdminPage/AdminPage.tsx @@ -6,7 +6,7 @@ import { IconCalendarUser, IconCoins, IconCurrencyDollar, - IconQrcode, + IconQrcode, IconSubtask, IconTopologyStar3, IconUser, } from "@tabler/icons-react"; @@ -21,6 +21,7 @@ import { RootState } from "../../redux/store.ts"; import OrganizationalStructureTab from "./tabs/OrganizationalStructureTab/OrganizationalStructureTab.tsx"; import { ReactNode } from "react"; import WorkShiftsPlanning from "./tabs/WorkShiftsPlanning/WorkShiftsPlanning.tsx"; +import Attributes from "./tabs/Attributes/Attributes.tsx"; const AdminPage = () => { const userRole = useSelector((state: RootState) => state.auth.role); @@ -88,6 +89,13 @@ const AdminPage = () => { Доходы и расходы )} + {isAdmin && ( + }> + Атрибуты карточек + + )} {getTabPanel("users", )} {getTabPanel("rolesAndPositions", )} @@ -96,6 +104,7 @@ const AdminPage = () => { {getTabPanel("workShiftsPlanning", )} {getTabPanel("workShifts", )} {getTabPanel("transactions", )} + {getTabPanel("attributes", )} diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/AttributesTab.tsx b/src/pages/AdminPage/tabs/Attributes/Attributes.tsx similarity index 87% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/AttributesTab.tsx rename to src/pages/AdminPage/tabs/Attributes/Attributes.tsx index 153d055..acbea49 100644 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/AttributesTab.tsx +++ b/src/pages/AdminPage/tabs/Attributes/Attributes.tsx @@ -1,15 +1,15 @@ -import { BaseTable } from "../../../../../../components/BaseTable/BaseTable.tsx"; +import { BaseTable } from "../../../../components/BaseTable/BaseTable.tsx"; import useAttributesTableColumns from "./hooks/attributesTableColumns.tsx"; -import useAttributesList from "../../../../../../hooks/useAttributesList.tsx"; +import useAttributesList from "../../../../hooks/useAttributesList.tsx"; import { ActionIcon, Flex, Group, Stack, Text, Tooltip } from "@mantine/core"; -import InlineButton from "../../../../../../components/InlineButton/InlineButton.tsx"; +import InlineButton from "../../../../components/InlineButton/InlineButton.tsx"; import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react"; import { modals } from "@mantine/modals"; -import { AttributeSchema, AttributeService } from "../../../../../../client"; -import { notifications } from "../../../../../../shared/lib/notifications.ts"; +import { AttributeSchema, AttributeService } from "../../../../client"; +import { notifications } from "../../../../shared/lib/notifications.ts"; import { MRT_TableOptions } from "mantine-react-table"; -const AttributesTab = () => { +const Attributes = () => { const columns = useAttributesTableColumns(); const { objects: attributes, refetch: refetchAttributes } = useAttributesList(); @@ -66,7 +66,7 @@ const AttributesTab = () => { return ( - + Добавить атрибут @@ -109,4 +109,4 @@ const AttributesTab = () => { ); }; -export default AttributesTab; +export default Attributes; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/components/AttributeTypeSelect.tsx b/src/pages/AdminPage/tabs/Attributes/components/AttributeTypeSelect.tsx similarity index 84% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/components/AttributeTypeSelect.tsx rename to src/pages/AdminPage/tabs/Attributes/components/AttributeTypeSelect.tsx index 8d683e8..31babd7 100644 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/components/AttributeTypeSelect.tsx +++ b/src/pages/AdminPage/tabs/Attributes/components/AttributeTypeSelect.tsx @@ -1,5 +1,5 @@ -import ObjectSelect, { ObjectSelectProps } from "../../../../../../../components/ObjectSelect/ObjectSelect.tsx"; -import { AttributeTypeSchema } from "../../../../../../../client"; +import ObjectSelect, { ObjectSelectProps } from "../../../../../components/ObjectSelect/ObjectSelect.tsx"; +import { AttributeTypeSchema } from "../../../../../client"; import useAttributeTypesList from "../hooks/useAttributeTypesList.tsx"; type Props = Omit, "data">; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/components/DefaultAttributeValueInput.tsx b/src/pages/AdminPage/tabs/Attributes/components/DefaultAttributeValueInput.tsx similarity index 97% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/components/DefaultAttributeValueInput.tsx rename to src/pages/AdminPage/tabs/Attributes/components/DefaultAttributeValueInput.tsx index a056a65..cd5c37c 100644 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/components/DefaultAttributeValueInput.tsx +++ b/src/pages/AdminPage/tabs/Attributes/components/DefaultAttributeValueInput.tsx @@ -1,7 +1,7 @@ import { Checkbox, NumberInput, TextInput } from "@mantine/core"; import { UseFormReturnType } from "@mantine/form"; import { DatePickerInput, DateTimePicker } from "@mantine/dates"; -import { AttributeSchema } from "../../../../../../../client"; +import { AttributeSchema } from "../../../../../client"; type Props = { form: UseFormReturnType>; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/hooks/attributesTableColumns.tsx b/src/pages/AdminPage/tabs/Attributes/hooks/attributesTableColumns.tsx similarity index 93% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/hooks/attributesTableColumns.tsx rename to src/pages/AdminPage/tabs/Attributes/hooks/attributesTableColumns.tsx index ee21381..1dfea1e 100644 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/hooks/attributesTableColumns.tsx +++ b/src/pages/AdminPage/tabs/Attributes/hooks/attributesTableColumns.tsx @@ -1,8 +1,8 @@ import { useMemo } from "react"; import { MRT_ColumnDef } from "mantine-react-table"; -import { AttributeSchema } from "../../../../../../../client"; +import { AttributeSchema } from "../../../../../client"; import { IconCheck, IconX } from "@tabler/icons-react"; -import { formatDate, formatDateTime } from "../../../../../../../types/utils.ts"; +import { formatDate, formatDateTime } from "../../../../../types/utils.ts"; const useAttributesTableColumns = () => { diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/hooks/useAttributeTypesList.tsx b/src/pages/AdminPage/tabs/Attributes/hooks/useAttributeTypesList.tsx similarity index 64% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/hooks/useAttributeTypesList.tsx rename to src/pages/AdminPage/tabs/Attributes/hooks/useAttributeTypesList.tsx index 011ca2b..278ca83 100644 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/hooks/useAttributeTypesList.tsx +++ b/src/pages/AdminPage/tabs/Attributes/hooks/useAttributeTypesList.tsx @@ -1,5 +1,5 @@ -import { AttributeService } from "../../../../../../../client"; -import ObjectList from "../../../../../../../hooks/objectList.tsx"; +import { AttributeService } from "../../../../../client"; +import ObjectList from "../../../../../hooks/objectList.tsx"; const useAttributeTypesList = () => ObjectList({ diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/modals/AttributeModal.tsx b/src/pages/AdminPage/tabs/Attributes/modals/AttributeModal.tsx similarity index 96% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/modals/AttributeModal.tsx rename to src/pages/AdminPage/tabs/Attributes/modals/AttributeModal.tsx index 353b366..9dd5533 100644 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/AttributesTab/modals/AttributeModal.tsx +++ b/src/pages/AdminPage/tabs/Attributes/modals/AttributeModal.tsx @@ -2,11 +2,11 @@ import { ContextModalProps } from "@mantine/modals"; import { Button, Checkbox, Stack, Textarea, TextInput } from "@mantine/core"; import { useEffect, useState } from "react"; import AttributeTypeSelect from "../components/AttributeTypeSelect.tsx"; -import { AttributeSchema, AttributeService } from "../../../../../../../client"; -import { convertRussianToSnakeCase } from "../../../utils/stringConverting.ts"; +import { AttributeSchema, AttributeService } from "../../../../../client"; +import { convertRussianToSnakeCase } from "../../../../CardsPage/drawers/ProjectEditDrawer/utils/stringConverting.ts"; import { useForm } from "@mantine/form"; import DefaultAttributeValueInput from "../components/DefaultAttributeValueInput.tsx"; -import { notifications } from "../../../../../../../shared/lib/notifications.ts"; +import { notifications } from "../../../../../shared/lib/notifications.ts"; type Props = { diff --git a/src/pages/CardsPage/components/CardsPageHeader/CardsPageHeader.tsx b/src/pages/CardsPage/components/CardsPageHeader/CardsPageHeader.tsx index 7e2a15e..5f6ef71 100644 --- a/src/pages/CardsPage/components/CardsPageHeader/CardsPageHeader.tsx +++ b/src/pages/CardsPage/components/CardsPageHeader/CardsPageHeader.tsx @@ -1,5 +1,5 @@ import { ActionIcon, Flex, rem, Text } from "@mantine/core"; -import { IconEdit, IconMenu2, IconMenuDeep } from "@tabler/icons-react"; +import { IconEdit, IconMenu2, IconMenuDeep, IconPlus } from "@tabler/icons-react"; import { motion } from "framer-motion"; import styles from "../../ui/CardsPage.module.css"; import PageBlock from "../../../../components/PageBlock/PageBlock.tsx"; @@ -7,30 +7,41 @@ import DisplayMode from "../../enums/DisplayMode.ts"; import { UseFormReturnType } from "@mantine/form"; import { CardsPageState } from "../../hooks/useCardsPageState.tsx"; import React from "react"; -import { ProjectSchema } from "../../../../client"; import ObjectSelect from "../../../../components/ObjectSelect/ObjectSelect.tsx"; import CardsTableFiltersModal from "../../modals/CardsTableFiltersModal.tsx"; import { useProjectsEditorContext } from "../../contexts/ProjectsEditorContext.tsx"; import { useSelector } from "react-redux"; import { RootState } from "../../../../redux/store.ts"; +import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx"; +import { modals } from "@mantine/modals"; type Props = { displayMode: DisplayMode; setDisplayMode: React.Dispatch>; form: UseFormReturnType; - projects: ProjectSchema[]; } const CardsPageHeader = ({ displayMode, setDisplayMode, form, - projects, }: Props) => { const { openProjectsEditor } = useProjectsEditorContext(); + const { selectedProject, setSelectedProject, projects, refetchProjects } = useProjectsContext(); const userRole = useSelector((state: RootState) => state.auth.role); const isAdmin = userRole === "admin"; + const handleCreateClick = () => { + modals.openContextModal({ + modal: "createProjectModal", + title: "Создание проекта", + withCloseButton: false, + innerProps: { + refetchProjects, + }, + }); + }; + const getHeaderInputsBoard = () => { return (
{isAdmin && ( - - - + <> + + + + + + + )}
); diff --git a/src/pages/CardsPage/contexts/CardPageContext.tsx b/src/pages/CardsPage/contexts/CardPageContext.tsx index 480b454..14b6182 100644 --- a/src/pages/CardsPage/contexts/CardPageContext.tsx +++ b/src/pages/CardsPage/contexts/CardPageContext.tsx @@ -1,12 +1,11 @@ import React, { createContext, FC, useContext, useEffect, useState } from "react"; -import { CardSchema, CardService, ProjectSchema } from "../../../client"; +import { CardSchema, CardService } from "../../../client"; type CardPageContextState = { selectedCard?: CardSchema; setSelectedCard: (card: CardSchema | undefined) => void; refetchCards: () => Promise; refetchCard: () => void; - selectedProject?: ProjectSchema | null; }; const CardPageContext = createContext( @@ -16,7 +15,6 @@ const CardPageContext = createContext( type CardPageContextStateProps = { refetchCards: () => Promise; defaultCardId?: number; - selectedProject?: ProjectSchema | null; } const useCardPageContextState = (props: CardPageContextStateProps) => { @@ -41,7 +39,6 @@ const useCardPageContextState = (props: CardPageContextStateProps) => { return { selectedCard, setSelectedCard, - selectedProject: props.selectedProject, refetchCards, refetchCard, }; diff --git a/src/pages/CardsPage/contexts/ProjectsEditorContext.tsx b/src/pages/CardsPage/contexts/ProjectsEditorContext.tsx index f157a67..6a965bc 100644 --- a/src/pages/CardsPage/contexts/ProjectsEditorContext.tsx +++ b/src/pages/CardsPage/contexts/ProjectsEditorContext.tsx @@ -5,37 +5,28 @@ type ProjectsEditorContextState = { openedProjectsEditor: boolean; openProjectsEditor: () => void; closeProjectsEditor: () => void; - onUpdate: () => void; }; const ProjectsEditorContext = createContext( undefined, ); -type ProjectsEditorContextStateProps = { - onUpdate: () => void; -} - -const useProjectsEditorContextState = ({ onUpdate }: ProjectsEditorContextStateProps) => { +const useProjectsEditorContextState = () => { const [opened, { open, close }] = useDisclosure(false); return { openedProjectsEditor: opened, openProjectsEditor: open, closeProjectsEditor: close, - onUpdate, }; }; type ProjectsEditorContextProviderProps = { children: React.ReactNode; -} & ProjectsEditorContextStateProps; +}; -export const ProjectsEditorContextProvider: FC = ({ - children, - ...props - }) => { - const state = useProjectsEditorContextState(props); +export const ProjectsEditorContextProvider: FC = ({ children }) => { + const state = useProjectsEditorContextState(); return ( @@ -48,7 +39,7 @@ export const useProjectsEditorContext = () => { const context = useContext(ProjectsEditorContext); if (!context) { throw new Error( - "useProjectsEditorContext must be used within a ProjectsEditorContextProvider", + "useProjectEditorContext must be used within a ProjectEditorContextProvider", ); } return context; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/ProjectsEditorDrawer.module.css b/src/pages/CardsPage/drawers/ProjectEditDrawer/ProjectEditDrawer.module.css similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/ProjectsEditorDrawer.module.css rename to src/pages/CardsPage/drawers/ProjectEditDrawer/ProjectEditDrawer.module.css diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/ProjectsEditorDrawer.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/ProjectEditDrawer.tsx similarity index 71% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/ProjectsEditorDrawer.tsx rename to src/pages/CardsPage/drawers/ProjectEditDrawer/ProjectEditDrawer.tsx index 470099b..4c258e8 100644 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/ProjectsEditorDrawer.tsx +++ b/src/pages/CardsPage/drawers/ProjectEditDrawer/ProjectEditDrawer.tsx @@ -1,13 +1,14 @@ import { Box, Drawer, rem, Tabs } from "@mantine/core"; -import { IconSettings, IconSubtask } from "@tabler/icons-react"; +import { IconHexagons, IconSettings, IconSubtask } from "@tabler/icons-react"; import { ReactNode } from "react"; import { motion } from "framer-motion"; import { useProjectsEditorContext } from "../../contexts/ProjectsEditorContext.tsx"; -import ProjectsTab from "./tabs/ProjectsTab/ProjectsTab.tsx"; -import AttributesTab from "./tabs/AttributesTab/AttributesTab.tsx"; +import General from "./tabs/General/General.tsx"; +import Attributes from "./tabs/Attributes/Attributes.tsx"; +import Modules from "./tabs/Modules/Modules.tsx"; -const ProjectsEditorDrawer = () => { +const ProjectEditDrawer = () => { const { closeProjectsEditor, openedProjectsEditor } = useProjectsEditorContext(); const getTabPanel = (value: string, component: ReactNode) => { @@ -45,16 +46,21 @@ const ProjectsEditorDrawer = () => { }, }}> }> - Проекты + Общее + + }> + Модули { - {getTabPanel("projects", )} - {getTabPanel("attributes", )} + {getTabPanel("general", )} + {getTabPanel("attributes", )} + {getTabPanel("modules", )} ); }; -export default ProjectsEditorDrawer; +export default ProjectEditDrawer; diff --git a/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Attributes/Attributes.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Attributes/Attributes.tsx new file mode 100644 index 0000000..ed55d97 --- /dev/null +++ b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Attributes/Attributes.tsx @@ -0,0 +1,71 @@ +import { ProjectService } from "../../../../../../client"; +import useAttributesList from "../../../../../../hooks/useAttributesList.tsx"; +import { useEffect, useState } from "react"; +import { useSet } from "@mantine/hooks"; +import useAttributesTableColumns from "./hooks/attributesTableColumns.tsx"; +import { notifications } from "../../../../../../shared/lib/notifications.ts"; +import { rem, Stack } from "@mantine/core"; +import { BaseTable } from "../../../../../../components/BaseTable/BaseTable.tsx"; +import eqSet from "../../utils/eqSet.ts"; +import InlineButton from "../../../../../../components/InlineButton/InlineButton.tsx"; +import { IconCheck } from "@tabler/icons-react"; +import { useProjectsContext } from "../../../../../../contexts/ProjectsContext.tsx"; + + +const Attributes = () => { + const { selectedProject: project, refetchProjects } = useProjectsContext(); + + const { objects: attributes } = useAttributesList(); + const [defaultSelectedAttributes, setDefaultSelectedAttributes] = useState(new Set(project?.attributes.map(m => m.id))); + const selectedAttributes = useSet(project?.attributes.map(a => a.id)); + const columns = useAttributesTableColumns({ selectedAttributes }); + + useEffect(() => { + selectedAttributes.clear(); + project?.attributes.forEach(attribute => { + selectedAttributes.add(attribute.id); + }); + setDefaultSelectedAttributes(new Set([...selectedAttributes])); + }, [project]); + + const onUpdateAttributesClick = () => { + if (!project) return; + ProjectService.updateProjectAttributes({ + requestBody: { + projectId: project.id, + attributeIds: selectedAttributes.values().toArray(), + }, + }) + .then(({ ok, message }) => { + if (!ok) { + notifications.error({ message }); + } + refetchProjects(); + }) + .catch(err => console.log(err)); + }; + + return ( + + + {!eqSet(selectedAttributes, defaultSelectedAttributes) && ( + + + Сохранить + + )} + + ); +}; + +export default Attributes; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/attributesTableColumns.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Attributes/hooks/attributesTableColumns.tsx similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/attributesTableColumns.tsx rename to src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Attributes/hooks/attributesTableColumns.tsx diff --git a/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/General.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/General.tsx new file mode 100644 index 0000000..6000d3f --- /dev/null +++ b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/General.tsx @@ -0,0 +1,114 @@ +import { Button, Fieldset, Flex, rem, Stack, Text, TextInput } from "@mantine/core"; +import { ProjectService } from "../../../../../../client"; +import { useForm } from "@mantine/form"; +import { notifications } from "../../../../../../shared/lib/notifications.ts"; +import { isEqual } from "lodash"; +import { useProjectsContext } from "../../../../../../contexts/ProjectsContext.tsx"; +import { modals } from "@mantine/modals"; +import { useProjectsEditorContext } from "../../../../contexts/ProjectsEditorContext.tsx"; + + +type ProjectForm = { + name: string; +} + +const General = () => { + const { selectedProject: project, refetchProjects } = useProjectsContext(); + const { closeProjectsEditor } = useProjectsEditorContext(); + if (!project) return; + + const form = useForm({ + initialValues: project, + validate: { + name: name => !name && "Название проекта не введено", + }, + }); + + const onProjectDelete = () => { + ProjectService.deleteProject({ + projectId: project.id, + }) + .then(({ ok, message }) => { + if (!ok) { + notifications.error({ message }); + return; + } + closeProjectsEditor(); + refetchProjects(); + }) + .catch(err => console.log(err)); + }; + + const onDeleteProjectClick = () => { + modals.openConfirmModal({ + title: "Удаление проекта", + children: ( + + Вы уверены что хотите удалить проект "{project.name}"? + + ), + labels: { confirm: "Да", cancel: "Нет" }, + confirmProps: { color: "red" }, + onConfirm: () => onProjectDelete(), + }); + }; + + const onSubmit = (values: ProjectForm) => { + ProjectService.updateProject({ + requestBody: { + project: { + id: project.id, + name: values.name, + }, + }, + }) + .then(({ ok, message }) => { + if (!ok) { + notifications.error({ message }); + return; + } + refetchProjects(); + }) + .catch(err => console.log(err)); + }; + + return ( +
onSubmit(values))}> + +
+ + + +
+ + + + + +
+
+ ); +}; + +export default General; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/projectsTableColumns.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/hooks/projectsTableColumns.tsx similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/projectsTableColumns.tsx rename to src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/hooks/projectsTableColumns.tsx diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/modals/CreateProjectModal.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/modals/CreateProjectModal.tsx similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/modals/CreateProjectModal.tsx rename to src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/modals/CreateProjectModal.tsx diff --git a/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/Modules.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/Modules.tsx new file mode 100644 index 0000000..156838f --- /dev/null +++ b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/Modules.tsx @@ -0,0 +1,70 @@ +import useModulesList from "./hooks/useModulesList.tsx"; +import { useEffect, useState } from "react"; +import { useSet } from "@mantine/hooks"; +import useModulesTableColumns from "./hooks/modulesTableColumns.tsx"; +import { ProjectService } from "../../../../../../client"; +import { notifications } from "../../../../../../shared/lib/notifications.ts"; +import { rem, Stack } from "@mantine/core"; +import { BaseTable } from "../../../../../../components/BaseTable/BaseTable.tsx"; +import eqSet from "../../utils/eqSet.ts"; +import InlineButton from "../../../../../../components/InlineButton/InlineButton.tsx"; +import { IconCheck } from "@tabler/icons-react"; +import { useProjectsContext } from "../../../../../../contexts/ProjectsContext.tsx"; + +const Modules = () => { + const { selectedProject: project, refetchProjects } = useProjectsContext(); + + const { objects: modules } = useModulesList(); + const [defaultSelectedModules, setDefaultSelectedModules] = useState( + new Set(project?.modules.map(m => m.id)), + ); + const selectedModules = useSet(); + const columns = useModulesTableColumns({ selectedModules }); + + useEffect(() => { + selectedModules.clear(); + project?.modules.forEach(module => { + selectedModules.add(module.id); + }); + setDefaultSelectedModules(new Set([...selectedModules])); + }, [project]); + + const updateProjectModules = () => { + if (!project) return; + ProjectService.updateProjectModules({ + requestBody: { + projectId: project.id, + moduleIds: selectedModules.values().toArray(), + }, + }) + .then(({ ok, message }) => { + if (!ok) { + notifications.error({ message }); + } + refetchProjects(); + }) + .catch(err => console.log(err)); + }; + + return ( + + + {!eqSet(selectedModules, defaultSelectedModules) && ( + + + Сохранить + + )} + + ); +}; + +export default Modules; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/modulesTableColumns.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/hooks/modulesTableColumns.tsx similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/modulesTableColumns.tsx rename to src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/hooks/modulesTableColumns.tsx diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/useModulesList.tsx b/src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/hooks/useModulesList.tsx similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/useModulesList.tsx rename to src/pages/CardsPage/drawers/ProjectEditDrawer/tabs/Modules/hooks/useModulesList.tsx diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/utils/defaultValueToStr.ts b/src/pages/CardsPage/drawers/ProjectEditDrawer/utils/defaultValueToStr.ts similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/utils/defaultValueToStr.ts rename to src/pages/CardsPage/drawers/ProjectEditDrawer/utils/defaultValueToStr.ts diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/utils/eqSet.ts b/src/pages/CardsPage/drawers/ProjectEditDrawer/utils/eqSet.ts similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/utils/eqSet.ts rename to src/pages/CardsPage/drawers/ProjectEditDrawer/utils/eqSet.ts diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/utils/stringConverting.ts b/src/pages/CardsPage/drawers/ProjectEditDrawer/utils/stringConverting.ts similarity index 100% rename from src/pages/CardsPage/drawers/ProjectsEditorDrawer/utils/stringConverting.ts rename to src/pages/CardsPage/drawers/ProjectEditDrawer/utils/stringConverting.ts diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/ProjectsTab.tsx b/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/ProjectsTab.tsx deleted file mode 100644 index 23301a8..0000000 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/ProjectsTab.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Group } from "@mantine/core"; -import { ProjectSchema } from "../../../../../../client"; -import ModulesPicker from "./components/ModulesPicker.tsx"; -import { useEffect, useState } from "react"; -import AttributesPicker from "./components/AttributesPicker.tsx"; -import useProjects from "../../../../hooks/useProjects.tsx"; -import ProjectsEditor from "./components/ProjectsEditor.tsx"; - -const ProjectsTab = () => { - const { projects, refetchProjects } = useProjects(); - const [selectedProject, setSelectedProject] = useState(null); - - useEffect(() => { - if (projects.length > 0) { - if (!selectedProject) { - setSelectedProject(projects[0]); - } else { - setSelectedProject(projects.find((project) => project.id === selectedProject.id) ?? null); - } - } - }, [projects]); - - return ( - - - - - - ); -}; - -export default ProjectsTab; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/AttributesPicker.tsx b/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/AttributesPicker.tsx deleted file mode 100644 index dcaa9c3..0000000 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/AttributesPicker.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { ProjectSchema, ProjectService } from "../../../../../../../client"; -import styles from "../../../ProjectsEditorDrawer.module.css"; -import { Center, rem, Stack, Title } from "@mantine/core"; -import { BaseTable } from "../../../../../../../components/BaseTable/BaseTable.tsx"; -import useAttributesList from "../../../../../../../hooks/useAttributesList.tsx"; -import useAttributesTableColumns from "../hooks/attributesTableColumns.tsx"; -import { useSet } from "@mantine/hooks"; -import { useEffect, useState } from "react"; -import { notifications } from "../../../../../../../shared/lib/notifications.ts"; -import InlineButton from "../../../../../../../components/InlineButton/InlineButton.tsx"; -import { IconCheck } from "@tabler/icons-react"; -import eqSet from "../../../utils/eqSet.ts"; - - -type Props = { - project: ProjectSchema | null; - refetchProjects: () => void; -} - -const AttributesPicker = ({ project, refetchProjects }: Props) => { - const { objects: attributes } = useAttributesList(); - const [defaultSelectedAttributes, setDefaultSelectedAttributes] = useState(new Set(project?.attributes.map(m => m.id))); - const selectedAttributes = useSet(project?.attributes.map(a => a.id)); - const columns = useAttributesTableColumns({ selectedAttributes }); - - useEffect(() => { - selectedAttributes.clear(); - project?.attributes.forEach(attribute => { - selectedAttributes.add(attribute.id); - }); - setDefaultSelectedAttributes(new Set([...selectedAttributes])); - }, [project]); - - const onUpdateAttributesClick = () => { - if (!project) return; - ProjectService.updateProjectAttributes({ - requestBody: { - projectId: project.id, - attributeIds: selectedAttributes.values().toArray(), - }, - }) - .then(({ ok, message }) => { - if (!ok) { - notifications.error({ message }); - } - refetchProjects(); - }) - .catch(err => console.log(err)); - }; - - return ( -
- -
- Атрибуты проекта -
- - {!eqSet(selectedAttributes, defaultSelectedAttributes) && ( - - - Сохранить - - )} -
-
- ); -}; - -export default AttributesPicker; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ModulesPicker.tsx b/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ModulesPicker.tsx deleted file mode 100644 index 705cefb..0000000 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ModulesPicker.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { ProjectSchema, ProjectService } from "../../../../../../../client"; -import useModulesList from "../hooks/useModulesList.tsx"; -import styles from "../../../ProjectsEditorDrawer.module.css"; -import { useSet } from "@mantine/hooks"; -import useModulesTableColumns from "../hooks/modulesTableColumns.tsx"; -import { BaseTable } from "../../../../../../../components/BaseTable/BaseTable.tsx"; -import { Center, rem, Stack, Title } from "@mantine/core"; -import { useEffect, useState } from "react"; -import InlineButton from "../../../../../../../components/InlineButton/InlineButton.tsx"; -import { IconCheck } from "@tabler/icons-react"; -import { notifications } from "../../../../../../../shared/lib/notifications.ts"; -import eqSet from "../../../utils/eqSet.ts"; - -type Props = { - project: ProjectSchema | null; - refetchProjects: () => void; -} - -const ModulesPicker = ({ project, refetchProjects }: Props) => { - const { objects: modules } = useModulesList(); - const [defaultSelectedModules, setDefaultSelectedModules] = useState( - new Set(project?.modules.map(m => m.id)), - ); - const selectedModules = useSet(); - const columns = useModulesTableColumns({ selectedModules }); - - useEffect(() => { - selectedModules.clear(); - project?.modules.forEach(module => { - selectedModules.add(module.id); - }); - setDefaultSelectedModules(new Set([...selectedModules])); - }, [project]); - - const updateProjectModules = () => { - if (!project) return; - ProjectService.updateProjectModules({ - requestBody: { - projectId: project.id, - moduleIds: selectedModules.values().toArray(), - }, - }) - .then(({ ok, message }) => { - if (!ok) { - notifications.error({ message }); - } - refetchProjects(); - }) - .catch(err => console.log(err)); - }; - - return ( -
- -
- Модули проекта -
- - {!eqSet(selectedModules, defaultSelectedModules) && ( - - - Сохранить - - )} -
-
- ); -}; - -export default ModulesPicker; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ProjectsEditor.tsx b/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ProjectsEditor.tsx deleted file mode 100644 index 123072d..0000000 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/components/ProjectsEditor.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import styles from "../../../ProjectsEditorDrawer.module.css"; -import { ActionIcon, Center, Flex, rem, Stack, Title, Tooltip } from "@mantine/core"; -import InlineButton from "../../../../../../../components/InlineButton/InlineButton.tsx"; -import { IconCheck, IconEdit, IconPlus, IconTrash } from "@tabler/icons-react"; -import { BaseTable } from "../../../../../../../components/BaseTable/BaseTable.tsx"; -import { MRT_TableOptions } from "mantine-react-table"; -import { FullProjectSchema, ProjectSchema } from "../../../../../../../client"; -import useProjectsTableColumns from "../hooks/projectsTableColumns.tsx"; -import useProjectsTab from "../hooks/useProjectsTab.tsx"; -import React from "react"; - -type Props = { - projects: ProjectSchema[]; - refetchProjects: () => void; - selectedProject: ProjectSchema | null; - setSelectedProject: React.Dispatch>; -} - -const ProjectsEditor = ({ - projects, - refetchProjects, - selectedProject, - setSelectedProject, - }: Props) => { - const { - editingProjects, - handleEditClick, - handleDeleteClick, - handleCreateClick, - } = useProjectsTab({ - refetchProjects, - }); - - const columns = useProjectsTableColumns({ editingProjects, selectedProject, setSelectedProject }); - - return ( -
- -
- Проекты -
- - ( - - - handleEditClick(row.original)} - variant={"default"}> - { - editingProjects.has(row.original.id) ? ( - - ) : ( - - ) - } - - - - handleDeleteClick(row.original)} - disabled={row.original.boardsCount > 0} - variant={"default"}> - - - - - ), - } as MRT_TableOptions - } - /> - - - Добавить - -
-
- ); -}; - -export default ProjectsEditor; diff --git a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/useProjectsTab.tsx b/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/useProjectsTab.tsx deleted file mode 100644 index 5b8ac1c..0000000 --- a/src/pages/CardsPage/drawers/ProjectsEditorDrawer/tabs/ProjectsTab/hooks/useProjectsTab.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { ProjectSchema, ProjectService } from "../../../../../../../client"; -import { notifications } from "../../../../../../../shared/lib/notifications.ts"; -import { useProjectsEditorContext } from "../../../../../contexts/ProjectsEditorContext.tsx"; -import { useMap } from "@mantine/hooks"; -import { modals } from "@mantine/modals"; - -type Props = { - refetchProjects: () => void; -} - -const useProjectsTab = ({ refetchProjects }: Props) => { - const { onUpdate } = useProjectsEditorContext(); - const editingProjects = useMap(); - - const updateProject = (project: ProjectSchema) => { - ProjectService.updateProject({ - requestBody: { - project, - }, - }) - .then(({ ok, message }) => { - if (!ok) { - notifications.error({ message }); - return; - } - editingProjects.delete(project.id); - refetchProjects(); - onUpdate(); - }) - .catch(err => console.log(err)); - }; - - const handleEditClick = (project: ProjectSchema) => { - const editedProject = editingProjects.get(project.id); - - if (!editedProject) { - editingProjects.set(project.id, project); - return; - } - - if (editedProject.name.length === 0) { - notifications.error({ message: "Имя проекта не может быть пустым" }); - return; - } - - updateProject(project); - }; - - const handleDeleteClick = (project: ProjectSchema) => { - ProjectService.deleteProject({ - projectId: project.id, - }) - .then(({ ok, message }) => { - if (!ok) { - notifications.error({ message }); - return; - } - refetchProjects(); - onUpdate(); - }) - .catch(err => console.log(err)); - }; - - const handleCreateClick = () => { - modals.openContextModal({ - modal: "createProjectModal", - title: "Создание проекта", - withCloseButton: false, - innerProps: { - refetchProjects, - }, - }); - }; - - return { - editingProjects, - handleEditClick, - handleDeleteClick, - handleCreateClick, - }; -}; - -export default useProjectsTab; diff --git a/src/pages/CardsPage/hooks/useBoards.tsx b/src/pages/CardsPage/hooks/useBoards.tsx index f1bb355..31694b7 100644 --- a/src/pages/CardsPage/hooks/useBoards.tsx +++ b/src/pages/CardsPage/hooks/useBoards.tsx @@ -1,18 +1,17 @@ import { useEffect, useState } from "react"; import { BoardSchema, BoardService } from "../../../client"; +import { useProjectsContext } from "../../../contexts/ProjectsContext.tsx"; -type Props = { - projectId?: number; -} -const useBoards = ({ projectId }: Props) => { +const useBoards = () => { + const { selectedProject } = useProjectsContext(); const [boards, setBoards] = useState([]); const refetchBoards = () => { - if (!projectId) return; + if (!selectedProject) return; BoardService.getBoards({ - projectId, + projectId: selectedProject.id, }) .then(data => { setBoards(data.boards); @@ -22,7 +21,7 @@ const useBoards = ({ projectId }: Props) => { useEffect(() => { refetchBoards(); - }, [projectId]); + }, [selectedProject]); return { boards, diff --git a/src/pages/CardsPage/hooks/useCardsPageState.tsx b/src/pages/CardsPage/hooks/useCardsPageState.tsx index 6f04a4b..bc73aea 100644 --- a/src/pages/CardsPage/hooks/useCardsPageState.tsx +++ b/src/pages/CardsPage/hooks/useCardsPageState.tsx @@ -3,28 +3,21 @@ import { useForm } from "@mantine/form"; import { useEffect, useState } from "react"; import { BaseMarketplaceSchema, BoardSchema, ClientSchema, ProjectSchema, StatusSchema } from "../../../client"; - -type Props = { - projects: ProjectSchema[]; -} - export type CardsPageState = { id: number | null; marketplace: BaseMarketplaceSchema | null; client: ClientSchema | null; - project: ProjectSchema | null; projectForTable: ProjectSchema | null; board: BoardSchema | null; status: StatusSchema | null; }; -const useCardsPageState = ({ projects }: Props) => { +const useCardsPageState = () => { const { objects } = useCardSummariesFull(); const form = useForm({ initialValues: { - project: null, id: null, marketplace: null, client: null, @@ -51,7 +44,7 @@ const useCardsPageState = ({ projects }: Props) => { } if (form.values.projectForTable) { result = result.filter( - obj => obj.board.projectId === form.values.project?.id, + obj => obj.board.projectId === form.values.projectForTable?.id, ); if (form.values.board) { @@ -78,12 +71,6 @@ const useCardsPageState = ({ projects }: Props) => { applyFilters(); }, [form.values, objects]); - useEffect(() => { - if (projects.length > 0 && form.values.project === null) { - form.setFieldValue("project", projects[0]); - } - }, [projects]); - return { data, form }; }; diff --git a/src/pages/CardsPage/ui/CardsPage.tsx b/src/pages/CardsPage/ui/CardsPage.tsx index db41580..98ae64a 100644 --- a/src/pages/CardsPage/ui/CardsPage.tsx +++ b/src/pages/CardsPage/ui/CardsPage.tsx @@ -13,16 +13,14 @@ import { useParams } from "@tanstack/react-router"; import { PrefillCardsWithExcelContextProvider } from "../contexts/PrefillDealsWithExcelContext.tsx"; import DisplayMode from "../enums/DisplayMode.ts"; import CardsPageHeader from "../components/CardsPageHeader/CardsPageHeader.tsx"; -import useProjects from "../hooks/useProjects.tsx"; import Boards from "../../../components/Dnd/Boards/Boards/Boards.tsx"; import useBoards from "../hooks/useBoards.tsx"; import { ProjectsEditorContextProvider } from "../contexts/ProjectsEditorContext.tsx"; -import ProjectsEditorDrawer from "../drawers/ProjectsEditorDrawer/ProjectsEditorDrawer.tsx"; +import ProjectEditDrawer from "../drawers/ProjectEditDrawer/ProjectEditDrawer.tsx"; export const CardsPage: FC = () => { - const { projects, refetchProjects } = useProjects(); - const { data, form } = useCardsPageState({ projects }); - const { boards, refetchBoards } = useBoards({ projectId: form.values.project?.id }); + const { data, form } = useCardsPageState(); + const { boards, refetchBoards } = useBoards(); const { dealId } = useParams({ strict: false }); const { summariesRaw, refetch: refetchSummaries } = useCardSummaries(); @@ -74,39 +72,37 @@ export const CardsPage: FC = () => { padding: 0, }} > - { - await refetchSummaries(); - }} - selectedProject={form.values.project} - > - - - + + { + await refetchSummaries(); + }} + > + + - - - - {getBody()} - - - - - - + + {getBody()} + + + + + + + + ); }; diff --git a/src/pages/CardsPage/utils/isModuleInProject.ts b/src/pages/CardsPage/utils/isModuleInProject.ts index 70aa924..e41b17a 100644 --- a/src/pages/CardsPage/utils/isModuleInProject.ts +++ b/src/pages/CardsPage/utils/isModuleInProject.ts @@ -6,6 +6,7 @@ export enum Modules { EMPLOYEES = "employees", CLIENTS = "clients", MANAGERS = "managers", + MEGA_MODULE = "hui", } const isModuleInProject = (module: Modules, project?: ProjectSchema | null) => {