@visns-studio/visns-components 5.13.5 → 5.13.7

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
@@ -24,19 +24,20 @@
24
24
  "dayjs": "^1.11.13",
25
25
  "fabric": "^6.7.0",
26
26
  "file-saver": "^2.0.5",
27
- "framer-motion": "^12.23.0",
27
+ "framer-motion": "^12.23.1",
28
28
  "html-react-parser": "^5.2.5",
29
29
  "lodash": "^4.17.21",
30
30
  "lodash.debounce": "^4.0.8",
31
31
  "lucide-react": "^0.525.0",
32
32
  "moment": "^2.30.1",
33
- "motion": "^12.23.0",
33
+ "motion": "^12.23.1",
34
34
  "numeral": "^2.0.6",
35
35
  "pluralize": "^8.0.0",
36
36
  "qrcode.react": "^4.2.0",
37
37
  "quill-image-uploader": "^1.3.0",
38
38
  "react-big-calendar": "^1.19.4",
39
39
  "react-copy-to-clipboard": "^5.1.0",
40
+ "react-currency-input-field": "^3.10.0",
40
41
  "react-datepicker": "^8.4.0",
41
42
  "react-dropzone": "^14.3.8",
42
43
  "react-grid-gallery": "^1.0.1",
@@ -87,7 +88,7 @@
87
88
  "react-dom": "^17.0.0 || ^18.0.0"
88
89
  },
89
90
  "name": "@visns-studio/visns-components",
90
- "version": "5.13.5",
91
+ "version": "5.13.7",
91
92
  "description": "Various packages to assist in the development of our Custom Applications.",
92
93
  "main": "src/index.js",
93
94
  "files": [
@@ -114,6 +114,7 @@ import {
114
114
  renderDateRangeColumn,
115
115
  renderStageCounterColumn,
116
116
  renderGalleryColumn,
117
+ renderTotalColumn,
117
118
  } from './columns/ColumnRenderers.jsx';
118
119
  import _ from 'lodash';
119
120
 
@@ -2720,6 +2721,11 @@ const DataGrid = forwardRef(
2720
2721
  setLocalInputValues,
2721
2722
  handleInputUpdate,
2722
2723
  });
2724
+ case 'total':
2725
+ return renderTotalColumn()({
2726
+ column,
2727
+ commonProps,
2728
+ });
2723
2729
  default:
2724
2730
  columnId = Array.isArray(column.id)
2725
2731
  ? column.id.join('-')
@@ -2472,3 +2472,52 @@ export const renderStageCounterColumn = ({ column, commonProps, navigate, onUpda
2472
2472
  },
2473
2473
  };
2474
2474
  };
2475
+
2476
+ // Calculate total for columns of type 'total'
2477
+ const calculateTotal = (entry, keys) => {
2478
+ let total = 0;
2479
+ if (Array.isArray(keys)) {
2480
+ total = keys.reduce(
2481
+ (sum, key) => sum + (parseFloat(entry[key]) || 0),
2482
+ 0
2483
+ );
2484
+ } else if (
2485
+ keys &&
2486
+ typeof keys === 'object' &&
2487
+ keys.price &&
2488
+ keys.unit
2489
+ ) {
2490
+ const { price: priceKeys, unit: unitKeys } = keys;
2491
+ if (unitKeys.length === 1) {
2492
+ const unitValue = parseFloat(entry[unitKeys[0]]) || 0;
2493
+ total = priceKeys.reduce(
2494
+ (sum, key) =>
2495
+ sum + (parseFloat(entry[key]) || 0) * unitValue,
2496
+ 0
2497
+ );
2498
+ } else if (priceKeys.length === unitKeys.length) {
2499
+ total = priceKeys.reduce(
2500
+ (sum, key, index) =>
2501
+ sum +
2502
+ (parseFloat(entry[key]) || 0) *
2503
+ (parseFloat(entry[unitKeys[index]]) || 0),
2504
+ 0
2505
+ );
2506
+ }
2507
+ }
2508
+ return total;
2509
+ };
2510
+
2511
+
2512
+ export const renderTotalColumn = () => {
2513
+ return {
2514
+ render: ({ data: rowData, column }) => {
2515
+ // For individual rows, calculate the total for that specific row
2516
+ const subtotal = calculateTotal(rowData, column.keys);
2517
+ return new Intl.NumberFormat('en-AU', {
2518
+ style: 'currency',
2519
+ currency: 'AUD',
2520
+ }).format(subtotal);
2521
+ },
2522
+ };
2523
+ };
@@ -5,6 +5,7 @@ import { toast } from 'react-toastify';
5
5
  import { Trash2, ArrowUp, ArrowDown, Copy, Droplets } from 'lucide-react';
6
6
  import { Compact } from '@uiw/react-color';
7
7
  import { confirmDialog } from '../utils/ConfirmDialog';
8
+ import CurrencyInput from 'react-currency-input-field';
8
9
 
9
10
  import CustomFetch from '../Fetch';
10
11
  import MultiSelect from '../MultiSelect';
@@ -419,6 +420,18 @@ const GenericEditableTable = ({
419
420
  return totalProjectCost * (percentage / 100);
420
421
  };
421
422
 
423
+ // Check if row matches where conditions
424
+ const matchesWhereConditions = (row, whereConditions) => {
425
+ if (!whereConditions || !Array.isArray(whereConditions)) {
426
+ return true;
427
+ }
428
+
429
+ return whereConditions.every(condition => {
430
+ const { id, value } = condition;
431
+ return row[id] === value;
432
+ });
433
+ };
434
+
422
435
  // Calculate total for columns of type 'total'
423
436
  const calculateTotal = (entry, keys) => {
424
437
  let total = 0;
@@ -454,6 +467,19 @@ const GenericEditableTable = ({
454
467
  return total;
455
468
  };
456
469
 
470
+ // Calculate total across all data with where clause filtering
471
+ const calculateTotalFromData = (data, keys, whereConditions) => {
472
+ if (!data || !Array.isArray(data)) {
473
+ return 0;
474
+ }
475
+
476
+ const filteredData = data.filter(row => matchesWhereConditions(row, whereConditions));
477
+
478
+ return filteredData.reduce((sum, entry) => {
479
+ return sum + calculateTotal(entry, keys);
480
+ }, 0);
481
+ };
482
+
457
483
  // Debounced update to save entire dataSets array
458
484
  const debouncedUpdate = useMemo(
459
485
  () =>
@@ -895,6 +921,27 @@ const GenericEditableTable = ({
895
921
  // For other colour columns, picker is rendered in the action column
896
922
  return null;
897
923
  case 'currency':
924
+ return (
925
+ <CurrencyInput
926
+ id={`currency-${column.id}-${keyCounter}`}
927
+ name={column.id}
928
+ placeholder="$0.00"
929
+ defaultValue={entry[column.id] || ''}
930
+ decimalsLimit={2}
931
+ prefix="$"
932
+ decimalSeparator="."
933
+ groupSeparator=","
934
+ onValueChange={(value) =>
935
+ handleFieldChange(
936
+ value || '',
937
+ column.id,
938
+ keyCounter
939
+ )
940
+ }
941
+ style={{ textAlign: 'right', width: '100%' }}
942
+ readOnly={column.readOnly || false}
943
+ />
944
+ );
898
945
  case 'number':
899
946
  return (
900
947
  <input
@@ -1051,6 +1098,26 @@ const GenericEditableTable = ({
1051
1098
  // For other colour columns, picker is rendered in the action column
1052
1099
  return null;
1053
1100
  case 'currency':
1101
+ return (
1102
+ <CurrencyInput
1103
+ id={`new-currency-${column.id}-${groupId || 'default'}`}
1104
+ name={column.id}
1105
+ placeholder="$0.00"
1106
+ defaultValue={value || ''}
1107
+ decimalsLimit={2}
1108
+ prefix="$"
1109
+ decimalSeparator="."
1110
+ groupSeparator=","
1111
+ onValueChange={(value) =>
1112
+ handleNewFieldChange(
1113
+ value || '',
1114
+ column.id,
1115
+ groupId
1116
+ )
1117
+ }
1118
+ style={{ textAlign: 'right', width: '100%' }}
1119
+ />
1120
+ );
1054
1121
  case 'number':
1055
1122
  return (
1056
1123
  <input
@@ -1594,18 +1661,19 @@ const GenericEditableTable = ({
1594
1661
  );
1595
1662
  }
1596
1663
  if (index === totalColIndex) {
1664
+ const totalColumn = columns[totalColIndex];
1597
1665
  const groupTotal =
1598
- group.entries.reduce(
1599
- (sum, entry) =>
1600
- sum +
1601
- calculateTotal(
1602
- entry,
1603
- columns[
1604
- totalColIndex
1605
- ].keys
1606
- ),
1607
- 0
1608
- );
1666
+ group.entries
1667
+ .filter(entry => matchesWhereConditions(entry, totalColumn.where))
1668
+ .reduce(
1669
+ (sum, entry) =>
1670
+ sum +
1671
+ calculateTotal(
1672
+ entry,
1673
+ totalColumn.keys
1674
+ ),
1675
+ 0
1676
+ );
1609
1677
  return (
1610
1678
  <td key={col.id}>
1611
1679
  {groupTotal.toLocaleString(
@@ -1749,17 +1817,18 @@ const GenericEditableTable = ({
1749
1817
  );
1750
1818
  }
1751
1819
  if (index === totalColIndex) {
1820
+ const totalColumn = columns[totalColIndex];
1752
1821
  const overallTotal =
1753
1822
  sortBySortOrder(
1754
1823
  localData
1755
- ).reduce(
1824
+ )
1825
+ .filter(entry => matchesWhereConditions(entry, totalColumn.where))
1826
+ .reduce(
1756
1827
  (sum, entry) =>
1757
1828
  sum +
1758
1829
  calculateTotal(
1759
1830
  entry,
1760
- columns[
1761
- totalColIndex
1762
- ].keys
1831
+ totalColumn.keys
1763
1832
  ),
1764
1833
  0
1765
1834
  );