ProductTable
const {
Button,
Input,
Space,
Switch,
Table,
GetRef,
Select,
TableColumnsType,
InputNumber,
Popconfirm,
Typography,
TableColumnType,
Spin
} = antd;
const { useState, useEffect, useRef, useMemo } = React;
const { SearchOutlined } = antdIcons;
const ProductTable = ({ products, edit }) => {
const [data, setData] = useState(products);
const [enableEditing, setEnableEditing] = useState(edit);
const [searchText, setSearchText] = useState("");
const [searchedColumn, setSearchedColumn] = useState("");
const searchInput = useRef(null);
const [loading, setLoading] = React.useState(false);
const handleSearch = (selectedKeys, confirm, dataIndex) => {
confirm();
setSearchText(selectedKeys[0]);
setSearchedColumn(dataIndex);
};
const handleReset = clearFilters => {
clearFilters();
setSearchText("");
};
const getColumnSearchProps = dataIndex => ({
filterDropdown: ({
setSelectedKeys,
selectedKeys,
confirm,
clearFilters,
close
}) => (
<div style={{ padding: 8 }} onKeyDown={e => e.stopPropagation()}>
<Input
ref={searchInput}
placeholder={`Search ${dataIndex}`}
value={selectedKeys[0]}
onChange={e =>
setSelectedKeys(e.target.value ? [e.target.value] : [])
}
onPressEnter={() => handleSearch(selectedKeys, confirm, dataIndex)}
style={{ marginBottom: 8, display: "block" }}
/>
<Space>
<Button
type="primary"
onClick={() => handleSearch(selectedKeys, confirm, dataIndex)}
icon={<SearchOutlined />}
size="small"
style={{ width: 90 }}
>
Search
</Button>
<Button
onClick={() => clearFilters && handleReset(clearFilters)}
size="small"
style={{ width: 90 }}
>
Reset
</Button>
<Button
type="link"
size="small"
onClick={() => {
confirm({ closeDropdown: false });
setSearchText(selectedKeys[0]);
setSearchedColumn(dataIndex);
}}
>
Filter
</Button>
<Button
type="link"
size="small"
onClick={() => {
close();
}}
>
close
</Button>
</Space>
</div>
),
filterIcon: filtered => (
<SearchOutlined style={{ color: filtered ? "#1677ff" : undefined }} />
),
onFilter: (value, record) =>
record[dataIndex]
.toString()
.toLowerCase()
.includes(value.toLowerCase()),
onFilterDropdownOpenChange: visible => {
if (visible) {
setTimeout(() => searchInput.current?.select(), 100);
}
}
});
const options = [
{
label: "NUR",
value: "NUR"
},
{
label: "I",
value: "I"
},
{
label: "II",
value: "II"
},
{
label: "III",
value: "III"
},
{
label: "IV",
value: "IV"
},
{
label: "V",
value: "V"
},
{
label: "VI",
value: "VI"
},
{
label: "VII",
value: "VII"
},
{
label: "VIII",
value: "VIII"
},
{
label: "IX",
value: "IX"
},
{
label: "X",
value: "X"
},
{
label: "XI",
value: "XI"
},
{
label: "XII",
value: "XII"
}
];
const handlePriceChange = (record, parentRecord, newPrice) => {
console.log(
`Price changed ${record.price} ${parentRecord.key} ${newPrice}`
);
const editIndex = data.findIndex(val => val.key === parentRecord.key);
const stockRowIndex = data[editIndex].stock.findIndex(
val => val.key === record.key
);
data[editIndex].stock[stockRowIndex].price = newPrice;
setData([...data]);
};
const expandedRowRender = record => {
const columns = [
{
title: "Price",
dataIndex: "price",
key: "price",
render: (text, _record) => {
return (
<InputNumber
disabled={!enableEditing}
value={_record.price}
onChange={value => {
handlePriceChange(_record, record, value);
}}
/>
);
}
},
{
title: "Quantity",
dataIndex: "quantity",
key: "quantity"
}
];
const data = record.stock;
return <Table columns={columns} dataSource={data} pagination={false} />;
};
const handleDelete = async key => {
const newData = data.filter(item => item.key !== key);
setData(newData);
const removedRecord = data.filter(item => item.key === key);
const delPayload = { oper: "del", _id: removedRecord[0]._id };
console.log(delPayload);
const response = await http.post(`/o/products`, delPayload);
};
const handleCategoryChange = (record, newValue) => {
console.log(`Category changed ${record.category} ${newValue}`);
console.log(newValue instanceof Array);
const editIndex = data.findIndex(val => val.key === record.key);
data[editIndex].category = newValue;
setData([...data]);
};
const update = async record => {
console.log(record);
setLoading(true);
const response = await http.post("v1/postProducts", record);
console.log(response);
setLoading(false);
};
const columns = [
{
title: "SKU",
dataIndex: "sku",
key: "sku"
},
{
title: "Title",
dataIndex: "title",
key: "title",
...getColumnSearchProps("title"),
sortDirections: ["descend", "ascend"]
},
{
title: "Description",
dataIndex: "description",
key: "description"
},
{
title: "Category",
dataIndex: "category",
key: "category",
render: (text, record) => (
<Select
mode="multiple"
allowClear
style={{
width: "100%"
}}
disabled={!enableEditing}
placeholder="Please select"
onChange={value => {
handleCategoryChange(record, value);
}}
defaultValue={record.category}
options={options}
/>
)
},
{
title: "Last Stock Price",
dataIndex: "last_stock_price",
key: "last_stock_price"
},
{
title: "Total Quantity",
dataIndex: "total_quantity",
key: "total_quantity"
},
{
title: "Actions",
dataIndex: "actions",
render: (_, record) =>
data.length >= 1 ? (
<>
<Popconfirm
title="Sure to delete?"
onConfirm={value => handleDelete(record.key, value)}
>
<a>Delete</a>
</Popconfirm>
<Typography.Link style={{marginLeft: "10px"}}onClick={() => update(record)}>
Update
</Typography.Link>
</>
) : null
}
];
useMemo(() => {
// fetchAllProducts(); // This will always use latest value of count
// setData([...products])
setEnableEditing(edit);
}, [edit]);
useMemo(() => {
setData([...products])// This will always use latest value of count
}, [products]);
return (
<>
<Spin spinning={loading} delay={500}>
<Table
dataSource={data}
columns={columns}
expandable={{
expandedRowRender
}}
/>
</Spin>
</>
);
};
return ProductTable;Last updated