added company group table
This commit is contained in:
parent
d2dc230f10
commit
83d4c2b894
@ -1,3 +1,82 @@
|
|||||||
|
import { Button, Space } from "antd";
|
||||||
|
import PageTitle from "../components/PageTitle";
|
||||||
|
import { CatalogueJurTable } from "../widgets/CatalogueJurTable/CatalogueJurTable";
|
||||||
|
import { PlusOutlined } from "@ant-design/icons";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useAppDispatch, useAppSelector } from "../store/store";
|
||||||
|
import { CatalogueJurForm } from "../widgets/CatalogueJurForm/CatalogueJurForm";
|
||||||
|
import { getCatalogueJurThunk } from "../store/slices/catalogueJurSlice/thunks";
|
||||||
|
import { CatalogueJurFormProps } from "../types/catalogueJur/catalogueJur";
|
||||||
|
import { createCatalogueJur } from "../services/api/directories/catalogue_jur";
|
||||||
|
import { CompanyGroupsList } from "../widgets/CompanyGroupsList/CompanyGroupsList";
|
||||||
|
|
||||||
export function CatalogueGroup() {
|
export function CatalogueGroup() {
|
||||||
return <h3>ГК и организации</h3>;
|
const dispatch = useAppDispatch();
|
||||||
|
const isGettingArchive = useAppSelector(
|
||||||
|
(state) => state.catalogue_jur.isGettingArchive,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [createFormOpen, setCreateFormOpen] = useState(false);
|
||||||
|
|
||||||
|
async function createJurHandler(values: CatalogueJurFormProps) {
|
||||||
|
try {
|
||||||
|
await createCatalogueJur(values);
|
||||||
|
dispatch(
|
||||||
|
getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
|
||||||
|
);
|
||||||
|
setCreateFormOpen(false);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: 12,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
height: "100vh",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Space style={{ justifyContent: "space-between" }}>
|
||||||
|
<PageTitle
|
||||||
|
header="Группы компаний и организаций"
|
||||||
|
location="Справочники"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={() => setCreateFormOpen(true)}
|
||||||
|
>
|
||||||
|
Создать ГК/ЮЛ
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
minHeight: 0,
|
||||||
|
display: "flex",
|
||||||
|
gap: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ width: 320, flexShrink: 0, minHeight: 0 }}>
|
||||||
|
<CompanyGroupsList/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ flex: 1, minWidth: 0, minHeight: 0, borderRadius:12, background:'white' }}>
|
||||||
|
<CatalogueJurTable outside_group={false} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{createFormOpen && (
|
||||||
|
<CatalogueJurForm
|
||||||
|
open={createFormOpen}
|
||||||
|
onCancel={() => {
|
||||||
|
setCreateFormOpen(false);
|
||||||
|
}}
|
||||||
|
onOk={(values) => {
|
||||||
|
createJurHandler(values);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,12 +16,12 @@ export function CatalogueJur() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [createFormOpen, setCreateFormOpen] = useState(false);
|
const [createFormOpen, setCreateFormOpen] = useState(false);
|
||||||
|
const outside_group = true
|
||||||
async function createJurHandler(values: CatalogueJurFormProps) {
|
async function createJurHandler(values: CatalogueJurFormProps) {
|
||||||
try {
|
try {
|
||||||
await createCatalogueJur(values);
|
await createCatalogueJur(values);
|
||||||
dispatch(
|
dispatch(
|
||||||
getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
|
getCatalogueJurThunk({ closed: isGettingArchive, outside_group: outside_group }),
|
||||||
);
|
);
|
||||||
setCreateFormOpen(false);
|
setCreateFormOpen(false);
|
||||||
} catch {}
|
} catch {}
|
||||||
@ -46,17 +46,7 @@ export function CatalogueJur() {
|
|||||||
Создать ЮЛ
|
Создать ЮЛ
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
<main
|
<CatalogueJurTable outside_group={outside_group}/>
|
||||||
style={{
|
|
||||||
flex: "1 1 auto",
|
|
||||||
minHeight: 0,
|
|
||||||
overflow: "auto",
|
|
||||||
backgroundColor: "white",
|
|
||||||
borderRadius: 12,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CatalogueJurTable />
|
|
||||||
</main>
|
|
||||||
{createFormOpen && (
|
{createFormOpen && (
|
||||||
<CatalogueJurForm
|
<CatalogueJurForm
|
||||||
open={createFormOpen}
|
open={createFormOpen}
|
||||||
|
|||||||
@ -12,4 +12,5 @@ export interface CatalogueJurSliceType{
|
|||||||
export interface GetCatalogueJurPropsI{
|
export interface GetCatalogueJurPropsI{
|
||||||
closed?:boolean
|
closed?:boolean
|
||||||
outside_group?:boolean
|
outside_group?:boolean
|
||||||
|
company_group_id?:string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +1,40 @@
|
|||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
import { getCompanyGroupsThunk } from './thunks';
|
import { getCompanyGroupsThunk } from "./thunks";
|
||||||
import type { CompanyGroupSliceType } from './types';
|
import type { CompanyGroupSliceType } from "./types";
|
||||||
|
import { ICompanyGroup } from "../../../types/companyGroups/companyGroups";
|
||||||
|
|
||||||
const initialState: CompanyGroupSliceType = {
|
const initialState: CompanyGroupSliceType = {
|
||||||
raw_rows: [],
|
raw_rows: [],
|
||||||
total_groups: 0,
|
total_groups: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
activeCompanyGroup: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const comGroupsSlice = createSlice({
|
const comGroupsSlice = createSlice({
|
||||||
name: 'company_groups',
|
name: "company_groups",
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {},
|
reducers: {
|
||||||
extraReducers: (builder) => {
|
setActiveCompanyGroup(state, action: PayloadAction<ICompanyGroup | null>) {
|
||||||
builder
|
state.activeCompanyGroup = action.payload;
|
||||||
.addCase(getCompanyGroupsThunk.pending, (state) => {
|
},
|
||||||
state.loading = true;
|
},
|
||||||
state.error = null;
|
extraReducers: (builder) => {
|
||||||
})
|
builder
|
||||||
.addCase(getCompanyGroupsThunk.fulfilled, (state, action) => {
|
.addCase(getCompanyGroupsThunk.pending, (state) => {
|
||||||
state.raw_rows = action.payload;
|
state.loading = true;
|
||||||
state.total_groups = action.payload.length;
|
state.error = null;
|
||||||
state.loading = false;
|
})
|
||||||
})
|
.addCase(getCompanyGroupsThunk.fulfilled, (state, action) => {
|
||||||
.addCase(getCompanyGroupsThunk.rejected, (state, action) => {
|
state.raw_rows = action.payload;
|
||||||
state.error = action.payload ?? 'Неизвестная ошибка';
|
state.total_groups = action.payload.length;
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
});
|
})
|
||||||
},
|
.addCase(getCompanyGroupsThunk.rejected, (state, action) => {
|
||||||
|
state.error = action.payload ?? "Неизвестная ошибка";
|
||||||
|
state.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
export const { setActiveCompanyGroup } = comGroupsSlice.actions;
|
||||||
export default comGroupsSlice.reducer;
|
export default comGroupsSlice.reducer;
|
||||||
|
|||||||
@ -5,4 +5,5 @@ export interface CompanyGroupSliceType {
|
|||||||
raw_rows: ICompanyGroup[];
|
raw_rows: ICompanyGroup[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
|
activeCompanyGroup?:ICompanyGroup | null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export interface ICatalogueJur {
|
|||||||
updated_at: Date;
|
updated_at: Date;
|
||||||
outside_group: boolean;
|
outside_group: boolean;
|
||||||
closed: boolean | string;
|
closed: boolean | string;
|
||||||
memberships?: unknown[];
|
memberships?: MemberShips[];
|
||||||
aliases?: JurAlliase[];
|
aliases?: JurAlliase[];
|
||||||
regional_office: {
|
regional_office: {
|
||||||
id: string;
|
id: string;
|
||||||
@ -23,6 +23,16 @@ export interface ICatalogueJur {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type KindType = "gsk" | "gsz"
|
||||||
|
|
||||||
|
export type MemberShips = {
|
||||||
|
related_group_id: string;
|
||||||
|
code: string;
|
||||||
|
kind: KindType;
|
||||||
|
name: string;
|
||||||
|
valid_from: Date;
|
||||||
|
};
|
||||||
|
|
||||||
export type JurAlliase = {
|
export type JurAlliase = {
|
||||||
alias: string;
|
alias: string;
|
||||||
created_at: Date;
|
created_at: Date;
|
||||||
@ -46,7 +56,9 @@ export type CatalogueJurFormProps = {
|
|||||||
crm_id: string;
|
crm_id: string;
|
||||||
entity_type: "ЮЛ" | "ИП";
|
entity_type: "ЮЛ" | "ИП";
|
||||||
name: string;
|
name: string;
|
||||||
aliases?: string[] | {value:string, label:string}[];
|
aliases?: string[] | { value: string; label: string }[];
|
||||||
company_group_id?: string;
|
company_group_id?: string;
|
||||||
regional_office_id?: string;
|
regional_office_id?: string;
|
||||||
|
gsk_id?: string;
|
||||||
|
gsz_id?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Modal, Form, Input, Select, Row, Col, InputNumber } from "antd";
|
import { Modal, Form, Input, Select, Row, Col, InputNumber } from "antd";
|
||||||
import { CatalogueJurFormProps } from "../../types/catalogueJur/catalogueJur";
|
import { CatalogueJurFormProps } from "../../types/catalogueJur/catalogueJur";
|
||||||
import { useAppDispatch, useAppSelector } from "../../store/store";
|
import { useAppDispatch, useAppSelector } from "../../store/store";
|
||||||
import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
|
import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
|
||||||
import { api } from "../../api/client";
|
|
||||||
import { RegionalOffice } from "../../api/types";
|
|
||||||
import { useAsyncData } from "../Admin/hooks";
|
|
||||||
import { fetchOneCatalogueJur } from "../../services/api/directories/catalogue_jur";
|
import { fetchOneCatalogueJur } from "../../services/api/directories/catalogue_jur";
|
||||||
|
import { fetchRelatedGroups } from "../../services/api/directories/company_groups";
|
||||||
|
import { RelatedGroupOut } from "../../types/api";
|
||||||
|
import { useMe } from "../../auth/useMe";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -23,34 +23,55 @@ export const CatalogueJurForm: React.FC<Props> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [form] = Form.useForm<CatalogueJurFormProps>();
|
const [form] = Form.useForm<CatalogueJurFormProps>();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const loadOffices = useCallback(
|
const { me } = useMe();
|
||||||
() => api.get<RegionalOffice[]>("/directories/regional-offices"),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
const offices = useAsyncData(loadOffices);
|
|
||||||
const type = Form.useWatch("entity_type", form);
|
|
||||||
|
|
||||||
const { raw_rows, loading } = useAppSelector((state) => state.company_groups);
|
const type = Form.useWatch("entity_type", form);
|
||||||
|
const activeCompanyGroup = useAppSelector(
|
||||||
|
(state) => state.company_groups.activeCompanyGroup,
|
||||||
|
);
|
||||||
const [initialDataLoading, setInitialDataLoading] = useState(false);
|
const [initialDataLoading, setInitialDataLoading] = useState(false);
|
||||||
|
const [gskData, setGskData] = useState<RelatedGroupOut[]>([]);
|
||||||
|
const [gszData, setGszData] = useState<RelatedGroupOut[]>([]);
|
||||||
|
const [loadingOptions, setLoadingOptions] = useState(false);
|
||||||
|
|
||||||
async function getInitialData() {
|
async function getInitialData() {
|
||||||
setInitialDataLoading(true);
|
setInitialDataLoading(true);
|
||||||
|
form.setFieldsValue({
|
||||||
|
company_group_id: jurId ? undefined : activeCompanyGroup?.id,
|
||||||
|
regional_office_id: me?.regional_office.id,
|
||||||
|
});
|
||||||
if (jurId) {
|
if (jurId) {
|
||||||
const data = await fetchOneCatalogueJur(jurId);
|
const data = await fetchOneCatalogueJur(jurId);
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
name: data?.name,
|
name: data?.name,
|
||||||
company_group_id: data?.company_group_id,
|
|
||||||
aliases: data?.aliases?.map((aliase) => aliase.alias),
|
aliases: data?.aliases?.map((aliase) => aliase.alias),
|
||||||
crm_id: data?.crm_id,
|
crm_id: data?.crm_id,
|
||||||
entity_type: data?.entity_type,
|
entity_type: data?.entity_type,
|
||||||
inn: data.inn,
|
inn: data.inn,
|
||||||
kpp: data?.kpp,
|
kpp: data?.kpp,
|
||||||
regional_office_id: data?.regional_office_id,
|
regional_office_id: data?.regional_office_id,
|
||||||
|
gsk_id: data.memberships?.find((elem) => elem.kind === "gsk")
|
||||||
|
?.related_group_id,
|
||||||
|
gsz_id: data.memberships?.find((elem) => elem.kind === "gsz")
|
||||||
|
?.related_group_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setInitialDataLoading(false);
|
setInitialDataLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getRelatedGroupsHandler() {
|
||||||
|
if (activeCompanyGroup?.id) {
|
||||||
|
setLoadingOptions(true);
|
||||||
|
const res = await fetchRelatedGroups(activeCompanyGroup?.id);
|
||||||
|
const gsks = res.filter((elem) => elem.kind === "gsk");
|
||||||
|
const gszs = res.filter((elem) => elem.kind === "gsz");
|
||||||
|
setGskData(gsks);
|
||||||
|
setGszData(gszs);
|
||||||
|
setLoadingOptions(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
try {
|
try {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
@ -58,7 +79,6 @@ export const CatalogueJurForm: React.FC<Props> = ({
|
|||||||
...values,
|
...values,
|
||||||
kpp: type === "ИП" ? undefined : values.kpp?.toString(),
|
kpp: type === "ИП" ? undefined : values.kpp?.toString(),
|
||||||
inn: jurId ? undefined : values?.inn?.toString(),
|
inn: jurId ? undefined : values?.inn?.toString(),
|
||||||
company_group_id: jurId ? undefined : values.company_group_id,
|
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
return;
|
return;
|
||||||
@ -71,16 +91,19 @@ export const CatalogueJurForm: React.FC<Props> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open && raw_rows.length === 0 && !loading) {
|
if (open) {
|
||||||
dispatch(getCompanyGroupsThunk());
|
dispatch(getCompanyGroupsThunk());
|
||||||
}
|
}
|
||||||
}, [open, raw_rows.length, loading, dispatch]);
|
}, [open, dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!!jurId) {
|
getInitialData();
|
||||||
getInitialData();
|
|
||||||
}
|
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getRelatedGroupsHandler();
|
||||||
|
}, [activeCompanyGroup]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={
|
title={
|
||||||
@ -183,30 +206,29 @@ export const CatalogueJurForm: React.FC<Props> = ({
|
|||||||
|
|
||||||
<Row gutter={16}>
|
<Row gutter={16}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item name="company_group_id" label="Входит в ГСК">
|
<Form.Item name="gsk_id" label="Входит в ГСК">
|
||||||
<Select
|
<Select
|
||||||
disabled={!!jurId}
|
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="— не указан —"
|
placeholder="— не указан —"
|
||||||
options={raw_rows?.map((g) => ({ value: g.id, label: g.name }))}
|
options={gskData?.map((g) => ({ value: g.id, label: g.name }))}
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
notFoundContent={loading ? "Загрузка" : "Нет вариантов"}
|
notFoundContent={loadingOptions ? "Загрузка" : "Нет вариантов"}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item name="regional_office_id" label="Входит в ГСЗ">
|
<Form.Item name="gsz_id" label="Входит в ГСЗ">
|
||||||
<Select
|
<Select
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="— не указан —"
|
placeholder="— не указан —"
|
||||||
options={offices?.data?.map((g) => ({
|
options={gszData?.map((g) => ({
|
||||||
value: g.id,
|
value: g.id,
|
||||||
label: g.name,
|
label: g.name,
|
||||||
}))}
|
}))}
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
notFoundContent={loading ? "Загрузка" : "Нет вариантов"}
|
notFoundContent={loadingOptions ? "Загрузка" : "Нет вариантов"}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { Button, Checkbox, Dropdown, Input, Space } from "antd";
|
import { Button, Checkbox, Dropdown, Input, Space, Tabs } from "antd";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import type { ColumnsType } from "antd/es/table";
|
import type { ColumnsType } from "antd/es/table";
|
||||||
import {
|
import {
|
||||||
@ -35,8 +35,17 @@ import {
|
|||||||
import { WithdrawCatalogueJurForm } from "../WithdrawCatalogueJurForm/WithdrawCatalogueJurForm";
|
import { WithdrawCatalogueJurForm } from "../WithdrawCatalogueJurForm/WithdrawCatalogueJurForm";
|
||||||
import { setIsGettingArchive } from "../../store/slices/catalogueJurSlice/catalogueJurSlice";
|
import { setIsGettingArchive } from "../../store/slices/catalogueJurSlice/catalogueJurSlice";
|
||||||
import { CatalogueJurForm } from "../CatalogueJurForm/CatalogueJurForm";
|
import { CatalogueJurForm } from "../CatalogueJurForm/CatalogueJurForm";
|
||||||
|
import Title from "antd/es/typography/Title";
|
||||||
|
import Text from "antd/es/typography/Text";
|
||||||
|
import { fetchRelatedGroups } from "../../services/api/directories/company_groups";
|
||||||
|
import { RelatedGroupOut } from "../../types/api";
|
||||||
|
|
||||||
export function CatalogueJurTable() {
|
interface CatalogueJurTableI {
|
||||||
|
outside_group: boolean;
|
||||||
|
}
|
||||||
|
type TabKey = "legal_entities" | "gsk" | "gsz";
|
||||||
|
|
||||||
|
export function CatalogueJurTable({ outside_group }: CatalogueJurTableI) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const rawRows = useAppSelector((state) => state.catalogue_jur.raw_rows);
|
const rawRows = useAppSelector((state) => state.catalogue_jur.raw_rows);
|
||||||
@ -44,12 +53,18 @@ export function CatalogueJurTable() {
|
|||||||
const isGettingArchive = useAppSelector(
|
const isGettingArchive = useAppSelector(
|
||||||
(state) => state.catalogue_jur.isGettingArchive,
|
(state) => state.catalogue_jur.isGettingArchive,
|
||||||
);
|
);
|
||||||
|
const activeCompanyGroup = useAppSelector(
|
||||||
|
(state) => state.company_groups.activeCompanyGroup,
|
||||||
|
);
|
||||||
|
|
||||||
const [moveCatalogueFormOpen, setMoveCatalogueFormOpen] = useState(false);
|
const [moveCatalogueFormOpen, setMoveCatalogueFormOpen] = useState(false);
|
||||||
const [editCatalogueFormOpen, setEditCatalogueFormOpen] = useState(false);
|
const [editCatalogueFormOpen, setEditCatalogueFormOpen] = useState(false);
|
||||||
const [withdrawCatalogueFormOpen, setWithdrawCatalogueFormOpen] =
|
const [withdrawCatalogueFormOpen, setWithdrawCatalogueFormOpen] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
const [activeTab, setActiveTab] = useState<TabKey>("legal_entities");
|
||||||
const [jurId, setJurId] = useState("");
|
const [jurId, setJurId] = useState("");
|
||||||
|
const [gskData, setGskData] = useState<RelatedGroupOut[]>([]);
|
||||||
|
const [gszData, setGszData] = useState<RelatedGroupOut[]>([]);
|
||||||
const { visibleKeys, setVisibleKeys } = useVisibleColumns(catalogueJurConfig);
|
const { visibleKeys, setVisibleKeys } = useVisibleColumns(catalogueJurConfig);
|
||||||
const {
|
const {
|
||||||
rawQuery,
|
rawQuery,
|
||||||
@ -71,9 +86,12 @@ export function CatalogueJurTable() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
function getCatalogueJur() {
|
function getCatalogueJur() {
|
||||||
// #TODO поменять на outside_group=true
|
|
||||||
dispatch(
|
dispatch(
|
||||||
getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
|
getCatalogueJurThunk({
|
||||||
|
closed: isGettingArchive,
|
||||||
|
outside_group: outside_group,
|
||||||
|
company_group_id:activeCompanyGroup?.id
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,13 +135,27 @@ export function CatalogueJurTable() {
|
|||||||
dispatch(
|
dispatch(
|
||||||
getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
|
getCatalogueJurThunk({ closed: isGettingArchive, outside_group: true }),
|
||||||
);
|
);
|
||||||
closeEditCatalogueJurHandler()
|
closeEditCatalogueJurHandler();
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getRelatedGroupsHandler() {
|
||||||
|
if (activeCompanyGroup?.id) {
|
||||||
|
const res = await fetchRelatedGroups(activeCompanyGroup?.id);
|
||||||
|
const gsks = res.filter((elem) => elem.kind === "gsk");
|
||||||
|
const gszs = res.filter((elem) => elem.kind === "gsz");
|
||||||
|
setGskData(gsks);
|
||||||
|
setGszData(gszs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCatalogueJur();
|
getCatalogueJur();
|
||||||
}, [isGettingArchive]);
|
}, [isGettingArchive, activeCompanyGroup]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getRelatedGroupsHandler();
|
||||||
|
}, [activeCompanyGroup]);
|
||||||
|
|
||||||
const extraColumns: ColumnsType<ICatalogueJur> = useMemo(
|
const extraColumns: ColumnsType<ICatalogueJur> = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@ -182,23 +214,62 @@ export function CatalogueJurTable() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
|
<div
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
height: "100%",
|
||||||
|
background: "white",
|
||||||
|
borderRadius: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!outside_group && (
|
||||||
|
<div
|
||||||
|
style={{ padding: "12px 16px", borderBottom: "1px solid #0f172a0f" }}
|
||||||
|
>
|
||||||
|
<Title level={5} style={{ margin: 0 }}>
|
||||||
|
{activeCompanyGroup?.name}
|
||||||
|
</Title>
|
||||||
|
<Text type="secondary" style={{ fontSize: 13 }}>
|
||||||
|
{activeCompanyGroup?.base_regional_office_name ?? ""}
|
||||||
|
{activeCompanyGroup?.legal_entities_count} организаций
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<Space
|
<Space
|
||||||
style={{
|
style={{
|
||||||
padding: "16px 12px",
|
padding: "0 12px",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
borderBottom: "1px",
|
borderBottom: "1px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Input
|
{outside_group ? (
|
||||||
allowClear
|
<Input
|
||||||
prefix={<SearchOutlined />}
|
allowClear
|
||||||
placeholder="Поиск по ГК, CRM ID или РФ"
|
prefix={<SearchOutlined />}
|
||||||
value={rawQuery}
|
placeholder="Поиск по ГК, CRM ID или РФ"
|
||||||
onChange={(e) => setRawQuery(e.target.value)}
|
value={rawQuery}
|
||||||
style={{ maxWidth: 320 }}
|
onChange={(e) => setRawQuery(e.target.value)}
|
||||||
/>
|
style={{ maxWidth: 320 }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Tabs
|
||||||
|
activeKey={activeTab}
|
||||||
|
onChange={(k) => setActiveTab(k as TabKey)}
|
||||||
|
style={{ marginBottom: 0 }}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: "legal_entities",
|
||||||
|
label: `ЮЛ ${activeCompanyGroup?.legal_entities_count}`,
|
||||||
|
},
|
||||||
|
{ key: "gsk", label: `ГСК ${gskData?.length ?? 0}` },
|
||||||
|
{ key: "gsz", label: `ГСЗ ${gszData?.length ?? 0}` },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<Space>
|
<Space>
|
||||||
{hasActiveFilters && (
|
{hasActiveFilters && (
|
||||||
<Button
|
<Button
|
||||||
@ -210,13 +281,14 @@ export function CatalogueJurTable() {
|
|||||||
Сбросить фильтры
|
Сбросить фильтры
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{activeTab === "legal_entities" && (
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={isGettingArchive}
|
checked={isGettingArchive}
|
||||||
onChange={(e) => dispatch(setIsGettingArchive(e.target.checked))}
|
onChange={(e) => dispatch(setIsGettingArchive(e.target.checked))}
|
||||||
>
|
>
|
||||||
Архив
|
Архив
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
)}
|
||||||
<ColumnSettings
|
<ColumnSettings
|
||||||
defs={catalogueJurConfig.columns}
|
defs={catalogueJurConfig.columns}
|
||||||
visibleKeys={visibleKeys}
|
visibleKeys={visibleKeys}
|
||||||
@ -224,7 +296,6 @@ export function CatalogueJurTable() {
|
|||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
</Space>
|
</Space>
|
||||||
|
|
||||||
<DataTable
|
<DataTable
|
||||||
sortState={sort}
|
sortState={sort}
|
||||||
onSortChange={setSort}
|
onSortChange={setSort}
|
||||||
@ -267,7 +338,7 @@ export function CatalogueJurTable() {
|
|||||||
jurId={jurId}
|
jurId={jurId}
|
||||||
open={editCatalogueFormOpen}
|
open={editCatalogueFormOpen}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
closeEditCatalogueJurHandler()
|
closeEditCatalogueJurHandler();
|
||||||
}}
|
}}
|
||||||
onOk={(values) => {
|
onOk={(values) => {
|
||||||
editJurHandler(values);
|
editJurHandler(values);
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { ICatalogueJur } from "../../types/catalogueJur/catalogueJur";
|
|||||||
|
|
||||||
export const catalogueJurConfig: TableConfig<ICatalogueJur> = {
|
export const catalogueJurConfig: TableConfig<ICatalogueJur> = {
|
||||||
rowKey: "id",
|
rowKey: "id",
|
||||||
searchableKeys: ["closed", "inn", "kpp", "name", "company_group_name", "entity_type"],
|
searchableKeys: ["closed", "inn", "kpp", "name", "entity_type"],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
key: "closed",
|
key: "closed",
|
||||||
@ -30,11 +30,6 @@ export const catalogueJurConfig: TableConfig<ICatalogueJur> = {
|
|||||||
title: "Организация",
|
title: "Организация",
|
||||||
features: { search: true, multiselect: true, sort: true },
|
features: { search: true, multiselect: true, sort: true },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: "company_group_name",
|
|
||||||
title: "ГК",
|
|
||||||
features: { search: true, multiselect: true, sort: true },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: "entity_type",
|
key: "entity_type",
|
||||||
title: "Тип",
|
title: "Тип",
|
||||||
|
|||||||
186
src/widgets/CompanyGroupsList/CompanyGroupsList.tsx
Normal file
186
src/widgets/CompanyGroupsList/CompanyGroupsList.tsx
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
import { Input, List, Spin, Empty, Typography, Tag } from "antd";
|
||||||
|
import { FolderOpenOutlined, SearchOutlined } from "@ant-design/icons";
|
||||||
|
import { useAppDispatch, useAppSelector } from "../../store/store";
|
||||||
|
import { getCompanyGroupsThunk } from "../../store/slices/companyGroupsSlice/thunks";
|
||||||
|
import { setActiveCompanyGroup } from "../../store/slices/companyGroupsSlice/companyGroupsSlice";
|
||||||
|
|
||||||
|
const { Text } = Typography;
|
||||||
|
|
||||||
|
export const CompanyGroupsList = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const rawRows = useAppSelector((state) => state.company_groups.raw_rows);
|
||||||
|
const loading = useAppSelector((state) => state.company_groups.loading);
|
||||||
|
const activeCompanyGroup = useAppSelector(
|
||||||
|
(state) => state.company_groups.activeCompanyGroup,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [query, setQuery] = useState("");
|
||||||
|
|
||||||
|
const filtered = useMemo(() => {
|
||||||
|
const q = query.trim().toLowerCase();
|
||||||
|
if (!q) return rawRows;
|
||||||
|
return rawRows.filter(
|
||||||
|
(g) =>
|
||||||
|
g.name.toLowerCase().includes(q) || g.crm_id?.toLowerCase().includes(q),
|
||||||
|
);
|
||||||
|
}, [rawRows, query]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(getCompanyGroupsThunk());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!activeCompanyGroup && rawRows?.length) {
|
||||||
|
dispatch(setActiveCompanyGroup(rawRows?.[0]));
|
||||||
|
}
|
||||||
|
}, [rawRows, activeCompanyGroup]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
height: "100%",
|
||||||
|
background: "#fff",
|
||||||
|
borderRight: "1px solid #f0f0f0",
|
||||||
|
borderRadius: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ padding: "12px 16px", borderBottom:"1px solid #0f172a0f" }}>
|
||||||
|
<Input
|
||||||
|
allowClear
|
||||||
|
prefix={<SearchOutlined style={{ color: "#bfbfbf" }} />}
|
||||||
|
placeholder={"Поиск по ЮЛ или ГСК"}
|
||||||
|
value={query}
|
||||||
|
onChange={(e) => setQuery(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ flex: 1, overflowY: "auto", padding: "10px" }}>
|
||||||
|
{loading ? (
|
||||||
|
<div style={{ textAlign: "center", padding: 24 }}>
|
||||||
|
<Spin />
|
||||||
|
</div>
|
||||||
|
) : filtered.length === 0 ? (
|
||||||
|
<Empty
|
||||||
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
|
description="Компании и организации не найдены"
|
||||||
|
style={{ marginTop: 32 }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<List
|
||||||
|
dataSource={filtered}
|
||||||
|
split={false}
|
||||||
|
renderItem={(item) => {
|
||||||
|
const active = item.id === activeCompanyGroup?.id;
|
||||||
|
return (
|
||||||
|
<List.Item
|
||||||
|
onClick={() => dispatch(setActiveCompanyGroup(item))}
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
borderRadius: 8,
|
||||||
|
padding: "10px 12px",
|
||||||
|
marginBottom: 4,
|
||||||
|
background: active ? "#e6f4ea" : "transparent",
|
||||||
|
boxShadow: active
|
||||||
|
? "inset 0 0 0 1px #2ea64b3d, inset 3px 0 0 #258141"
|
||||||
|
: "inset 0 0 0 1px #0f172a14",
|
||||||
|
transition: "background 0.15s",
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
if (!active) {
|
||||||
|
(e.currentTarget as HTMLElement).style.background =
|
||||||
|
"#fafafa";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
if (!active) {
|
||||||
|
(e.currentTarget as HTMLElement).style.background =
|
||||||
|
"transparent";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%",
|
||||||
|
gap: 12,
|
||||||
|
minWidth: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tag
|
||||||
|
style={{
|
||||||
|
borderRadius: 8,
|
||||||
|
width: 28,
|
||||||
|
height: 28,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
color={"success"}
|
||||||
|
>
|
||||||
|
<FolderOpenOutlined
|
||||||
|
style={{
|
||||||
|
fontSize: 18,
|
||||||
|
color: "green",
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tag>
|
||||||
|
|
||||||
|
<div style={{ flex: 1, minWidth: 0 }}>
|
||||||
|
<Text
|
||||||
|
strong
|
||||||
|
ellipsis
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
type="secondary"
|
||||||
|
ellipsis
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
fontSize: 12,
|
||||||
|
lineHeight: "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
CRM ID: {item.crm_id ?? "-"}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Tag
|
||||||
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
borderRadius: 10,
|
||||||
|
background: "#f5f5f5",
|
||||||
|
border: "none",
|
||||||
|
color: "#595959",
|
||||||
|
fontWeight: 500,
|
||||||
|
minWidth: 24,
|
||||||
|
height: 20,
|
||||||
|
lineHeight: "20px",
|
||||||
|
textAlign: "center",
|
||||||
|
padding: "0 8px",
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.legal_entities_count}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
</List.Item>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -46,7 +46,7 @@ export function CompanyGroupsTable() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', height: '100%'}}>
|
||||||
<Space
|
<Space
|
||||||
style={{
|
style={{
|
||||||
padding: '16px 12px',
|
padding: '16px 12px',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user