服务模块
This commit is contained in:
@@ -1,26 +1,47 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { Form, Input, InputNumber, Button, Card, Typography, Modal, message, Divider, Select } from 'antd';
|
||||
import { PlusOutlined, DeleteOutlined, EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import React, { useState, useEffect, useMemo } from "react";
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Button,
|
||||
Card,
|
||||
Typography,
|
||||
Modal,
|
||||
message,
|
||||
Divider,
|
||||
Select,
|
||||
} from "antd";
|
||||
import {
|
||||
PlusOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
CheckOutlined,
|
||||
CloseOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { supabase } from "@/config/supabase";
|
||||
import { supabaseService } from "@/hooks/supabaseService";
|
||||
const { Text } = Typography;
|
||||
const SectionList = ({
|
||||
const SectionList = ({
|
||||
form,
|
||||
isView,
|
||||
formValues,
|
||||
type,
|
||||
currentCurrency = 'CNY'
|
||||
currentCurrency = "TWD",
|
||||
}) => {
|
||||
const [editingSectionIndex, setEditingSectionIndex] = useState(null);
|
||||
const [editingSectionName, setEditingSectionName] = useState('');
|
||||
const [editingSectionName, setEditingSectionName] = useState("");
|
||||
const [templateModalVisible, setTemplateModalVisible] = useState(false);
|
||||
const [availableSections, setAvailableSections] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [units, setUnits] = useState([]);
|
||||
const [loadingUnits, setLoadingUnits] = useState(false);
|
||||
const CURRENCY_SYMBOLS = {
|
||||
CNY: "¥",
|
||||
TWD: "NT$",
|
||||
USD: "$",
|
||||
};
|
||||
|
||||
// 内部计算方法
|
||||
const calculateItemAmount = (quantity, price) => {
|
||||
const safeQuantity = Number(quantity) || 0;
|
||||
const safePrice = Number(price) || 0;
|
||||
@@ -36,19 +57,13 @@ const SectionList = ({
|
||||
};
|
||||
|
||||
const formatCurrency = (amount) => {
|
||||
const CURRENCY_SYMBOLS = {
|
||||
CNY: "¥",
|
||||
TWD: "NT$",
|
||||
USD: "$",
|
||||
};
|
||||
const safeAmount = Number(amount) || 0;
|
||||
return `${CURRENCY_SYMBOLS[currentCurrency] || ""}${safeAmount.toLocaleString("zh-CN", {
|
||||
return `${CURRENCY_SYMBOLS[currentCurrency] || "NT$"}${safeAmount.toLocaleString("zh-TW", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`;
|
||||
};
|
||||
|
||||
// 获取可用的小节模板
|
||||
const fetchAvailableSections = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@@ -56,6 +71,7 @@ const SectionList = ({
|
||||
.from("resources")
|
||||
.select("*")
|
||||
.eq("type", "sections")
|
||||
.eq("attributes->>template_type", [type])
|
||||
.order("created_at", { ascending: false });
|
||||
|
||||
if (error) throw error;
|
||||
@@ -68,195 +84,235 @@ const SectionList = ({
|
||||
}
|
||||
};
|
||||
|
||||
// 处理小节名称编辑
|
||||
const handleSectionNameEdit = (sectionIndex, initialValue) => {
|
||||
setEditingSectionIndex(sectionIndex);
|
||||
setEditingSectionName(initialValue || '');
|
||||
setEditingSectionName(initialValue || "");
|
||||
};
|
||||
|
||||
const handleSectionNameSave = () => {
|
||||
if (!editingSectionName.trim()) {
|
||||
message.error('请输入小节名称');
|
||||
message.error("请输入小节名称");
|
||||
return;
|
||||
}
|
||||
|
||||
const sections = form.getFieldValue('sections');
|
||||
const sections = form.getFieldValue("sections");
|
||||
const newSections = [...sections];
|
||||
newSections[editingSectionIndex] = {
|
||||
...newSections[editingSectionIndex],
|
||||
sectionName: editingSectionName.trim()
|
||||
sectionName: editingSectionName.trim(),
|
||||
};
|
||||
form.setFieldValue('sections', newSections);
|
||||
form.setFieldValue("sections", newSections);
|
||||
setEditingSectionIndex(null);
|
||||
setEditingSectionName('');
|
||||
setEditingSectionName("");
|
||||
};
|
||||
|
||||
// 添加项目
|
||||
const handleAddItem = (add) => {
|
||||
add({
|
||||
key: uuidv4(),
|
||||
name: '',
|
||||
description: '',
|
||||
name: "",
|
||||
description: "",
|
||||
quantity: 1,
|
||||
price: 0,
|
||||
unit: ''
|
||||
unit: "",
|
||||
});
|
||||
};
|
||||
|
||||
// 处理使用模板
|
||||
const handleUseTemplate = (template, add) => {
|
||||
const newSection = {
|
||||
key: uuidv4(),
|
||||
sectionName: template.attributes.name,
|
||||
items: (template.attributes.items || []).map(item => ({
|
||||
items: (template.attributes.items || []).map((item) => ({
|
||||
key: uuidv4(),
|
||||
name: item.name || '',
|
||||
description: item.description || '',
|
||||
name: item.name || "",
|
||||
description: item.description || "",
|
||||
price: item.price || 0,
|
||||
quantity: item.quantity || 1,
|
||||
unit: item.unit || '',
|
||||
unit: item.unit || "",
|
||||
})),
|
||||
};
|
||||
add(newSection);
|
||||
setTemplateModalVisible(false);
|
||||
message.success('套用模版成功');
|
||||
message.success("套用模版成功");
|
||||
};
|
||||
|
||||
// 处理创建自定义小节
|
||||
const handleCreateCustom = (add, fieldsLength) => {
|
||||
add({
|
||||
key: uuidv4(),
|
||||
sectionName: `服务类型 ${fieldsLength + 1}`,
|
||||
items: [{
|
||||
key: uuidv4(),
|
||||
name: '',
|
||||
description: '',
|
||||
quantity: 1,
|
||||
price: 0,
|
||||
unit: ''
|
||||
}]
|
||||
items: [
|
||||
{
|
||||
key: uuidv4(),
|
||||
name: "",
|
||||
description: "",
|
||||
quantity: 1,
|
||||
price: 0,
|
||||
unit: "",
|
||||
},
|
||||
],
|
||||
});
|
||||
setTemplateModalVisible(false);
|
||||
};
|
||||
|
||||
// 获取单位列表
|
||||
const fetchUnits = async () => {
|
||||
setLoadingUnits(true);
|
||||
try {
|
||||
const { data: units } = await supabaseService.select('resources', {
|
||||
const { data: units } = await supabaseService.select("resources", {
|
||||
filter: {
|
||||
'type': { eq: 'units' },
|
||||
'attributes->>template_type': { in: `(${type},common)` }
|
||||
type: { eq: "units" },
|
||||
"attributes->>template_type": { in: `(${type},common)` },
|
||||
},
|
||||
order: {
|
||||
column: 'created_at',
|
||||
ascending: false
|
||||
}
|
||||
column: "created_at",
|
||||
ascending: false,
|
||||
},
|
||||
});
|
||||
setUnits(units || []);
|
||||
} catch (error) {
|
||||
message.error('获取单位列表失败');
|
||||
message.error("获取单位列表失败");
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoadingUnits(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 在组件加载时获取单位列表
|
||||
useEffect(() => {
|
||||
fetchUnits();
|
||||
}, []);
|
||||
|
||||
// 新增单位
|
||||
const handleAddUnit = async (unitName) => {
|
||||
try {
|
||||
const { error } = await supabase
|
||||
.from('resources')
|
||||
.insert([{
|
||||
type: 'units',
|
||||
const { error } = await supabase.from("resources").insert([
|
||||
{
|
||||
type: "units",
|
||||
attributes: {
|
||||
name: unitName
|
||||
name: unitName,
|
||||
template_type: type,
|
||||
},
|
||||
schema_version: 1
|
||||
}]);
|
||||
schema_version: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
if (error) throw error;
|
||||
message.success('新增单位成功');
|
||||
message.success("新增单位成功");
|
||||
fetchUnits();
|
||||
return true;
|
||||
} catch (error) {
|
||||
message.error('新增单位失败');
|
||||
message.error("新增单位失败");
|
||||
console.error(error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 模板选择弹窗内容
|
||||
const renderTemplateModalContent = (add, fieldsLength) => (
|
||||
<div className="space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{availableSections.map(section => (
|
||||
<div
|
||||
key={section.id}
|
||||
className="group relative bg-white rounded-lg shadow-sm border border-gray-200 hover:shadow-lg transition-all duration-300 cursor-pointer"
|
||||
onClick={() => handleUseTemplate(section, add)}
|
||||
>
|
||||
<div className="p-6">
|
||||
<div className="text-center mb-4">
|
||||
<h3 className="text-lg font-medium group-hover:text-blue-500 transition-colors">
|
||||
{section.attributes.name}
|
||||
</h3>
|
||||
<div className="text-sm text-gray-500 mt-1">
|
||||
{section.attributes.items?.length || 0} 个项目
|
||||
{availableSections.length > 0 ? (
|
||||
<div className="flex flex-col">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{availableSections.map((section) => (
|
||||
<div
|
||||
key={section.id}
|
||||
className="group relative bg-white rounded-lg shadow-sm border border-gray-200 hover:shadow-lg transition-all duration-300 cursor-pointer"
|
||||
onClick={() => handleUseTemplate(section, add)}
|
||||
>
|
||||
<div className="p-6">
|
||||
<div className="text-center mb-4">
|
||||
<h3 className="text-lg font-medium group-hover:text-blue-500 transition-colors">
|
||||
{section.attributes.name}
|
||||
</h3>
|
||||
<div className="text-sm text-gray-500 mt-1">
|
||||
{section.attributes.items?.length || 0} 个项目
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 mt-4 border-t pt-4">
|
||||
{(section.attributes.items || [])
|
||||
.slice(0, 3)
|
||||
.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex justify-between items-center"
|
||||
>
|
||||
<span className="text-sm text-gray-600 truncate flex-1">
|
||||
{item.name}
|
||||
</span>
|
||||
<span className="text-sm text-gray-500 ml-2">
|
||||
{formatCurrency(item.price)}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
{(section.attributes.items || []).length > 3 && (
|
||||
<div className="text-sm text-gray-500 text-center">
|
||||
还有 {section.attributes.items.length - 3} 个项目...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 pt-4 border-t flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">总金额</span>
|
||||
<span className="text-base font-medium text-blue-500">
|
||||
{formatCurrency(
|
||||
(section.attributes.items || []).reduce(
|
||||
(sum, item) =>
|
||||
sum + (item.price * (item.quantity || 1) || 0),
|
||||
0
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 mt-4 border-t pt-4">
|
||||
{(section.attributes.items || []).slice(0, 3).map((item, index) => (
|
||||
<div key={index} className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600 truncate flex-1">{item.name}</span>
|
||||
<span className="text-sm text-gray-500 ml-2">{formatCurrency(item.price)}</span>
|
||||
</div>
|
||||
))}
|
||||
{(section.attributes.items || []).length > 3 && (
|
||||
<div className="text-sm text-gray-500 text-center">
|
||||
还有 {section.attributes.items.length - 3} 个项目...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 pt-4 border-t flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">总金额</span>
|
||||
<span className="text-base font-medium text-blue-500">
|
||||
{formatCurrency(
|
||||
(section.attributes.items || []).reduce(
|
||||
(sum, item) => sum + (item.price * (item.quantity || 1) || 0),
|
||||
0
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
type="dashed"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => handleCreateCustom(add, fieldsLength)}
|
||||
className="w-1/3 border-2"
|
||||
>
|
||||
自定义模块
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => handleCreateCustom(add, fieldsLength)}
|
||||
className="bg-blue-600 hover:bg-blue-700 border-0 shadow-md hover:shadow-lg transition-all duration-200 h-10 px-6 rounded-lg flex items-center gap-2"
|
||||
>
|
||||
<span className="font-medium">自定义模块</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center py-16 px-4">
|
||||
<div className="w-48 h-48 mb-8">
|
||||
<svg
|
||||
className="w-full h-full text-gray-200"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={1}
|
||||
d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-medium text-gray-900 mb-2">
|
||||
暂无可用模板
|
||||
</h3>
|
||||
<p className="text-gray-500 text-center max-w-sm mb-8">
|
||||
您可以选择创建一个自定义模块开始使用
|
||||
</p>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => handleCreateCustom(add, fieldsLength)}
|
||||
size="large"
|
||||
className="shadow-md hover:shadow-lg transition-shadow"
|
||||
>
|
||||
创建自定义模块
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
// 修改项目小计的计算,将其封装为 memo 组件
|
||||
const ItemSubtotal = React.memo(({ quantity, price, currentCurrency }) => {
|
||||
const subtotal = useMemo(() => {
|
||||
const safeQuantity = Number(quantity) || 0;
|
||||
@@ -273,7 +329,6 @@ const SectionList = ({
|
||||
);
|
||||
});
|
||||
|
||||
// 修改小节总计的计算,将其封装为 memo 组件
|
||||
const SectionTotal = React.memo(({ items, currentCurrency }) => {
|
||||
const total = useMemo(() => {
|
||||
if (!Array.isArray(items)) return 0;
|
||||
@@ -281,7 +336,7 @@ const SectionList = ({
|
||||
if (!item) return sum;
|
||||
const safeQuantity = Number(item.quantity) || 0;
|
||||
const safePrice = Number(item.price) || 0;
|
||||
return sum + (safeQuantity * safePrice);
|
||||
return sum + safeQuantity * safePrice;
|
||||
}, 0);
|
||||
}, [items]);
|
||||
|
||||
@@ -302,11 +357,11 @@ const SectionList = ({
|
||||
<Form.List name="sections">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-4 overflow-auto">
|
||||
{fields.map((field, sectionIndex) => (
|
||||
<Card
|
||||
key={field.key}
|
||||
className="shadow-sm rounded-lg"
|
||||
className="shadow-sm rounded-lg min-w-[1000px]"
|
||||
type="inner"
|
||||
title={
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -315,7 +370,9 @@ const SectionList = ({
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
value={editingSectionName}
|
||||
onChange={(e) => setEditingSectionName(e.target.value)}
|
||||
onChange={(e) =>
|
||||
setEditingSectionName(e.target.value)
|
||||
}
|
||||
onPressEnter={handleSectionNameSave}
|
||||
autoFocus
|
||||
className="w-48"
|
||||
@@ -331,7 +388,7 @@ const SectionList = ({
|
||||
icon={<CloseOutlined />}
|
||||
onClick={() => {
|
||||
setEditingSectionIndex(null);
|
||||
setEditingSectionName('');
|
||||
setEditingSectionName("");
|
||||
}}
|
||||
className="text-red-500"
|
||||
/>
|
||||
@@ -340,17 +397,26 @@ const SectionList = ({
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-1 h-4 bg-purple-500 rounded-full" />
|
||||
<Text strong className="text-lg">
|
||||
{form.getFieldValue(['sections', sectionIndex, 'sectionName'])
|
||||
|| `服务类型 ${sectionIndex + 1}`}
|
||||
{form.getFieldValue([
|
||||
"sections",
|
||||
sectionIndex,
|
||||
"sectionName",
|
||||
]) || `服务类型 ${sectionIndex + 1}`}
|
||||
</Text>
|
||||
{!isView && (
|
||||
<Button
|
||||
type="link"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => handleSectionNameEdit(
|
||||
sectionIndex,
|
||||
form.getFieldValue(['sections', sectionIndex, 'sectionName'])
|
||||
)}
|
||||
onClick={() =>
|
||||
handleSectionNameEdit(
|
||||
sectionIndex,
|
||||
form.getFieldValue([
|
||||
"sections",
|
||||
sectionIndex,
|
||||
"sectionName",
|
||||
])
|
||||
)
|
||||
}
|
||||
className="text-gray-400 hover:text-blue-500"
|
||||
/>
|
||||
)}
|
||||
@@ -368,11 +434,9 @@ const SectionList = ({
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{/* 项目列表 */}
|
||||
<Form.List name={[field.name, "items"]}>
|
||||
{(itemFields, { add: addItem, remove: removeItem }) => (
|
||||
<>
|
||||
{/* 表头 */}
|
||||
<div className="grid grid-cols-[3fr_4fr_1fr_1fr_2fr_1fr_40px] gap-4 mb-2 text-gray-500 px-2">
|
||||
<div>项目明细</div>
|
||||
<div>描述/备注</div>
|
||||
@@ -383,7 +447,6 @@ const SectionList = ({
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
{/* 项目列表 */}
|
||||
{itemFields.map((itemField, itemIndex) => (
|
||||
<div
|
||||
key={itemField.key}
|
||||
@@ -413,9 +476,10 @@ const SectionList = ({
|
||||
loading={loadingUnits}
|
||||
showSearch
|
||||
allowClear
|
||||
options={units.map(unit => ({
|
||||
style={{ minWidth: "120px" }}
|
||||
options={units.map((unit) => ({
|
||||
label: unit.attributes.name,
|
||||
value: unit.attributes.name
|
||||
value: unit.attributes.name,
|
||||
}))}
|
||||
onDropdownVisibleChange={(open) => {
|
||||
if (open) fetchUnits();
|
||||
@@ -423,48 +487,32 @@ const SectionList = ({
|
||||
dropdownRender={(menu) => (
|
||||
<>
|
||||
{menu}
|
||||
<Divider style={{ margin: '8px 0' }} />
|
||||
<Select.Option value="ADD_NEW">
|
||||
<Button
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
block
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
Modal.confirm({
|
||||
title: '新增单位',
|
||||
content: (
|
||||
<Input
|
||||
placeholder="请输入单位名称"
|
||||
onChange={(e) => {
|
||||
Modal.confirm.update({
|
||||
okButtonProps: {
|
||||
disabled: !e.target.value.trim()
|
||||
}
|
||||
});
|
||||
}}
|
||||
ref={(input) => {
|
||||
if (input) {
|
||||
setTimeout(() => input.focus(), 100);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
),
|
||||
onOk: async (close) => {
|
||||
const unitName = document.querySelector('.ant-modal-content input').value.trim();
|
||||
if (await handleAddUnit(unitName)) {
|
||||
const currentItems = form.getFieldValue(['sections', field.name, 'items']);
|
||||
currentItems[itemField.name].unit = unitName;
|
||||
form.setFieldValue(['sections', field.name, 'items'], currentItems);
|
||||
close();
|
||||
}
|
||||
}
|
||||
});
|
||||
<Divider style={{ margin: "12px 0" }} />
|
||||
<div style={{ padding: "4px" }}>
|
||||
<Input.Search
|
||||
placeholder="输入新单位名称"
|
||||
enterButton={<PlusOutlined />}
|
||||
onSearch={async (value) => {
|
||||
if (!value.trim()) return;
|
||||
if (
|
||||
await handleAddUnit(value.trim())
|
||||
) {
|
||||
const currentItems =
|
||||
form.getFieldValue([
|
||||
"sections",
|
||||
field.name,
|
||||
"items",
|
||||
]);
|
||||
currentItems[itemField.name].unit =
|
||||
value.trim();
|
||||
form.setFieldValue(
|
||||
["sections", field.name, "items"],
|
||||
currentItems
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
新增单位
|
||||
</Button>
|
||||
</Select.Option>
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
@@ -474,18 +522,34 @@ const SectionList = ({
|
||||
name={[itemField.name, "quantity"]}
|
||||
className="!mb-0"
|
||||
>
|
||||
<InputNumber placeholder="数量" min={0} className="w-full" />
|
||||
<InputNumber
|
||||
placeholder="数量"
|
||||
min={0}
|
||||
className="w-full"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
{...itemField}
|
||||
name={[itemField.name, "price"]}
|
||||
className="!mb-0"
|
||||
>
|
||||
<InputNumber placeholder="单价" min={0} className="w-full" />
|
||||
<InputNumber
|
||||
placeholder="单价"
|
||||
min={0}
|
||||
className="w-full"
|
||||
/>
|
||||
</Form.Item>
|
||||
<ItemSubtotal
|
||||
quantity={formValues?.sections?.[sectionIndex]?.items?.[itemIndex]?.quantity}
|
||||
price={formValues?.sections?.[sectionIndex]?.items?.[itemIndex]?.price}
|
||||
<ItemSubtotal
|
||||
quantity={
|
||||
formValues?.sections?.[sectionIndex]?.items?.[
|
||||
itemIndex
|
||||
]?.quantity
|
||||
}
|
||||
price={
|
||||
formValues?.sections?.[sectionIndex]?.items?.[
|
||||
itemIndex
|
||||
]?.price
|
||||
}
|
||||
currentCurrency={currentCurrency}
|
||||
/>
|
||||
{!isView && itemFields.length > 1 && (
|
||||
@@ -511,7 +575,7 @@ const SectionList = ({
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<SectionTotal
|
||||
<SectionTotal
|
||||
items={formValues?.sections?.[sectionIndex]?.items}
|
||||
currentCurrency={currentCurrency}
|
||||
/>
|
||||
@@ -555,4 +619,5 @@ const SectionList = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionList;
|
||||
|
||||
export default SectionList;
|
||||
|
||||
Reference in New Issue
Block a user