quata模块完成
This commit is contained in:
@@ -1,16 +1,35 @@
|
||||
import { Card, Table, Button, Space, Input, message, Popconfirm, Form, Tag, Typography } from "antd";
|
||||
import { DownOutlined, UpOutlined,EyeOutlined,EditOutlined } from "@ant-design/icons";
|
||||
import {
|
||||
Card,
|
||||
Table,
|
||||
Button,
|
||||
Space,
|
||||
Input,
|
||||
message,
|
||||
Popconfirm,
|
||||
Form,
|
||||
Tag,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import {
|
||||
DownOutlined,
|
||||
UpOutlined,
|
||||
EyeOutlined,
|
||||
EditOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { supabase } from "@/config/supabase";
|
||||
|
||||
import UnitManagement from "@/pages/company/service/unit";
|
||||
import Sections from "@/pages/company/service/sections";
|
||||
import CategoryDrawer from "@/pages/company/service/classify";
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
const ServicePage = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState([]);
|
||||
const [categories, setCategories] = useState([]);
|
||||
const navigate = useNavigate();
|
||||
const [editingKey, setEditingKey] = useState('');
|
||||
const [editingKey, setEditingKey] = useState("");
|
||||
|
||||
// 获取服务模板列表
|
||||
const fetchServices = async () => {
|
||||
@@ -32,19 +51,35 @@ const ServicePage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 添加获取分类数据的方法
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
const { data: categoriesData, error } = await supabase
|
||||
.from('resources')
|
||||
.select('*')
|
||||
.eq('type', 'categories')
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (error) throw error;
|
||||
setCategories(categoriesData || []);
|
||||
} catch (error) {
|
||||
console.error('获取分类数据失败:', error);
|
||||
message.error('获取分类数据失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 修改保存逻辑
|
||||
const handleSaveItem = async (record) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { serviceId, sectionIndex, itemIndex } = record;
|
||||
|
||||
|
||||
// 找到当前服务模板
|
||||
const currentService = data.find(item => item.id === serviceId);
|
||||
const currentService = data.find((item) => item.id === serviceId);
|
||||
if (!currentService) {
|
||||
throw new Error('Service not found');
|
||||
throw new Error("Service not found");
|
||||
}
|
||||
|
||||
// 创建新的 attributes 对象,避免直接修改状态
|
||||
const newAttributes = {
|
||||
...currentService.attributes,
|
||||
templateName: currentService.attributes.templateName,
|
||||
@@ -60,47 +95,57 @@ const ServicePage = () => {
|
||||
name: record.name,
|
||||
price: Number(record.price) || 0,
|
||||
quantity: Number(record.quantity) || 0,
|
||||
description: record.description || '',
|
||||
unit: record.unit || ''
|
||||
description: record.description || "",
|
||||
unit: record.unit || "",
|
||||
};
|
||||
}
|
||||
return item;
|
||||
})
|
||||
}),
|
||||
};
|
||||
}
|
||||
return section;
|
||||
})
|
||||
}),
|
||||
};
|
||||
|
||||
// 重新计算总金额
|
||||
newAttributes.totalAmount = newAttributes.sections.reduce((total, section) => {
|
||||
return total + section.items.reduce((sectionTotal, item) =>
|
||||
sectionTotal + ((Number(item.price) || 0) * (Number(item.quantity) || 0)), 0);
|
||||
}, 0);
|
||||
newAttributes.totalAmount = newAttributes.sections.reduce(
|
||||
(total, section) => {
|
||||
return (
|
||||
total +
|
||||
section.items.reduce(
|
||||
(sectionTotal, item) =>
|
||||
sectionTotal +
|
||||
(Number(item.price) || 0) * (Number(item.quantity) || 0),
|
||||
0
|
||||
)
|
||||
);
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
// 调用 supabase 更新数据
|
||||
const { error } = await supabase
|
||||
.from('resources')
|
||||
.update({
|
||||
.from("resources")
|
||||
.update({
|
||||
type: "serviceTemplate",
|
||||
attributes: newAttributes
|
||||
attributes: newAttributes,
|
||||
})
|
||||
.eq('id', serviceId);
|
||||
.eq("id", serviceId);
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
// 更新本地状态
|
||||
setData(prevData => prevData.map(item =>
|
||||
item.id === serviceId
|
||||
? { ...item, attributes: newAttributes }
|
||||
: item
|
||||
));
|
||||
setData((prevData) =>
|
||||
prevData.map((item) =>
|
||||
item.id === serviceId ? { ...item, attributes: newAttributes } : item
|
||||
)
|
||||
);
|
||||
|
||||
setEditingKey('');
|
||||
message.success('保存成功');
|
||||
setEditingKey("");
|
||||
message.success("保存成功");
|
||||
} catch (error) {
|
||||
console.error('保存失败:', error);
|
||||
message.error('保存失败');
|
||||
console.error("保存失败:", error);
|
||||
message.error("保存失败");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -111,11 +156,11 @@ const ServicePage = () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { serviceId, sectionIndex, itemIndex } = record;
|
||||
|
||||
|
||||
// 找到目标服务
|
||||
const targetService = data.find(item => item.id === serviceId);
|
||||
if (!targetService) throw new Error('Service not found');
|
||||
|
||||
const targetService = data.find((item) => item.id === serviceId);
|
||||
if (!targetService) throw new Error("Service not found");
|
||||
|
||||
// 创建新的 attributes 对象,避免直接修改状态
|
||||
const newAttributes = {
|
||||
...targetService.attributes,
|
||||
@@ -123,40 +168,51 @@ const ServicePage = () => {
|
||||
if (secIdx === sectionIndex) {
|
||||
return {
|
||||
...section,
|
||||
items: section.items.filter((_, idx) => idx !== itemIndex)
|
||||
items: section.items.filter((_, idx) => idx !== itemIndex),
|
||||
};
|
||||
}
|
||||
return section;
|
||||
})
|
||||
}),
|
||||
};
|
||||
|
||||
// 重新计算总金额
|
||||
newAttributes.totalAmount = newAttributes.sections.reduce((total, section) => {
|
||||
return total + section.items.reduce((sectionTotal, item) =>
|
||||
sectionTotal + ((Number(item.price) || 0) * (Number(item.quantity) || 0)), 0);
|
||||
}, 0);
|
||||
newAttributes.totalAmount = newAttributes.sections.reduce(
|
||||
(total, section) => {
|
||||
return (
|
||||
total +
|
||||
section.items.reduce(
|
||||
(sectionTotal, item) =>
|
||||
sectionTotal +
|
||||
(Number(item.price) || 0) * (Number(item.quantity) || 0),
|
||||
0
|
||||
)
|
||||
);
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
// 调用 supabase 更新数据
|
||||
const { error } = await supabase
|
||||
.from('resources')
|
||||
.update({
|
||||
attributes: newAttributes
|
||||
.from("resources")
|
||||
|
||||
.update({
|
||||
attributes: newAttributes,
|
||||
})
|
||||
.eq('id', serviceId);
|
||||
.eq("id", serviceId);
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
// 更新本地状态
|
||||
setData(prevData => prevData.map(item =>
|
||||
item.id === serviceId
|
||||
? { ...item, attributes: newAttributes }
|
||||
: item
|
||||
));
|
||||
setData((prevData) =>
|
||||
prevData.map((item) =>
|
||||
item.id === serviceId ? { ...item, attributes: newAttributes } : item
|
||||
)
|
||||
);
|
||||
|
||||
message.success('删除成功');
|
||||
message.success("删除成功");
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error);
|
||||
message.error('删<><E588A0><EFBFBD>失败');
|
||||
console.error("删除失败:", error);
|
||||
message.error("删除失败");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -166,21 +222,21 @@ const ServicePage = () => {
|
||||
const handleDeleteService = async (serviceId) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
|
||||
// 调用 supabase 删除数据
|
||||
const { error } = await supabase
|
||||
.from('resources')
|
||||
.from("resources")
|
||||
.delete()
|
||||
.eq('id', serviceId);
|
||||
.eq("id", serviceId);
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
// 更新本地状态
|
||||
setData(prevData => prevData.filter(item => item.id !== serviceId));
|
||||
message.success('删除成功');
|
||||
setData((prevData) => prevData.filter((item) => item.id !== serviceId));
|
||||
message.success("删除成功");
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error);
|
||||
message.error('删除失败');
|
||||
console.error("删除失败:", error);
|
||||
message.error("删除失败");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -198,38 +254,39 @@ const ServicePage = () => {
|
||||
title: "分类",
|
||||
dataIndex: ["attributes", "category"],
|
||||
key: "category",
|
||||
render: (category) => {
|
||||
if (!category || !Array.isArray(category)) return null;
|
||||
render: (categories) => {
|
||||
if (!categories || !Array.isArray(categories)) return null;
|
||||
|
||||
return (
|
||||
<Paragraph
|
||||
ellipsis={{
|
||||
rows: 1,
|
||||
tooltip: (
|
||||
<Space size={[0, 8]} wrap>
|
||||
{category.map((cat, index) => (
|
||||
{categories.map((category) => (
|
||||
<Tag
|
||||
size="small"
|
||||
key={`${cat}-${index}`}
|
||||
key={category.id}
|
||||
color="blue"
|
||||
className="px-2 py-1 rounded-md"
|
||||
>
|
||||
{cat}
|
||||
{category.name}
|
||||
</Tag>
|
||||
))}
|
||||
</Space>
|
||||
)
|
||||
),
|
||||
}}
|
||||
className="mb-0"
|
||||
>
|
||||
<Space size={[0, 8]} nowrap>
|
||||
{category.map((cat, index) => (
|
||||
{categories.map((category) => (
|
||||
<Tag
|
||||
size="small"
|
||||
key={`${cat}-${index}`}
|
||||
key={category.id}
|
||||
color="blue"
|
||||
className="px-2 py-1 rounded-md"
|
||||
>
|
||||
{cat}
|
||||
{category.name}
|
||||
</Tag>
|
||||
))}
|
||||
</Space>
|
||||
@@ -241,18 +298,18 @@ const ServicePage = () => {
|
||||
title: "描述",
|
||||
dataIndex: ["attributes", "description"],
|
||||
key: "description",
|
||||
width: 300,
|
||||
className: "min-w-[100px] ",
|
||||
render: (text) => (
|
||||
<Paragraph
|
||||
ellipsis={{
|
||||
rows: 2,
|
||||
tooltip: text
|
||||
tooltip: text,
|
||||
}}
|
||||
className="mb-0"
|
||||
>
|
||||
{text}
|
||||
</Paragraph>
|
||||
)
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "总金额",
|
||||
@@ -260,7 +317,7 @@ const ServicePage = () => {
|
||||
key: "totalAmount",
|
||||
className: "min-w-[150px] text-right",
|
||||
render: (amount) => (
|
||||
<span style={{ color: '#f50', fontWeight: 'bold' }}>
|
||||
<span style={{ color: "#f50", fontWeight: "bold" }}>
|
||||
¥
|
||||
{amount?.toLocaleString("zh-CN", {
|
||||
minimumFractionDigits: 2,
|
||||
@@ -272,21 +329,25 @@ const ServicePage = () => {
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
fixed: 'right',
|
||||
fixed: "right",
|
||||
width: 220,
|
||||
render: (_, record) => (
|
||||
<Space onClick={e => e.stopPropagation()}>
|
||||
<Space onClick={(e) => e.stopPropagation()}>
|
||||
<Button
|
||||
type="link"
|
||||
icon={<EyeOutlined />}
|
||||
onClick={() => navigate(`/company/serviceTemplateInfo/${record.id}`)}
|
||||
onClick={() =>
|
||||
navigate(`/company/serviceTemplateInfo/${record.id}`)
|
||||
}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => navigate(`/company/serviceTemplateInfo/${record.id}?edit=true`)}
|
||||
onClick={() =>
|
||||
navigate(`/company/serviceTemplateInfo/${record.id}?edit=true`)
|
||||
}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
@@ -298,11 +359,7 @@ const ServicePage = () => {
|
||||
okButtonProps={{ danger: true }}
|
||||
onConfirm={() => handleDeleteService(record.id)}
|
||||
>
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
className="text-red-600"
|
||||
>
|
||||
<Button type="link" danger className="text-red-600">
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
@@ -326,19 +383,26 @@ const ServicePage = () => {
|
||||
name={[record.sectionIndex, "items", record.itemIndex, "name"]}
|
||||
className="!mb-0"
|
||||
>
|
||||
<Input
|
||||
value={text}
|
||||
onChange={e => {
|
||||
<Input
|
||||
value={text}
|
||||
onChange={(e) => {
|
||||
const newData = [...data];
|
||||
const targetService = newData.find(item => item.id === record.serviceId);
|
||||
const targetItem = targetService.attributes.sections[record.sectionIndex].items[record.itemIndex];
|
||||
const targetService = newData.find(
|
||||
(item) => item.id === record.serviceId
|
||||
);
|
||||
const targetItem =
|
||||
targetService.attributes.sections[record.sectionIndex].items[
|
||||
record.itemIndex
|
||||
];
|
||||
targetItem.name = e.target.value;
|
||||
setData(newData);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
) : text;
|
||||
}
|
||||
) : (
|
||||
text
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "描述",
|
||||
@@ -349,16 +413,25 @@ const ServicePage = () => {
|
||||
const isEditing = record.key === editingKey;
|
||||
return isEditing ? (
|
||||
<Form.Item
|
||||
name={[record.sectionIndex, "items", record.itemIndex, "description"]}
|
||||
name={[
|
||||
record.sectionIndex,
|
||||
"items",
|
||||
record.itemIndex,
|
||||
"description",
|
||||
]}
|
||||
className="!mb-0"
|
||||
>
|
||||
<Input.TextArea
|
||||
rows={1}
|
||||
value={text}
|
||||
onChange={e => {
|
||||
<Input
|
||||
value={text}
|
||||
onChange={(e) => {
|
||||
const newData = [...data];
|
||||
const targetService = newData.find(item => item.id === record.serviceId);
|
||||
const targetItem = targetService.attributes.sections[record.sectionIndex].items[record.itemIndex];
|
||||
const targetService = newData.find(
|
||||
(item) => item.id === record.serviceId
|
||||
);
|
||||
const targetItem =
|
||||
targetService.attributes.sections[record.sectionIndex].items[
|
||||
record.itemIndex
|
||||
];
|
||||
targetItem.description = e.target.value;
|
||||
setData(newData);
|
||||
}}
|
||||
@@ -368,14 +441,14 @@ const ServicePage = () => {
|
||||
<Paragraph
|
||||
ellipsis={{
|
||||
rows: 2,
|
||||
tooltip: text
|
||||
tooltip: text,
|
||||
}}
|
||||
className="mb-0"
|
||||
>
|
||||
{text}
|
||||
</Paragraph>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "单价",
|
||||
@@ -385,26 +458,32 @@ const ServicePage = () => {
|
||||
render: (price, record) => {
|
||||
const isEditing = record.key === editingKey;
|
||||
return isEditing ? (
|
||||
<Input
|
||||
<Input
|
||||
type="number"
|
||||
value={price}
|
||||
onChange={e => {
|
||||
value={price}
|
||||
onChange={(e) => {
|
||||
const newData = [...data];
|
||||
const targetService = newData.find(item => item.id === record.serviceId);
|
||||
const targetItem = targetService.attributes.sections[record.sectionIndex].items[record.itemIndex];
|
||||
const targetService = newData.find(
|
||||
(item) => item.id === record.serviceId
|
||||
);
|
||||
const targetItem =
|
||||
targetService.attributes.sections[record.sectionIndex].items[
|
||||
record.itemIndex
|
||||
];
|
||||
targetItem.price = Number(e.target.value);
|
||||
setData(newData);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<span className="text-gray-600">
|
||||
¥{price?.toLocaleString("zh-CN", {
|
||||
¥
|
||||
{price?.toLocaleString("zh-CN", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "数量",
|
||||
@@ -414,19 +493,26 @@ const ServicePage = () => {
|
||||
render: (quantity, record) => {
|
||||
const isEditing = record.key === editingKey;
|
||||
return isEditing ? (
|
||||
<Input
|
||||
<Input
|
||||
type="number"
|
||||
value={quantity}
|
||||
onChange={e => {
|
||||
value={quantity}
|
||||
onChange={(e) => {
|
||||
const newData = [...data];
|
||||
const targetService = newData.find(item => item.id === record.serviceId);
|
||||
const targetItem = targetService.attributes.sections[record.sectionIndex].items[record.itemIndex];
|
||||
const targetService = newData.find(
|
||||
(item) => item.id === record.serviceId
|
||||
);
|
||||
const targetItem =
|
||||
targetService.attributes.sections[record.sectionIndex].items[
|
||||
record.itemIndex
|
||||
];
|
||||
targetItem.quantity = Number(e.target.value);
|
||||
setData(newData);
|
||||
}}
|
||||
/>
|
||||
) : <span className="text-gray-600">{quantity}</span>;
|
||||
}
|
||||
) : (
|
||||
<span className="text-gray-600">{quantity}</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "小计",
|
||||
@@ -446,37 +532,39 @@ const ServicePage = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
title: "操作",
|
||||
key: "action",
|
||||
width: "150px",
|
||||
render: (_, record) => {
|
||||
const isEditing = record.key === editingKey;
|
||||
return isEditing ? (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
className="text-green-600"
|
||||
onClick={() => handleSaveItem(record, record.sectionIndex, record.itemIndex)}
|
||||
onClick={() =>
|
||||
handleSaveItem(record, record.sectionIndex, record.itemIndex)
|
||||
}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
className="text-gray-600"
|
||||
onClick={() => setEditingKey('')}
|
||||
onClick={() => setEditingKey("")}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
) : (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
className="text-blue-600"
|
||||
disabled={editingKey !== ''}
|
||||
disabled={editingKey !== ""}
|
||||
onClick={() => setEditingKey(record.key)}
|
||||
>
|
||||
编辑
|
||||
@@ -489,19 +577,19 @@ const ServicePage = () => {
|
||||
okButtonProps={{ danger: true }}
|
||||
onConfirm={() => handleDeleteItem(record)}
|
||||
>
|
||||
<Button
|
||||
type="link"
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
className="text-red-600"
|
||||
disabled={editingKey !== ''}
|
||||
disabled={editingKey !== ""}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// 修改 expandedRowRender 函数,确保 key 的唯一性
|
||||
@@ -520,8 +608,9 @@ const ServicePage = () => {
|
||||
总计: ¥
|
||||
{section.items
|
||||
.reduce(
|
||||
(total, item) =>
|
||||
total + (Number(item.price) || 0) * (Number(item.quantity) || 0),
|
||||
(total, item) =>
|
||||
total +
|
||||
(Number(item.price) || 0) * (Number(item.quantity) || 0),
|
||||
0
|
||||
)
|
||||
.toLocaleString("zh-CN", {
|
||||
@@ -532,11 +621,11 @@ const ServicePage = () => {
|
||||
</div>
|
||||
}
|
||||
headStyle={{
|
||||
background: 'rgba(59, 130, 246, 0.05)',
|
||||
borderBottom: '1px solid rgba(59, 130, 246, 0.1)'
|
||||
background: "rgba(59, 130, 246, 0.05)",
|
||||
borderBottom: "1px solid rgba(59, 130, 246, 0.1)",
|
||||
}}
|
||||
bodyStyle={{
|
||||
background: 'rgba(59, 130, 246, 0.02)'
|
||||
background: "rgba(59, 130, 246, 0.02)",
|
||||
}}
|
||||
>
|
||||
<Table
|
||||
@@ -546,7 +635,7 @@ const ServicePage = () => {
|
||||
key: `${record.id}-${sectionIndex}-${itemIndex}`,
|
||||
serviceId: record.id,
|
||||
sectionIndex,
|
||||
itemIndex
|
||||
itemIndex,
|
||||
}))}
|
||||
pagination={false}
|
||||
className="rounded-lg overflow-hidden"
|
||||
@@ -559,6 +648,7 @@ const ServicePage = () => {
|
||||
|
||||
useEffect(() => {
|
||||
fetchServices();
|
||||
fetchCategories();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -567,12 +657,18 @@ const ServicePage = () => {
|
||||
title={<span className="text-xl font-medium">服务模版管理</span>}
|
||||
className="h-full w-full overflow-auto"
|
||||
extra={
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => navigate("/company/serviceTemplateInfo")}
|
||||
>
|
||||
新建模版
|
||||
</Button>
|
||||
<Space>
|
||||
<Sections />
|
||||
<UnitManagement />
|
||||
<CategoryDrawer />
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => navigate("/company/serviceTemplateInfo")}
|
||||
>
|
||||
新建模版
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table
|
||||
@@ -587,29 +683,34 @@ const ServicePage = () => {
|
||||
expandIcon: ({ expanded, onExpand, record }) => (
|
||||
<Button
|
||||
type="link"
|
||||
onClick={e => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onExpand(record, e);
|
||||
}}
|
||||
icon={expanded ? <UpOutlined /> : <DownOutlined />}
|
||||
className={`
|
||||
transition-all duration-300
|
||||
${expanded
|
||||
? 'text-blue-600'
|
||||
: 'text-gray-400 hover:text-blue-600'
|
||||
${
|
||||
expanded
|
||||
? "text-blue-600"
|
||||
: "text-gray-400 hover:text-blue-600"
|
||||
}
|
||||
`}
|
||||
/>
|
||||
),
|
||||
rowExpandable: record => record.attributes.sections?.length > 0,
|
||||
rowExpandable: (record) => record.attributes.sections?.length > 0,
|
||||
}}
|
||||
className="rounded-lg overflow-hidden"
|
||||
rowClassName={(record, index) => `
|
||||
cursor-pointer transition-colors
|
||||
${index % 2 === 0 ? 'bg-white dark:bg-gray-800' : 'bg-gray-50 dark:bg-gray-750'}
|
||||
${
|
||||
index % 2 === 0
|
||||
? "bg-white dark:bg-gray-800"
|
||||
: "bg-gray-50 dark:bg-gray-750"
|
||||
}
|
||||
hover:bg-blue-50 dark:hover:bg-blue-900/20
|
||||
`}
|
||||
expandedRowClassName={() => 'bg-blue-50/50 dark:bg-blue-900/10'}
|
||||
expandedRowClassName={() => "bg-blue-50/50 dark:bg-blue-900/10"}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user