diff --git a/src/client/index.ts b/src/client/index.ts index 4993f49..4b2720f 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -32,6 +32,9 @@ export type { BaseEnumListSchema } from './models/BaseEnumListSchema'; export type { BaseEnumSchema } from './models/BaseEnumSchema'; export type { BaseMarketplaceSchema } from './models/BaseMarketplaceSchema'; export type { BaseMessageSchema } from './models/BaseMessageSchema'; +export type { BasePlaceSchema } from './models/BasePlaceSchema'; +export type { BasePlaceTypeSchema } from './models/BasePlaceTypeSchema'; +export type { BasePlaceTypeWithCountSchema } from './models/BasePlaceTypeWithCountSchema'; export type { BaseProjectSchema } from './models/BaseProjectSchema'; export type { BaseShippingWarehouseSchema } from './models/BaseShippingWarehouseSchema'; export type { BaseStatusSchema } from './models/BaseStatusSchema'; @@ -159,6 +162,10 @@ export type { CreatePaymentRecordRequest } from './models/CreatePaymentRecordReq export type { CreatePaymentRecordResponse } from './models/CreatePaymentRecordResponse'; export type { CreatePayRateRequest } from './models/CreatePayRateRequest'; export type { CreatePayRateResponse } from './models/CreatePayRateResponse'; +export type { CreatePlaceRequest } from './models/CreatePlaceRequest'; +export type { CreatePlaceResponse } from './models/CreatePlaceResponse'; +export type { CreatePlaceTypeRequest } from './models/CreatePlaceTypeRequest'; +export type { CreatePlaceTypeResponse } from './models/CreatePlaceTypeResponse'; export type { CreatePositionRequest } from './models/CreatePositionRequest'; export type { CreatePositionResponse } from './models/CreatePositionResponse'; export type { CreateProjectRequest } from './models/CreateProjectRequest'; @@ -197,6 +204,8 @@ export type { DeletePaymentRecordRequest } from './models/DeletePaymentRecordReq export type { DeletePaymentRecordResponse } from './models/DeletePaymentRecordResponse'; export type { DeletePayRateRequest } from './models/DeletePayRateRequest'; export type { DeletePayRateResponse } from './models/DeletePayRateResponse'; +export type { DeletePlaceResponse } from './models/DeletePlaceResponse'; +export type { DeletePlaceTypeResponse } from './models/DeletePlaceTypeResponse'; export type { DeletePositionRequest } from './models/DeletePositionRequest'; export type { DeletePositionResponse } from './models/DeletePositionResponse'; export type { DeleteProjectResponse } from './models/DeleteProjectResponse'; @@ -221,10 +230,15 @@ export type { DepartmentSectionSchema } from './models/DepartmentSectionSchema'; export type { EditMessageRequest } from './models/EditMessageRequest'; export type { EditMessageResponse } from './models/EditMessageResponse'; export type { EditMessageSchema } from './models/EditMessageSchema'; +export type { EditPlaceRequest } from './models/EditPlaceRequest'; +export type { EditPlaceResponse } from './models/EditPlaceResponse'; +export type { EditPlaceTypeRequest } from './models/EditPlaceTypeRequest'; +export type { EditPlaceTypeResponse } from './models/EditPlaceTypeResponse'; export type { FinishPauseByShiftIdResponse } from './models/FinishPauseByShiftIdResponse'; export type { FinishPauseByUserIdResponse } from './models/FinishPauseByUserIdResponse'; export type { FinishShiftByIdResponse } from './models/FinishShiftByIdResponse'; export type { FinishShiftResponse } from './models/FinishShiftResponse'; +export type { FlatPlaceTypeSchema } from './models/FlatPlaceTypeSchema'; export type { FullProjectSchema } from './models/FullProjectSchema'; export type { GenerateInviteCodeRequest } from './models/GenerateInviteCodeRequest'; export type { GenerateInviteCodeResponse } from './models/GenerateInviteCodeResponse'; @@ -261,10 +275,13 @@ export type { GetClientMarketplacesRequest } from './models/GetClientMarketplace export type { GetClientMarketplacesResponse } from './models/GetClientMarketplacesResponse'; export type { GetDepartmentSectionsResponse } from './models/GetDepartmentSectionsResponse'; export type { GetDepartmentsResponse } from './models/GetDepartmentsResponse'; +export type { GetFlatPlaceTypesResponse } from './models/GetFlatPlaceTypesResponse'; export type { GetManagersResponse } from './models/GetManagersResponse'; export type { GetMessagesRequest } from './models/GetMessagesRequest'; export type { GetMessagesResponse } from './models/GetMessagesResponse'; export type { GetPaymentRecordsResponse } from './models/GetPaymentRecordsResponse'; +export type { GetPlacesResponse } from './models/GetPlacesResponse'; +export type { GetPlaceTypesResponse } from './models/GetPlaceTypesResponse'; export type { GetPlannedWorkShiftsResponse } from './models/GetPlannedWorkShiftsResponse'; export type { GetProductBarcodePdfRequest } from './models/GetProductBarcodePdfRequest'; export type { GetProductBarcodePdfResponse } from './models/GetProductBarcodePdfResponse'; @@ -312,6 +329,8 @@ export type { PayRateSchema } from './models/PayRateSchema'; export type { PayRateSchemaBase } from './models/PayRateSchemaBase'; export type { PayrollSchemeSchema } from './models/PayrollSchemeSchema'; export type { PermissionSchema } from './models/PermissionSchema'; +export type { PlaceSchema } from './models/PlaceSchema'; +export type { PlaceTypeSchema } from './models/PlaceTypeSchema'; export type { PlannedWorkShiftSchema } from './models/PlannedWorkShiftSchema'; export type { PlanningTableRow } from './models/PlanningTableRow'; export type { PositionSchema } from './models/PositionSchema'; @@ -483,5 +502,6 @@ export { TaskService } from './services/TaskService'; export { TimeTrackingService } from './services/TimeTrackingService'; export { TransactionService } from './services/TransactionService'; export { UserService } from './services/UserService'; +export { WmsService } from './services/WmsService'; export { WorkShiftsService } from './services/WorkShiftsService'; export { WorkShiftsPlanningService } from './services/WorkShiftsPlanningService'; diff --git a/src/client/models/BasePlaceSchema.ts b/src/client/models/BasePlaceSchema.ts new file mode 100644 index 0000000..0b84083 --- /dev/null +++ b/src/client/models/BasePlaceSchema.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type BasePlaceSchema = { + parentId: (number | null); + placeTypeId: number; +}; + diff --git a/src/client/models/BasePlaceTypeSchema.ts b/src/client/models/BasePlaceTypeSchema.ts new file mode 100644 index 0000000..52abfbe --- /dev/null +++ b/src/client/models/BasePlaceTypeSchema.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type BasePlaceTypeSchema = { + name: string; + parentId: (number | null); +}; + diff --git a/src/client/models/BasePlaceTypeWithCountSchema.ts b/src/client/models/BasePlaceTypeWithCountSchema.ts new file mode 100644 index 0000000..08d110d --- /dev/null +++ b/src/client/models/BasePlaceTypeWithCountSchema.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type BasePlaceTypeWithCountSchema = { + name: string; + parentId: (number | null); + childCount: number; +}; + diff --git a/src/client/models/CancelCardBillRequest.ts b/src/client/models/CancelCardBillRequest.ts index dbdc509..b717454 100644 --- a/src/client/models/CancelCardBillRequest.ts +++ b/src/client/models/CancelCardBillRequest.ts @@ -4,5 +4,6 @@ /* eslint-disable */ export type CancelCardBillRequest = { cardId: number; + force?: (boolean | null); }; diff --git a/src/client/models/CreatePlaceRequest.ts b/src/client/models/CreatePlaceRequest.ts new file mode 100644 index 0000000..d70c3d3 --- /dev/null +++ b/src/client/models/CreatePlaceRequest.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { BasePlaceSchema } from './BasePlaceSchema'; +export type CreatePlaceRequest = { + place: BasePlaceSchema; +}; + diff --git a/src/client/models/CreatePlaceResponse.ts b/src/client/models/CreatePlaceResponse.ts new file mode 100644 index 0000000..0703d41 --- /dev/null +++ b/src/client/models/CreatePlaceResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type CreatePlaceResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/CreatePlaceTypeRequest.ts b/src/client/models/CreatePlaceTypeRequest.ts new file mode 100644 index 0000000..f9ad178 --- /dev/null +++ b/src/client/models/CreatePlaceTypeRequest.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { BasePlaceTypeSchema } from './BasePlaceTypeSchema'; +export type CreatePlaceTypeRequest = { + placeType: BasePlaceTypeSchema; +}; + diff --git a/src/client/models/CreatePlaceTypeResponse.ts b/src/client/models/CreatePlaceTypeResponse.ts new file mode 100644 index 0000000..8019cd4 --- /dev/null +++ b/src/client/models/CreatePlaceTypeResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type CreatePlaceTypeResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/DeletePlaceResponse.ts b/src/client/models/DeletePlaceResponse.ts new file mode 100644 index 0000000..22a4d16 --- /dev/null +++ b/src/client/models/DeletePlaceResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type DeletePlaceResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/DeletePlaceTypeResponse.ts b/src/client/models/DeletePlaceTypeResponse.ts new file mode 100644 index 0000000..876efbd --- /dev/null +++ b/src/client/models/DeletePlaceTypeResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type DeletePlaceTypeResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/EditPlaceRequest.ts b/src/client/models/EditPlaceRequest.ts new file mode 100644 index 0000000..6af5ebe --- /dev/null +++ b/src/client/models/EditPlaceRequest.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PlaceSchema } from './PlaceSchema'; +export type EditPlaceRequest = { + place: PlaceSchema; +}; + diff --git a/src/client/models/EditPlaceResponse.ts b/src/client/models/EditPlaceResponse.ts new file mode 100644 index 0000000..babc03e --- /dev/null +++ b/src/client/models/EditPlaceResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type EditPlaceResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/EditPlaceTypeRequest.ts b/src/client/models/EditPlaceTypeRequest.ts new file mode 100644 index 0000000..23b348f --- /dev/null +++ b/src/client/models/EditPlaceTypeRequest.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { FlatPlaceTypeSchema } from './FlatPlaceTypeSchema'; +export type EditPlaceTypeRequest = { + placeType: FlatPlaceTypeSchema; +}; + diff --git a/src/client/models/EditPlaceTypeResponse.ts b/src/client/models/EditPlaceTypeResponse.ts new file mode 100644 index 0000000..46c5d05 --- /dev/null +++ b/src/client/models/EditPlaceTypeResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type EditPlaceTypeResponse = { + ok: boolean; + message: string; +}; + diff --git a/src/client/models/FlatPlaceTypeSchema.ts b/src/client/models/FlatPlaceTypeSchema.ts new file mode 100644 index 0000000..e6ba63c --- /dev/null +++ b/src/client/models/FlatPlaceTypeSchema.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type FlatPlaceTypeSchema = { + name: string; + parentId: (number | null); + id: number; +}; + diff --git a/src/client/models/GetFlatPlaceTypesResponse.ts b/src/client/models/GetFlatPlaceTypesResponse.ts new file mode 100644 index 0000000..12c47aa --- /dev/null +++ b/src/client/models/GetFlatPlaceTypesResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { FlatPlaceTypeSchema } from './FlatPlaceTypeSchema'; +export type GetFlatPlaceTypesResponse = { + placeTypes: Array; +}; + diff --git a/src/client/models/GetPlaceTypesResponse.ts b/src/client/models/GetPlaceTypesResponse.ts new file mode 100644 index 0000000..3feba8a --- /dev/null +++ b/src/client/models/GetPlaceTypesResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PlaceTypeSchema } from './PlaceTypeSchema'; +export type GetPlaceTypesResponse = { + placeTypes: Array; +}; + diff --git a/src/client/models/GetPlacesResponse.ts b/src/client/models/GetPlacesResponse.ts new file mode 100644 index 0000000..cd3907c --- /dev/null +++ b/src/client/models/GetPlacesResponse.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PlaceSchema } from './PlaceSchema'; +export type GetPlacesResponse = { + places: Array; +}; + diff --git a/src/client/models/PlaceSchema.ts b/src/client/models/PlaceSchema.ts new file mode 100644 index 0000000..687d81d --- /dev/null +++ b/src/client/models/PlaceSchema.ts @@ -0,0 +1,14 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { BasePlaceTypeWithCountSchema } from './BasePlaceTypeWithCountSchema'; +export type PlaceSchema = { + parentId: (number | null); + placeTypeId: number; + id: number; + number: number; + children?: Array; + placeType: BasePlaceTypeWithCountSchema; +}; + diff --git a/src/client/models/PlaceTypeSchema.ts b/src/client/models/PlaceTypeSchema.ts new file mode 100644 index 0000000..b60b0f7 --- /dev/null +++ b/src/client/models/PlaceTypeSchema.ts @@ -0,0 +1,12 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type PlaceTypeSchema = { + name: string; + parentId: (number | null); + id: number; + children?: Array; + placesCount: number; +}; + diff --git a/src/client/services/WmsService.ts b/src/client/services/WmsService.ts new file mode 100644 index 0000000..c5be167 --- /dev/null +++ b/src/client/services/WmsService.ts @@ -0,0 +1,211 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { CreatePlaceRequest } from '../models/CreatePlaceRequest'; +import type { CreatePlaceResponse } from '../models/CreatePlaceResponse'; +import type { CreatePlaceTypeRequest } from '../models/CreatePlaceTypeRequest'; +import type { CreatePlaceTypeResponse } from '../models/CreatePlaceTypeResponse'; +import type { DeletePlaceResponse } from '../models/DeletePlaceResponse'; +import type { DeletePlaceTypeResponse } from '../models/DeletePlaceTypeResponse'; +import type { EditPlaceRequest } from '../models/EditPlaceRequest'; +import type { EditPlaceResponse } from '../models/EditPlaceResponse'; +import type { EditPlaceTypeRequest } from '../models/EditPlaceTypeRequest'; +import type { EditPlaceTypeResponse } from '../models/EditPlaceTypeResponse'; +import type { GetFlatPlaceTypesResponse } from '../models/GetFlatPlaceTypesResponse'; +import type { GetPlacesResponse } from '../models/GetPlacesResponse'; +import type { GetPlaceTypesResponse } from '../models/GetPlaceTypesResponse'; +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; +export class WmsService { + /** + * Get Place Types + * @returns GetPlaceTypesResponse Successful Response + * @throws ApiError + */ + public static getPlaceTypes(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/wms/place-type', + }); + } + /** + * Create Place Type + * @returns CreatePlaceTypeResponse Successful Response + * @throws ApiError + */ + public static createPlaceType({ + requestBody, + }: { + requestBody: CreatePlaceTypeRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/wms/place-type', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Edit Place Type + * @returns EditPlaceTypeResponse Successful Response + * @throws ApiError + */ + public static editPlaceType({ + requestBody, + }: { + requestBody: EditPlaceTypeRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PATCH', + url: '/wms/place-type', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Get Flat Place Types + * @returns GetFlatPlaceTypesResponse Successful Response + * @throws ApiError + */ + public static getFlatPlaceTypes({ + parentPlaceTypeId, + }: { + parentPlaceTypeId: number, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/wms/place-type/flat/{parent_place_type_id}', + path: { + 'parent_place_type_id': parentPlaceTypeId, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Delete Place Type + * @returns DeletePlaceTypeResponse Successful Response + * @throws ApiError + */ + public static deletePlaceType({ + placeTypeId, + }: { + placeTypeId: number, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'DELETE', + url: '/wms/place-type/{place_type_id}', + path: { + 'place_type_id': placeTypeId, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Get Places + * @returns GetPlacesResponse Successful Response + * @throws ApiError + */ + public static getPlaces(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/wms/place', + }); + } + /** + * Create Place + * @returns CreatePlaceResponse Successful Response + * @throws ApiError + */ + public static createPlace({ + requestBody, + }: { + requestBody: CreatePlaceRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/wms/place', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Edit Place + * @returns EditPlaceResponse Successful Response + * @throws ApiError + */ + public static editPlace({ + requestBody, + }: { + requestBody: EditPlaceRequest, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PATCH', + url: '/wms/place', + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Delete Place + * @returns DeletePlaceResponse Successful Response + * @throws ApiError + */ + public static deletePlace({ + placeId, + }: { + placeId: number, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'DELETE', + url: '/wms/place/{place_id}', + path: { + 'place_id': placeId, + }, + errors: { + 422: `Validation Error`, + }, + }); + } + /** + * Generate Place Qr Code Pdf + * @returns any Successful Response + * @throws ApiError + */ + public static getPlaceQrCodePdf({ + placeId, + isShort, + }: { + placeId: number, + isShort: boolean, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/wms/place/pdf/{place_id}/{is_short}', + path: { + 'place_id': placeId, + 'is_short': isShort, + }, + errors: { + 422: `Validation Error`, + }, + }); + } +} diff --git a/src/modals/modals.ts b/src/modals/modals.ts index 2de725b..bf78175 100644 --- a/src/modals/modals.ts +++ b/src/modals/modals.ts @@ -42,6 +42,8 @@ import AttributeModal from "../pages/AdminPage/tabs/Attributes/modals/AttributeM import CreateProjectModal from "../pages/CardsPage/drawers/ProjectEditDrawer/tabs/General/modals/CreateProjectModal.tsx"; import CardTagModal from "../pages/CardsPage/drawers/ProjectEditDrawer/tabs/Tags/modals/CardTagModal.tsx"; +import PlaceTypeModal from "../pages/AdminPage/tabs/WarehouseManagement/placeType/modals/PlaceTypeModal.tsx"; +import PlaceModal from "../pages/AdminPage/tabs/WarehouseManagement/place/modals/PlaceModal.tsx"; export const modals = { enterDeadline: EnterDeadlineModal, @@ -82,4 +84,6 @@ export const modals = { attributeModal: AttributeModal, createProjectModal: CreateProjectModal, cardTagModal: CardTagModal, + placeTypeModal: PlaceTypeModal, + placeModal: PlaceModal, }; diff --git a/src/pages/AdminPage/AdminPage.tsx b/src/pages/AdminPage/AdminPage.tsx index 654ac8c..e1a0ddf 100644 --- a/src/pages/AdminPage/AdminPage.tsx +++ b/src/pages/AdminPage/AdminPage.tsx @@ -9,6 +9,7 @@ import { IconQrcode, IconSubtask, IconTopologyStar3, IconUser, + IconBuildingWarehouse, } from "@tabler/icons-react"; import UsersTab from "./tabs/Users/UsersTab.tsx"; import { motion } from "framer-motion"; @@ -22,6 +23,7 @@ import OrganizationalStructureTab from "./tabs/OrganizationalStructureTab/Organi import { ReactNode } from "react"; import WorkShiftsPlanning from "./tabs/WorkShiftsPlanning/WorkShiftsPlanning.tsx"; import Attributes from "./tabs/Attributes/Attributes.tsx"; +import WarehouseManagementTab from "./tabs/WarehouseManagement/WarehouseManagementTab.tsx"; const AdminPage = () => { const userRole = useSelector((state: RootState) => state.auth.role); @@ -96,6 +98,11 @@ const AdminPage = () => { Атрибуты карточек )} + }> + Управление складом + {getTabPanel("users", )} {getTabPanel("rolesAndPositions", )} @@ -105,6 +112,7 @@ const AdminPage = () => { {getTabPanel("workShifts", )} {getTabPanel("transactions", )} {getTabPanel("attributes", )} + {getTabPanel("warehouseManagement", )} diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/WarehouseManagementTab.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/WarehouseManagementTab.tsx new file mode 100644 index 0000000..c8d77ee --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/WarehouseManagementTab.tsx @@ -0,0 +1,28 @@ +import { WarehouseManagementTabContextProvider } from "./placeType/contexts/WarehouseManagementTabContext.tsx"; +import { WmsPage, WmsSegmentedControl } from "./placeType/components/WmsSegmentedControl.tsx"; +import { useState } from "react"; +import PlaceTypesEditor from "./placeType/components/PlaceTypesEditor.tsx"; +import PlacesEditor from "./place/components/PlacesEditor.tsx"; + +const WarehouseManagementTab = () => { + const [page, setPage] = useState(WmsPage.PLACE); + + return ( + + { + setPage(parseInt(event)); + }} + /> + {page === WmsPage.PLACE_TYPE ? ( + + ) : ( + + )} + + ); +}; + +export default WarehouseManagementTab; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/place/components/Place.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/Place.tsx new file mode 100644 index 0000000..2475b6d --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/Place.tsx @@ -0,0 +1,57 @@ +import { DataTable } from "mantine-datatable"; +import { IconChevronRight, IconSpace } from "@tabler/icons-react"; +import clsx from "clsx"; +import classes from "../../../OrganizationalStructureTab/components/DepartmentsTree/DepartmentsTree.module.css"; +import { useState } from "react"; +import { PlaceSchema } from "../../../../../../client"; +import PlaceActions from "./PlaceActions.tsx"; + +type Props = { + place: PlaceSchema; +} + +const Place = ({ place }: Props) => { + const [placeTypeIds, setPlaceTypeIds] = useState([]); + + return ( + ( + <> + + + {placeType.name} {number} + + ), + }, + { + accessor: "actions", + title: "", + width: "0%", + render: (place) => ( + + ), + }, + ]} + records={place.children?.sort((a, b) => a.id - b.id)} + rowExpansion={{ + allowMultiple: true, + expanded: { recordIds: placeTypeIds, onRecordIdsChange: setPlaceTypeIds }, + content: ({ record }) => ( + + ), + }} + /> + ); +}; + +export default Place; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlaceActions.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlaceActions.tsx new file mode 100644 index 0000000..01ba4b3 --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlaceActions.tsx @@ -0,0 +1,69 @@ +import { PlaceSchema } from "../../../../../../client"; +import { IconBoxAlignBottom, IconPlaylistAdd, IconQrcode, IconTrash } from "@tabler/icons-react"; +import { ActionIcon, Flex, Tooltip } from "@mantine/core"; +import React, { ReactNode } from "react"; +import { useWarehouseManagementTabContext } from "../../placeType/contexts/WarehouseManagementTabContext.tsx"; + + +type Props = { + place: PlaceSchema; +} + +const PlaceActions = ({ place }: Props) => { + const { placeCrud, onCreatePlace, generateQrCode } = useWarehouseManagementTabContext(); + + const getAction = ( + label: string, + func: () => void, + icon: ReactNode, + disabled: boolean = false, + ) => { + return ( + + ) => { + e.stopPropagation(); + func(); + }} + disabled={disabled} + > + {icon} + + + ); + }; + + const actions = [ + getAction( + "Распечатать QR-код", + () => generateQrCode(place, false), + , + ), + getAction( + "Распечатать QR-код ", + () => generateQrCode(place, true), + , + ), + getAction( + "Добавить", + () => onCreatePlace(place), + , + place.placeType.childCount === 0, + ), + getAction( + "Удалить", + () => placeCrud.onDelete && placeCrud.onDelete(place), + , + place.children?.length !== 0, + ), + ]; + + return ( + + {...actions} + + ); +}; + +export default PlaceActions; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlaceTypeSelect.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlaceTypeSelect.tsx new file mode 100644 index 0000000..fe57cbc --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlaceTypeSelect.tsx @@ -0,0 +1,23 @@ +import { FC } from "react"; +import { FlatPlaceTypeSchema } from "../../../../../../client"; +import ObjectSelect, { ObjectSelectProps } from "../../../../../../components/ObjectSelect/ObjectSelect.tsx"; + +type Props = Omit< + ObjectSelectProps, + "getValueFn" | "getLabelFn" +>; + +const PlaceTypeSelect: FC = (props) => { + return ( + placeType.name} + getValueFn={(placeType: FlatPlaceTypeSchema) => placeType.id.toString()} + clearable + searchable + {...props} + onClear={() => props.onChange(null)} + /> + ); +}; + +export default PlaceTypeSelect; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlacesEditor.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlacesEditor.tsx new file mode 100644 index 0000000..a2d591e --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/place/components/PlacesEditor.tsx @@ -0,0 +1,67 @@ +import { Button, Group, Stack } from "@mantine/core"; +import { IconChevronRight, IconSpace } from "@tabler/icons-react"; +import clsx from "clsx"; +import classes from "../../../OrganizationalStructureTab/components/DepartmentsTree/DepartmentsTree.module.css"; +import { DataTable } from "mantine-datatable"; +import { useState } from "react"; +import { useWarehouseManagementTabContext } from "../../placeType/contexts/WarehouseManagementTabContext.tsx"; +import PlaceActions from "./PlaceActions.tsx"; +import Place from "./Place.tsx"; + +const PlacesEditor = () => { + const { places, onCreatePlace } = useWarehouseManagementTabContext(); + const [placeIds, setPlaceIds] = useState([]); + + return ( + + + + + ( + <> + + + {placeType.name} {number} + + ), + }, + { + accessor: "actions", + title: "", + width: "0%", + render: (place) => ( + + ), + }, + ]} + records={places.sort((a, b) => a.id - b.id)} + rowExpansion={{ + allowMultiple: true, + expanded: { recordIds: placeIds, onRecordIdsChange: setPlaceIds }, + content: ({ record }) => ( + + ), + }} + /> + + ); +}; + +export default PlacesEditor; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/place/hooks/usePlacesCrud.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/place/hooks/usePlacesCrud.tsx new file mode 100644 index 0000000..61f52fc --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/place/hooks/usePlacesCrud.tsx @@ -0,0 +1,56 @@ +import { useCRUD } from "../../../../../../hooks/useCRUD.tsx"; +import { BasePlaceSchema, PlaceSchema, WmsService } from "../../../../../../client"; +import { notifications } from "../../../../../../shared/lib/notifications.ts"; + + +export type PlaceCrud = { + onCreate: (element: BasePlaceSchema) => void, + onDelete: (element: PlaceSchema) => void, + onChange: (element: PlaceSchema) => void +} + +type Props = { + fetchPlaces: () => void; +} + +const usePlacesCrud = ({ fetchPlaces }: Props): PlaceCrud => { + return useCRUD({ + onChange: (place: PlaceSchema) => { + WmsService.editPlace({ + requestBody: { place }, + }) + .then(({ ok, message }) => { + fetchPlaces(); + if (ok) return; + notifications.error({ message }); + }) + .catch(err => console.log(err)); + }, + onDelete: (place: PlaceSchema) => { + WmsService.deletePlace({ + placeId: place.id, + }) + .then(({ ok, message }) => { + fetchPlaces(); + if (ok) return; + notifications.error({ message }); + }) + .catch(err => console.log(err)); + }, + onCreate: (place: BasePlaceSchema) => { + WmsService.createPlace({ + requestBody: { + place, + }, + }) + .then(({ ok, message }) => { + fetchPlaces(); + if (ok) return; + notifications.error({ message }); + }) + .catch(err => console.log(err)); + }, + }); +}; + +export default usePlacesCrud; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/place/hooks/usePlacesList.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/place/hooks/usePlacesList.tsx new file mode 100644 index 0000000..d6807a2 --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/place/hooks/usePlacesList.tsx @@ -0,0 +1,11 @@ +import { WmsService } from "../../../../../../client"; +import ObjectList from "../../../../../../hooks/objectList.tsx"; + +const usePlacesList = () => + ObjectList({ + queryFn: WmsService.getPlaces, + getObjectsFn: response => response.places, + queryKey: "getAllPlaces", + }); + +export default usePlacesList; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/place/modals/PlaceModal.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/place/modals/PlaceModal.tsx new file mode 100644 index 0000000..792362a --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/place/modals/PlaceModal.tsx @@ -0,0 +1,65 @@ +import { ContextModalProps } from "@mantine/modals"; +import { FlatPlaceTypeSchema, PlaceSchema } from "../../../../../../client"; +import { Button, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { PlaceCrud } from "../hooks/usePlacesCrud.tsx"; +import PlaceTypeSelect from "../components/PlaceTypeSelect.tsx"; + +type Props = { + placeCrud: PlaceCrud; + parent?: PlaceSchema; + placeTypes: FlatPlaceTypeSchema[]; +} + +type PlaceModalForm = { + placeType: PlaceSchema | null; +} + +const PlaceModal = ({ + context, + id, + innerProps, + }: ContextModalProps) => { + const { parent, placeCrud, placeTypes } = innerProps; + + const closeModal = () => { + context.closeContextModal(id); + }; + + const initialValues: PlaceModalForm = { + placeType: null, + }; + const form = useForm({ + initialValues, + validate: { + placeType: placeType => !placeType && "Необходимо указать тип", + }, + }); + + const onSubmit = (values: PlaceModalForm) => { + if (!values.placeType) return; + placeCrud.onCreate({ + placeTypeId: values.placeType.id, + parentId: parent?.id || null, + }); + closeModal(); + }; + + return ( +
onSubmit(values))}> + + + + + +
+ ); +}; + +export default PlaceModal; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceType.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceType.tsx new file mode 100644 index 0000000..798dd2b --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceType.tsx @@ -0,0 +1,57 @@ +import { PlaceTypeSchema } from "../../../../../../client"; +import { DataTable } from "mantine-datatable"; +import { IconChevronRight, IconSpace } from "@tabler/icons-react"; +import clsx from "clsx"; +import classes from "../../../OrganizationalStructureTab/components/DepartmentsTree/DepartmentsTree.module.css"; +import { useState } from "react"; +import PlaceTypeActions from "./PlaceTypeActions.tsx"; + +type Props = { + placeType: PlaceTypeSchema; +} + +const PlaceType = ({ placeType }: Props) => { + const [placeTypeIds, setPlaceTypeIds] = useState([]); + + return ( + ( + <> + + + {name} + + ), + }, + { + accessor: "actions", + title: "", + width: "0%", + render: (placeType) => ( + + ), + }, + ]} + records={placeType.children?.sort((a, b) => a.id - b.id)} + rowExpansion={{ + allowMultiple: true, + expanded: { recordIds: placeTypeIds, onRecordIdsChange: setPlaceTypeIds }, + content: ({ record }) => ( + + ), + }} + /> + ); +}; + +export default PlaceType; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceTypeActions.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceTypeActions.tsx new file mode 100644 index 0000000..d447b73 --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceTypeActions.tsx @@ -0,0 +1,84 @@ +import { PlaceTypeSchema } from "../../../../../../client"; +import { IconEdit, IconPlaylistAdd, IconTrash } from "@tabler/icons-react"; +import { ActionIcon, Flex, Tooltip } from "@mantine/core"; +import React, { ReactNode } from "react"; +import { useWarehouseManagementTabContext } from "../contexts/WarehouseManagementTabContext.tsx"; +import { modals } from "@mantine/modals"; + + +type Props = { + placeType: PlaceTypeSchema; +} + +const PlaceTypeActions = ({ placeType }: Props) => { + const { placeTypeCrud } = useWarehouseManagementTabContext(); + + const getAction = ( + label: string, + func: () => void, + icon: ReactNode, + disabled: boolean = false, + ) => { + return ( + + ) => { + e.stopPropagation(); + func(); + }} + > + {icon} + + + ); + }; + + const actions = [ + getAction( + "Добавить", + () => { + modals.openContextModal({ + modal: "placeTypeModal", + title: "Создание типа места на складе", + withCloseButton: false, + innerProps: { + placeTypeCrud, + parent: placeType, + }, + }); + }, + , + ), + getAction( + "Редактировать", + () => { + modals.openContextModal({ + modal: "placeTypeModal", + title: "Редактирование типа места на складе", + withCloseButton: false, + innerProps: { + placeTypeCrud, + element: placeType, + }, + }); + }, + , + ), + getAction( + "Удалить", + () => placeTypeCrud.onDelete && placeTypeCrud.onDelete(placeType), + , + placeType.placesCount !== 0 || placeType.children?.length !== 0, + ), + ]; + + return ( + + {...actions} + + ); +}; + +export default PlaceTypeActions; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceTypesEditor.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceTypesEditor.tsx new file mode 100644 index 0000000..50b0e4d --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/PlaceTypesEditor.tsx @@ -0,0 +1,77 @@ +import { Button, Group, Stack } from "@mantine/core"; +import { useWarehouseManagementTabContext } from "../contexts/WarehouseManagementTabContext.tsx"; +import { IconChevronRight, IconSpace } from "@tabler/icons-react"; +import clsx from "clsx"; +import classes from "../../../OrganizationalStructureTab/components/DepartmentsTree/DepartmentsTree.module.css"; +import { DataTable } from "mantine-datatable"; +import { useState } from "react"; +import PlaceType from "./PlaceType.tsx"; +import PlaceTypeActions from "./PlaceTypeActions.tsx"; +import { modals } from "@mantine/modals"; + +const PlaceTypesEditor = () => { + const { placeTypes, placeTypeCrud } = useWarehouseManagementTabContext(); + const [placeTypeIds, setPlaceTypeIds] = useState([]); + + return ( + + + + + ( + <> + + + {name} + + ), + }, + { + accessor: "actions", + title: "", + width: "0%", + render: (placeType) => ( + + ), + }, + ]} + records={placeTypes.sort((a, b) => a.id - b.id)} + rowExpansion={{ + allowMultiple: true, + expanded: { recordIds: placeTypeIds, onRecordIdsChange: setPlaceTypeIds }, + content: ({ record }) => ( + + ), + }} + /> + + ); +}; + +export default PlaceTypesEditor; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/WmsSegmentedControl.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/WmsSegmentedControl.tsx new file mode 100644 index 0000000..31ccf73 --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/components/WmsSegmentedControl.tsx @@ -0,0 +1,28 @@ +import { SegmentedControl, SegmentedControlProps } from "@mantine/core"; +import { FC } from "react"; + +export enum WmsPage { + PLACE, + PLACE_TYPE, +} + +type Props = Omit; +const data = [ + { + label: "Места на складе", + value: WmsPage.PLACE.toString(), + }, + { + label: "Типы мест на складе", + value: WmsPage.PLACE_TYPE.toString(), + }, +]; + +export const WmsSegmentedControl: FC = props => { + return ( + + ); +}; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/contexts/WarehouseManagementTabContext.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/contexts/WarehouseManagementTabContext.tsx new file mode 100644 index 0000000..12fe9f1 --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/contexts/WarehouseManagementTabContext.tsx @@ -0,0 +1,104 @@ +import React, { createContext, FC, useContext } from "react"; +import { PlaceSchema, PlaceTypeSchema, WmsService } from "../../../../../../client"; +import usePlaceTypesList from "../hooks/usePlaceTypesList.tsx"; +import usePlaceTypesCrud, { PlaceTypeCrud } from "../hooks/usePlaceTypesCrud.tsx"; +import usePlacesList from "../../place/hooks/usePlacesList.tsx"; +import usePlacesCrud, { PlaceCrud } from "../../place/hooks/usePlacesCrud.tsx"; +import { modals } from "@mantine/modals"; + +type WarehouseManagementTabContextState = { + refetchPlaceTypes: () => void; + placeTypeCrud: PlaceTypeCrud; + placeTypes: PlaceTypeSchema[]; + refetchPlaces: () => void; + placeCrud: PlaceCrud; + places: PlaceSchema[]; + onCreatePlace: (place?: PlaceSchema) => void; + generateQrCode: (place: PlaceSchema, isShort: boolean) => void; +}; + +const WarehouseManagementTabContext = createContext( + undefined, +); + +const useWarehouseManagementTabContextState = () => { + const { objects: placeTypes, refetch: refetchPlaceTypes } = usePlaceTypesList(); + const { objects: places, refetch: refetchPlaces } = usePlacesList(); + + const placeTypeCrud: PlaceTypeCrud = usePlaceTypesCrud({ + fetchPlaceTypes: refetchPlaceTypes, + }); + + const placeCrud: PlaceCrud = usePlacesCrud({ + fetchPlaces: refetchPlaces, + }); + + const onCreatePlace = (place?: PlaceSchema) => { + WmsService.getFlatPlaceTypes({ + parentPlaceTypeId: place?.placeTypeId || -1, + }) + .then(({ placeTypes }) => { + if (placeTypes.length === 1) { + placeCrud.onCreate({ + parentId: place?.id || null, + placeTypeId: placeTypes[0].id, + }); + return; + } + + modals.openContextModal({ + modal: "placeModal", + title: "Создание места на складе", + withCloseButton: false, + innerProps: { + placeCrud, + parent: place, + placeTypes, + }, + }); + }) + .catch(err => console.log(err)); + }; + + const generateQrCode = (place: PlaceSchema, isShort: boolean) => { + const pdfWindow = window.open( + `${import.meta.env.VITE_API_URL}/wms/place/pdf/${place.id}/${isShort}`, + ); + if (!pdfWindow) return; + pdfWindow.print(); + }; + + return { + placeTypes, + placeTypeCrud, + refetchPlaceTypes, + places, + placeCrud, + refetchPlaces, + onCreatePlace, + generateQrCode, + }; +}; + +type WarehouseManagementTabContextProviderProps = { + children: React.ReactNode; +}; + +export const WarehouseManagementTabContextProvider: FC = ({ children }) => { + const state = useWarehouseManagementTabContextState(); + return ( + + {children} + + ); +}; + +export const useWarehouseManagementTabContext = () => { + const context = useContext(WarehouseManagementTabContext); + if (!context) { + throw new Error( + "useWarehouseManagementTabContext must be used within a WarehouseManagementTabContextProvider", + ); + } + return context; +}; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/useFlatPlaceTypesList.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/useFlatPlaceTypesList.tsx new file mode 100644 index 0000000..2ca74ee --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/useFlatPlaceTypesList.tsx @@ -0,0 +1,11 @@ +import { WmsService } from "../../../../../../client"; +import ObjectList from "../../../../../../hooks/objectList.tsx"; + +const useFlatPlaceTypesList = (parentPlaceTypeId: number = -1) => + ObjectList({ + queryFn: () => WmsService.getFlatPlaceTypes({ parentPlaceTypeId }), + getObjectsFn: response => response.placeTypes, + queryKey: "getFlatPlaceTypes", + }); + +export default useFlatPlaceTypesList; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/usePlaceTypesCrud.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/usePlaceTypesCrud.tsx new file mode 100644 index 0000000..f0fa39d --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/usePlaceTypesCrud.tsx @@ -0,0 +1,56 @@ +import { useCRUD } from "../../../../../../hooks/useCRUD.tsx"; +import { BasePlaceTypeSchema, FlatPlaceTypeSchema, WmsService } from "../../../../../../client"; +import { notifications } from "../../../../../../shared/lib/notifications.ts"; + + +export type PlaceTypeCrud = { + onCreate: (element: BasePlaceTypeSchema) => void, + onDelete: (element: FlatPlaceTypeSchema) => void, + onChange: (element: FlatPlaceTypeSchema) => void +} + +type Props = { + fetchPlaceTypes: () => void; +} + +const usePlaceTypesCrud = ({ fetchPlaceTypes }: Props): PlaceTypeCrud => { + return useCRUD({ + onChange: (placeType: FlatPlaceTypeSchema) => { + WmsService.editPlaceType({ + requestBody: { placeType }, + }) + .then(({ ok, message }) => { + fetchPlaceTypes(); + if (ok) return; + notifications.error({ message }); + }) + .catch(err => console.log(err)); + }, + onDelete: (placeType: FlatPlaceTypeSchema) => { + WmsService.deletePlaceType({ + placeTypeId: placeType.id, + }) + .then(({ ok, message }) => { + fetchPlaceTypes(); + if (ok) return; + notifications.error({ message }); + }) + .catch(err => console.log(err)); + }, + onCreate: (placeType: BasePlaceTypeSchema) => { + WmsService.createPlaceType({ + requestBody: { + placeType, + }, + }) + .then(({ ok, message }) => { + fetchPlaceTypes(); + if (ok) return; + notifications.error({ message }); + }) + .catch(err => console.log(err)); + }, + }); +}; + +export default usePlaceTypesCrud; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/usePlaceTypesList.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/usePlaceTypesList.tsx new file mode 100644 index 0000000..11eea8b --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/hooks/usePlaceTypesList.tsx @@ -0,0 +1,11 @@ +import { WmsService } from "../../../../../../client"; +import ObjectList from "../../../../../../hooks/objectList.tsx"; + +const usePlaceTypesList = () => + ObjectList({ + queryFn: WmsService.getPlaceTypes, + getObjectsFn: response => response.placeTypes, + queryKey: "getAllPlaceTypes", + }); + +export default usePlaceTypesList; diff --git a/src/pages/AdminPage/tabs/WarehouseManagement/placeType/modals/PlaceTypeModal.tsx b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/modals/PlaceTypeModal.tsx new file mode 100644 index 0000000..bb55910 --- /dev/null +++ b/src/pages/AdminPage/tabs/WarehouseManagement/placeType/modals/PlaceTypeModal.tsx @@ -0,0 +1,76 @@ +import { ContextModalProps } from "@mantine/modals"; +import { BasePlaceTypeSchema, PlaceTypeSchema } from "../../../../../../client"; +import { PlaceTypeCrud } from "../hooks/usePlaceTypesCrud.tsx"; +import { Button, Stack, TextInput } from "@mantine/core"; +import { useForm } from "@mantine/form"; + +type Props = { + placeTypeCrud: PlaceTypeCrud; + element?: PlaceTypeSchema & BasePlaceTypeSchema; + parent?: PlaceTypeSchema; +} + +type PlaceTypeModalForm = { + name: string; +} + +const PlaceTypeModal = ({ + context, + id, + innerProps, + }: ContextModalProps) => { + const { element, parent, placeTypeCrud } = innerProps; + + const closeModal = () => { + context.closeContextModal(id); + }; + + const initialValues: PlaceTypeModalForm = { + name: innerProps.element?.name ?? "", + }; + const form = useForm({ + initialValues, + validate: { + name: name => !name && "Необходимо указать название", + }, + }); + + const isChanged = (): boolean => { + return initialValues.name !== form.values.name; + }; + + const onSubmit = (values: PlaceTypeModalForm) => { + if (element) { + if (isChanged()) { + placeTypeCrud.onChange({ + name: values.name ?? "", + id: element?.id, + parentId: element?.parentId ?? null, + }); + } + } else { + placeTypeCrud.onCreate({ + name: values.name ?? "", + parentId: parent?.id ?? null, + }); + } + closeModal(); + }; + + return ( +
onSubmit(values))}> + + + + + +
+ ); +}; + +export default PlaceTypeModal;