@@ -26,6 +26,55 @@ import { Box } from "@mui/system";
2626import { useSettings } from "../../hooks/use-settings" ;
2727import { isEqual } from "lodash" ; // Import lodash for deep comparison
2828
29+ // Resolve dot-delimited property paths against arbitrary data objects.
30+ const getNestedValue = ( source , path ) => {
31+ if ( ! source ) {
32+ return undefined ;
33+ }
34+ if ( ! path ) {
35+ return source ;
36+ }
37+
38+ return path . split ( "." ) . reduce ( ( acc , key ) => {
39+ if ( acc === undefined || acc === null ) {
40+ return undefined ;
41+ }
42+ if ( typeof acc !== "object" ) {
43+ return undefined ;
44+ }
45+ return acc [ key ] ;
46+ } , source ) ;
47+ } ;
48+
49+ // Resolve dot-delimited column ids against the original row data so nested fields can sort/filter properly.
50+ const getRowValueByColumnId = ( row , columnId ) => {
51+ if ( ! row ?. original || ! columnId ) {
52+ return undefined ;
53+ }
54+
55+ if ( columnId . includes ( "@odata" ) ) {
56+ return row . original [ columnId ] ;
57+ }
58+
59+ return getNestedValue ( row . original , columnId ) ;
60+ } ;
61+
62+ const compareNullable = ( aVal , bVal ) => {
63+ if ( aVal === null && bVal === null ) {
64+ return 0 ;
65+ }
66+ if ( aVal === null ) {
67+ return 1 ;
68+ }
69+ if ( bVal === null ) {
70+ return - 1 ;
71+ }
72+ if ( aVal === bVal ) {
73+ return 0 ;
74+ }
75+ return aVal > bVal ? 1 : - 1 ;
76+ } ;
77+
2978export const CippDataTable = ( props ) => {
3079 const {
3180 queryKey,
@@ -107,22 +156,6 @@ export const CippDataTable = (props) => {
107156 useEffect ( ( ) => {
108157 if ( getRequestData . isSuccess ) {
109158 const allPages = getRequestData . data . pages ;
110- const getNestedValue = ( obj , path ) => {
111- if ( ! path ) {
112- return obj ;
113- }
114-
115- const keys = path . split ( "." ) ;
116- let result = obj ;
117- for ( const key of keys ) {
118- if ( result && typeof result === "object" && key in result ) {
119- result = result [ key ] ;
120- } else {
121- return undefined ;
122- }
123- }
124- return result ;
125- } ;
126159
127160 const combinedResults = allPages . flatMap ( ( page ) => {
128161 const nestedData = getNestedValue ( page , api . dataKey ) ;
@@ -448,49 +481,56 @@ export const CippDataTable = (props) => {
448481 } ,
449482 sortingFns : {
450483 dateTimeNullsLast : ( a , b , id ) => {
451- const aVal = a ?. original ?. [ id ] ?? null ;
452- const bVal = b ?. original ?. [ id ] ?? null ;
453- if ( aVal === null && bVal === null ) {
454- return 0 ;
455- }
456- if ( aVal === null ) {
457- return 1 ;
458- }
459- if ( bVal === null ) {
460- return - 1 ;
461- }
462- return aVal > bVal ? 1 : - 1 ;
484+ const aRaw = getRowValueByColumnId ( a , id ) ;
485+ const bRaw = getRowValueByColumnId ( b , id ) ;
486+ const aDate = aRaw ? new Date ( aRaw ) : null ;
487+ const bDate = bRaw ? new Date ( bRaw ) : null ;
488+ const aTime = aDate && ! Number . isNaN ( aDate . getTime ( ) ) ? aDate . getTime ( ) : null ;
489+ const bTime = bDate && ! Number . isNaN ( bDate . getTime ( ) ) ? bDate . getTime ( ) : null ;
490+
491+ return compareNullable ( aTime , bTime ) ;
463492 } ,
464493 number : ( a , b , id ) => {
465- const aVal = a ?. original ?. [ id ] ?? null ;
466- const bVal = b ?. original ?. [ id ] ?? null ;
467- if ( aVal === null && bVal === null ) {
468- return 0 ;
469- }
470- if ( aVal === null ) {
471- return 1 ;
472- }
473- if ( bVal === null ) {
474- return - 1 ;
475- }
476- return aVal - bVal ;
494+ const aRaw = getRowValueByColumnId ( a , id ) ;
495+ const bRaw = getRowValueByColumnId ( b , id ) ;
496+ const aNum = typeof aRaw === "number" ? aRaw : Number ( aRaw ) ;
497+ const bNum = typeof bRaw === "number" ? bRaw : Number ( bRaw ) ;
498+ const aVal = Number . isNaN ( aNum ) ? null : aNum ;
499+ const bVal = Number . isNaN ( bNum ) ? null : bNum ;
500+
501+ return compareNullable ( aVal , bVal ) ;
477502 } ,
478503 boolean : ( a , b , id ) => {
479- const aVal = a ?. original ?. [ id ] ?? null ;
480- const bVal = b ?. original ?. [ id ] ?? null ;
481- if ( aVal === null && bVal === null ) {
482- return 0 ;
483- }
484- if ( aVal === null ) {
485- return 1 ;
486- }
487- if ( bVal === null ) {
488- return - 1 ;
489- }
490- // Convert to numbers: true = 1, false = 0
491- const aNum = aVal === true ? 1 : 0 ;
492- const bNum = bVal === true ? 1 : 0 ;
493- return aNum - bNum ;
504+ const aRaw = getRowValueByColumnId ( a , id ) ;
505+ const bRaw = getRowValueByColumnId ( b , id ) ;
506+ const toBool = ( value ) => {
507+ if ( value === null || value === undefined ) {
508+ return null ;
509+ }
510+ if ( typeof value === "boolean" ) {
511+ return value ;
512+ }
513+ if ( typeof value === "string" ) {
514+ const lower = value . toLowerCase ( ) ;
515+ if ( lower === "true" || lower === "yes" ) {
516+ return true ;
517+ }
518+ if ( lower === "false" || lower === "no" ) {
519+ return false ;
520+ }
521+ }
522+ if ( typeof value === "number" ) {
523+ return value !== 0 ;
524+ }
525+ return null ;
526+ } ;
527+
528+ const aBool = toBool ( aRaw ) ;
529+ const bBool = toBool ( bRaw ) ;
530+ const aNumeric = aBool === null ? null : aBool ? 1 : 0 ;
531+ const bNumeric = bBool === null ? null : bBool ? 1 : 0 ;
532+
533+ return compareNullable ( aNumeric , bNumeric ) ;
494534 } ,
495535 } ,
496536 filterFns : {
0 commit comments