OrderManagement
const { useState, useRef, useEffect, useCallback } = React;
const {
Form,
Input,
InputNumber,
Popconfirm,
Table,
Typography,
Segmented,
Badge,
Descriptions,
Tabs,
Button,
Radio,
Divider,
Select,
Tour,
Result,
Modal,
DatePicker,
Space,
Spin,
ConfigProvider,
theme
} = antd;
const OrderManagement = () => {
const [customers, setCustomers] = useState([]);
const [orderConstruct, setOrderConstruct] = useState({});
const [orderSequence, setOrderSequence] = useState("");
const [showStudentDetails, setShowStudentDetails] = useState(false);
const dispatch = useDispatch();
const [transactionDate, setTransactionDate] = useState(
new Date().toISOString()
);
const [selectedCustomer, setSelectedCustomer] = useState({
class: { label: "" }
});
const ref1 = useRef(null);
const ref2 = useRef(null);
const ref3 = useRef(null);
const ref4 = useRef(null);
const [open, setOpen] = useState(false);
const [studentName, setStudentName] = useState("");
const [studentClass, setStudentClass] = useState("");
const [studentClassGroup, setStudentClassGroup] = useState("");
const [studentMobile, setStudentMobile] = useState("");
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const [orderLines, setOrderLines] = useState([]);
const [count, setCount] = useState(0);
const [editingKey, setEditingKey] = useState("");
const isEditing = record => record.key === editingKey;
const steps = [
{
title: "Add new order item",
description: "Click this button to add new order lines.",
cover: (
<img
alt="tour.png"
src="https://user-images.githubusercontent.com/5378891/197385811-55df8480-7ff4-44bd-9d43-a7dade598d70.png"
/>
),
target: () => ref1.current
},
{
title: "Order Lines",
description:
"List of order items that have been added. You can edit/delete as well.",
target: () => ref2.current
},
{
title: "Payment Mode",
description: "Select a payment mode and provide details.",
target: () => ref3.current
},
{
title: "Review",
description:
"Review the order details and finzalize by receiving payment from customer",
target: () => ref4.current
}
];
const edit = record => {
console.log(record);
form.setFieldsValue({
sku: "",
description: "",
quantity: 0,
price: 0,
...record
});
setEditingKey(record.key);
};
const handleDelete = key => {
const newData = orderLines.filter(item => item.key !== key);
setOrderLines([...newData]);
};
const cancel = () => {
setEditingKey("");
};
const handleQuantityChange = (newValue, record) => {
const key = record.key;
// console.log(newValue, record);
const productRef = products.find(val => val.title === record.description);
// console.log(productRef);
const newData = orderLines.map(row => {
if (row.key === key) {
return {
...row,
quantity: newValue,
price: newValue * productRef.last_stock_price
};
}
return row;
});
// console.log(newData);
setOrderLines(newData);
};
const save = async key => {
try {
const row = await form.validateFields();
const newData = [...orderLines];
const index = newData.findIndex(item => key === item.key);
if (index > -1) {
const item = newData[index];
newData.splice(index, 1, {
...item,
...row
});
setOrderLines(newData);
setEditingKey("");
} else {
newData.push(row);
setOrderLines(newData);
setEditingKey("");
}
} catch (errInfo) {
console.log("Validate Failed:", errInfo);
}
};
const columns = [
{
title: "SKU",
dataIndex: "sku",
width: "25%",
inputType: "text",
editable: true
},
{
title: "Description",
dataIndex: "description",
width: "15%",
inputType: "list",
editable: true,
render: (_, record) => (
<Select
showSearch
style={{
width: 200
}}
value={record["description"]}
placeholder="Search to Select"
optionFilterProp="children"
onChange={value => handleProductChange(value, record, "description")}
filterOption={(input, option) =>
(option?.label ?? "").includes(input)
}
filterSort={(optionA, optionB) =>
(optionA?.label ?? "")
.toLowerCase()
.localeCompare((optionB?.label ?? "").toLowerCase())
}
options={(products || []).map(d => ({
value: d.title,
label: d.title
}))}
></Select>
)
},
{
title: "Quantity",
dataIndex: "quantity",
width: "20%",
inputType: "number",
editable: true,
render: (_, record) => (
<InputNumber
value={record["quantity"]}
onChange={value => handleQuantityChange(value, record)}
/>
)
},
{
title: "Price",
dataIndex: "price",
width: "20%",
inputType: "number",
editable: false
}
];
const handleProductChange = (value, record, dataIndex) => {
const key = record.key;
// console.log(value, record, dataIndex);
const productRef = products.find(val => val.title === value);
// console.log(productRef);
const newData = orderLines.map(row => {
if (row.key === key) {
return {
...row,
description: productRef.title,
sku: productRef.sku,
quantity: 1,
price: productRef.last_stock_price
};
}
return row;
});
console.log(newData);
setOrderLines(newData);
};
const handleAdd = () => {
const newData = {
key: count,
sku: "",
description: "",
quantity: 0,
price: 0
};
setOrderLines([...orderLines, newData]);
setCount(count + 1);
form.setFieldsValue({ orderLines: orderLines });
};
const mergedColumns = columns.map(col => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => ({
record,
inputType: col.inputType,
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record)
})
};
});
const [studentId, setStudentId] = useState();
const debouncedFetchData = useCallback(
(delay => {
let timerId;
return searchValue => {
clearTimeout(timerId);
timerId = setTimeout(() => fetchStudentDetails(searchValue), delay);
};
})(800),
[] // Dependencies array
);
const handleSearch = newValue => {
debouncedFetchData(newValue);
// fetchStudentDetails(newValue);
};
const studentAttributes = [
{
key: "1",
label: "Name",
children: studentName
},
{
key: "2",
label: "Class",
children: studentClass
},
{
key: "3",
label: "Mobile Number",
children: studentMobile
}
];
const handleChange = newValue => {
const customerRef = customers.find(val => val._id === newValue);
console.log(customerRef);
setSelectedCustomer(customerRef);
setStudentName(customerRef.name);
setStudentClass(customerRef.class.label);
setStudentClassGroup(customerRef.class.label.split(" ")[0]);
setStudentMobile(customerRef.mobile_number);
setShowStudentDetails(true);
};
useEffect(() => {
fetchProducts(); // This will always use latest value of count
}, [studentClassGroup]);
const fetchProducts = async searchTerms => {
try {
setLoading(true);
const response = await http.get(
`/v1/getProducts?category=${studentClassGroup}&nd=${new Date().getTime()}`
);
setProducts(response.data);
console.log(products);
} catch (error) {
console.error("Error fetching student details:", error);
// Handle error appropriately
} finally {
setLoading(false);
}
};
const fetchStudentDetails = async searchTerms => {
try {
setLoading(true);
const response = await http.get(
`/o/recs/registration?oquery=$or=sequence=*${searchTerms}^class.label=*${searchTerms}^mobile_number=*${searchTerms}&stream=true`
);
setCustomers(response.data);
} catch (error) {
console.error("Error fetching student details:", error);
// Handle error appropriately
} finally {
setLoading(false);
}
};
form.setFieldsValue({ orderLines: orderLines });
/****** Payment Mode */
const [payMode, setPayMode] = useState("Cash");
/****** Review & Finalize */
const [isModalOpen, setIsModalOpen] = useState(false);
const finalizeOrder = values => {
setOrderConstruct({
customerName: studentName,
studentClass,
customerMobile: studentMobile,
totalAmount: values.orderLines.reduce((acc, val) => {
return (acc += val.price);
}, 0),
transactionDate: values.transaction_date,
...values
});
};
useEffect(() => {
console.log(orderConstruct);
}, [orderConstruct]);
const showModal = () => {
setIsModalOpen(true);
};
const handleOk = () => {
setIsModalOpen(false);
};
const handleCancel = () => {
setIsModalOpen(false);
};
const confirm = () => {
//postAPICall and then show modal
//"/o/om_orders/new"
setLoading(true);
http.post("/v1/postOrders", orderConstruct).then(response => {
console.log(response);
form.resetFields();
dispatch({
type: "UPDATE",
payload: {
orderCreated: true
}
});
showModal();
setLoading(false);
});
};
const reviewItems = [
{
key: "2",
label: "Payment Mode",
children: payMode
},
{
key: "10",
label: "Order Items",
children: (
<>
{orderLines.map(val => {
return (
<>
<span>{val.sku}</span>
<br />
</>
);
})}
</>
)
},
{
key: "11",
label: "Finalize",
children: (
<Form.Item
wrapperCol={{
span: 12,
offset: 6
}}
>
<Space>
<Popconfirm
title="Receive Payment"
description="Are you sure to proceed?"
onConfirm={confirm}
onCancel={cancel}
okText="Yes"
cancelText="No"
>
<Button
type="primary"
htmlType="submit"
ref={ref4}
style={{
marginBottom: 16
}}
>
Receive Payment
</Button>
</Popconfirm>
</Space>
</Form.Item>
)
}
];
const onChange = key => {
console.log(key);
};
const [formLayout, setFormLayout] = useState("inline");
const onFormLayoutChange = ({ layout }) => {
setFormLayout(layout);
};
const onFinish = values => {
console.log("Received values of form: ", values);
finalizeOrder(values);
};
const tabs = [
{
key: "1",
label: "New Order",
children: (
<div
style={{
background: "black",
padding: "20px"
}}
>
<ConfigProvider theme={{ algorithm: theme.darkAlgorithm }}>
<Spin spinning={loading} delay={500}>
<Form
form={form}
layout={formLayout}
onFinish={onFinish}
initialValues={{
layout: "inline"
}}
style={{
maxWidth: "100%"
}}
>
<Form.Item label="Admission#" name="selectedCustomer">
<Select
showSearch
value={studentId}
style={{
width: 360
}}
placeholder="Search"
defaultActiveFirstOption={false}
suffixIcon={null}
filterOption={false}
onSearch={handleSearch}
onChange={handleChange}
notFoundContent={null}
options={(customers || []).map(d => ({
value: d._id,
label: `${d.name}-${d.mobile_number}-${d.class.label}-${d.father_name}`
}))}
/>
</Form.Item>
{showStudentDetails && (
<Button
type="primary"
style={{ position: "absolute", right: "10px", top: "0px" }}
onClick={() => setOpen(true)}
>
Begin Tour
</Button>
)}
{showStudentDetails && (
<React.Fragment>
<Divider>Student Details</Divider>
<Descriptions bordered items={studentAttributes} />
</React.Fragment>
)}
{showStudentDetails && (
<React.Fragment>
<Divider>Order Items</Divider>
<Space direction="vertical">
<Button
ref={ref1}
onClick={handleAdd}
type="primary"
style={{
marginBottom: 16
}}
>
Add a row
</Button>
<Form.Item name="orderLines">
<Table
// components={{
// body: {
// cell: EditableCell
// }
// }}
ref={ref2}
bordered
dataSource={orderLines}
columns={mergedColumns}
style={{ width: "800px" }}
rowClassName="editable-row"
pagination={{
onChange: cancel
}}
/>
</Form.Item>
</Space>
<Divider>Payment Mode</Divider>
<Segmented
ref={ref3}
options={["Cash", "Cheque", "Card", "UPI"]}
value={payMode}
onChange={setPayMode}
/>
{payMode === "Cash" && (
<Space direction="horizontal">
<Form.Item
label="Payment Date"
name="transaction_date"
rules={[
{
required: true,
message: "Please input date!"
}
]}
>
<DatePicker onChange={onChange} />
</Form.Item>
</Space>
)}
{payMode === "Card" && (
<Space direction="horizontal">
<Form.Item
label="Payment Date"
name="transaction_date"
rules={[
{
required: true,
message: "Please input date!"
}
]}
>
<DatePicker
onChange={onChange}
value={transactionDate}
/>
</Form.Item>
<Form.Item
label="Approval code"
name="approval_code"
rules={[
{
required: true,
message: "Please approval code!"
}
]}
>
<Input />
</Form.Item>
<Form.Item
label="Reference No"
name="reference_no"
rules={[
{
required: true,
message: "Reference No"
}
]}
>
<Input />
</Form.Item>
</Space>
)}
{payMode === "UPI" && (
<Space direction="horizontal">
<Form.Item
label="Payment Date"
name="transaction_date"
rules={[
{
required: true,
message: "Please input date!"
}
]}
>
<DatePicker onChange={onChange} />
</Form.Item>
<Form.Item
label="Approval code"
name="approval_code"
rules={[
{
required: true,
message: "Please approval code!"
}
]}
>
<Input />
</Form.Item>
<Form.Item
label="Reference No"
name="reference_no"
rules={[
{
required: true,
message: "Reference No"
}
]}
>
<Input />
</Form.Item>
</Space>
)}
{payMode === "Cheque" && (
<Space direction="horizontal">
<Form.Item
label="Cheque Date"
name="transaction_date"
rules={[
{
required: true,
message: "Please input date!"
}
]}
>
<DatePicker onChange={onChange} />
</Form.Item>
<Form.Item
label="Cheque No"
name="chequeno"
rules={[
{
required: true,
message: "Please input date!"
}
]}
>
<Input />
</Form.Item>
</Space>
)}
<Divider>Review & Finalize</Divider>
<Descriptions bordered items={reviewItems} />
<Tour
open={open}
onClose={() => setOpen(false)}
steps={steps}
/>
<Modal
title="Order Received"
open={isModalOpen}
onOk={handleOk}
onCancel={handleCancel}
>
<Result
status="success"
title="Successfully Purchased"
subTitle={`Order number: ${orderSequence}`}
/>
</Modal>
</React.Fragment>
)}
</Form>
</Spin>
</ConfigProvider>
</div>
)
},
{
key: "2",
label: "All Orders",
children: AllOrders()
},
{
key: "3",
label: "Manage",
children: ProductManagement()
},
{
key: "4",
label: "Invoices",
children: "Coming Soon!"
}
];
return <Tabs defaultActiveKey="1" items={tabs} onChange={onChange} />;
};
return OrderManagement;Last updated