create-cundi-app 1.0.18 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/package.json.template +1 -1
- package/template/src/App.no-samples.tsx +5 -4
- package/template/src/App.tsx +24 -4
- package/template/src/i18n.ts +56 -0
- package/template/src/pages/samples/basic-type-test/create.tsx +14 -1
- package/template/src/pages/samples/basic-type-test/edit.tsx +14 -1
- package/template/src/pages/samples/basic-type-test/list.tsx +16 -0
- package/template/src/pages/samples/order/create.tsx +50 -0
- package/template/src/pages/samples/order/edit.tsx +139 -0
- package/template/src/pages/samples/order/index.ts +4 -0
- package/template/src/pages/samples/order/list.tsx +59 -0
- package/template/src/pages/samples/order/show.tsx +69 -0
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ant-design/icons": "^5.5.1",
|
|
26
26
|
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
|
27
|
-
"@cundi/refine-xaf": "^1.0.
|
|
27
|
+
"@cundi/refine-xaf": "^1.0.17",
|
|
28
28
|
"@cundi/react-chat-widget": "^1.0.1",
|
|
29
29
|
"@refinedev/antd": "^6.0.3",
|
|
30
30
|
"@refinedev/cli": "^2.16.50",
|
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
MirrorTypeMappingConfigList,
|
|
56
56
|
MirrorTypeMappingConfigCreate,
|
|
57
57
|
MirrorTypeMappingConfigEdit,
|
|
58
|
+
CustomSider,
|
|
58
59
|
} from "@cundi/refine-xaf";
|
|
59
60
|
|
|
60
61
|
import { accessControlProvider } from "./accessControlProvider";
|
|
@@ -177,10 +178,10 @@ const InnerApp: React.FC = () => {
|
|
|
177
178
|
fallback={<CatchAllNavigate to="/login" />}
|
|
178
179
|
>
|
|
179
180
|
{ /* {CHAT_START} */}
|
|
180
|
-
<ThemedLayout Header={HeaderWithChat}>
|
|
181
|
+
<ThemedLayout Header={HeaderWithChat} Sider={CustomSider}>
|
|
181
182
|
{ /* {CHAT_END} */}
|
|
182
183
|
{ /* {NO_CHAT_START}
|
|
183
|
-
<ThemedLayout Header={Header}>
|
|
184
|
+
<ThemedLayout Header={Header} Sider={CustomSider}>
|
|
184
185
|
{NO_CHAT_END} */ }
|
|
185
186
|
<Outlet />
|
|
186
187
|
</ThemedLayout>
|
|
@@ -234,10 +235,10 @@ const InnerApp: React.FC = () => {
|
|
|
234
235
|
element={
|
|
235
236
|
<Authenticated key="catch-all">
|
|
236
237
|
{ /* {CHAT_START} */}
|
|
237
|
-
<ThemedLayout Header={HeaderWithChat}>
|
|
238
|
+
<ThemedLayout Header={HeaderWithChat} Sider={CustomSider}>
|
|
238
239
|
{ /* {CHAT_END} */}
|
|
239
240
|
{ /* {NO_CHAT_START}
|
|
240
|
-
<ThemedLayout Header={Header}>
|
|
241
|
+
<ThemedLayout Header={Header} Sider={CustomSider}>
|
|
241
242
|
{NO_CHAT_END} */ }
|
|
242
243
|
<Outlet />
|
|
243
244
|
</ThemedLayout>
|
package/template/src/App.tsx
CHANGED
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
MirrorTypeMappingConfigList,
|
|
57
57
|
MirrorTypeMappingConfigCreate,
|
|
58
58
|
MirrorTypeMappingConfigEdit,
|
|
59
|
+
CustomSider,
|
|
59
60
|
} from "@cundi/refine-xaf";
|
|
60
61
|
|
|
61
62
|
import { accessControlProvider } from "./accessControlProvider";
|
|
@@ -78,6 +79,7 @@ import { DrawioTestList } from "./pages/samples/drawio-test/list";
|
|
|
78
79
|
import { DrawioTestCreate } from "./pages/samples/drawio-test/create";
|
|
79
80
|
import { DrawioTestEdit } from "./pages/samples/drawio-test/edit";
|
|
80
81
|
import { DrawioTestShow } from "./pages/samples/drawio-test/show";
|
|
82
|
+
import { OrderList, OrderCreate, OrderEdit, OrderShow } from "./pages/samples/order";
|
|
81
83
|
|
|
82
84
|
// {CHAT_START}
|
|
83
85
|
import { ChatProvider } from "./components/ChatPanel";
|
|
@@ -138,6 +140,17 @@ const InnerApp: React.FC = () => {
|
|
|
138
140
|
parent: "Model",
|
|
139
141
|
},
|
|
140
142
|
},
|
|
143
|
+
{
|
|
144
|
+
name: "Order",
|
|
145
|
+
list: "/Orders",
|
|
146
|
+
create: "/Orders/create",
|
|
147
|
+
edit: "/Orders/edit/:id",
|
|
148
|
+
show: "/Orders/show/:id",
|
|
149
|
+
meta: {
|
|
150
|
+
label: t("sider.order"),
|
|
151
|
+
parent: "Model",
|
|
152
|
+
},
|
|
153
|
+
},
|
|
141
154
|
{
|
|
142
155
|
name: "TiptapTest",
|
|
143
156
|
list: "/TiptapTests",
|
|
@@ -272,10 +285,10 @@ const InnerApp: React.FC = () => {
|
|
|
272
285
|
fallback={<CatchAllNavigate to="/login" />}
|
|
273
286
|
>
|
|
274
287
|
{ /* {CHAT_START} */}
|
|
275
|
-
<ThemedLayout Header={HeaderWithChat}>
|
|
288
|
+
<ThemedLayout Header={HeaderWithChat} Sider={CustomSider}>
|
|
276
289
|
{ /* {CHAT_END} */}
|
|
277
290
|
{ /* {NO_CHAT_START}
|
|
278
|
-
<ThemedLayout Header={Header}>
|
|
291
|
+
<ThemedLayout Header={Header} Sider={CustomSider}>
|
|
279
292
|
{NO_CHAT_END} */ }
|
|
280
293
|
<Outlet />
|
|
281
294
|
</ThemedLayout>
|
|
@@ -317,6 +330,13 @@ const InnerApp: React.FC = () => {
|
|
|
317
330
|
<Route path="show/:id" element={<DrawioTestShow />} />
|
|
318
331
|
</Route>
|
|
319
332
|
|
|
333
|
+
<Route path="/Orders">
|
|
334
|
+
<Route index element={<OrderList />} />
|
|
335
|
+
<Route path="create" element={<OrderCreate />} />
|
|
336
|
+
<Route path="edit/:id" element={<OrderEdit />} />
|
|
337
|
+
<Route path="show/:id" element={<OrderShow />} />
|
|
338
|
+
</Route>
|
|
339
|
+
|
|
320
340
|
{/* Core routes */}
|
|
321
341
|
<Route path="/ApplicationUsers">
|
|
322
342
|
<Route index element={<ApplicationUserList />} />
|
|
@@ -363,10 +383,10 @@ const InnerApp: React.FC = () => {
|
|
|
363
383
|
element={
|
|
364
384
|
<Authenticated key="catch-all">
|
|
365
385
|
{ /* {CHAT_START} */}
|
|
366
|
-
<ThemedLayout Header={HeaderWithChat}>
|
|
386
|
+
<ThemedLayout Header={HeaderWithChat} Sider={CustomSider}>
|
|
367
387
|
{ /* {CHAT_END} */}
|
|
368
388
|
{ /* {NO_CHAT_START}
|
|
369
|
-
<ThemedLayout Header={Header}>
|
|
389
|
+
<ThemedLayout Header={Header} Sider={CustomSider}>
|
|
370
390
|
{NO_CHAT_END} */ }
|
|
371
391
|
<Outlet />
|
|
372
392
|
</ThemedLayout>
|
package/template/src/i18n.ts
CHANGED
|
@@ -17,6 +17,7 @@ const enExtended = {
|
|
|
17
17
|
samples: "Samples",
|
|
18
18
|
model: "Model",
|
|
19
19
|
basicTypeTest: "Basic Type",
|
|
20
|
+
order: "Master-Details",
|
|
20
21
|
tiptapTest: "Tiptap Editor",
|
|
21
22
|
drawioTest: "Drawio Editor",
|
|
22
23
|
fullTextSearch: "Full Text Search",
|
|
@@ -53,12 +54,39 @@ const enExtended = {
|
|
|
53
54
|
doubleValue: "Double Value",
|
|
54
55
|
dateTimeValue: "DateTime Value",
|
|
55
56
|
boolValue: "Bool Value",
|
|
57
|
+
statusValue: "Status",
|
|
58
|
+
status: {
|
|
59
|
+
Draft: "Draft",
|
|
60
|
+
Active: "Active",
|
|
61
|
+
Completed: "Completed",
|
|
62
|
+
Cancelled: "Cancelled",
|
|
63
|
+
},
|
|
56
64
|
imageValue: "Image Value",
|
|
57
65
|
},
|
|
66
|
+
order: {
|
|
67
|
+
orderNumber: "Order Number",
|
|
68
|
+
orderDate: "Order Date",
|
|
69
|
+
customerName: "Customer Name",
|
|
70
|
+
notes: "Notes",
|
|
71
|
+
totalAmount: "Total Amount",
|
|
72
|
+
items: "Order Items",
|
|
73
|
+
},
|
|
74
|
+
orderItem: {
|
|
75
|
+
title: "Order Item",
|
|
76
|
+
productName: "Product Name",
|
|
77
|
+
quantity: "Quantity",
|
|
78
|
+
unitPrice: "Unit Price",
|
|
79
|
+
subtotal: "Subtotal",
|
|
80
|
+
},
|
|
81
|
+
validation: {
|
|
82
|
+
required: "This field is required",
|
|
83
|
+
},
|
|
58
84
|
types: {
|
|
59
85
|
Article: "Article",
|
|
60
86
|
Product: "Product",
|
|
61
87
|
BasicTypeTest: "Basic Type",
|
|
88
|
+
Order: "Order",
|
|
89
|
+
OrderItem: "Order Item",
|
|
62
90
|
},
|
|
63
91
|
};
|
|
64
92
|
|
|
@@ -73,6 +101,7 @@ const zhTWExtended = {
|
|
|
73
101
|
samples: "範例",
|
|
74
102
|
model: "資料模型",
|
|
75
103
|
basicTypeTest: "基本型別",
|
|
104
|
+
order: "主從式資料",
|
|
76
105
|
tiptapTest: "Tiptap 編輯器",
|
|
77
106
|
drawioTest: "Drawio 編輯器",
|
|
78
107
|
fullTextSearch: "全文檢索",
|
|
@@ -109,12 +138,39 @@ const zhTWExtended = {
|
|
|
109
138
|
doubleValue: "浮點數",
|
|
110
139
|
dateTimeValue: "日期時間",
|
|
111
140
|
boolValue: "布林值",
|
|
141
|
+
statusValue: "狀態",
|
|
142
|
+
status: {
|
|
143
|
+
Draft: "草稿",
|
|
144
|
+
Active: "啟用",
|
|
145
|
+
Completed: "完成",
|
|
146
|
+
Cancelled: "取消",
|
|
147
|
+
},
|
|
112
148
|
imageValue: "圖片",
|
|
113
149
|
},
|
|
150
|
+
order: {
|
|
151
|
+
orderNumber: "訂單編號",
|
|
152
|
+
orderDate: "訂單日期",
|
|
153
|
+
customerName: "客戶名稱",
|
|
154
|
+
notes: "備註",
|
|
155
|
+
totalAmount: "總金額",
|
|
156
|
+
items: "訂單明細",
|
|
157
|
+
},
|
|
158
|
+
orderItem: {
|
|
159
|
+
title: "訂單明細",
|
|
160
|
+
productName: "產品名稱",
|
|
161
|
+
quantity: "數量",
|
|
162
|
+
unitPrice: "單價",
|
|
163
|
+
subtotal: "小計",
|
|
164
|
+
},
|
|
165
|
+
validation: {
|
|
166
|
+
required: "此欄位為必填",
|
|
167
|
+
},
|
|
114
168
|
types: {
|
|
115
169
|
Article: "文章",
|
|
116
170
|
Product: "產品",
|
|
117
171
|
BasicTypeTest: "基本型別",
|
|
172
|
+
Order: "訂單",
|
|
173
|
+
OrderItem: "訂單明細",
|
|
118
174
|
},
|
|
119
175
|
};
|
|
120
176
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Create, useForm } from "@refinedev/antd";
|
|
3
|
-
import { Form, Input, InputNumber, DatePicker, Switch } from "antd";
|
|
3
|
+
import { Form, Input, InputNumber, DatePicker, Switch, Select } from "antd";
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
5
|
import { Base64Upload } from "@cundi/refine-xaf";
|
|
6
6
|
import dayjs from "dayjs";
|
|
@@ -56,6 +56,19 @@ export const BasicTypeTestCreate: React.FC = () => {
|
|
|
56
56
|
>
|
|
57
57
|
<Switch />
|
|
58
58
|
</Form.Item>
|
|
59
|
+
<Form.Item
|
|
60
|
+
label={t("basicTypeTest.statusValue")}
|
|
61
|
+
name="StatusValue"
|
|
62
|
+
>
|
|
63
|
+
<Select
|
|
64
|
+
options={[
|
|
65
|
+
{ value: "Draft", label: t("basicTypeTest.status.Draft") },
|
|
66
|
+
{ value: "Active", label: t("basicTypeTest.status.Active") },
|
|
67
|
+
{ value: "Completed", label: t("basicTypeTest.status.Completed") },
|
|
68
|
+
{ value: "Cancelled", label: t("basicTypeTest.status.Cancelled") },
|
|
69
|
+
]}
|
|
70
|
+
/>
|
|
71
|
+
</Form.Item>
|
|
59
72
|
<Form.Item
|
|
60
73
|
label={t("basicTypeTest.imageValue")}
|
|
61
74
|
name="ImageValue"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Edit, useForm } from "@refinedev/antd";
|
|
3
|
-
import { Form, Input, InputNumber, DatePicker, Switch } from "antd";
|
|
3
|
+
import { Form, Input, InputNumber, DatePicker, Switch, Select } from "antd";
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
5
|
import { Base64Upload } from "@cundi/refine-xaf";
|
|
6
6
|
import dayjs from "dayjs";
|
|
@@ -56,6 +56,19 @@ export const BasicTypeTestEdit: React.FC = () => {
|
|
|
56
56
|
>
|
|
57
57
|
<Switch />
|
|
58
58
|
</Form.Item>
|
|
59
|
+
<Form.Item
|
|
60
|
+
label={t("basicTypeTest.statusValue")}
|
|
61
|
+
name="StatusValue"
|
|
62
|
+
>
|
|
63
|
+
<Select
|
|
64
|
+
options={[
|
|
65
|
+
{ value: "Draft", label: t("basicTypeTest.status.Draft") },
|
|
66
|
+
{ value: "Active", label: t("basicTypeTest.status.Active") },
|
|
67
|
+
{ value: "Completed", label: t("basicTypeTest.status.Completed") },
|
|
68
|
+
{ value: "Cancelled", label: t("basicTypeTest.status.Cancelled") },
|
|
69
|
+
]}
|
|
70
|
+
/>
|
|
71
|
+
</Form.Item>
|
|
59
72
|
<Form.Item
|
|
60
73
|
label={t("basicTypeTest.imageValue")}
|
|
61
74
|
name="ImageValue"
|
|
@@ -46,6 +46,22 @@ export const BasicTypeTestList: React.FC = () => {
|
|
|
46
46
|
// @ts-ignore
|
|
47
47
|
defaultVisible
|
|
48
48
|
/>
|
|
49
|
+
<Table.Column
|
|
50
|
+
dataIndex="StatusValue"
|
|
51
|
+
title={t("basicTypeTest.statusValue")}
|
|
52
|
+
sorter
|
|
53
|
+
render={(value: string) => (
|
|
54
|
+
<Tag color={
|
|
55
|
+
value === "Active" ? "green" :
|
|
56
|
+
value === "Completed" ? "blue" :
|
|
57
|
+
value === "Cancelled" ? "red" : "default"
|
|
58
|
+
}>
|
|
59
|
+
{t(`basicTypeTest.status.${value}`, value)}
|
|
60
|
+
</Tag>
|
|
61
|
+
)}
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
defaultVisible
|
|
64
|
+
/>
|
|
49
65
|
<Table.Column
|
|
50
66
|
dataIndex="ImageValue"
|
|
51
67
|
title={t("basicTypeTest.imageValue")}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Create, useForm } from "@refinedev/antd";
|
|
3
|
+
import { Form, Input, DatePicker } from "antd";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import dayjs from "dayjs";
|
|
6
|
+
|
|
7
|
+
export const OrderCreate: React.FC = () => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
const { formProps, saveButtonProps } = useForm({
|
|
10
|
+
redirect: "edit",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Create saveButtonProps={saveButtonProps}>
|
|
15
|
+
<Form {...formProps} layout="vertical">
|
|
16
|
+
<Form.Item
|
|
17
|
+
label={t("order.orderNumber")}
|
|
18
|
+
name="OrderNumber"
|
|
19
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
20
|
+
>
|
|
21
|
+
<Input />
|
|
22
|
+
</Form.Item>
|
|
23
|
+
<Form.Item
|
|
24
|
+
label={t("order.orderDate")}
|
|
25
|
+
name="OrderDate"
|
|
26
|
+
getValueProps={(value) => ({
|
|
27
|
+
value: value ? dayjs(value) : dayjs(),
|
|
28
|
+
})}
|
|
29
|
+
getValueFromEvent={(date) => date?.toISOString()}
|
|
30
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
31
|
+
>
|
|
32
|
+
<DatePicker style={{ width: "100%" }} />
|
|
33
|
+
</Form.Item>
|
|
34
|
+
<Form.Item
|
|
35
|
+
label={t("order.customerName")}
|
|
36
|
+
name="CustomerName"
|
|
37
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
38
|
+
>
|
|
39
|
+
<Input />
|
|
40
|
+
</Form.Item>
|
|
41
|
+
<Form.Item
|
|
42
|
+
label={t("order.notes")}
|
|
43
|
+
name="Notes"
|
|
44
|
+
>
|
|
45
|
+
<Input.TextArea rows={3} />
|
|
46
|
+
</Form.Item>
|
|
47
|
+
</Form>
|
|
48
|
+
</Create>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Edit, useForm } from "@refinedev/antd";
|
|
3
|
+
import { Form, Input, DatePicker, InputNumber, Card } from "antd";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import { RelatedList } from "@cundi/refine-xaf";
|
|
6
|
+
import { useTable } from "@refinedev/antd";
|
|
7
|
+
import { Table } from "antd";
|
|
8
|
+
import dayjs from "dayjs";
|
|
9
|
+
|
|
10
|
+
// OrderItem Form Fields Component
|
|
11
|
+
const OrderItemFormFields: React.FC<{ mode: "create" | "edit" }> = () => {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
<Form.Item
|
|
17
|
+
label={t("orderItem.productName")}
|
|
18
|
+
name="ProductName"
|
|
19
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
20
|
+
>
|
|
21
|
+
<Input />
|
|
22
|
+
</Form.Item>
|
|
23
|
+
<Form.Item
|
|
24
|
+
label={t("orderItem.quantity")}
|
|
25
|
+
name="Quantity"
|
|
26
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
27
|
+
>
|
|
28
|
+
<InputNumber min={1} style={{ width: "100%" }} />
|
|
29
|
+
</Form.Item>
|
|
30
|
+
<Form.Item
|
|
31
|
+
label={t("orderItem.unitPrice")}
|
|
32
|
+
name="UnitPrice"
|
|
33
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
34
|
+
>
|
|
35
|
+
<InputNumber min={0} precision={2} style={{ width: "100%" }} prefix="$" />
|
|
36
|
+
</Form.Item>
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const OrderEdit: React.FC = () => {
|
|
42
|
+
const { t } = useTranslation();
|
|
43
|
+
const { formProps, saveButtonProps, query } = useForm({
|
|
44
|
+
meta: {
|
|
45
|
+
expand: ["Items"],
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const orderId = query?.data?.data?.Oid as string | undefined;
|
|
50
|
+
|
|
51
|
+
// Fetch order items for the RelatedList
|
|
52
|
+
const { tableProps } = useTable({
|
|
53
|
+
resource: "OrderItem",
|
|
54
|
+
filters: {
|
|
55
|
+
permanent: [
|
|
56
|
+
{ field: "Order/Oid", operator: "eq", value: orderId || "" }
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
syncWithLocation: false,
|
|
60
|
+
queryOptions: {
|
|
61
|
+
enabled: !!orderId,
|
|
62
|
+
},
|
|
63
|
+
pagination: {
|
|
64
|
+
mode: "off"
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Convert readonly array to mutable array for RelatedList
|
|
69
|
+
const dataSource = tableProps.dataSource ? [...tableProps.dataSource] : [];
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Edit saveButtonProps={saveButtonProps}>
|
|
73
|
+
<Form {...formProps} layout="vertical">
|
|
74
|
+
<Form.Item
|
|
75
|
+
label={t("order.orderNumber")}
|
|
76
|
+
name="OrderNumber"
|
|
77
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
78
|
+
>
|
|
79
|
+
<Input />
|
|
80
|
+
</Form.Item>
|
|
81
|
+
<Form.Item
|
|
82
|
+
label={t("order.orderDate")}
|
|
83
|
+
name="OrderDate"
|
|
84
|
+
getValueProps={(value) => ({
|
|
85
|
+
value: value ? dayjs(value) : null,
|
|
86
|
+
})}
|
|
87
|
+
getValueFromEvent={(date) => date?.toISOString()}
|
|
88
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
89
|
+
>
|
|
90
|
+
<DatePicker style={{ width: "100%" }} />
|
|
91
|
+
</Form.Item>
|
|
92
|
+
<Form.Item
|
|
93
|
+
label={t("order.customerName")}
|
|
94
|
+
name="CustomerName"
|
|
95
|
+
rules={[{ required: true, message: t("validation.required") }]}
|
|
96
|
+
>
|
|
97
|
+
<Input />
|
|
98
|
+
</Form.Item>
|
|
99
|
+
<Form.Item
|
|
100
|
+
label={t("order.notes")}
|
|
101
|
+
name="Notes"
|
|
102
|
+
>
|
|
103
|
+
<Input.TextArea rows={3} />
|
|
104
|
+
</Form.Item>
|
|
105
|
+
</Form>
|
|
106
|
+
|
|
107
|
+
{/* Order Items (Details) */}
|
|
108
|
+
<Card title={t("order.items")} style={{ marginTop: 16 }}>
|
|
109
|
+
<RelatedList
|
|
110
|
+
resource="OrderItem"
|
|
111
|
+
masterField="Order"
|
|
112
|
+
masterId={orderId}
|
|
113
|
+
dataSource={dataSource}
|
|
114
|
+
FormFields={OrderItemFormFields}
|
|
115
|
+
modalTitle={t("orderItem.title")}
|
|
116
|
+
>
|
|
117
|
+
<Table.Column
|
|
118
|
+
dataIndex="ProductName"
|
|
119
|
+
title={t("orderItem.productName")}
|
|
120
|
+
/>
|
|
121
|
+
<Table.Column
|
|
122
|
+
dataIndex="Quantity"
|
|
123
|
+
title={t("orderItem.quantity")}
|
|
124
|
+
/>
|
|
125
|
+
<Table.Column
|
|
126
|
+
dataIndex="UnitPrice"
|
|
127
|
+
title={t("orderItem.unitPrice")}
|
|
128
|
+
render={(value: number) => value ? `$${value.toFixed(2)}` : "-"}
|
|
129
|
+
/>
|
|
130
|
+
<Table.Column
|
|
131
|
+
dataIndex="Subtotal"
|
|
132
|
+
title={t("orderItem.subtotal")}
|
|
133
|
+
render={(value: number) => value ? `$${value.toFixed(2)}` : "-"}
|
|
134
|
+
/>
|
|
135
|
+
</RelatedList>
|
|
136
|
+
</Card>
|
|
137
|
+
</Edit>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { BaseRecord } from "@refinedev/core";
|
|
3
|
+
import { EditButton, ShowButton, DeleteButton } from "@refinedev/antd";
|
|
4
|
+
import { Table, Space, Tag } from "antd";
|
|
5
|
+
import { SmartList } from "@cundi/refine-xaf";
|
|
6
|
+
import { useTranslation } from "react-i18next";
|
|
7
|
+
|
|
8
|
+
export const OrderList: React.FC = () => {
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<SmartList
|
|
13
|
+
resource="Order"
|
|
14
|
+
searchFields={["OrderNumber", "CustomerName"]}
|
|
15
|
+
>
|
|
16
|
+
<Table.Column
|
|
17
|
+
dataIndex="OrderNumber"
|
|
18
|
+
title={t("order.orderNumber")}
|
|
19
|
+
sorter
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
defaultVisible
|
|
22
|
+
/>
|
|
23
|
+
<Table.Column
|
|
24
|
+
dataIndex="OrderDate"
|
|
25
|
+
title={t("order.orderDate")}
|
|
26
|
+
sorter
|
|
27
|
+
render={(value: string) => value ? new Date(value).toLocaleDateString() : "-"}
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
defaultVisible
|
|
30
|
+
/>
|
|
31
|
+
<Table.Column
|
|
32
|
+
dataIndex="CustomerName"
|
|
33
|
+
title={t("order.customerName")}
|
|
34
|
+
sorter
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
defaultVisible
|
|
37
|
+
/>
|
|
38
|
+
<Table.Column
|
|
39
|
+
dataIndex="TotalAmount"
|
|
40
|
+
title={t("order.totalAmount")}
|
|
41
|
+
sorter
|
|
42
|
+
render={(value: number) => value ? `$${value.toFixed(2)}` : "$0.00"}
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
defaultVisible
|
|
45
|
+
/>
|
|
46
|
+
<Table.Column
|
|
47
|
+
title={t("buttons.list")}
|
|
48
|
+
dataIndex="actions"
|
|
49
|
+
render={(_, record: BaseRecord) => (
|
|
50
|
+
<Space>
|
|
51
|
+
<EditButton hideText size="small" recordItemId={record.Oid} />
|
|
52
|
+
<ShowButton hideText size="small" recordItemId={record.Oid} />
|
|
53
|
+
<DeleteButton hideText size="small" recordItemId={record.Oid} />
|
|
54
|
+
</Space>
|
|
55
|
+
)}
|
|
56
|
+
/>
|
|
57
|
+
</SmartList>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Show } from "@refinedev/antd";
|
|
3
|
+
import { useShow } from "@refinedev/core";
|
|
4
|
+
import { Typography, Table, Card, Descriptions } from "antd";
|
|
5
|
+
import { useTranslation } from "react-i18next";
|
|
6
|
+
|
|
7
|
+
const { Title } = Typography;
|
|
8
|
+
|
|
9
|
+
export const OrderShow: React.FC = () => {
|
|
10
|
+
const { t } = useTranslation();
|
|
11
|
+
const { query } = useShow({
|
|
12
|
+
meta: {
|
|
13
|
+
expand: ["Items"],
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
const { data, isLoading } = query;
|
|
17
|
+
const record = data?.data;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Show isLoading={isLoading}>
|
|
21
|
+
<Descriptions bordered column={1}>
|
|
22
|
+
<Descriptions.Item label={t("order.orderNumber")}>
|
|
23
|
+
{record?.OrderNumber}
|
|
24
|
+
</Descriptions.Item>
|
|
25
|
+
<Descriptions.Item label={t("order.orderDate")}>
|
|
26
|
+
{record?.OrderDate ? new Date(record.OrderDate).toLocaleDateString() : "-"}
|
|
27
|
+
</Descriptions.Item>
|
|
28
|
+
<Descriptions.Item label={t("order.customerName")}>
|
|
29
|
+
{record?.CustomerName}
|
|
30
|
+
</Descriptions.Item>
|
|
31
|
+
<Descriptions.Item label={t("order.totalAmount")}>
|
|
32
|
+
${record?.TotalAmount?.toFixed(2) || "0.00"}
|
|
33
|
+
</Descriptions.Item>
|
|
34
|
+
<Descriptions.Item label={t("order.notes")}>
|
|
35
|
+
{record?.Notes || "-"}
|
|
36
|
+
</Descriptions.Item>
|
|
37
|
+
</Descriptions>
|
|
38
|
+
|
|
39
|
+
<Card title={t("order.items")} style={{ marginTop: 16 }}>
|
|
40
|
+
<Table
|
|
41
|
+
dataSource={record?.Items || []}
|
|
42
|
+
rowKey="Oid"
|
|
43
|
+
pagination={false}
|
|
44
|
+
bordered
|
|
45
|
+
size="small"
|
|
46
|
+
>
|
|
47
|
+
<Table.Column
|
|
48
|
+
dataIndex="ProductName"
|
|
49
|
+
title={t("orderItem.productName")}
|
|
50
|
+
/>
|
|
51
|
+
<Table.Column
|
|
52
|
+
dataIndex="Quantity"
|
|
53
|
+
title={t("orderItem.quantity")}
|
|
54
|
+
/>
|
|
55
|
+
<Table.Column
|
|
56
|
+
dataIndex="UnitPrice"
|
|
57
|
+
title={t("orderItem.unitPrice")}
|
|
58
|
+
render={(value: number) => value ? `$${value.toFixed(2)}` : "-"}
|
|
59
|
+
/>
|
|
60
|
+
<Table.Column
|
|
61
|
+
dataIndex="Subtotal"
|
|
62
|
+
title={t("orderItem.subtotal")}
|
|
63
|
+
render={(value: number) => value ? `$${value.toFixed(2)}` : "-"}
|
|
64
|
+
/>
|
|
65
|
+
</Table>
|
|
66
|
+
</Card>
|
|
67
|
+
</Show>
|
|
68
|
+
);
|
|
69
|
+
};
|