parent
46d88a255a
commit
99edde20a3
@ -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,12 +1,6 @@
|
|||||||
import { STATUS_LABEL_MAPPER } from "../../../config";
|
import { STATUS_LABEL_MAPPER } from "../../config";
|
||||||
|
|
||||||
export const columns = [
|
export const columns = [
|
||||||
{
|
|
||||||
title: "Id",
|
|
||||||
dataIndex: "id",
|
|
||||||
key: "id",
|
|
||||||
width: 50,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "Адрес",
|
title: "Адрес",
|
||||||
dataIndex: "address",
|
dataIndex: "address",
|
||||||
Loading…
Reference in new issue