@visns-studio/visns-components 5.13.16 → 5.13.18
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
CHANGED
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
89
89
|
},
|
|
90
90
|
"name": "@visns-studio/visns-components",
|
|
91
|
-
"version": "5.13.
|
|
91
|
+
"version": "5.13.18",
|
|
92
92
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
93
93
|
"main": "src/index.js",
|
|
94
94
|
"files": [
|
|
@@ -642,28 +642,30 @@ function GenericDetail({
|
|
|
642
642
|
if (!url) return toast.error('Export URL not found');
|
|
643
643
|
|
|
644
644
|
let exportUrl = url;
|
|
645
|
-
|
|
645
|
+
|
|
646
646
|
// Replace {id} placeholder with actual ID value
|
|
647
647
|
if (key && data[key]) {
|
|
648
648
|
exportUrl = url.replace('{id}', data[key]);
|
|
649
649
|
} else if (url.includes('{id}') && data.id) {
|
|
650
650
|
exportUrl = url.replace('{id}', data.id);
|
|
651
651
|
}
|
|
652
|
-
|
|
652
|
+
|
|
653
653
|
// Legacy support: append key value to URL if no placeholder found
|
|
654
654
|
if (!url.includes('{id}') && key && data[key]) {
|
|
655
655
|
exportUrl = `${url}/${data[key]}`;
|
|
656
656
|
}
|
|
657
|
-
|
|
657
|
+
|
|
658
658
|
if (method === 'POST') {
|
|
659
659
|
// Create a form to submit POST request
|
|
660
660
|
const form = document.createElement('form');
|
|
661
661
|
form.method = 'POST';
|
|
662
662
|
form.action = exportUrl;
|
|
663
663
|
form.target = '_blank';
|
|
664
|
-
|
|
664
|
+
|
|
665
665
|
// Add CSRF token if available
|
|
666
|
-
const csrfToken = document
|
|
666
|
+
const csrfToken = document
|
|
667
|
+
.querySelector('meta[name="csrf-token"]')
|
|
668
|
+
?.getAttribute('content');
|
|
667
669
|
if (csrfToken) {
|
|
668
670
|
const csrfInput = document.createElement('input');
|
|
669
671
|
csrfInput.type = 'hidden';
|
|
@@ -671,7 +673,7 @@ function GenericDetail({
|
|
|
671
673
|
csrfInput.value = csrfToken;
|
|
672
674
|
form.appendChild(csrfInput);
|
|
673
675
|
}
|
|
674
|
-
|
|
676
|
+
|
|
675
677
|
document.body.appendChild(form);
|
|
676
678
|
form.submit();
|
|
677
679
|
document.body.removeChild(form);
|
|
@@ -1434,9 +1436,9 @@ function GenericDetail({
|
|
|
1434
1436
|
return renderTotal();
|
|
1435
1437
|
default:
|
|
1436
1438
|
if (id === 'proposalDynamic') {
|
|
1437
|
-
return size === 'full' && truncatedValue
|
|
1438
|
-
|
|
1439
|
-
<iframe
|
|
1439
|
+
return size === 'full' && truncatedValue ? (
|
|
1440
|
+
<div className={styles.proposalDynamicContainer}>
|
|
1441
|
+
<iframe
|
|
1440
1442
|
srcDoc={`
|
|
1441
1443
|
<!DOCTYPE html>
|
|
1442
1444
|
<html>
|
|
@@ -1493,18 +1495,21 @@ function GenericDetail({
|
|
|
1493
1495
|
width: '100%',
|
|
1494
1496
|
minHeight: '400px',
|
|
1495
1497
|
border: 'none',
|
|
1496
|
-
backgroundColor: 'transparent'
|
|
1498
|
+
backgroundColor: 'transparent',
|
|
1497
1499
|
}}
|
|
1498
1500
|
onLoad={(e) => {
|
|
1499
1501
|
const iframe = e.target;
|
|
1500
|
-
const doc =
|
|
1502
|
+
const doc =
|
|
1503
|
+
iframe.contentDocument ||
|
|
1504
|
+
iframe.contentWindow.document;
|
|
1501
1505
|
const height = doc.body.scrollHeight;
|
|
1502
1506
|
iframe.style.height = height + 'px';
|
|
1503
1507
|
}}
|
|
1504
1508
|
/>
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1509
|
+
</div>
|
|
1510
|
+
) : (
|
|
1511
|
+
<div className={styles.proposalDynamicContainer}>
|
|
1512
|
+
<iframe
|
|
1508
1513
|
srcDoc={`
|
|
1509
1514
|
<!DOCTYPE html>
|
|
1510
1515
|
<html>
|
|
@@ -1531,16 +1536,19 @@ function GenericDetail({
|
|
|
1531
1536
|
width: '100%',
|
|
1532
1537
|
minHeight: '200px',
|
|
1533
1538
|
border: 'none',
|
|
1534
|
-
backgroundColor: 'transparent'
|
|
1539
|
+
backgroundColor: 'transparent',
|
|
1535
1540
|
}}
|
|
1536
1541
|
onLoad={(e) => {
|
|
1537
1542
|
const iframe = e.target;
|
|
1538
|
-
const doc =
|
|
1543
|
+
const doc =
|
|
1544
|
+
iframe.contentDocument ||
|
|
1545
|
+
iframe.contentWindow.document;
|
|
1539
1546
|
const height = doc.body.scrollHeight;
|
|
1540
1547
|
iframe.style.height = height + 'px';
|
|
1541
1548
|
}}
|
|
1542
1549
|
/>
|
|
1543
|
-
|
|
1550
|
+
</div>
|
|
1551
|
+
);
|
|
1544
1552
|
}
|
|
1545
1553
|
return size === 'full' && truncatedValue
|
|
1546
1554
|
? parse(`<br /><p>${truncatedValue}</p>`)
|
|
@@ -2672,7 +2680,8 @@ function GenericDetail({
|
|
|
2672
2680
|
)
|
|
2673
2681
|
}
|
|
2674
2682
|
>
|
|
2675
|
-
{activeTabConfig.export
|
|
2683
|
+
{activeTabConfig.export
|
|
2684
|
+
.label || 'Export'}
|
|
2676
2685
|
</button>
|
|
2677
2686
|
)}
|
|
2678
2687
|
|
|
@@ -3004,21 +3013,27 @@ function GenericDetail({
|
|
|
3004
3013
|
// Replace URL parameters like {key} with actual values
|
|
3005
3014
|
const replaceUrlParams = (url) => {
|
|
3006
3015
|
if (!url) return url;
|
|
3007
|
-
|
|
3016
|
+
|
|
3008
3017
|
// Handle the new urlKey parameter
|
|
3009
|
-
const urlKey =
|
|
3010
|
-
|
|
3018
|
+
const urlKey =
|
|
3019
|
+
activeTabConfig.urlKey || 'dataId';
|
|
3020
|
+
|
|
3011
3021
|
let replacementValue;
|
|
3012
3022
|
if (urlKey === 'dataId') {
|
|
3013
3023
|
// Use routeParams for dataId (backward compatibility)
|
|
3014
|
-
replacementValue =
|
|
3024
|
+
replacementValue =
|
|
3025
|
+
routeParams[urlParam] || '';
|
|
3015
3026
|
} else {
|
|
3016
3027
|
// Use data object for other keys, supporting dot notation
|
|
3017
|
-
replacementValue = urlKey
|
|
3018
|
-
|
|
3019
|
-
|
|
3028
|
+
replacementValue = urlKey
|
|
3029
|
+
.split('.')
|
|
3030
|
+
.reduce((obj, key) => {
|
|
3031
|
+
return obj && obj[key] !== undefined
|
|
3032
|
+
? obj[key]
|
|
3033
|
+
: '';
|
|
3034
|
+
}, data);
|
|
3020
3035
|
}
|
|
3021
|
-
|
|
3036
|
+
|
|
3022
3037
|
// Replace both {key} and {dataId} patterns for backward compatibility
|
|
3023
3038
|
return url
|
|
3024
3039
|
.replace(/{key}/g, replacementValue)
|
|
@@ -3050,7 +3065,9 @@ function GenericDetail({
|
|
|
3050
3065
|
entityData={data}
|
|
3051
3066
|
routeParams={routeParams}
|
|
3052
3067
|
fetchData={handleReload}
|
|
3053
|
-
showDescription={
|
|
3068
|
+
showDescription={
|
|
3069
|
+
activeTabConfig.showDescription
|
|
3070
|
+
}
|
|
3054
3071
|
/>
|
|
3055
3072
|
);
|
|
3056
3073
|
case 'scheduling':
|
|
@@ -3062,6 +3079,7 @@ function GenericDetail({
|
|
|
3062
3079
|
modalOpen={modalOpen}
|
|
3063
3080
|
preloadedOptions={preloadedOptions}
|
|
3064
3081
|
setData={setData}
|
|
3082
|
+
userProfile={userProfile}
|
|
3065
3083
|
/>
|
|
3066
3084
|
);
|
|
3067
3085
|
case 'custom':
|
|
@@ -210,6 +210,7 @@ const GenericEditableTable = ({
|
|
|
210
210
|
dataId,
|
|
211
211
|
preloadedOptions,
|
|
212
212
|
setData, // callback to update the parent state
|
|
213
|
+
userProfile, // user profile for permission checks
|
|
213
214
|
}) => {
|
|
214
215
|
const isInitialLoad = useRef(true);
|
|
215
216
|
const { columns, rows, form, title } = schedulingConfig;
|
|
@@ -217,6 +218,21 @@ const GenericEditableTable = ({
|
|
|
217
218
|
const hasColourColumn = columns.some((col) => col.id === 'colours');
|
|
218
219
|
const hasMarginRow = rows && rows.marginRow;
|
|
219
220
|
|
|
221
|
+
// Check if user has permission to view margin rows
|
|
222
|
+
const hasMarginPermission = () => {
|
|
223
|
+
if (!rows?.marginRoles || !Array.isArray(rows.marginRoles)) {
|
|
224
|
+
return true; // Show by default if no marginRoles specified
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (!userProfile?.roles) {
|
|
228
|
+
return false; // Hide if marginRoles exist but no user profile
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return userProfile.roles.some(role =>
|
|
232
|
+
rows.marginRoles.includes(role.name)
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
|
|
220
236
|
// dataSets: each item => { created_at: string, data: array of rows }
|
|
221
237
|
const [dataSets, setDataSets] = useState([]);
|
|
222
238
|
// Index of the currently active dataset
|
|
@@ -359,6 +375,14 @@ const GenericEditableTable = ({
|
|
|
359
375
|
setSelectedRows(new Set());
|
|
360
376
|
}, [dataSets, activeDatasetIndex, hasMarginRow, rows.marginRow]);
|
|
361
377
|
|
|
378
|
+
// Initialize newEntry with default values when columns change
|
|
379
|
+
useEffect(() => {
|
|
380
|
+
const defaultValues = getDefaultRowValues();
|
|
381
|
+
if (!hasCategory) {
|
|
382
|
+
setNewEntry(defaultValues);
|
|
383
|
+
}
|
|
384
|
+
}, [columns, hasCategory]);
|
|
385
|
+
|
|
362
386
|
// Helper to sort by sort_order
|
|
363
387
|
const sortBySortOrder = (dataArray) =>
|
|
364
388
|
[...dataArray].sort((a, b) => a.sort_order - b.sort_order);
|
|
@@ -400,6 +424,73 @@ const GenericEditableTable = ({
|
|
|
400
424
|
return undefined;
|
|
401
425
|
};
|
|
402
426
|
|
|
427
|
+
// Helper function to get default values for new row
|
|
428
|
+
const getDefaultRowValues = () => {
|
|
429
|
+
const defaultValues = {};
|
|
430
|
+
columns.forEach((column) => {
|
|
431
|
+
switch (column.type) {
|
|
432
|
+
case 'dropdown':
|
|
433
|
+
if (column.options && column.options.length > 0) {
|
|
434
|
+
defaultValues[column.id] = column.options[0].id;
|
|
435
|
+
}
|
|
436
|
+
break;
|
|
437
|
+
case 'dropdown-ajax':
|
|
438
|
+
// Reset to empty for ajax dropdowns
|
|
439
|
+
defaultValues[column.id] = '';
|
|
440
|
+
break;
|
|
441
|
+
case 'currency':
|
|
442
|
+
case 'number':
|
|
443
|
+
case 'text':
|
|
444
|
+
case 'date':
|
|
445
|
+
case 'html5_date':
|
|
446
|
+
// Reset to empty string for input fields
|
|
447
|
+
defaultValues[column.id] = '';
|
|
448
|
+
break;
|
|
449
|
+
case 'multi-dropdown-ajax':
|
|
450
|
+
// Reset to empty for multi-select
|
|
451
|
+
defaultValues[column.id] = '';
|
|
452
|
+
break;
|
|
453
|
+
case 'total':
|
|
454
|
+
// Don't reset total fields as they are calculated
|
|
455
|
+
break;
|
|
456
|
+
case 'colour':
|
|
457
|
+
// Reset colour fields
|
|
458
|
+
defaultValues[column.id] = '';
|
|
459
|
+
break;
|
|
460
|
+
default:
|
|
461
|
+
// Reset any other field types to empty string
|
|
462
|
+
defaultValues[column.id] = '';
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
return defaultValues;
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
// Helper function to get add row background color (same logic as getRowBackground)
|
|
470
|
+
const getAddRowBackground = (newRowData, groupId = null) => {
|
|
471
|
+
if (!newRowData) newRowData = {};
|
|
472
|
+
|
|
473
|
+
// Ensure default status values are applied for color calculation
|
|
474
|
+
const enrichedRowData = { ...newRowData };
|
|
475
|
+
columns.forEach((column) => {
|
|
476
|
+
if (column.type === 'dropdown' && column.options && column.options.length > 0) {
|
|
477
|
+
if (!enrichedRowData[column.id]) {
|
|
478
|
+
enrichedRowData[column.id] = column.options[0].id;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// Check if there's a colour picked from the colours column
|
|
484
|
+
const coloursValue = enrichedRowData.colours || enrichedRowData.row_colour;
|
|
485
|
+
if (coloursValue) {
|
|
486
|
+
return `${coloursValue}40`; // Add 40% opacity
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Check for status color if no manual color is set
|
|
490
|
+
const statusColor = getStatusColor(enrichedRowData);
|
|
491
|
+
return statusColor ? `${statusColor}40` : undefined; // Add 40% opacity
|
|
492
|
+
};
|
|
493
|
+
|
|
403
494
|
// Calculate total project cost (sum of all entries excluding margin row)
|
|
404
495
|
const calculateTotalProjectCost = (dataEntries) => {
|
|
405
496
|
const totalColIndex = columns.findIndex((c) => c.type === 'total');
|
|
@@ -658,11 +749,12 @@ const GenericEditableTable = ({
|
|
|
658
749
|
setDataSets(updatedDataSets);
|
|
659
750
|
debouncedUpdate(updatedDataSets);
|
|
660
751
|
|
|
661
|
-
// Reset new-entry state
|
|
752
|
+
// Reset new-entry state with default values
|
|
753
|
+
const defaultValues = getDefaultRowValues();
|
|
662
754
|
if (hasCategory) {
|
|
663
|
-
setNewEntries((prev) => ({ ...prev, [groupId]:
|
|
755
|
+
setNewEntries((prev) => ({ ...prev, [groupId]: defaultValues }));
|
|
664
756
|
} else {
|
|
665
|
-
setNewEntry(
|
|
757
|
+
setNewEntry(defaultValues);
|
|
666
758
|
}
|
|
667
759
|
toast.success('Row added');
|
|
668
760
|
};
|
|
@@ -1101,10 +1193,11 @@ const GenericEditableTable = ({
|
|
|
1101
1193
|
case 'currency':
|
|
1102
1194
|
return (
|
|
1103
1195
|
<CurrencyInput
|
|
1196
|
+
key={`new-currency-${column.id}-${groupId || 'default'}-${value || 'empty'}`}
|
|
1104
1197
|
id={`new-currency-${column.id}-${groupId || 'default'}`}
|
|
1105
1198
|
name={column.id}
|
|
1106
1199
|
placeholder="$0.00"
|
|
1107
|
-
|
|
1200
|
+
value={value || ''}
|
|
1108
1201
|
decimalsLimit={2}
|
|
1109
1202
|
prefix="$"
|
|
1110
1203
|
decimalSeparator="."
|
|
@@ -1165,9 +1258,10 @@ const GenericEditableTable = ({
|
|
|
1165
1258
|
/>
|
|
1166
1259
|
);
|
|
1167
1260
|
case 'dropdown':
|
|
1261
|
+
const defaultValue = value || (column.options && column.options.length > 0 ? column.options[0].id : '');
|
|
1168
1262
|
return (
|
|
1169
1263
|
<select
|
|
1170
|
-
value={
|
|
1264
|
+
value={defaultValue}
|
|
1171
1265
|
onChange={(e) =>
|
|
1172
1266
|
handleNewFieldChange(
|
|
1173
1267
|
e.target.value,
|
|
@@ -1312,95 +1406,99 @@ const GenericEditableTable = ({
|
|
|
1312
1406
|
<td></td>
|
|
1313
1407
|
</tr>
|
|
1314
1408
|
|
|
1315
|
-
{/*
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1409
|
+
{/* Margin - Show only if user has permission */}
|
|
1410
|
+
{hasMarginPermission() && (
|
|
1411
|
+
<>
|
|
1412
|
+
<tr style={{ backgroundColor: '#f8f9fa' }}>
|
|
1413
|
+
<td colSpan={6} style={{ padding: '8px' }}>
|
|
1414
|
+
{rows?.marginLabel || 'LKD'} Margin (in %)
|
|
1415
|
+
</td>
|
|
1416
|
+
<td
|
|
1417
|
+
colSpan={2}
|
|
1418
|
+
style={{ padding: '8px', textAlign: 'center' }}
|
|
1419
|
+
>
|
|
1420
|
+
<input
|
|
1421
|
+
type="number"
|
|
1422
|
+
value={marginPercentage}
|
|
1423
|
+
onChange={(e) =>
|
|
1424
|
+
handleMarginPercentageChange(
|
|
1425
|
+
parseFloat(e.target.value) || 0
|
|
1426
|
+
)
|
|
1427
|
+
}
|
|
1428
|
+
placeholder="0"
|
|
1429
|
+
style={{
|
|
1430
|
+
padding: '4px',
|
|
1431
|
+
border: '1px solid #ccc',
|
|
1432
|
+
borderRadius: '3px',
|
|
1433
|
+
textAlign: 'center',
|
|
1434
|
+
marginRight: '4px',
|
|
1435
|
+
}}
|
|
1436
|
+
/>
|
|
1437
|
+
</td>
|
|
1438
|
+
<td
|
|
1439
|
+
colSpan={2}
|
|
1440
|
+
style={{ padding: '8px', textAlign: 'right' }}
|
|
1441
|
+
>
|
|
1442
|
+
{marginAmount.toLocaleString('en-AU', {
|
|
1443
|
+
style: 'currency',
|
|
1444
|
+
currency: 'AUD',
|
|
1445
|
+
})}
|
|
1446
|
+
</td>
|
|
1447
|
+
<td></td>
|
|
1448
|
+
</tr>
|
|
1353
1449
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1450
|
+
{/* Total Project Cost */}
|
|
1451
|
+
<tr style={{ backgroundColor: '#e9ecef', fontWeight: 'bold' }}>
|
|
1452
|
+
<td colSpan={6} style={{ padding: '8px' }}>
|
|
1453
|
+
Total {rows?.marginLabel || 'LKD'} Project Cost
|
|
1454
|
+
</td>
|
|
1455
|
+
<td
|
|
1456
|
+
colSpan={4}
|
|
1457
|
+
style={{ padding: '8px', textAlign: 'right' }}
|
|
1458
|
+
>
|
|
1459
|
+
{totalLkdProjectCost.toLocaleString('en-AU', {
|
|
1460
|
+
style: 'currency',
|
|
1461
|
+
currency: 'AUD',
|
|
1462
|
+
})}
|
|
1463
|
+
</td>
|
|
1464
|
+
<td></td>
|
|
1465
|
+
</tr>
|
|
1370
1466
|
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1467
|
+
{/* Total GST */}
|
|
1468
|
+
<tr style={{ backgroundColor: '#e9ecef' }}>
|
|
1469
|
+
<td colSpan={6} style={{ padding: '8px' }}>
|
|
1470
|
+
Total GST
|
|
1471
|
+
</td>
|
|
1472
|
+
<td
|
|
1473
|
+
colSpan={4}
|
|
1474
|
+
style={{ padding: '8px', textAlign: 'right' }}
|
|
1475
|
+
>
|
|
1476
|
+
{totalLkdGst.toLocaleString('en-AU', {
|
|
1477
|
+
style: 'currency',
|
|
1478
|
+
currency: 'AUD',
|
|
1479
|
+
})}
|
|
1480
|
+
</td>
|
|
1481
|
+
<td></td>
|
|
1482
|
+
</tr>
|
|
1387
1483
|
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1484
|
+
{/* Total Project Cost (Including GST) */}
|
|
1485
|
+
<tr style={{ backgroundColor: '#e9ecef', fontWeight: 'bold' }}>
|
|
1486
|
+
<td colSpan={6} style={{ padding: '8px' }}>
|
|
1487
|
+
Total {rows?.marginLabel || 'LKD'} Project Cost (Including GST)
|
|
1488
|
+
</td>
|
|
1489
|
+
<td
|
|
1490
|
+
colSpan={4}
|
|
1491
|
+
style={{ padding: '8px', textAlign: 'right' }}
|
|
1492
|
+
>
|
|
1493
|
+
{totalLkdWithGst.toLocaleString('en-AU', {
|
|
1494
|
+
style: 'currency',
|
|
1495
|
+
currency: 'AUD',
|
|
1496
|
+
})}
|
|
1497
|
+
</td>
|
|
1498
|
+
<td></td>
|
|
1499
|
+
</tr>
|
|
1500
|
+
</>
|
|
1501
|
+
)}
|
|
1404
1502
|
</>
|
|
1405
1503
|
);
|
|
1406
1504
|
};
|
|
@@ -1409,7 +1507,12 @@ const GenericEditableTable = ({
|
|
|
1409
1507
|
const renderNewRowForm = (groupId = null) => {
|
|
1410
1508
|
const newRowData = hasCategory ? newEntries[groupId] || {} : newEntry;
|
|
1411
1509
|
return (
|
|
1412
|
-
<tr
|
|
1510
|
+
<tr
|
|
1511
|
+
className={styles.newRow}
|
|
1512
|
+
style={{
|
|
1513
|
+
background: getAddRowBackground(newRowData, groupId),
|
|
1514
|
+
}}
|
|
1515
|
+
>
|
|
1413
1516
|
<td className={styles.checkboxColumn}></td>
|
|
1414
1517
|
{columns.map((column) => (
|
|
1415
1518
|
<td
|