@evenicanpm/portal-table-ui 1.8.0 → 1.8.2
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 +4 -4
- package/src/features/table/components/dashboard/table/details/templates/invoice-details.tsx +185 -152
- package/src/features/table/components/dashboard/table/details/templates/template-registry.ts +4 -8
- package/src/features/table/components/dashboard/table/table-row/action-button.tsx +2 -2
- package/src/features/table/components/dashboard/table/table-row/table-row.tsx +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evenicanpm/portal-table-ui",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@arrows/multimethod": "^2.1.0",
|
|
44
|
-
"@evenicanpm/portal-types-schemas": "^1.8.
|
|
45
|
-
"@evenicanpm/ui": "^1.8.
|
|
44
|
+
"@evenicanpm/portal-types-schemas": "^1.8.1",
|
|
45
|
+
"@evenicanpm/ui": "^1.8.1",
|
|
46
46
|
"@mui/lab": "^7.0.1-beta.19",
|
|
47
47
|
"@tanstack/react-query": "^5.90.11",
|
|
48
48
|
"date-fns": "^4.1.0"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "d82197e04ab3e322c51a112929cec75dd842d5f6"
|
|
51
51
|
}
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Card,
|
|
5
|
+
Divider,
|
|
6
|
+
Paper,
|
|
7
|
+
Skeleton,
|
|
8
|
+
Table,
|
|
9
|
+
TableBody,
|
|
10
|
+
TableCell,
|
|
11
|
+
TableContainer,
|
|
12
|
+
TableHead,
|
|
13
|
+
TableRow,
|
|
14
|
+
Typography,
|
|
15
|
+
useMediaQuery,
|
|
16
|
+
useTheme,
|
|
17
|
+
} from "@mui/material";
|
|
3
18
|
import Grid2 from "@mui/material/Grid2";
|
|
4
19
|
import { StatusPill } from "../../status-pill";
|
|
5
20
|
import { ActionButton } from "../../table-row/action-button";
|
|
@@ -18,12 +33,9 @@ const formatCurrency = (amount?: number): string => {
|
|
|
18
33
|
|
|
19
34
|
const formatDate = (dateString?: string): string => {
|
|
20
35
|
if (!dateString) return "—";
|
|
21
|
-
|
|
22
36
|
try {
|
|
23
37
|
const date = new Date(dateString);
|
|
24
|
-
// Check if date is valid
|
|
25
38
|
if (isNaN(date.getTime())) return dateString;
|
|
26
|
-
|
|
27
39
|
return new Intl.DateTimeFormat("en-US", {
|
|
28
40
|
year: "numeric",
|
|
29
41
|
month: "long",
|
|
@@ -66,12 +78,10 @@ interface InvoiceData {
|
|
|
66
78
|
|
|
67
79
|
const isDataEmpty = (data: InvoiceData | null | undefined): boolean => {
|
|
68
80
|
if (!data) return true;
|
|
69
|
-
|
|
70
81
|
const hasNoLineItems =
|
|
71
82
|
!data.SalesInvoiceLine || data.SalesInvoiceLine.length === 0;
|
|
72
83
|
const hasNoBasicInfo = !data.CompanyName && !data.Name && !data.InvoiceDate;
|
|
73
84
|
const hasNoAmounts = !data.Amount && data.Amount !== 0;
|
|
74
|
-
|
|
75
85
|
return hasNoLineItems && hasNoBasicInfo && hasNoAmounts;
|
|
76
86
|
};
|
|
77
87
|
|
|
@@ -83,17 +93,25 @@ export const InvoiceDetailsTemplate = ({
|
|
|
83
93
|
actions,
|
|
84
94
|
resourceName = "invoice",
|
|
85
95
|
}: DetailsTemplateProps) => {
|
|
96
|
+
const theme = useTheme();
|
|
97
|
+
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
|
|
98
|
+
|
|
86
99
|
const invoice = data as InvoiceData;
|
|
87
100
|
|
|
101
|
+
// Responsive width
|
|
102
|
+
const containerWidth = isMobile ? "95%" : "75%";
|
|
103
|
+
|
|
88
104
|
if (!loading && (!invoice || isDataEmpty(invoice))) {
|
|
89
105
|
return (
|
|
90
|
-
<Box sx={{ p: 3, width:
|
|
91
|
-
<Card
|
|
106
|
+
<Box sx={{ p: { xs: 2, sm: 3 }, width: containerWidth, mx: "auto" }}>
|
|
107
|
+
<Card
|
|
108
|
+
sx={{ p: { xs: 3, sm: 6 }, borderRadius: 3, textAlign: "center" }}
|
|
109
|
+
>
|
|
92
110
|
<Typography variant="h6" color="text.secondary" gutterBottom>
|
|
93
111
|
No Data Available
|
|
94
112
|
</Typography>
|
|
95
113
|
<Typography variant="body2" color="text.secondary">
|
|
96
|
-
|
|
114
|
+
We couldn't find any details for selected invoice.
|
|
97
115
|
</Typography>
|
|
98
116
|
</Card>
|
|
99
117
|
</Box>
|
|
@@ -105,59 +123,79 @@ export const InvoiceDetailsTemplate = ({
|
|
|
105
123
|
const tax = invoice?.TotalTaxAmount ?? 0;
|
|
106
124
|
const total = invoice?.Amount ?? 0;
|
|
107
125
|
|
|
108
|
-
// Fixed column
|
|
126
|
+
// Fixed column definitions with specific widths
|
|
109
127
|
const columns = [
|
|
110
|
-
{ label: "#",
|
|
111
|
-
{ label: "Product",
|
|
112
|
-
{ label: "Qty",
|
|
113
|
-
{ label: "Unit",
|
|
114
|
-
{ label: "Unit Price",
|
|
115
|
-
{ label: "Discount",
|
|
116
|
-
{ label: "Line Total",
|
|
117
|
-
{ label: "",
|
|
128
|
+
{ label: "#", width: 60 },
|
|
129
|
+
{ label: "Product", width: 200 },
|
|
130
|
+
{ label: "Qty", width: 60 },
|
|
131
|
+
{ label: "Unit", width: 60 },
|
|
132
|
+
{ label: "Unit Price", width: 120 },
|
|
133
|
+
{ label: "Discount", width: 100 },
|
|
134
|
+
{ label: "Line Total", width: 120 },
|
|
135
|
+
{ label: "", width: 40 },
|
|
118
136
|
];
|
|
119
137
|
|
|
138
|
+
// Calculate total width for table container
|
|
139
|
+
const totalTableWidth = columns.reduce((sum, col) => sum + col.width, 0);
|
|
140
|
+
|
|
120
141
|
if (loading) {
|
|
121
142
|
return (
|
|
122
|
-
<Box sx={{ p: 3, width:
|
|
143
|
+
<Box sx={{ p: { xs: 2, sm: 3 }, width: containerWidth, mx: "auto" }}>
|
|
123
144
|
<Box display="flex" justifyContent="space-between" mb={3}>
|
|
124
145
|
<Skeleton variant="rectangular" width={100} height={32} />
|
|
125
146
|
<Skeleton variant="rectangular" width={120} height={40} />
|
|
126
147
|
</Box>
|
|
127
|
-
<Card sx={{ p: 4, borderRadius: 3 }}>
|
|
128
|
-
<Grid2 container spacing={4}>
|
|
148
|
+
<Card sx={{ p: { xs: 2, sm: 4 }, borderRadius: 3 }}>
|
|
149
|
+
<Grid2 container spacing={{ xs: 2, sm: 4 }}>
|
|
129
150
|
{Array.from({ length: 4 }).map((_, i) => (
|
|
130
|
-
|
|
131
|
-
<Grid2 size={6} key={`skeleton-${i}`}>
|
|
151
|
+
<Grid2 size={{ xs: 12, sm: 6 }} key={`skeleton-${i}`}>
|
|
132
152
|
<Skeleton width="40%" height={20} />
|
|
133
153
|
<Skeleton width="80%" />
|
|
134
154
|
<Skeleton width="60%" />
|
|
135
155
|
</Grid2>
|
|
136
156
|
))}
|
|
137
157
|
</Grid2>
|
|
138
|
-
<Divider sx={{ my: 3 }} />
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
158
|
+
<Divider sx={{ my: { xs: 2, sm: 3 } }} />
|
|
159
|
+
|
|
160
|
+
{/* Table skeleton with scroll */}
|
|
161
|
+
<TableContainer
|
|
162
|
+
component={Paper}
|
|
163
|
+
sx={{ boxShadow: "none", overflowX: "auto" }}
|
|
164
|
+
>
|
|
165
|
+
<Table sx={{ minWidth: totalTableWidth }}>
|
|
166
|
+
<TableHead>
|
|
167
|
+
<TableRow>
|
|
168
|
+
{columns.map((col) => (
|
|
169
|
+
<TableCell
|
|
170
|
+
key={col.label}
|
|
171
|
+
sx={{ width: col.width, minWidth: col.width }}
|
|
172
|
+
>
|
|
173
|
+
<Skeleton width="80%" />
|
|
174
|
+
</TableCell>
|
|
175
|
+
))}
|
|
176
|
+
</TableRow>
|
|
177
|
+
</TableHead>
|
|
178
|
+
<TableBody>
|
|
179
|
+
{Array.from({ length: 4 }).map((_, idx) => (
|
|
180
|
+
<TableRow key={`skeleton-${idx}`}>
|
|
181
|
+
{columns.map((col) => (
|
|
182
|
+
<TableCell
|
|
183
|
+
key={col.label}
|
|
184
|
+
sx={{ width: col.width, minWidth: col.width }}
|
|
185
|
+
>
|
|
186
|
+
<Skeleton width="80%" />
|
|
187
|
+
</TableCell>
|
|
188
|
+
))}
|
|
189
|
+
</TableRow>
|
|
190
|
+
))}
|
|
191
|
+
</TableBody>
|
|
192
|
+
</Table>
|
|
193
|
+
</TableContainer>
|
|
194
|
+
|
|
156
195
|
<Box mt={3} display="flex" justifyContent="flex-end">
|
|
157
|
-
<Box width={300}>
|
|
196
|
+
<Box width={{ xs: "100%", sm: 300 }}>
|
|
158
197
|
{Array.from({ length: 3 }).map((_, i) => (
|
|
159
198
|
<Box
|
|
160
|
-
// biome-ignore lint: no-array-index-key
|
|
161
199
|
key={`skeleton-${i}`}
|
|
162
200
|
display="flex"
|
|
163
201
|
justifyContent="space-between"
|
|
@@ -175,12 +213,14 @@ export const InvoiceDetailsTemplate = ({
|
|
|
175
213
|
}
|
|
176
214
|
|
|
177
215
|
return (
|
|
178
|
-
<Box sx={{ p: 3, width:
|
|
216
|
+
<Box sx={{ p: { xs: 2, sm: 3 }, width: containerWidth, mx: "auto" }}>
|
|
179
217
|
{/* Header */}
|
|
180
218
|
<Box
|
|
181
219
|
display="flex"
|
|
182
220
|
justifyContent="space-between"
|
|
183
221
|
alignItems="center"
|
|
222
|
+
flexWrap="wrap"
|
|
223
|
+
gap={2}
|
|
184
224
|
mb={3}
|
|
185
225
|
>
|
|
186
226
|
{invoice?.Status !== undefined && (
|
|
@@ -190,12 +230,10 @@ export const InvoiceDetailsTemplate = ({
|
|
|
190
230
|
statusTextMap={statusTextMap}
|
|
191
231
|
/>
|
|
192
232
|
)}
|
|
193
|
-
<Box display="flex" gap={2}>
|
|
233
|
+
<Box display="flex" gap={2} alignItems="center">
|
|
194
234
|
{actions?.map((action) => {
|
|
195
|
-
const isPaid = invoice.Status === 3;
|
|
196
|
-
|
|
235
|
+
const isPaid = invoice.Status === 3;
|
|
197
236
|
const enabled = !isPaid && action.isEnabled;
|
|
198
|
-
|
|
199
237
|
if (!enabled) {
|
|
200
238
|
return (
|
|
201
239
|
<span
|
|
@@ -208,7 +246,6 @@ export const InvoiceDetailsTemplate = ({
|
|
|
208
246
|
/>
|
|
209
247
|
);
|
|
210
248
|
}
|
|
211
|
-
|
|
212
249
|
return (
|
|
213
250
|
<ActionButton
|
|
214
251
|
key={action.label}
|
|
@@ -223,7 +260,7 @@ export const InvoiceDetailsTemplate = ({
|
|
|
223
260
|
|
|
224
261
|
{/* Notes Section */}
|
|
225
262
|
{invoice?.Notes && (
|
|
226
|
-
<Card sx={{ p: 3, borderRadius: 3, mb: 3 }}>
|
|
263
|
+
<Card sx={{ p: { xs: 2, sm: 3 }, borderRadius: 3, mb: 3 }}>
|
|
227
264
|
<Typography variant="subtitle1" color="text.secondary" mb={1}>
|
|
228
265
|
Notes
|
|
229
266
|
</Typography>
|
|
@@ -238,7 +275,7 @@ export const InvoiceDetailsTemplate = ({
|
|
|
238
275
|
)}
|
|
239
276
|
|
|
240
277
|
{/* Main Invoice Card */}
|
|
241
|
-
<Card sx={{ p: 3, borderRadius: 3 }}>
|
|
278
|
+
<Card sx={{ p: { xs: 2, sm: 3 }, borderRadius: 3 }}>
|
|
242
279
|
{/* Details Section */}
|
|
243
280
|
{(invoice?.CompanyName ||
|
|
244
281
|
invoice?.Name ||
|
|
@@ -248,10 +285,9 @@ export const InvoiceDetailsTemplate = ({
|
|
|
248
285
|
<Typography variant="subtitle1" color="text.secondary" mb={2}>
|
|
249
286
|
Details
|
|
250
287
|
</Typography>
|
|
251
|
-
|
|
252
|
-
<Grid2 container spacing={4}>
|
|
288
|
+
<Grid2 container spacing={{ xs: 2, sm: 4 }}>
|
|
253
289
|
{invoice?.CompanyName && (
|
|
254
|
-
<Grid2 size={6}>
|
|
290
|
+
<Grid2 size={{ xs: 12, sm: 6 }}>
|
|
255
291
|
<Typography variant="body2" color="text.secondary">
|
|
256
292
|
From
|
|
257
293
|
</Typography>
|
|
@@ -259,46 +295,45 @@ export const InvoiceDetailsTemplate = ({
|
|
|
259
295
|
{invoice.CompanyName}
|
|
260
296
|
</Typography>
|
|
261
297
|
{invoice.CompanyEmail && (
|
|
262
|
-
<Typography variant="body2">
|
|
298
|
+
<Typography variant="body2" sx={{ wordBreak: "break-all" }}>
|
|
263
299
|
{invoice.CompanyEmail}
|
|
264
300
|
</Typography>
|
|
265
301
|
)}
|
|
266
302
|
{invoice.CompanyAddress && (
|
|
267
|
-
<Typography variant="body2">
|
|
303
|
+
<Typography variant="body2" sx={{ whiteSpace: "pre-wrap" }}>
|
|
268
304
|
{invoice.CompanyAddress}
|
|
269
305
|
</Typography>
|
|
270
306
|
)}
|
|
271
307
|
</Grid2>
|
|
272
308
|
)}
|
|
273
|
-
|
|
274
309
|
{invoice?.Name && (
|
|
275
|
-
<Grid2 size={6}>
|
|
310
|
+
<Grid2 size={{ xs: 12, sm: 6 }}>
|
|
276
311
|
<Typography variant="body2" color="text.secondary">
|
|
277
312
|
Bill To
|
|
278
313
|
</Typography>
|
|
279
314
|
<Typography fontWeight={600}>{invoice.Name}</Typography>
|
|
280
315
|
{invoice.Email && (
|
|
281
|
-
<Typography variant="body2"
|
|
316
|
+
<Typography variant="body2" sx={{ wordBreak: "break-all" }}>
|
|
317
|
+
{invoice.Email}
|
|
318
|
+
</Typography>
|
|
282
319
|
)}
|
|
283
320
|
{invoice.BillingAddress && (
|
|
284
|
-
<Typography variant="body2">
|
|
321
|
+
<Typography variant="body2" sx={{ whiteSpace: "pre-wrap" }}>
|
|
285
322
|
{invoice.BillingAddress}
|
|
286
323
|
</Typography>
|
|
287
324
|
)}
|
|
288
325
|
</Grid2>
|
|
289
326
|
)}
|
|
290
|
-
|
|
291
327
|
{invoice?.InvoiceDate && (
|
|
292
|
-
<Grid2 size={6}>
|
|
328
|
+
<Grid2 size={{ xs: 12, sm: 6 }}>
|
|
293
329
|
<Typography variant="body2" color="text.secondary">
|
|
294
330
|
Invoice Date
|
|
295
331
|
</Typography>
|
|
296
332
|
<Typography>{formatDate(invoice.InvoiceDate)}</Typography>
|
|
297
333
|
</Grid2>
|
|
298
334
|
)}
|
|
299
|
-
|
|
300
335
|
{invoice?.DueDate && (
|
|
301
|
-
<Grid2 size={6}>
|
|
336
|
+
<Grid2 size={{ xs: 12, sm: 6 }}>
|
|
302
337
|
<Typography variant="body2" color="text.secondary">
|
|
303
338
|
Due Date
|
|
304
339
|
</Typography>
|
|
@@ -306,116 +341,114 @@ export const InvoiceDetailsTemplate = ({
|
|
|
306
341
|
</Grid2>
|
|
307
342
|
)}
|
|
308
343
|
</Grid2>
|
|
309
|
-
|
|
310
|
-
<Divider sx={{ my: 3 }} />
|
|
344
|
+
<Divider sx={{ my: { xs: 2, sm: 3 } }} />
|
|
311
345
|
</>
|
|
312
346
|
)}
|
|
313
347
|
|
|
314
348
|
{/* Line Items Section */}
|
|
315
349
|
{items.length > 0 ? (
|
|
316
350
|
<>
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
351
|
+
<TableContainer>
|
|
352
|
+
<Table sx={{ minWidth: totalTableWidth }}>
|
|
353
|
+
<TableHead>
|
|
354
|
+
<TableRow>
|
|
355
|
+
{columns.map((col) => (
|
|
356
|
+
<TableCell
|
|
357
|
+
key={col.label}
|
|
358
|
+
sx={{
|
|
359
|
+
width: col.width,
|
|
360
|
+
minWidth: col.width,
|
|
361
|
+
fontWeight: 600,
|
|
362
|
+
backgroundColor: theme.palette.background.paper,
|
|
363
|
+
}}
|
|
364
|
+
>
|
|
365
|
+
<Typography variant="body2" fontWeight={600}>
|
|
366
|
+
{col.label}
|
|
367
|
+
</Typography>
|
|
368
|
+
</TableCell>
|
|
369
|
+
))}
|
|
370
|
+
</TableRow>
|
|
371
|
+
</TableHead>
|
|
372
|
+
<TableBody>
|
|
373
|
+
{items.map((item, idx) => {
|
|
374
|
+
const productName = item.ProductName || "-";
|
|
375
|
+
const unitPrice = item.Price ?? 0;
|
|
376
|
+
const quantity = item.Quantity ?? 0;
|
|
377
|
+
const lineTotal = item.NetAmount ?? unitPrice * quantity;
|
|
378
|
+
|
|
379
|
+
return (
|
|
380
|
+
<TableRow key={`${item.ItemId}-${idx}`}>
|
|
381
|
+
<TableCell sx={{ width: 60, minWidth: 60 }}>
|
|
382
|
+
<Typography variant="body2">
|
|
383
|
+
{item?.ItemId || idx + 1}
|
|
384
|
+
</Typography>
|
|
385
|
+
</TableCell>
|
|
386
|
+
<TableCell sx={{ width: 200, minWidth: 200 }}>
|
|
387
|
+
<Typography variant="body2">{productName}</Typography>
|
|
388
|
+
</TableCell>
|
|
389
|
+
<TableCell sx={{ width: 60, minWidth: 60 }}>
|
|
390
|
+
<Typography variant="body2">{quantity}</Typography>
|
|
391
|
+
</TableCell>
|
|
392
|
+
<TableCell sx={{ width: 60, minWidth: 60 }}>
|
|
393
|
+
<Typography variant="body2">
|
|
394
|
+
{item?.UnitOfMeasure || "—"}
|
|
395
|
+
</Typography>
|
|
396
|
+
</TableCell>
|
|
397
|
+
<TableCell sx={{ width: 120, minWidth: 120 }}>
|
|
398
|
+
<Typography variant="body2">
|
|
399
|
+
{formatCurrency(unitPrice)}
|
|
400
|
+
</Typography>
|
|
401
|
+
</TableCell>
|
|
402
|
+
<TableCell sx={{ width: 100, minWidth: 100 }}>
|
|
403
|
+
<Typography
|
|
404
|
+
variant="body2"
|
|
405
|
+
color={
|
|
406
|
+
item.HasDiscount ? "error.main" : "text.secondary"
|
|
407
|
+
}
|
|
408
|
+
>
|
|
409
|
+
{item.HasDiscount
|
|
410
|
+
? `-${formatCurrency(item.DiscountAmount)}`
|
|
411
|
+
: formatCurrency(0)}
|
|
412
|
+
</Typography>
|
|
413
|
+
</TableCell>
|
|
414
|
+
<TableCell sx={{ width: 100, minWidth: 100 }}>
|
|
415
|
+
<Typography variant="body2" fontWeight={500}>
|
|
416
|
+
{formatCurrency(lineTotal)}
|
|
417
|
+
</Typography>
|
|
418
|
+
</TableCell>
|
|
419
|
+
<TableCell
|
|
420
|
+
sx={{ width: 40, minWidth: 40 }}
|
|
421
|
+
align="center"
|
|
422
|
+
>
|
|
423
|
+
{item.HasDiscount && (
|
|
424
|
+
<Typography color="error.main" fontWeight={700}>
|
|
425
|
+
*
|
|
426
|
+
</Typography>
|
|
427
|
+
)}
|
|
428
|
+
</TableCell>
|
|
429
|
+
</TableRow>
|
|
430
|
+
);
|
|
431
|
+
})}
|
|
432
|
+
</TableBody>
|
|
433
|
+
</Table>
|
|
434
|
+
</TableContainer>
|
|
399
435
|
|
|
400
436
|
{/* Totals */}
|
|
401
437
|
<Box mt={3} display="flex" justifyContent="flex-end">
|
|
402
|
-
<Box width={300}>
|
|
438
|
+
<Box width={{ xs: "100%", sm: 300 }}>
|
|
403
439
|
<Box display="flex" justifyContent="space-between" mb={1}>
|
|
404
440
|
<Typography variant="body2">Subtotal</Typography>
|
|
405
441
|
<Typography variant="body2" fontWeight={500}>
|
|
406
442
|
{formatCurrency(subtotal)}
|
|
407
443
|
</Typography>
|
|
408
444
|
</Box>
|
|
409
|
-
|
|
410
445
|
<Box display="flex" justifyContent="space-between" mb={1}>
|
|
411
446
|
<Typography variant="body2">Tax</Typography>
|
|
412
447
|
<Typography variant="body2" fontWeight={500}>
|
|
413
448
|
{formatCurrency(tax)}
|
|
414
449
|
</Typography>
|
|
415
450
|
</Box>
|
|
416
|
-
|
|
417
451
|
<Divider sx={{ my: 1.5 }} />
|
|
418
|
-
|
|
419
452
|
<Box display="flex" justifyContent="space-between" mt={1}>
|
|
420
453
|
<Typography variant="body1" fontWeight={700}>
|
|
421
454
|
Total
|
package/src/features/table/components/dashboard/table/details/templates/template-registry.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
3
|
-
StatusColorMap,
|
|
4
|
-
StatusTextMap,
|
|
5
|
-
} from "src/features/table/types/schemas";
|
|
1
|
+
import type * as Types from "../../../../../types";
|
|
6
2
|
import { InvoiceDetailsTemplate } from "./invoice-details";
|
|
7
3
|
|
|
8
4
|
/**
|
|
@@ -12,10 +8,10 @@ import { InvoiceDetailsTemplate } from "./invoice-details";
|
|
|
12
8
|
*/
|
|
13
9
|
export interface DetailsTemplateProps {
|
|
14
10
|
data: unknown;
|
|
15
|
-
statusColorMap: StatusColorMap;
|
|
16
|
-
statusTextMap: StatusTextMap;
|
|
11
|
+
statusColorMap: Types.Schemas.StatusColorMap;
|
|
12
|
+
statusTextMap: Types.Schemas.StatusTextMap;
|
|
17
13
|
loading?: boolean;
|
|
18
|
-
actions?:
|
|
14
|
+
actions?: Types.Schemas.UIAction[];
|
|
19
15
|
resourceName?: string;
|
|
20
16
|
}
|
|
21
17
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Button, CircularProgress, IconButton } from "@mui/material";
|
|
2
2
|
import { useMutation } from "@tanstack/react-query";
|
|
3
|
-
import type
|
|
3
|
+
import type * as Types from "../../../../types";
|
|
4
4
|
|
|
5
5
|
interface ActionButtonProps {
|
|
6
6
|
docId: string;
|
|
7
|
-
action: UIAction;
|
|
7
|
+
action: Types.Schemas.UIAction;
|
|
8
8
|
resourceName: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -4,7 +4,6 @@ import TableCell from "@mui/material/TableCell";
|
|
|
4
4
|
import TableRow from "@mui/material/TableRow";
|
|
5
5
|
import { styled } from "@mui/system";
|
|
6
6
|
import type React from "react";
|
|
7
|
-
import type { UIAction } from "src/features/table/types/schemas";
|
|
8
7
|
import type * as Types from "../../../../types";
|
|
9
8
|
import { ActionButton } from "./action-button";
|
|
10
9
|
|
|
@@ -39,7 +38,7 @@ export type DocumentTableProps = {
|
|
|
39
38
|
/** */
|
|
40
39
|
handleClick: React.Dispatch<React.SetStateAction<string | number | null>>;
|
|
41
40
|
/** Actions renderer */
|
|
42
|
-
actions: UIAction[];
|
|
41
|
+
actions: Types.Schemas.UIAction[];
|
|
43
42
|
/** Does this view config have actions? */
|
|
44
43
|
/** The id field for the document (used for knowing what to set selected id to) */
|
|
45
44
|
id: string | number;
|