Update postamat id when make point working

dev
Platon Yasev 3 years ago
parent 46d88a255a
commit 99edde20a3

@ -13,7 +13,7 @@ export const useUpdateStatus = ({ onSuccess }) => {
},
onSuccess: () => {
toggleUpdateCounter();
onSuccess();
onSuccess?.();
},
});
};

@ -2,15 +2,21 @@ import { useQueryClient } from "@tanstack/react-query";
import { usePopup } from "../../../stores/usePopup";
import { useUpdateStatus } from "../../../hooks/useUpdateStatus";
import { Button } from "antd";
import { STATUSES } from "../../../config";
export const ChangeStatusButton = ({ selectedIds, selectedStatus }) => {
export const ChangeStatusButton = ({
selectedIds,
selectedStatus,
onOpenMakeWorkingModal,
onSuccess,
}) => {
const queryClient = useQueryClient();
const { setPopup } = usePopup();
const { mutate: updateStatus } = useUpdateStatus({
onSuccess: () => {
queryClient.invalidateQueries(["on-approval-points"]);
setPopup(null);
onSuccess();
},
});
@ -22,12 +28,18 @@ export const ChangeStatusButton = ({ selectedIds, selectedStatus }) => {
"location_ids[]": selectedIds,
});
updateStatus(params);
if (selectedStatus === STATUSES.working) {
onOpenMakeWorkingModal();
} else {
updateStatus(params);
}
};
return (
<Button type="primary" onClick={handleClick}>
Обновить статус
</Button>
<>
<Button type="primary" onClick={handleClick}>
Обновить статус
</Button>
</>
);
};

@ -6,7 +6,11 @@ import { Button } from "antd";
import { useExportOnApprovalData } from "./useExportOnApprovalData";
import { ChangeStatusButton } from "./ChangeStatusButton";
export const Header = ({ selectedIds, onClearSelected }) => {
export const Header = ({
selectedIds,
onClearSelected,
onOpenMakeWorkingModal,
}) => {
const [status, setStatus] = useState(STATUSES.pending);
const handleClear = (e) => {
@ -23,6 +27,8 @@ export const Header = ({ selectedIds, onClearSelected }) => {
<ChangeStatusButton
selectedIds={selectedIds}
selectedStatus={status}
onOpenMakeWorkingModal={onOpenMakeWorkingModal}
onSuccess={onClearSelected}
/>
</>
)

@ -0,0 +1,86 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api, getPoints } from "../../../../api";
import { Button, Modal } from "antd";
import { MakeWorkingTable } from "./MakeWorkingTable";
import { useEffect, useState } from "react";
import { usePopup } from "../../../../stores/usePopup";
import { useUpdateStatus } from "../../../../hooks/useUpdateStatus";
import { STATUSES } from "../../../../config";
const useUpdatePostamatId = () => {
return useMutation({
mutationFn: (params) => {
return api.put(
`/api/placement_points/update_postamat_id?${params.toString()}`
);
},
});
};
export const MakeWorkingModal = ({ selectedIds, onClose, onSuccess }) => {
const { data } = useQuery(["make-working-table", selectedIds], async () => {
const params = new URLSearchParams({
page: 1,
page_size: 100,
"location_ids[]": selectedIds,
});
return await getPoints(params);
});
const [dataSource, setDataSource] = useState([]);
useEffect(() => {
setDataSource(data?.results);
}, [data]);
const queryClient = useQueryClient();
const { setPopup } = usePopup();
const { mutateAsync: updatePostamatId } = useUpdatePostamatId();
const { mutateAsync: updateStatus } = useUpdateStatus({});
const handleUpdate = () => {
const updatePostamatPromises = dataSource.map((it) => {
const params = new URLSearchParams({
id: it.id,
postamat_id: it.postamat_id,
});
return updatePostamatId(params);
});
const updateStatusParams = new URLSearchParams({
status: STATUSES.working,
"location_ids[]": selectedIds,
});
const updateStatusPromise = updateStatus(updateStatusParams);
Promise.all([...updatePostamatPromises, updateStatusPromise]).then(() => {
queryClient.invalidateQueries(["on-approval-points"]);
setPopup(null);
onSuccess();
onClose();
});
};
return (
<Modal
open={true}
title="Укажите идентификаторы постаматов"
onCancel={onClose}
width={800}
footer={[
<Button key="ok-button" type="primary" onClick={handleUpdate}>
Обновить статус
</Button>,
]}
>
{dataSource && (
<MakeWorkingTable data={dataSource} onChange={setDataSource} />
)}
</Modal>
);
};

@ -0,0 +1,156 @@
import { Form, InputNumber, Table as AntdTable } from "antd";
import React, { useContext, useEffect, useRef, useState } from "react";
import { columns as defaultColumns } from "./columns";
import "./style.css";
const EditableContext = React.createContext(null);
const EditableRow = ({ index, ...props }) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
const EditableCell = ({
title,
editable,
children,
dataIndex,
record,
handleSave,
...restProps
}) => {
const [editing, setEditing] = useState(false);
const inputRef = useRef(null);
const form = useContext(EditableContext);
useEffect(() => {
if (editing) {
inputRef.current.focus();
}
}, [editing]);
const toggleEdit = () => {
setEditing(!editing);
form.setFieldsValue({
[dataIndex]: record[dataIndex],
});
};
const save = async () => {
try {
const values = await form.validateFields();
toggleEdit();
handleSave({
...record,
...values,
});
} catch (errInfo) {
console.log("Save failed:", errInfo);
}
};
let childNode = children;
if (editable) {
childNode = editing ? (
<Form.Item
style={{
margin: 0,
}}
name={dataIndex}
rules={[
{
required: true,
message: `Укажите ${title}`,
},
]}
>
<InputNumber
ref={inputRef}
onPressEnter={save}
onBlur={save}
className="w-full"
min={0}
precision={0}
/>
</Form.Item>
) : (
<div
className="editable-cell-value-wrap"
style={{
paddingRight: 24,
}}
onClick={toggleEdit}
>
{children}
</div>
);
}
return <td {...restProps}>{childNode}</td>;
};
export const MakeWorkingTable = ({ data, onChange }) => {
const handleSave = (row) => {
const newData = [...data];
const index = newData.findIndex((item) => row.id === item.id);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
onChange(newData);
};
const components = {
body: {
row: EditableRow,
cell: EditableCell,
},
};
const columns = defaultColumns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave,
}),
};
});
const SCROLL = {
y: "max-content",
x: "max-content",
};
return (
<AntdTable
components={components}
size="small"
pagination={false}
dataSource={data}
columns={columns}
rowKey="id"
sticky={true}
rowClassName={() => "editable-row"}
className="!max-w-full"
scroll={SCROLL}
/>
);
};

@ -0,0 +1,40 @@
import { STATUS_LABEL_MAPPER } from "../../../../config";
export const columns = [
{
title: "Id",
dataIndex: "id",
key: "id",
width: 50,
},
{
title: "Адрес",
dataIndex: "address",
key: "address",
width: 200,
},
{
title: "Категория",
dataIndex: "category",
key: "category",
width: "120px",
ellipsis: true,
},
{
title: "Статус",
dataIndex: "status",
key: "status",
width: "120px",
ellipsis: true,
render: (_, record) => {
return STATUS_LABEL_MAPPER[record.status];
},
},
{
title: "Id постамата",
dataIndex: "postamat_id",
key: "postamat_id",
width: "120px",
editable: true,
},
];

@ -0,0 +1,17 @@
.editable-cell {
position: relative;
}
.editable-cell-value-wrap {
padding: 5px 12px;
cursor: pointer;
border: 1px solid #d9d9d9;
border-radius: 4px;
min-height: 24px;
}
.editable-row:hover .editable-cell-value-wrap {
padding: 5px 12px;
border: 1px solid #d9d9d9;
border-radius: 2px;
}

@ -1,5 +1,5 @@
import { Table } from "../Table";
import { columns } from "../InitialTable/columns";
import { columns } from "../columns";
import { useQuery } from "@tanstack/react-query";
import { getPoints } from "../../../api";
import { useCallback, useState } from "react";
@ -8,6 +8,18 @@ import { STATUSES } from "../../../config";
import { useMergeTableData } from "../useMergeTableData";
import { Header } from "./Header";
import { useOnApprovalPointsFilters } from "../../../stores/useOnApprovalPointsFilters";
import { MakeWorkingModal } from "./MakeWorkingTable/MakeWorkingModal";
const tableCols = [
...columns,
{
title: "Id постамата",
dataIndex: "postamat_id",
key: "postamat_id",
width: "70px",
ellipsis: true,
},
];
export const OnApprovalTable = ({ fullWidth }) => {
const [pageSize, setPageSize] = useState(PAGE_SIZE);
@ -16,6 +28,8 @@ export const OnApprovalTable = ({ fullWidth }) => {
const {
filters: { region },
} = useOnApprovalPointsFilters();
const [isMakeWorkingModalOpened, setIsMakeWorkingModalOpened] =
useState(false);
const clearSelected = () => setSelectedIds([]);
@ -47,19 +61,32 @@ export const OnApprovalTable = ({ fullWidth }) => {
};
return (
<Table
header={
<Header selectedIds={selectedIds} onClearSelected={clearSelected} />
}
rowSelection={rowSelection}
data={mergedData}
onPageChange={handlePageChange}
page={page}
pageSize={pageSize}
isClickedPointLoading={isClickedPointLoading}
columns={columns}
fullWidth={fullWidth}
loading={isInitialLoading}
/>
<>
<Table
header={
<Header
selectedIds={selectedIds}
onClearSelected={clearSelected}
onOpenMakeWorkingModal={() => setIsMakeWorkingModalOpened(true)}
/>
}
rowSelection={rowSelection}
data={mergedData}
onPageChange={handlePageChange}
page={page}
pageSize={pageSize}
isClickedPointLoading={isClickedPointLoading}
columns={tableCols}
fullWidth={fullWidth}
loading={isInitialLoading}
/>
{isMakeWorkingModalOpened && (
<MakeWorkingModal
selectedIds={selectedIds}
onClose={() => setIsMakeWorkingModalOpened(false)}
onSuccess={clearSelected}
/>
)}
</>
);
};

@ -3,11 +3,11 @@ import { Table } from "../Table";
import { usePointSelection } from "../../../stores/usePointSelection";
import { useClickedPointConfig } from "../../../stores/useClickedPointConfig";
import { usePendingTableData } from "./usePendingTableData";
import { columns } from "./columns";
import { columns } from "../columns";
import { HeaderWrapper } from "../HeaderWrapper";
import { useExportPendingData } from "./useExportPendingData";
export const InitialTable = ({ fullWidth }) => {
export const PendingTable = ({ fullWidth }) => {
const { selection, include, exclude } = usePointSelection();
const { clickedPointConfig } = useClickedPointConfig();
const [page, setPage] = useState(1);

@ -2,11 +2,11 @@
padding: 0 !important;
}
.ant-table {
.table__wrapper .ant-table {
@apply max-w-[calc(100vw-320px)];
}
.ant-table[data-fullwidth="true"] {
.table__wrapper .ant-table[data-fullwidth="true"] {
@apply max-w-[100vw];
}

@ -53,6 +53,7 @@ export const Table = React.memo(
>
<AntdTable
size="small"
className="table__wrapper"
locale={{ emptyText: <Empty description="Нет данных" /> }}
pagination={{
pageSize,

@ -1,7 +1,7 @@
import { useMode } from "../../stores/useMode";
import { MODES } from "../../config";
import { InitialTable } from "./InitialTable/InitialTable";
import { OnApprovalTable } from "./ApproveAndWorkingTable/OnApprovalTable";
import { PendingTable } from "./PendingTable/PendingTable";
import { OnApprovalTable } from "./OnApprovalTable/OnApprovalTable";
import { WorkingTable } from "./WorkingTable/WorkingTable";
export const TableWrapper = ({ fullWidth }) => {
@ -15,5 +15,5 @@ export const TableWrapper = ({ fullWidth }) => {
return <WorkingTable fullWidth={fullWidth} />;
}
return <InitialTable fullWidth={fullWidth} />;
return <PendingTable fullWidth={fullWidth} />;
};

@ -1,12 +1,6 @@
import { STATUS_LABEL_MAPPER } from "../../../config";
import { STATUS_LABEL_MAPPER } from "../../config";
export const columns = [
{
title: "Id",
dataIndex: "id",
key: "id",
width: 50,
},
{
title: "Адрес",
dataIndex: "address",

@ -3,7 +3,7 @@ import { immer } from "zustand/middleware/immer";
import { MODES } from "../config";
const store = (set) => ({
mode: MODES.PENDING,
mode: MODES.ON_APPROVAL,
setMode: (mode) => {
set((state) => {

Loading…
Cancel
Save